Index: wallpapers/image/CMakeLists.txt =================================================================== --- wallpapers/image/CMakeLists.txt +++ wallpapers/image/CMakeLists.txt @@ -4,6 +4,7 @@ image.cpp imageplugin.cpp backgroundlistmodel.cpp + slidemodel.cpp ) ecm_qt_declare_logging_category(image_SRCS HEADER debug.h Index: wallpapers/image/backgroundlistmodel.h =================================================================== --- wallpapers/image/backgroundlistmodel.h +++ wallpapers/image/backgroundlistmodel.h @@ -67,7 +67,8 @@ PathRole, PackageNameRole, RemovableRole, - PendingDeletionRole + PendingDeletionRole, + ToggleRole }; static const int BLUR_INCREMENT = 9; @@ -105,10 +106,13 @@ void backgroundsFound(const QStringList &paths, const QString &token); void processPaths(const QStringList &paths); +protected: + QPointer m_wallpaper; + QString m_findToken; + private: QSize bestSize(const KPackage::Package &package) const; - QPointer m_wallpaper; QList m_packages; QSet m_removableWallpapers; QHash m_sizeCache; @@ -116,7 +120,6 @@ KDirWatch m_dirwatch; QCache m_imageCache; - QString m_findToken; int m_screenshotSize; QHash m_pendingDeletion; }; Index: wallpapers/image/image.h =================================================================== --- wallpapers/image/image.h +++ wallpapers/image/image.h @@ -48,6 +48,7 @@ } class BackgroundListModel; +class SlideModel; class Image : public QObject, public QQmlParserStatus { @@ -57,11 +58,13 @@ Q_PROPERTY(RenderingMode renderingMode READ renderingMode WRITE setRenderingMode NOTIFY renderingModeChanged) Q_PROPERTY(QUrl wallpaperPath READ wallpaperPath NOTIFY wallpaperPathChanged) Q_PROPERTY(QAbstractItemModel *wallpaperModel READ wallpaperModel CONSTANT) + Q_PROPERTY(QAbstractItemModel *slideshowModel READ slideshowModel CONSTANT) Q_PROPERTY(int slideTimer READ slideTimer WRITE setSlideTimer NOTIFY slideTimerChanged) Q_PROPERTY(QStringList usersWallpapers READ usersWallpapers WRITE setUsersWallpapers NOTIFY usersWallpapersChanged) Q_PROPERTY(QStringList slidePaths READ slidePaths WRITE setSlidePaths NOTIFY slidePathsChanged) Q_PROPERTY(QSize targetSize READ targetSize WRITE setTargetSize NOTIFY targetSizeChanged) Q_PROPERTY(QString photosPath READ photosPath CONSTANT) + Q_PROPERTY(QStringList uncheckedSlides READ uncheckedSlides WRITE setUncheckedSlides NOTIFY uncheckedSlidesChanged) public: @@ -82,6 +85,7 @@ Q_INVOKABLE void addSlidePath(const QString &path); Q_INVOKABLE void removeSlidePath(const QString &path); + Q_INVOKABLE void toggleSlide(const QString &path, bool checked); Q_INVOKABLE void getNewWallpaper(QQuickItem *ctx = nullptr); Q_INVOKABLE void showFileDialog(); @@ -98,6 +102,7 @@ KPackage::Package *package(); QAbstractItemModel* wallpaperModel(); + QAbstractItemModel* slideshowModel(); int slideTimer() const; void setSlideTimer(int time); @@ -116,6 +121,9 @@ QString photosPath() const; + QStringList uncheckedSlides() const; + void setUncheckedSlides(QStringList& uncheckedSlides); + public Q_SLOTS: void nextSlide(); void removeWallpaper(QString name); @@ -130,6 +138,7 @@ void slidePathsChanged(); void resizeMethodChanged(); void customWallpaperPicked(const QString &path); + void uncheckedSlidesChanged(); protected Q_SLOTS: void showAddSlidePathsDialog(); @@ -175,9 +184,11 @@ QStringList m_slideshowBackgrounds; QStringList m_unseenSlideshowBackgrounds; QStringList m_slidePaths; + QStringList m_uncheckedSlides; QTimer m_timer; int m_currentSlide; BackgroundListModel *m_model; + SlideModel* m_slideshowModel; QFileDialog *m_dialog; QString m_img; QDateTime m_previousModified; Index: wallpapers/image/image.cpp =================================================================== --- wallpapers/image/image.cpp +++ wallpapers/image/image.cpp @@ -25,6 +25,7 @@ #include "image.h" #include "debug.h" +#include #include #include // FLT_MAX @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -53,6 +55,7 @@ #include #include #include "backgroundlistmodel.h" +#include "slidemodel.h" #include @@ -64,6 +67,7 @@ m_mode(SingleImage), m_currentSlide(-1), m_model(nullptr), + m_slideshowModel(nullptr), m_dialog(nullptr) { m_wallpaperPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Wallpaper/Images")); @@ -275,6 +279,15 @@ return m_model; } +QAbstractItemModel* Image::slideshowModel() +{ + if (!m_slideshowModel) { + m_slideshowModel = new SlideModel(this, this); + m_slideshowModel->reload(m_slidePaths); + } + return m_slideshowModel; +} + int Image::slideTimer() const { return m_delay; @@ -336,7 +349,9 @@ updateDirWatch(m_slidePaths); startSlideshow(); } - + if (m_slideshowModel) { + m_slideshowModel->reload(m_slidePaths); + } emit slidePathsChanged(); } @@ -357,7 +372,9 @@ if (m_mode == SlideShow) { updateDirWatch(m_slidePaths); } - + if (m_slideshowModel) { + m_slideshowModel->reload(m_slidePaths); + } emit slidePathsChanged(); startSlideshow(); } @@ -367,15 +384,35 @@ { if (m_slidePaths.contains(path)) { m_slidePaths.removeAll(path); + Q_FOREACH(const QString& slide, m_uncheckedSlides) { + if (slide.startsWith(QUrl::fromLocalFile(path).toString())) { + m_uncheckedSlides.removeAll(slide); + } + } if (m_mode == SlideShow) { updateDirWatch(m_slidePaths); } - + if (m_slideshowModel) { + m_slideshowModel->removeDir(path); + } emit slidePathsChanged(); startSlideshow(); } } +void Image::toggleSlide(const QString &path, bool checked) +{ + if (checked && m_uncheckedSlides.contains(path)) { + m_uncheckedSlides.removeAll(path); + emit uncheckedSlidesChanged(); + startSlideshow(); + } else if (!checked && ! m_uncheckedSlides.contains(path)) { + m_uncheckedSlides.append(path); + emit uncheckedSlidesChanged(); + startSlideshow(); + } +} + void Image::pathDirty(const QString& path) { updateDirWatch(QStringList(path)); @@ -582,8 +619,9 @@ startSlideshow(); return; } - m_slideshowBackgrounds = paths; + m_slideshowBackgrounds.erase(std::remove_if(m_slideshowBackgrounds.begin(), m_slideshowBackgrounds.end(), + [&](QString& path) {return m_uncheckedSlides.contains(QUrl::fromLocalFile(path).toString());}), m_slideshowBackgrounds.end()); m_unseenSlideshowBackgrounds.clear(); // start slideshow if (m_slideshowBackgrounds.isEmpty()) { @@ -793,6 +831,7 @@ { if(m_slideshowBackgrounds.removeAll(path)) { m_unseenSlideshowBackgrounds.removeAll(path); + m_uncheckedSlides.removeAll(path); if(path == m_img) { nextSlide(); } @@ -856,3 +895,16 @@ } } +QStringList Image::uncheckedSlides() const +{ + return m_uncheckedSlides; +} + +void Image::setUncheckedSlides(QStringList& uncheckedSlides) +{ + if (uncheckedSlides == m_uncheckedSlides) { + return; + } + m_uncheckedSlides = uncheckedSlides; + emit uncheckedSlidesChanged(); +} Index: wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml =================================================================== --- wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml +++ wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml @@ -19,6 +19,7 @@ import QtQuick 2.0 import QtQuick.Controls.Private 1.0 +import QtQuick.Controls 2.3 as QtControls2 import QtGraphicalEffects 1.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents @@ -28,7 +29,6 @@ KCM.GridDelegate { id: wallpaperDelegate - property alias color: backgroundRect.color property bool selected: (wallpapersGrid.currentIndex == index) opacity: model.pendingDeletion ? 0.5 : 1 @@ -43,20 +43,20 @@ Kirigami.Action { icon.name: "document-open-folder" tooltip: i18nd("plasma_wallpaper_org.kde.image", "Open Containing Folder") - onTriggered: imageWallpaper.wallpaperModel.openContainingFolder(index) + onTriggered: imageModel.openContainingFolder(index) }, Kirigami.Action { icon.name: "edit-undo" visible: model.pendingDeletion tooltip: i18nd("plasma_wallpaper_org.kde.image", "Restore wallpaper") - onTriggered: imageWallpaper.wallpaperModel.setPendingDeletion(index, !model.pendingDeletion) + onTriggered: imageModel.setPendingDeletion(index, !model.pendingDeletion) }, Kirigami.Action { icon.name: "edit-delete" tooltip: i18nd("plasma_wallpaper_org.kde.image", "Remove Wallpaper") - visible: model.removable && !model.pendingDeletion + visible: model.removable && !model.pendingDeletion && configDialog.currentWallpaper == "org.kde.image" onTriggered: { - imageWallpaper.wallpaperModel.setPendingDeletion(index, true); + imageModel.setPendingDeletion(index, true); if (wallpapersGrid.currentIndex === index) { wallpapersGrid.currentIndex = (index + 1) % wallpapersGrid.count; } @@ -116,6 +116,14 @@ return QPixmapItem.PreserveAspectFit; } } + + QtControls2.CheckBox { + visible: configDialog.currentWallpaper == "org.kde.slideshow" + anchors.right: parent.right + anchors.top: parent.top + checked: model.toggled + onToggled: imageWallpaper.toggleSlide(model.path, checked) + } } onClicked: { Index: wallpapers/image/imagepackage/contents/ui/config.qml =================================================================== --- wallpapers/image/imagepackage/contents/ui/config.qml +++ wallpapers/image/imagepackage/contents/ui/config.qml @@ -38,6 +38,7 @@ property alias cfg_Blur: blurRadioButton.checked property var cfg_SlidePaths: "" property int cfg_SlideInterval: 0 + property var cfg_UncheckedSlides: "" function saveConfig() { imageWallpaper.commitDeletion(); @@ -57,12 +58,18 @@ return Qt.size(Screen.width, Screen.height) } onSlidePathsChanged: cfg_SlidePaths = slidePaths + onUncheckedSlidesChanged: cfg_UncheckedSlides = uncheckedSlides } onCfg_SlidePathsChanged: { imageWallpaper.slidePaths = cfg_SlidePaths } + onCfg_UncheckedSlidesChanged: { + imageWallpaper.uncheckedSlides = cfg_UncheckedSlides + console.log(cfg_UncheckedSlides) + } + property int hoursIntervalValue: Math.floor(cfg_SlideInterval / 3600) property int minutesIntervalValue: Math.floor(cfg_SlideInterval % 3600) / 60 property int secondsIntervalValue: cfg_SlideInterval % 3600 % 60 @@ -238,30 +245,59 @@ text: i18nd("plasma_wallpaper_org.kde.image","Seconds") } } - QtControls2.ScrollView { - id: foldersScroll - Layout.fillHeight: true; + Kirigami.Heading { + text: "Folders" + level: 2 + } + GridLayout { + columns: 2 Layout.fillWidth: true - Component.onCompleted: foldersScroll.background.visible = true; - ListView { - id: slidePathsView - anchors.margins: 4 - model: imageWallpaper.slidePaths - delegate: QtControls2.Label { - text: modelData - width: slidePathsView.width - height: Math.max(paintedHeight, removeButton.height); - QtControls2.ToolButton { - id: removeButton - anchors { - verticalCenter: parent.verticalCenter - right: parent.right + Layout.fillHeight: true + columnSpacing: Kirigami.Units.largeSpacing + QtControls2.ScrollView { + id: foldersScroll + Layout.fillWidth: true + Layout.fillHeight: true + Component.onCompleted: foldersScroll.background.visible = true; + ListView { + id: slidePathsView + anchors.margins: 4 + model: imageWallpaper.slidePaths + delegate: Kirigami.BasicListItem { + text: modelData + width: slidePathsView.width + height: Math.max(paintedHeight, removeButton.height); + QtControls2.ToolButton { + id: removeButton + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + icon.name: "list-remove" + onClicked: imageWallpaper.removeSlidePath(modelData); } - icon.name: "list-remove" - onClicked: imageWallpaper.removeSlidePath(modelData); } } } + Loader { + sourceComponent: thumbnailsComponent + Layout.fillWidth: true + Layout.fillHeight: true + anchors.fill: undefined + } + QtControls2.Button { + Layout.alignment: Qt.AlignRight + icon.name: "list-add" + text: i18nd("plasma_wallpaper_org.kde.image","Add Folder...") + onClicked: imageWallpaper.showAddSlidePathsDialog() + } + QtControls2.Button { + Layout.alignment: Qt.AlignRight + icon.name: "get-hot-new-stuff" + text: i18nd("plasma_wallpaper_org.kde.image","Get New Wallpapers...") + visible: KAuthorized.authorize("ghns") + onClicked: imageWallpaper.getNewWallpaper(this); + } } } } @@ -271,12 +307,12 @@ KCM.GridView { id: wallpapersGrid anchors.fill: parent - + property var imageModel: (configDialog.currentWallpaper == "org.kde.image")? imageWallpaper.wallpaperModel : imageWallpaper.slideshowModel //that min is needed as the module will be populated in an async way //and only on demand so we can't ensure it already exists - view.currentIndex: Math.min(imageWallpaper.wallpaperModel.indexOf(cfg_Image), imageWallpaper.wallpaperModel.count-1) + view.currentIndex: Math.min(imageModel.indexOf(cfg_Image), imageModel.count-1) //kill the space for label under thumbnails - view.model: imageWallpaper.wallpaperModel + view.model: imageModel view.delegate: WallpaperDelegate { color: cfg_Color } @@ -314,14 +350,8 @@ RowLayout { id: buttonsRow Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + visible: configDialog.currentWallpaper == "org.kde.image" QtControls2.Button { - visible: (configDialog.currentWallpaper == "org.kde.slideshow") - icon.name: "list-add" - text: i18nd("plasma_wallpaper_org.kde.image","Add Folder...") - onClicked: imageWallpaper.showAddSlidePathsDialog() - } - QtControls2.Button { - visible: (configDialog.currentWallpaper == "org.kde.image") icon.name: "list-add" text: i18nd("plasma_wallpaper_org.kde.image","Add Image...") onClicked: imageWallpaper.showFileDialog(); Index: wallpapers/image/imagepackage/contents/ui/main.qml =================================================================== --- wallpapers/image/imagepackage/contents/ui/main.qml +++ wallpapers/image/imagepackage/contents/ui/main.qml @@ -68,6 +68,7 @@ targetSize: Qt.size(root.width, root.height) slidePaths: wallpaper.configuration.SlidePaths slideTimer: wallpaper.configuration.SlideInterval + uncheckedSlides: wallpaper.configuration.UncheckedSlides } onFillModeChanged: Qt.callLater(loadImage); Index: wallpapers/image/slidemodel.h =================================================================== --- /dev/null +++ wallpapers/image/slidemodel.h @@ -0,0 +1,21 @@ +#ifndef SLIDEMODEL_H +#define SLIDEMODEL_H + +#endif + +#include "backgroundlistmodel.h" + +class SlideModel : public BackgroundListModel +{ + Q_OBJECT +public: + using BackgroundListModel::BackgroundListModel; + + void reload(const QStringList &selected); + void removeDir(const QString &selected); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const; +private Q_SLOTS: + void removeBackgrounds(const QStringList &paths, const QString &token); + void backgroundsFound(const QStringList &paths, const QString &token); +}; Index: wallpapers/image/slidemodel.cpp =================================================================== --- /dev/null +++ wallpapers/image/slidemodel.cpp @@ -0,0 +1,61 @@ +#include "slidemodel.h" + +void SlideModel::reload(const QStringList &selected) +{ + BackgroundFinder *finder = new BackgroundFinder(m_wallpaper.data(), selected); + connect(finder, &BackgroundFinder::backgroundsFound, this, &SlideModel::backgroundsFound); + m_findToken = finder->token(); + finder->start(); +} + +void SlideModel::backgroundsFound(const QStringList& paths, const QString& token) +{ + if (token != m_findToken) { + return; + } + processPaths(paths); +} + + +void SlideModel::removeDir(const QString &path) +{ + BackgroundFinder *finder = new BackgroundFinder(m_wallpaper.data(), QStringList{path}); + connect(finder, &BackgroundFinder::backgroundsFound, this, &SlideModel::removeBackgrounds); + m_findToken = finder->token(); + finder->start(); +} + +void SlideModel::removeBackgrounds(const QStringList &paths, const QString &token) +{ + if (token != m_findToken) { + return; + } + Q_FOREACH (QString file, paths) { + removeBackground(file); + } +} + +QVariant SlideModel::data(const QModelIndex &index, int role) const +{ + if(role == ToggleRole){ + return !m_wallpaper->uncheckedSlides().contains(data(index, PathRole).toString()); + } else { + return BackgroundListModel::data(index, role); + } +} +QHash SlideModel::roleNames() const +{ + return { + { Qt::DisplayRole, "display" }, + { Qt::DecorationRole, "decoration" }, + { AuthorRole, "author" }, + { ScreenshotRole, "screenshot" }, + { ResolutionRole, "resolution" }, + { PathRole, "path" }, + { PackageNameRole, "packageName" }, + { RemovableRole, "removable" }, + { PendingDeletionRole, "pendingDeletion"}, + { ToggleRole, "toggled"} + }; +}; + Index: wallpapers/image/slideshowpackage/contents/config/main.xml =================================================================== --- wallpapers/image/slideshowpackage/contents/config/main.xml +++ wallpapers/image/slideshowpackage/contents/config/main.xml @@ -34,6 +34,10 @@ 1000 + + + +