diff --git a/desktoppackage/contents/activitymanager/ActivityItem.qml b/desktoppackage/contents/activitymanager/ActivityItem.qml --- a/desktoppackage/contents/activitymanager/ActivityItem.qml +++ b/desktoppackage/contents/activitymanager/ActivityItem.qml @@ -33,47 +33,14 @@ property string background : "" - function updateBackgroundRetry(valid) { - // TODO: (comment by David) - // - // Registering a a QQuickImageProvider with - // ForceAsynchronousImageLoading (so you can just exec() in the main - // method without blocking) will probably be both simpler code - // and more robust. - - if (valid) { - // Try to get the pixmap, if it is not available, this function - // will be called again when the thumbnailer finishes its job - // console.log("Loading background for " + root.title); - backgroundWallpaper.pixmap = ActivitySwitcher.Backend.wallpaperThumbnail( - background, - backgroundWallpaper.width, - backgroundWallpaper.height, - updateBackgroundRetry - ); - - backgroundColor.visible = false; - - } else { - backgroundColor.color = "#000000"; - backgroundColor.visible = true; - } - } - - function updateBackground() { - if (background == "") return; - - updateBackgroundRetry(true); - } - onBackgroundChanged: if (background[0] != '#') { // We have a proper wallpaper, hurroo! - updateBackground(); + backgroundColor.visible = false; } else { // We have only a color - backgroundColor.color = background - backgroundColor.visible = true + backgroundColor.color = background; + backgroundColor.visible = true; } signal clicked @@ -83,10 +50,6 @@ // Marco removed displayAspectRatio height : width * 9.0 / 16.0 - onWidthChanged : updateBackground() - onHeightChanged : updateBackground() - - Item { anchors { fill: parent @@ -104,15 +67,16 @@ opacity: root.selected ? .8 : .5 } - KQuickControlsAddonsComponents.QPixmapItem { + Image { id: backgroundWallpaper anchors.fill: parent visible: !backgroundColor.visible + source: "image://wallpaperthumbnail/" + background + sourceSize: size } - // Title and the icon Rectangle { diff --git a/imports/activitymanager/CMakeLists.txt b/imports/activitymanager/CMakeLists.txt --- a/imports/activitymanager/CMakeLists.txt +++ b/imports/activitymanager/CMakeLists.txt @@ -1,7 +1,7 @@ find_package (ECM 0.0.8 REQUIRED NO_MODULE) set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) -find_package (Qt5 REQUIRED NO_MODULE COMPONENTS Widgets Qml X11Extras) +find_package (Qt5 REQUIRED NO_MODULE COMPONENTS Widgets Qml X11Extras Quick) find_package (KF5I18n ${KF5_DEP_VERSION} CONFIG REQUIRED) find_package (KF5Config ${KF5_DEP_VERSION} CONFIG REQUIRED) find_package (KF5CoreAddons ${KF5_DEP_VERSION} CONFIG REQUIRED) @@ -32,6 +32,7 @@ activityswitcherextensionplugin Qt5::Core + Qt5::Quick Qt5::Qml Qt5::Widgets Qt5::X11Extras diff --git a/imports/activitymanager/sortedactivitiesmodel.cpp b/imports/activitymanager/sortedactivitiesmodel.cpp --- a/imports/activitymanager/sortedactivitiesmodel.cpp +++ b/imports/activitymanager/sortedactivitiesmodel.cpp @@ -142,11 +142,11 @@ const auto background = backgroundFromConfig(containment); + if (background.isEmpty()) continue; + if (newForActivity[activity] != background) { changedActivities << activity; - if (!background.isEmpty()) { - newForActivity[activity] = background; - } + newForActivity[activity] = background; } } diff --git a/imports/activitymanager/switcherbackend.h b/imports/activitymanager/switcherbackend.h --- a/imports/activitymanager/switcherbackend.h +++ b/imports/activitymanager/switcherbackend.h @@ -63,9 +63,6 @@ bool shouldShowSwitcher() const; void setShouldShowSwitcher(const bool &shouldShowSwitcher); - QPixmap wallpaperThumbnail(const QString &path, int width, int height, - const QJSValue &callback); - QAbstractItemModel *runningActivitiesModel() const; QAbstractItemModel *stoppedActivitiesModel() const; @@ -78,11 +75,11 @@ const QKeySequence &shortcut, Handler &&handler); - enum Direction { Next, Previous }; + void switchToActivity(Direction i); private Q_SLOTS: @@ -102,9 +99,6 @@ QTimer m_modKeyPollingTimer; QString m_previousActivity; - KImageCache *m_wallpaperCache; - QSet m_previewJobs; - SortedActivitiesModel *m_runningActivitiesModel; SortedActivitiesModel *m_stoppedActivitiesModel; diff --git a/imports/activitymanager/switcherbackend.cpp b/imports/activitymanager/switcherbackend.cpp --- a/imports/activitymanager/switcherbackend.cpp +++ b/imports/activitymanager/switcherbackend.cpp @@ -29,6 +29,10 @@ #include #include +// Qml and QtQuick +#include +#include + // KDE #include #include @@ -134,6 +138,87 @@ } } + class ThumbnailImageResponse: public QQuickImageResponse { + public: + ThumbnailImageResponse(const QString &id, const QSize &requestedSize); + + QQuickTextureFactory *textureFactory() const; + + void run(); + + private: + QString m_id; + QSize m_requestedSize; + QQuickTextureFactory *m_texture; + }; + + ThumbnailImageResponse::ThumbnailImageResponse(const QString &id, + const QSize &requestedSize) + : m_id(id) + , m_requestedSize(requestedSize) + , m_texture(Q_NULLPTR) + { + int width = m_requestedSize.width(); + int height = m_requestedSize.height(); + + if (width <= 0) { + width = 320; + } + + if (height <= 0) { + height = 240; + } + + if (m_id.isEmpty()) { + emit finished(); + return; + } + + const auto file = QUrl::fromUserInput(m_id); + + KFileItemList list; + list.append(KFileItem(file, QString(), 0)); + + auto job = + KIO::filePreview(list, QSize(width, height)); + job->setScaleType(KIO::PreviewJob::Scaled); + job->setIgnoreMaximumSize(true); + + connect(job, &KIO::PreviewJob::gotPreview, + this, [this,file] (const KFileItem& item, const QPixmap& pixmap) { + Q_UNUSED(item); + + auto image = pixmap.toImage(); + + m_texture = QQuickTextureFactory::textureFactoryForImage(image); + emit finished(); + }, Qt::QueuedConnection); + + connect(job, &KIO::PreviewJob::failed, + this, [this,job] (const KFileItem& item) { + Q_UNUSED(item); + qWarning() << "SwitcherBackend: FAILED to get the thumbnail" + << job->errorString() + << job->detailedErrorStrings(); + emit finished(); + }); + } + + QQuickTextureFactory *ThumbnailImageResponse::textureFactory() const + { + return m_texture; + } + + class ThumbnailImageProvider: public QQuickAsyncImageProvider { + public: + QQuickImageResponse *requestImageResponse(const QString &id, + const QSize &requestedSize) + { + return new ThumbnailImageResponse(id, requestedSize); + } + }; + + } // local namespace @@ -164,8 +249,6 @@ , m_runningActivitiesModel(new SortedActivitiesModel({KActivities::Info::Running, KActivities::Info::Stopping}, this)) , m_stoppedActivitiesModel(new SortedActivitiesModel({KActivities::Info::Stopped, KActivities::Info::Starting}, this)) { - m_wallpaperCache = new KImageCache("activityswitcher_wallpaper_preview", 10485760); - registerShortcut(ACTION_NAME_NEXT_ACTIVITY, i18n("Walk through activities"), Qt::META + Qt::Key_Tab, @@ -188,13 +271,12 @@ SwitcherBackend::~SwitcherBackend() { - delete m_wallpaperCache; } QObject *SwitcherBackend::instance(QQmlEngine *engine, QJSEngine *scriptEngine) { - Q_UNUSED(engine) Q_UNUSED(scriptEngine) + engine->addImageProvider("wallpaperthumbnail", new ThumbnailImageProvider()); return new SwitcherBackend(); } @@ -335,72 +417,6 @@ emit shouldShowSwitcherChanged(m_shouldShowSwitcher); } -QPixmap SwitcherBackend::wallpaperThumbnail(const QString &path, int width, int height, - const QJSValue &_callback) -{ - QPixmap preview = QPixmap(QSize(1, 1)); - - QJSValue callback(_callback); - - if (path.isEmpty()) { - callback.call({false}); - return preview; - } - - if (width == 0) { - width = 320; - } - - if (height == 0) { - height = 240; - } - - - const auto pixmapKey = path + "/" - + QString::number(width) + "x" - + QString::number(height); - - if (m_wallpaperCache->findPixmap(pixmapKey, &preview)) { - return preview; - } - - QUrl file = QUrl::fromLocalFile(path); - - if (!m_previewJobs.contains(file) && file.isValid()) { - m_previewJobs.insert(file); - - KFileItemList list; - list.append(KFileItem(file, QString(), 0)); - - KIO::PreviewJob* job = - KIO::filePreview(list, QSize(width, height)); - job->setScaleType(KIO::PreviewJob::Scaled); - job->setIgnoreMaximumSize(true); - - connect(job, &KIO::PreviewJob::gotPreview, - this, [=] (const KFileItem& item, const QPixmap& pixmap) mutable { - Q_UNUSED(item); - m_wallpaperCache->insertPixmap(pixmapKey, pixmap); - m_previewJobs.remove(file); - - callback.call({true}); - }); - - connect(job, &KIO::PreviewJob::failed, - this, [=] (const KFileItem& item) mutable { - Q_UNUSED(item); - m_previewJobs.remove(file); - - qWarning() << "SwitcherBackend: FAILED to get the thumbnail for " - << path << job->detailedErrorStrings(&file); - callback.call({false}); - }); - - } - - return preview; -} - QAbstractItemModel *SwitcherBackend::runningActivitiesModel() const { return m_runningActivitiesModel;