diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-06-30 11:29:31 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-07-02 12:43:43 +0200 |
commit | 7bb27be8c5ce9a67a413022d627d9580cddbe64e (patch) | |
tree | 3284f172868869a220d801297c55f67015d17497 /src | |
parent | afd0051c5cfb6ccb1d361d89c36b9c494c29ec5e (diff) |
Refactor QQuickIconLoader.
Instead using a QObject with a single icon member variable
that needs to be instantiated for each task bar button, introduce a static
load function that takes a member function pointer accepting a QVariant.
For synchronous requests, invoke it immediately; connect it to a slot
for network requests.
Task-number: QTBUG-36730
Change-Id: Ic70422d98d0bc3d486b32fb3534400b9fff8d324
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/winextras/qquickiconloader.cpp | 147 | ||||
-rw-r--r-- | src/imports/winextras/qquickiconloader_p.h | 76 | ||||
-rw-r--r-- | src/imports/winextras/qquicktaskbarbutton.cpp | 26 | ||||
-rw-r--r-- | src/imports/winextras/qquicktaskbarbutton_p.h | 6 | ||||
-rw-r--r-- | src/imports/winextras/qquickthumbnailtoolbutton.cpp | 24 | ||||
-rw-r--r-- | src/imports/winextras/qquickthumbnailtoolbutton_p.h | 7 |
6 files changed, 178 insertions, 108 deletions
diff --git a/src/imports/winextras/qquickiconloader.cpp b/src/imports/winextras/qquickiconloader.cpp index e1b7506..5ed7445 100644 --- a/src/imports/winextras/qquickiconloader.cpp +++ b/src/imports/winextras/qquickiconloader.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com> - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWinExtras module of the Qt Toolkit. @@ -42,105 +42,110 @@ #include "qquickiconloader_p.h" -#include <QUrl> #include <QQmlEngine> #include <QNetworkAccessManager> #include <QFileInfo> #include <QNetworkRequest> #include <QNetworkReply> -#include <QPixmap> #include <QQuickImageProvider> #include <QQmlFile> #include <qt_windows.h> -#include <QDebug> QT_BEGIN_NAMESPACE -QQuickIconLoader::QQuickIconLoader(QObject *parent) : - QObject(parent) +QVariant QQuickIconLoader::loadFromFile(const QUrl &url, QVariant::Type type) { -} - -void QQuickIconLoader::load(const QUrl &url, QQmlEngine *engine) -{ - m_icon = QIcon(); - QString scheme = url.scheme(); - if (scheme == QLatin1String("qrc") || scheme == QLatin1String("file")) - loadFromFile(url); - else if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) - loadFromNetwork(url, engine); - else if (scheme == QLatin1String("image")) - loadFromImageProvider(url, engine); -} - -QIcon QQuickIconLoader::icon() const -{ - return m_icon; -} - -void QQuickIconLoader::onRequestFinished(QNetworkReply *reply) -{ - disconnect(reply->manager(), 0, this, 0); - if (reply->error() == QNetworkReply::NoError) { - QByteArray data = reply->readAll(); - QPixmap pixmap; - if (pixmap.loadFromData(data)) { - m_icon = QIcon(pixmap); - emit finished(); - } - } else { - qWarning().nospace() << "Cannot load " << reply->url().toString() << " (" << qPrintable(reply->errorString()) << ")"; - } - reply->deleteLater(); -} - -void QQuickIconLoader::loadFromFile(const QUrl &url) -{ - QString path = QQmlFile::urlToLocalFileOrQrc(url); + const QString path = QQmlFile::urlToLocalFileOrQrc(url); if (QFileInfo(path).exists()) { - m_icon = QIcon(path); - emit finished(); + switch (type) { + case QMetaType::QIcon: + return QVariant(QIcon(path)); + case QMetaType::QPixmap: + return QVariant(QPixmap(path)); + default: + qWarning("%s: Unsupported type: %d", Q_FUNC_INFO, int(type)); + break; + } } + return QVariant(); } -void QQuickIconLoader::loadFromNetwork(const QUrl &url, QQmlEngine *engine) +QNetworkReply *QQuickIconLoader::loadFromNetwork(const QUrl &url, const QQmlEngine *engine) { - QNetworkRequest request(url); - QNetworkAccessManager *manager = engine->networkAccessManager(); - connect(manager, SIGNAL(finished(QNetworkReply*)), SLOT(onRequestFinished(QNetworkReply*))); - manager->get(request); + return engine->networkAccessManager()->get(QNetworkRequest(url)); } -static inline QString imageProviderId(const QUrl &url) -{ - return url.host(); -} - -static inline QString imageId(const QUrl &url) -{ - return url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); -} - -void QQuickIconLoader::loadFromImageProvider(const QUrl &url, QQmlEngine *engine) +QVariant QQuickIconLoader::loadFromImageProvider(const QUrl &url, const QQmlEngine *engine, + QVariant::Type type, QSize requestedSize) { const QString providerId = url.host(); const QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid; QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(providerId)); QSize size; - QSize requestSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); + if (!requestedSize.isValid()) + requestedSize = QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); if (provider) imageType = provider->imageType(); - if (imageType == QQuickImageProvider::Image) { - QImage image = provider->requestImage(imageId, &size, requestSize); + QPixmap pixmap; + switch (imageType) { + case QQuickImageProvider::Image: { + QImage image = provider->requestImage(imageId, &size, requestedSize); if (!image.isNull()) - m_icon = QIcon(QPixmap::fromImage(image)); - } else if (imageType == QQuickImageProvider::Pixmap) { - QPixmap pixmap = provider->requestPixmap(imageId, &size, requestSize); - if (!pixmap.isNull()) - m_icon = QIcon(pixmap); + pixmap = QPixmap::fromImage(image); + } + break; + case QQuickImageProvider::Pixmap: + pixmap = provider->requestPixmap(imageId, &size, requestedSize); + break; + default: + break; } - emit finished(); + if (!pixmap.isNull()) { + switch (type) { + case QMetaType::QIcon: + return QVariant(QIcon(pixmap)); + case QMetaType::QPixmap: + return QVariant(pixmap); + default: + qWarning("%s: Unsupported type: %d", Q_FUNC_INFO, int(type)); + break; + } + } + return QVariant(); +} + +QQuickIconLoaderNetworkReplyHandler::QQuickIconLoaderNetworkReplyHandler(QNetworkReply *reply, QVariant::Type type) + : QObject(reply) + , m_type(type) +{ + connect(reply, &QNetworkReply::finished, this, &QQuickIconLoaderNetworkReplyHandler::onRequestFinished); +} + +void QQuickIconLoaderNetworkReplyHandler::onRequestFinished() +{ + QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); + Q_ASSERT(reply); + if (reply->error() != QNetworkReply::NoError) { + qWarning() << Q_FUNC_INFO << reply->url() << "failed:" << reply->errorString(); + return; + } + const QByteArray data = reply->readAll(); + QPixmap pixmap; + if (pixmap.loadFromData(data)) { + switch (m_type) { + case QMetaType::QIcon: + emit finished(QVariant(QIcon(pixmap))); + break; + case QMetaType::QPixmap: + emit finished(QVariant(pixmap)); + break; + default: + qWarning("%s: Unsupported type: %d", Q_FUNC_INFO, int(m_type)); + break; + } + } + reply->deleteLater(); } QT_END_NAMESPACE diff --git a/src/imports/winextras/qquickiconloader_p.h b/src/imports/winextras/qquickiconloader_p.h index 0df9b01..3d4d13d 100644 --- a/src/imports/winextras/qquickiconloader_p.h +++ b/src/imports/winextras/qquickiconloader_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com> - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWinExtras module of the Qt Toolkit. @@ -44,7 +44,11 @@ #define QQUICKICONLOADER_P_H #include <QObject> +#include <QVariant> +#include <QUrl> #include <QIcon> +#include <QPixmap> +#include <QDebug> QT_BEGIN_NAMESPACE @@ -52,29 +56,77 @@ class QIcon; class QQmlEngine; class QNetworkReply; -class QQuickIconLoader : public QObject +class QQuickIconLoader +{ +public: + enum LoadResult { + LoadOk, + LoadError, + LoadNetworkRequestStarted, + }; + + // Load a QIcon (pass type = QMetaType::QIcon) or a QPixmap (pass type = + // QMetaType::QPixmap) from url. The function takes an object and member + // function pointer to a slot accepting a QVariant. For resources that can + // loaded synchronously ("file", "qrc" or "image"), the member function pointer + // will be invoked immediately with the result. For network resources, it will be + // connected to an object handling the network reply and invoked once it finishes. + template <typename Object> + static LoadResult load(const QUrl &url, const QQmlEngine *engine, + QVariant::Type type, const QSize &requestedSize, + Object *receiver, void (Object::*function)(const QVariant &)); + +private: + QQuickIconLoader() {} + static QVariant loadFromFile(const QUrl &url, QVariant::Type type); + static QVariant loadFromImageProvider(const QUrl &url, const QQmlEngine *engine, + QVariant::Type type, QSize requestedSize); + static QNetworkReply *loadFromNetwork(const QUrl &url, const QQmlEngine *engine); +}; + +// Internal handler which loads the resource once QNetworkReply finishes +class QQuickIconLoaderNetworkReplyHandler : public QObject { Q_OBJECT public: - explicit QQuickIconLoader(QObject *parent = 0); - void load(const QUrl &url, QQmlEngine *engine); - QIcon icon() const; + explicit QQuickIconLoaderNetworkReplyHandler(QNetworkReply *reply, QVariant::Type); Q_SIGNALS: - void finished(); + void finished(const QVariant &); private Q_SLOTS: - void onRequestFinished(QNetworkReply*); + void onRequestFinished(); private: - void loadFromFile(const QUrl &url); - void loadFromNetwork(const QUrl &url, QQmlEngine *engine); - void loadFromImageProvider(const QUrl &url, QQmlEngine *engine); - - QIcon m_icon; + const QVariant::Type m_type; }; +template <typename Object> +QQuickIconLoader::LoadResult + QQuickIconLoader::load(const QUrl &url, const QQmlEngine *engine, + QVariant::Type type, const QSize &requestedSize, + Object *receiver, void (Object::*function)(const QVariant &)) +{ + const QString scheme = url.scheme(); + if (scheme.startsWith(QLatin1String("http"))) { + if (QNetworkReply *reply = QQuickIconLoader::loadFromNetwork(url, engine)) { + QQuickIconLoaderNetworkReplyHandler *handler = new QQuickIconLoaderNetworkReplyHandler(reply, type); + QObject::connect(handler, &QQuickIconLoaderNetworkReplyHandler::finished, receiver, function); + return LoadNetworkRequestStarted; + } + return LoadError; + } + const QVariant resource = scheme == QLatin1String("image") + ? QQuickIconLoader::loadFromImageProvider(url, engine, type, requestedSize) + : QQuickIconLoader::loadFromFile(url, type); // qrc, file + if (resource.isValid()) { + (receiver->*function)(resource); + return LoadOk; + } + return LoadError; +} + QT_END_NAMESPACE #endif // QQUICKICONLOADER_P_H diff --git a/src/imports/winextras/qquicktaskbarbutton.cpp b/src/imports/winextras/qquicktaskbarbutton.cpp index 97e0765..b644b78 100644 --- a/src/imports/winextras/qquicktaskbarbutton.cpp +++ b/src/imports/winextras/qquicktaskbarbutton.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com> - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWinExtras module of the Qt Toolkit. @@ -41,7 +41,10 @@ ****************************************************************************/ #include "qquicktaskbarbutton_p.h" +#include "qquickiconloader_p.h" + #include <QQuickWindow> +#include <QVariant> QT_BEGIN_NAMESPACE @@ -73,7 +76,6 @@ QT_BEGIN_NAMESPACE QQuickTaskbarOverlay::QQuickTaskbarOverlay(QWinTaskbarButton *button, QObject *parent) : QObject(parent), m_button(button) { - connect(&m_loader, SIGNAL(finished()), SLOT(iconLoaded())); } QUrl QQuickTaskbarOverlay::iconSource() const @@ -83,10 +85,20 @@ QUrl QQuickTaskbarOverlay::iconSource() const void QQuickTaskbarOverlay::setIconSource(const QUrl &iconSource) { - if (m_iconSource != iconSource) { + if (m_iconSource == iconSource) + return; + + if (iconSource.isEmpty()) { + m_button->clearOverlayIcon(); + m_iconSource = iconSource; + emit iconSourceChanged(); + return; + } + + if (QQuickIconLoader::load(iconSource, qmlEngine(parent()), QVariant::Icon, QSize(), + this, &QQuickTaskbarOverlay::iconLoaded) != QQuickIconLoader::LoadError) { m_iconSource = iconSource; emit iconSourceChanged(); - m_loader.load(m_iconSource, qmlEngine(parent())); } } @@ -103,11 +115,9 @@ void QQuickTaskbarOverlay::setAccessibleDescription(const QString &description) } } -void QQuickTaskbarOverlay::iconLoaded() +void QQuickTaskbarOverlay::iconLoaded(const QVariant &value) { - QIcon icon = m_loader.icon(); - if (!icon.isNull()) - m_button->setOverlayIcon(icon); + m_button->setOverlayIcon(value.value<QIcon>()); } QQuickTaskbarButton::QQuickTaskbarButton(QQuickItem *parent) : QQuickItem(parent), diff --git a/src/imports/winextras/qquicktaskbarbutton_p.h b/src/imports/winextras/qquicktaskbarbutton_p.h index d24947d..2849dab 100644 --- a/src/imports/winextras/qquicktaskbarbutton_p.h +++ b/src/imports/winextras/qquicktaskbarbutton_p.h @@ -47,10 +47,9 @@ #include <QWinTaskbarButton> #include <QWinTaskbarProgress> -#include "qquickiconloader_p.h" - QT_BEGIN_NAMESPACE +class QVariant; class QQuickTaskbarButtonPrivate; class QQuickTaskbarOverlay : public QObject @@ -73,11 +72,10 @@ Q_SIGNALS: void accessibleDescriptionChanged(); private Q_SLOTS: - void iconLoaded(); + void iconLoaded(const QVariant &); private: QUrl m_iconSource; - QQuickIconLoader m_loader; QWinTaskbarButton *m_button; }; diff --git a/src/imports/winextras/qquickthumbnailtoolbutton.cpp b/src/imports/winextras/qquickthumbnailtoolbutton.cpp index 7f84988..31875e7 100644 --- a/src/imports/winextras/qquickthumbnailtoolbutton.cpp +++ b/src/imports/winextras/qquickthumbnailtoolbutton.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com> - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWinExtras module of the Qt Toolkit. @@ -41,6 +41,7 @@ ****************************************************************************/ #include "qquickthumbnailtoolbutton_p.h" +#include "qquickiconloader_p.h" #include <QWinThumbnailToolButton> @@ -66,7 +67,6 @@ QQuickThumbnailToolButton::QQuickThumbnailToolButton(QObject *parent) : QObject(parent), m_button(new QWinThumbnailToolButton(this)) { connect(m_button, SIGNAL(clicked()), SIGNAL(clicked())); - connect(&m_loader, SIGNAL(finished()), SLOT(iconLoaded())); } QQuickThumbnailToolButton::~QQuickThumbnailToolButton() @@ -80,10 +80,19 @@ QQuickThumbnailToolButton::~QQuickThumbnailToolButton() */ void QQuickThumbnailToolButton::setIconSource(const QUrl &iconSource) { - if (m_iconSource != iconSource) { + if (m_iconSource == iconSource) + return; + + if (iconSource.isEmpty()) { + m_button->setIcon(QIcon()); + m_iconSource = iconSource; + emit iconSourceChanged(); + } + + if (QQuickIconLoader::load(iconSource, qmlEngine(this), QVariant::Icon, QSize(), + this, &QQuickThumbnailToolButton::iconLoaded) != QQuickIconLoader::LoadError) { m_iconSource = iconSource; emit iconSourceChanged(); - m_loader.load(m_iconSource, qmlEngine(this)); } } @@ -213,11 +222,10 @@ bool QQuickThumbnailToolButton::isFlat() const return m_button->isFlat(); } -void QQuickThumbnailToolButton::iconLoaded() +void QQuickThumbnailToolButton::iconLoaded(const QVariant &value) { - QIcon icon = m_loader.icon(); - if (!icon.isNull()) - m_button->setIcon(icon); + if (value.isValid()) + m_button->setIcon(value.value<QIcon>()); } QT_END_NAMESPACE diff --git a/src/imports/winextras/qquickthumbnailtoolbutton_p.h b/src/imports/winextras/qquickthumbnailtoolbutton_p.h index 82fcdae..8235206 100644 --- a/src/imports/winextras/qquickthumbnailtoolbutton_p.h +++ b/src/imports/winextras/qquickthumbnailtoolbutton_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com> - ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWinExtras module of the Qt Toolkit. @@ -47,8 +47,6 @@ #include <QWinThumbnailToolBar> #include <QUrl> -#include "qquickiconloader_p.h" - QT_BEGIN_NAMESPACE class QQuickThumbnailToolButton : public QObject @@ -92,12 +90,11 @@ Q_SIGNALS: void flatChanged(); private Q_SLOTS: - void iconLoaded(); + void iconLoaded(const QVariant &); private: QUrl m_iconSource; QWinThumbnailToolButton *m_button; - QQuickIconLoader m_loader; friend class QQuickThumbnailToolBar; }; |