Commit 2003b267 authored by David Redondo's avatar David Redondo Committed by Nate Graham

Image Wallpaper Slideshow - display the list of images that will be shown

Summary:
This shows all the pictures inside the folders added to the Folders list. I also tried to make single pictures excludable via a checkbox on the thumbnail. This is the first time for me programming with QT/QML/Singals-Slots and I tried to use as much existing code as possible. The thumbnail view is the same as for single images and I simply subclassed the listmodel. However even if I tried to do everything like the code for slidePaths it doesn't work correctly. The checking/unchecking of images only applies on restart of plasmashell. Maybe it's a single mistake that is easily spotted by a more experienced programmer otherwise if the thumbnail view is accepted I can also revert all the checkbox stuff.

FEATURE: 403703
FIXED-IN: 5.16.0

{F6595564}

Reviewers: #vdg, ngraham, davidedmundson

Reviewed By: #vdg, ngraham, davidedmundson

Subscribers: filipf, mart, alexde, davidedmundson, ngraham, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D18809
parent 19144ab0
......@@ -4,6 +4,7 @@ set(image_SRCS
image.cpp
imageplugin.cpp
backgroundlistmodel.cpp
slidemodel.cpp
)
ecm_qt_declare_logging_category(image_SRCS HEADER debug.h
......
......@@ -105,18 +105,20 @@ protected Q_SLOTS:
void backgroundsFound(const QStringList &paths, const QString &token);
void processPaths(const QStringList &paths);
protected:
QPointer<Image> m_wallpaper;
QString m_findToken;
QList<KPackage::Package> m_packages;
private:
QSize bestSize(const KPackage::Package &package) const;
QPointer<Image> m_wallpaper;
QList<KPackage::Package> m_packages;
QSet<QString> m_removableWallpapers;
QHash<QString, QSize> m_sizeCache;
QHash<QUrl, QPersistentModelIndex> m_previewJobs;
KDirWatch m_dirwatch;
QCache<QString, QPixmap> m_imageCache;
QString m_findToken;
int m_screenshotSize;
QHash<QString, int> m_pendingDeletion;
};
......
......@@ -53,6 +53,7 @@
#include <Plasma/PluginLoader>
#include <qstandardpaths.h>
#include "backgroundlistmodel.h"
#include "slidemodel.h"
#include <KPackage/PackageLoader>
......@@ -64,6 +65,7 @@ Image::Image(QObject *parent)
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 +277,15 @@ QAbstractItemModel* Image::wallpaperModel()
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 +347,9 @@ void Image::setSlidePaths(const QStringList &slidePaths)
updateDirWatch(m_slidePaths);
startSlideshow();
}
if (m_slideshowModel) {
m_slideshowModel->reload(m_slidePaths);
}
emit slidePathsChanged();
}
......@@ -357,7 +370,9 @@ void Image::addSlidePath(const QString &path)
if (m_mode == SlideShow) {
updateDirWatch(m_slidePaths);
}
if (m_slideshowModel) {
m_slideshowModel->addDirs({m_slidePaths});
}
emit slidePathsChanged();
startSlideshow();
}
......@@ -370,6 +385,28 @@ void Image::removeSlidePath(const QString &path)
if (m_mode == SlideShow) {
updateDirWatch(m_slidePaths);
}
if (m_slideshowModel) {
bool haveParent = false;
QStringList children;
for (const QString& slidePath : m_slidePaths) {
if (path.startsWith(slidePath)) {
haveParent = true;
}
if (slidePath.startsWith(path)) {
children.append(slidePath);
}
}
/*If we have the parent directory do nothing since the directories are recursively searched.
* If we have child directories just reload since removing the parent and then readding the children would
* induce a race.*/
if (!haveParent) {
if (children.size() > 0) {
m_slideshowModel->reload(m_slidePaths);
} else {
m_slideshowModel->removeDir(path);
}
}
}
emit slidePathsChanged();
startSlideshow();
......@@ -582,7 +619,6 @@ void Image::backgroundsFound(const QStringList &paths, const QString &token)
startSlideshow();
return;
}
m_slideshowBackgrounds = paths;
m_unseenSlideshowBackgrounds.clear();
// start slideshow
......@@ -856,3 +892,7 @@ void Image::commitDeletion()
}
}
void Image::openFolder(const QString& path)
{
new KRun(QUrl::fromLocalFile(path), nullptr);
}
......@@ -48,6 +48,7 @@ namespace KNS3 {
}
class BackgroundListModel;
class SlideModel;
class Image : public QObject, public QQmlParserStatus
{
......@@ -57,6 +58,7 @@ class Image : public QObject, public QQmlParserStatus
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)
......@@ -82,6 +84,7 @@ class Image : public QObject, public QQmlParserStatus
Q_INVOKABLE void addSlidePath(const QString &path);
Q_INVOKABLE void removeSlidePath(const QString &path);
Q_INVOKABLE void openFolder(const QString& path);
Q_INVOKABLE void getNewWallpaper(QQuickItem *ctx = nullptr);
Q_INVOKABLE void showFileDialog();
......@@ -98,6 +101,7 @@ class Image : public QObject, public QQmlParserStatus
KPackage::Package *package();
QAbstractItemModel* wallpaperModel();
QAbstractItemModel* slideshowModel();
int slideTimer() const;
void setSlideTimer(int time);
......@@ -116,7 +120,7 @@ class Image : public QObject, public QQmlParserStatus
QString photosPath() const;
public Q_SLOTS:
public Q_SLOTS:
void nextSlide();
void removeWallpaper(QString name);
......@@ -178,6 +182,7 @@ class Image : public QObject, public QQmlParserStatus
QTimer m_timer;
int m_currentSlide;
BackgroundListModel *m_model;
SlideModel* m_slideshowModel;
QFileDialog *m_dialog;
QString m_img;
QDateTime m_previousModified;
......
......@@ -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 @@ import org.kde.kcm 1.1 as KCM
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 @@ KCM.GridDelegate {
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;
}
......
......@@ -238,30 +238,70 @@ ColumnLayout {
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.fillHeight: true
Layout.preferredWidth: 0.25 * parent.width
Component.onCompleted: foldersScroll.background.visible = true;
ListView {
id: slidePathsView
anchors.margins: 4
model: imageWallpaper.slidePaths
delegate: Kirigami.SwipeListItem {
id: folderDelegate
actions: [
Kirigami.Action {
iconName: "list-remove"
tooltip: i18nd("plasma_wallpaper_org.kde.image", "Remove Folder")
onTriggered: imageWallpaper.removeSlidePath(modelData)
},
Kirigami.Action {
icon.name: "document-open-folder"
tooltip: i18nd("plasma_wallpaper_org.kde.image", "Open Folder")
onTriggered: imageWallpaper.openFolder(modelData)
}
]
QtControls2.Label {
text: modelData.endsWith("/") ? modelData.split('/').reverse()[1] : modelData.split('/').pop()
Layout.fillWidth: true
QtControls2.ToolTip.text: modelData
QtControls2.ToolTip.visible: folderDelegate.hovered
QtControls2.ToolTip.delay: 1000
QtControls2.ToolTip.timeout: 5000
}
icon.name: "list-remove"
onClicked: imageWallpaper.removeSlidePath(modelData);
width: slidePathsView.width
height: paintedHeight;
}
}
}
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 +311,12 @@ ColumnLayout {
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
}
......@@ -307,21 +347,16 @@ ColumnLayout {
Loader {
anchors.fill: parent
sourceComponent: (configDialog.currentWallpaper == "org.kde.image") ? thumbnailsComponent : foldersComponent
sourceComponent: (configDialog.currentWallpaper == "org.kde.image") ? thumbnailsComponent :
((configDialog.currentWallpaper == "org.kde.slideshow") ? foldersComponent : undefined)
}
}
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();
......
#include "slidemodel.h"
void SlideModel::reload(const QStringList &selected)
{
if (!m_packages.isEmpty()) {
beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1);
m_packages.clear();
endRemoveRows();
emit countChanged();
}
addDirs(selected);
}
void SlideModel::addDirs(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);
finder->start();
}
void SlideModel::removeBackgrounds(const QStringList &paths, const QString &token)
{
Q_FOREACH (const QString &file, paths) {
removeBackground(file);
}
}
#ifndef SLIDEMODEL_H
#define SLIDEMODEL_H
#include "backgroundlistmodel.h"
class SlideModel : public BackgroundListModel
{
Q_OBJECT
public:
using BackgroundListModel::BackgroundListModel;
void reload(const QStringList &selected);
void addDirs(const QStringList &selected);
void removeDir(const QString &selected);
private Q_SLOTS:
void removeBackgrounds(const QStringList &paths, const QString &token);
void backgroundsFound(const QStringList &paths, const QString &token);
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment