diff --git a/wallpapers/image/backgroundlistmodel.cpp b/wallpapers/image/backgroundlistmodel.cpp index 6473179c..1a5576b1 100644 --- a/wallpapers/image/backgroundlistmodel.cpp +++ b/wallpapers/image/backgroundlistmodel.cpp @@ -1,589 +1,590 @@ /*************************************************************************** * Copyright 2007 Paolo Capriotti * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #ifndef BACKGROUNDLISTMODEL_CPP #define BACKGROUNDLISTMODEL_CPP #include "backgroundlistmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "image.h" QStringList BackgroundFinder::m_suffixes; ImageSizeFinder::ImageSizeFinder(const QString &path, QObject *parent) : QObject(parent), m_path(path) { } void ImageSizeFinder::run() { QImage image(m_path); Q_EMIT sizeFound(m_path, image.size()); } BackgroundListModel::BackgroundListModel(Image *wallpaper, QObject *parent) : QAbstractListModel(parent), m_wallpaper(wallpaper) { connect(&m_dirwatch, &KDirWatch::deleted, this, &BackgroundListModel::removeBackground); //TODO: on Qt 4.4 use the ui scale factor QFontMetrics fm(QGuiApplication::font()); m_screenshotSize = fm.width('M') * 15; m_imageCache = new KImageCache(QStringLiteral("plasma_wallpaper_preview"), 10485760); } BackgroundListModel::~BackgroundListModel() { delete m_imageCache; } QHash BackgroundListModel::BackgroundListModel::roleNames() const { return { { Qt::DisplayRole, "display" }, { Qt::DecorationRole, "decoration" }, { AuthorRole, "author" }, { ScreenshotRole, "screenshot" }, { ResolutionRole, "resolution" }, { PathRole, "path" }, { PackageNameRole, "packageName" }, { RemovableRole, "removable" }, { PendingDeletionRole, "pendingDeletion" }, }; } void BackgroundListModel::removeBackground(const QString &path) { - QModelIndex index; - while ((index = indexOf(path)).isValid()) { - beginRemoveRows(QModelIndex(), index.row(), index.row()); - m_packages.removeAt(index.row()); + int index = -1; + while ((index = indexOf(path)) >= 0) { + beginRemoveRows(QModelIndex(), index, index); + m_packages.removeAt(index); endRemoveRows(); emit countChanged(); } } void BackgroundListModel::reload() { reload(QStringList()); } void BackgroundListModel::reload(const QStringList &selected) { if (!m_packages.isEmpty()) { beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1); m_packages.clear(); endRemoveRows(); emit countChanged(); } if (!m_wallpaper) { return; } if (!selected.isEmpty()) { qDebug() << "selected" << selected; processPaths(selected); } const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("wallpapers/"), QStandardPaths::LocateDirectory); qDebug() << " WP : -------" << dirs; BackgroundFinder *finder = new BackgroundFinder(m_wallpaper.data(), dirs); connect(finder, &BackgroundFinder::backgroundsFound, this, &BackgroundListModel::backgroundsFound); m_findToken = finder->token(); finder->start(); m_removableWallpapers = QSet::fromList(selected); } void BackgroundListModel::backgroundsFound(const QStringList &paths, const QString &token) { if (token == m_findToken) { processPaths(paths); } } void BackgroundListModel::processPaths(const QStringList &paths) { if (!m_wallpaper) { return; } QList newPackages; Q_FOREACH (QString file, paths) { // check if the path is a symlink and if it is, // work with the target rather than the symlink QFileInfo info(file); if (info.isSymLink()) { file = info.symLinkTarget(); } // now check if the path contains "contents" part // which could indicate that the file is part of some other // package (could have been symlinked) and we should work // with the package (which can already be present) rather // than just one file from it int contentsIndex = file.indexOf(QStringLiteral("contents")); // FIXME: additionally check for metadata.desktop being present // which would confirm a package but might be slowing things if (contentsIndex != -1) { file.truncate(contentsIndex); } // so now we have a path to a package, check if we're not // processing the same path twice (this is different from // the "!contains(file)" call lower down, that one checks paths // already in the model and does not include the paths // that are being checked in here); we want to check for duplicates // if and only if we actually changed the path (so the conditions from above // are reused here as that means we did change the path) if ((info.isSymLink() || contentsIndex != -1) && paths.contains(file)) { continue; } if (!contains(file) && QFile::exists(file)) { KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Wallpaper/Images")); package.setPath(file); if (package.isValid()) { m_wallpaper->findPreferedImageInPackage(package); newPackages << package; } } } // add new files to dirwatch Q_FOREACH (const KPackage::Package &b, newPackages) { if (!m_dirwatch.contains(b.path())) { m_dirwatch.addFile(b.path()); } } if (!newPackages.isEmpty()) { const int start = rowCount(); beginInsertRows(QModelIndex(), start, start + newPackages.size() - 1); m_packages.append(newPackages); endInsertRows(); emit countChanged(); } //qDebug() << t.elapsed(); } void BackgroundListModel::addBackground(const QString& path) { if (!m_wallpaper || !contains(path)) { if (!m_dirwatch.contains(path)) { m_dirwatch.addFile(path); } beginInsertRows(QModelIndex(), 0, 0); KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Wallpaper/Images")); m_removableWallpapers.insert(path); package.setPath(path); m_wallpaper->findPreferedImageInPackage(package); qDebug() << "WP Bckground added " << path << package.isValid(); m_packages.prepend(package); endInsertRows(); emit countChanged(); } } -QModelIndex BackgroundListModel::indexOf(const QString &path) const +int BackgroundListModel::indexOf(const QString &path) const { for (int i = 0; i < m_packages.size(); i++) { // packages will end with a '/', but the path passed in may not QString package = m_packages[i].path(); if (package.at(package.length() - 1) == QChar::fromLatin1('/')) { package.truncate(package.length() - 1); } + //remove eventual file:/// + const QString filteredPath = QUrl(path).path(); - if (path.startsWith(package)) { + if (filteredPath.startsWith(package)) { // FIXME: ugly hack to make a difference between local files in the same dir // package->path does not contain the actual file name - qDebug() << "WP prefix" << m_packages[i].contentsPrefixPaths() << m_packages[i].filePath("preferred") << package << path; + qDebug() << "WP prefix" << m_packages[i].contentsPrefixPaths() << m_packages[i].filePath("preferred") << package << filteredPath; QStringList ps = m_packages[i].contentsPrefixPaths(); bool prefixempty = ps.count() == 0; if (!prefixempty) { prefixempty = ps[0].isEmpty(); } - - //For local files (user wallpapers) path == m_packages[i].filePath("preferred") - //E.X. path = "/home/kde/next.png" + //For local files (user wallpapers) filteredPath == m_packages[i].filePath("preferred") + //E.X. filteredPath = "/home/kde/next.png" //m_packages[i].filePath("preferred") = "/home/kde/next.png" // - //But for the system wallpapers this is not the case. path != m_packages[i].filePath("preferred") - //E.X. path = /usr/share/wallpapers/Next/" + //But for the system wallpapers this is not the case. filteredPath != m_packages[i].filePath("preferred") + //E.X. filteredPath = /usr/share/wallpapers/Next/" //m_packages[i].filePath("preferred") = "/usr/share/wallpapers/Next/contents/images/1920x1080.png" - if ((path == m_packages[i].filePath("preferred")) || m_packages[i].filePath("preferred").contains(path)) { - qDebug() << "WP TRUE" << (!m_packages[i].contentsPrefixPaths().isEmpty()) << (path == m_packages[i].filePath("preferred")); - return index(i, 0); + if ((filteredPath == m_packages[i].filePath("preferred")) || m_packages[i].filePath("preferred").contains(filteredPath)) { + qDebug() << "WP TRUE" << (!m_packages[i].contentsPrefixPaths().isEmpty()) << (filteredPath == m_packages[i].filePath("preferred")); + return i; } } } - return QModelIndex(); + return -1; } bool BackgroundListModel::contains(const QString &path) const { //qDebug() << "WP contains: " << path << indexOf(path).isValid(); - return indexOf(path).isValid(); + return indexOf(path) >= 0; } int BackgroundListModel::rowCount(const QModelIndex &) const { return m_packages.size(); } QSize BackgroundListModel::bestSize(const KPackage::Package &package) const { if (m_sizeCache.contains(package.path())) { return m_sizeCache.value(package.path()); } const QString image = package.filePath("preferred"); if (image.isEmpty()) { return QSize(); } ImageSizeFinder *finder = new ImageSizeFinder(image); connect(finder, &ImageSizeFinder::sizeFound, this, &BackgroundListModel::sizeFound); QThreadPool::globalInstance()->start(finder); QSize size(-1, -1); const_cast(this)->m_sizeCache.insert(package.path(), size); return size; } void BackgroundListModel::sizeFound(const QString &path, const QSize &s) { if (!m_wallpaper) { return; } - QModelIndex index = indexOf(path); - if (index.isValid()) { - KPackage::Package package = m_packages.at(index.row()); + int idx = indexOf(path); + if (idx >= 0) { + KPackage::Package package = m_packages.at(idx); m_sizeCache.insert(package.path(), s); - emit dataChanged(index, index); + emit dataChanged(index(idx, 0), index(idx, 0)); } } QVariant BackgroundListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= m_packages.size()) { return QVariant(); } KPackage::Package b = package(index.row()); if (!b.isValid()) { return QVariant(); } switch (role) { case Qt::DisplayRole: { QString title = b.metadata().isValid() ? b.metadata().name() : QString(); if (title.isEmpty()) { return QFileInfo(b.filePath("preferred")).completeBaseName(); } return title; } break; case ScreenshotRole: { QPixmap preview = QPixmap(QSize(m_screenshotSize*1.6, m_screenshotSize)); if (m_imageCache->findPixmap(b.filePath("preferred"), &preview)) { return preview; } // qDebug() << "WP preferred: " << b.filePath("preferred"); // qDebug() << "WP screenshot: " << b.filePath("screenshot"); QUrl file = QUrl::fromLocalFile(b.filePath("preferred")); if (!m_previewJobs.contains(file) && file.isValid()) { KFileItemList list; list.append(KFileItem(file, QString(), 0)); QStringList availablePlugins = KIO::PreviewJob::availablePlugins(); KIO::PreviewJob* job = KIO::filePreview(list, QSize(m_screenshotSize*1.6, m_screenshotSize), &availablePlugins); job->setIgnoreMaximumSize(true); connect(job, &KIO::PreviewJob::gotPreview, this, &BackgroundListModel::showPreview); connect(job, &KIO::PreviewJob::failed, this, &BackgroundListModel::previewFailed); const_cast(this)->m_previewJobs.insert(file, QPersistentModelIndex(index)); } return QVariant(); } break; case AuthorRole: if (b.metadata().isValid() && !b.metadata().authors().isEmpty()) { return b.metadata().authors().first().name(); } else { return QString(); } break; case ResolutionRole:{ QSize size = bestSize(b); if (size.isValid()) { return QString::fromLatin1("%1x%2").arg(size.width()).arg(size.height()); } return QString(); } break; case PathRole: return QUrl::fromLocalFile(b.filePath("preferred")); break; case PackageNameRole: return !b.metadata().isValid() || b.metadata().pluginId().isEmpty() ? b.filePath("preferred") : b.metadata().pluginId(); break; case RemovableRole: { QString localWallpapers = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/wallpapers/"; QString path = b.filePath("preferred"); return path.startsWith(localWallpapers) || m_removableWallpapers.contains(path); } break; case PendingDeletionRole: { QUrl wallpaperUrl = QUrl::fromLocalFile(b.filePath("preferred")); return m_pendingDeletion.contains(wallpaperUrl.toLocalFile()) ? m_pendingDeletion[wallpaperUrl.toLocalFile()] : false; } break; default: return QVariant(); break; } Q_UNREACHABLE(); } bool BackgroundListModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) { return false; } if (role == PendingDeletionRole) { KPackage::Package b = package(index.row()); if (!b.isValid()) { return false; } const QUrl wallpaperUrl = QUrl::fromLocalFile(b.filePath("preferred")); m_pendingDeletion[wallpaperUrl.toLocalFile()] = value.toBool(); emit dataChanged(index, index); return true; } return false; } void BackgroundListModel::showPreview(const KFileItem &item, const QPixmap &preview) { if (!m_wallpaper) { return; } QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } KPackage::Package b = package(index.row()); if (!b.isValid()) { return; } m_imageCache->insertPixmap(b.filePath("preferred"), preview); //qDebug() << "WP preview size:" << preview.size(); emit dataChanged(index, index); } void BackgroundListModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } KPackage::Package BackgroundListModel::package(int index) const { return m_packages.at(index); } void BackgroundListModel::setPendingDeletion(int rowIndex, bool pendingDeletion) { setData(index(rowIndex, 0), pendingDeletion, PendingDeletionRole); } const QStringList BackgroundListModel::wallpapersAwaitingDeletion() { QStringList candidates; for (const KPackage::Package &b : m_packages) { const QUrl wallpaperUrl = QUrl::fromLocalFile(b.filePath("preferred")); if (m_pendingDeletion.contains(wallpaperUrl.toLocalFile()) && m_pendingDeletion[wallpaperUrl.toLocalFile()]) { candidates << wallpaperUrl.toLocalFile(); } } return candidates; } BackgroundFinder::BackgroundFinder(Image *wallpaper, const QStringList &paths) : QThread(wallpaper), m_paths(paths), m_token(QUuid().toString()) { } BackgroundFinder::~BackgroundFinder() { wait(); } QString BackgroundFinder::token() const { return m_token; } const QStringList &BackgroundFinder::suffixes() { if (m_suffixes.isEmpty()) { QSet suffixes; QMimeDatabase db; Q_FOREACH (const QByteArray &mimeType, QImageReader::supportedMimeTypes()) { QMimeType mime(db.mimeTypeForName(mimeType)); Q_FOREACH (const QString &pattern, mime.globPatterns()) { suffixes.insert(pattern); } } m_suffixes = suffixes.toList(); } return m_suffixes; } bool BackgroundFinder::isAcceptableSuffix(const QString &suffix) { // Despite its name, suffixes() returns a list of glob patterns. // Therefore the file suffix check needs to include the "*." prefix. const QStringList &globPatterns = suffixes(); return globPatterns.contains("*."+suffix.toLower()); } void BackgroundFinder::run() { QTime t; t.start(); QStringList papersFound; QDir dir; dir.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::Readable); dir.setNameFilters(suffixes()); KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Wallpaper/Images")); int i; for (i = 0; i < m_paths.count(); ++i) { const QString path = m_paths.at(i); dir.setPath(path); const QFileInfoList files = dir.entryInfoList(); Q_FOREACH (const QFileInfo &wp, files) { if (wp.isDir()) { //qDebug() << "scanning directory" << wp.fileName(); const QString name = wp.fileName(); if (name == QString::fromLatin1(".") || name == QString::fromLatin1("..")) { // do nothing continue; } const QString filePath = wp.filePath(); if (QFile::exists(filePath + QString::fromLatin1("/metadata.desktop")) || QFile::exists(filePath + QString::fromLatin1("/metadata.json"))) { package.setPath(filePath); if (package.isValid()) { if (!package.filePath("images").isEmpty()) { papersFound << package.path(); } //qDebug() << "adding package" << wp.filePath(); continue; } } // add this to the directories we should be looking at m_paths.append(filePath); } else { //qDebug() << "adding image file" << wp.filePath(); papersFound << wp.filePath(); } } } //qDebug() << "WP background found!" << papersFound.size() << "in" << i << "dirs, taking" << t.elapsed() << "ms"; Q_EMIT backgroundsFound(papersFound, m_token); deleteLater(); } #endif // BACKGROUNDLISTMODEL_CPP diff --git a/wallpapers/image/backgroundlistmodel.h b/wallpapers/image/backgroundlistmodel.h index 69cee2c8..9ed0e81f 100644 --- a/wallpapers/image/backgroundlistmodel.h +++ b/wallpapers/image/backgroundlistmodel.h @@ -1,149 +1,149 @@ /*************************************************************************** * Copyright 2007 Paolo Capriotti * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #ifndef BACKGROUNDLISTMODEL_H #define BACKGROUNDLISTMODEL_H #include "image.h" #include #include #include #include #include #include #include #include #include class QEventLoop; class KProgressDialog; class Image; class ImageSizeFinder : public QObject, public QRunnable { Q_OBJECT public: ImageSizeFinder(const QString &path, QObject *parent = 0); void run() override; Q_SIGNALS: void sizeFound(const QString &path, const QSize &size); private: QString m_path; }; class BackgroundListModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(int count READ count NOTIFY countChanged) public: enum { AuthorRole = Qt::UserRole, ScreenshotRole, ResolutionRole, PathRole, PackageNameRole, RemovableRole, PendingDeletionRole }; static const int BLUR_INCREMENT = 9; static const int MARGIN = 6; BackgroundListModel(Image *listener, QObject *parent); ~BackgroundListModel() override; QHash roleNames() const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE ; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) Q_DECL_OVERRIDE; KPackage::Package package(int index) const; void reload(); void reload(const QStringList &selected); void addBackground(const QString &path); - QModelIndex indexOf(const QString &path) const; + Q_INVOKABLE int indexOf(const QString &path) const; virtual bool contains(const QString &bg) const; int count() const {return m_packages.size();}; Q_INVOKABLE void setPendingDeletion(int rowIndex, bool pendingDeletion); const QStringList wallpapersAwaitingDeletion(); Q_SIGNALS: void countChanged(); protected Q_SLOTS: void removeBackground(const QString &path); void showPreview(const KFileItem &item, const QPixmap &preview); void previewFailed(const KFileItem &item); void sizeFound(const QString &path, const QSize &s); void backgroundsFound(const QStringList &paths, const QString &token); void processPaths(const QStringList &paths); private: QSize bestSize(const KPackage::Package &package) const; QPointer m_wallpaper; QList m_packages; QSet m_removableWallpapers; QHash m_sizeCache; QHash m_previewJobs; KDirWatch m_dirwatch; KImageCache* m_imageCache; QString m_findToken; int m_screenshotSize; QHash m_pendingDeletion; }; class BackgroundFinder : public QThread { Q_OBJECT public: BackgroundFinder(Image *wallpaper, const QStringList &p); ~BackgroundFinder() override; QString token() const; static const QStringList &suffixes(); static bool isAcceptableSuffix(const QString &suffix); Q_SIGNALS: void backgroundsFound(const QStringList &paths, const QString &token); protected: void run() override; private: QStringList m_paths; QString m_token; static QStringList m_suffixes; }; #endif // BACKGROUNDLISTMODEL_H diff --git a/wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml b/wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml index 5ddc05b7..942d0476 100644 --- a/wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml +++ b/wallpapers/image/imagepackage/contents/ui/WallpaperDelegate.qml @@ -1,183 +1,170 @@ /* * Copyright 2013 Marco Martin * Copyright 2014 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls.Private 1.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents MouseArea { id: wallpaperDelegate width: wallpapersGrid.cellWidth height: wallpapersGrid.cellHeight property alias color: backgroundRect.color property bool selected: (wallpapersGrid.currentIndex == index) opacity: model.pendingDeletion ? 0.5 : 1 - onSelectedChanged: { - if (selected) { - cfg_Image = model.path - } - } - hoverEnabled: true //note: this *doesn't* use system colors since it represent a //skeymorphic photograph rather than a widget Rectangle { id: background color: "white" anchors { fill: parent margins: units.smallSpacing } opacity: 0.8 Rectangle { id: backgroundRect color: cfg_Color anchors { fill: parent margins: units.smallSpacing * 2 } QIconItem { anchors.centerIn: parent width: units.iconSizes.large height: width icon: "view-preview" visible: !walliePreview.visible } QPixmapItem { id: walliePreview anchors.fill: parent visible: model.screenshot != null smooth: true pixmap: model.screenshot fillMode: { if (cfg_FillMode == Image.Stretch) { return QPixmapItem.Stretch; } else if (cfg_FillMode == Image.PreserveAspectFit) { return QPixmapItem.PreserveAspectFit; } else if (cfg_FillMode == Image.PreserveAspectCrop) { return QPixmapItem.PreserveAspectCrop; } else if (cfg_FillMode == Image.Tile) { return QPixmapItem.Tile; } else if (cfg_FillMode == Image.TileVertically) { return QPixmapItem.TileVertically; } else if (cfg_FillMode == Image.TileHorizontally) { return QPixmapItem.TileHorizontally; } return QPixmapItem.Pad; } } PlasmaComponents.ToolButton { anchors { top: parent.top right: parent.right margins: units.smallSpacing } iconSource: "list-remove" tooltip: i18nd("plasma_applet_org.kde.image", "Remove wallpaper") flat: false visible: model.removable && !model.pendingDeletion onClicked: { imageWallpaper.wallpaperModel.setPendingDeletion(index, true); if (wallpapersGrid.currentIndex === index) { wallpapersGrid.currentIndex = (index + 1) % wallpapersGrid.count; } } opacity: wallpaperDelegate.containsMouse ? 1 : 0 Behavior on opacity { PropertyAnimation { duration: units.longDuration easing.type: Easing.OutQuad } } } PlasmaComponents.ToolButton { anchors { top: parent.top right: parent.right margins: units.smallSpacing } iconSource: "edit-undo" tooltip: i18nd("plasma_applet_org.kde.image", "Restore wallpaper") flat: false visible: model.pendingDeletion onClicked: imageWallpaper.wallpaperModel.setPendingDeletion(index, !model.pendingDeletion) opacity: wallpaperDelegate.containsMouse ? 1 : 0 Behavior on opacity { PropertyAnimation { duration: units.longDuration easing.type: Easing.OutQuad } } } } } Rectangle { opacity: selected ? 1.0 : 0 anchors.fill: background border.width: units.smallSpacing * 2 border.color: syspal.highlight color: "transparent" Behavior on opacity { PropertyAnimation { duration: units.longDuration easing.type: Easing.OutQuad } } } Timer { interval: 1000 // FIXME TODO: Use platform value for tooltip activation delay. running: wallpaperDelegate.containsMouse && !pressed && model.display onTriggered: { if (model.author) { Tooltip.showText(wallpaperDelegate, Qt.point(wallpaperDelegate.mouseX, wallpaperDelegate.mouseY), i18nd("plasma_applet_org.kde.image", "%1 by %2", model.display, model.author)); } else { Tooltip.showText(wallpaperDelegate, Qt.point(wallpaperDelegate.mouseX, wallpaperDelegate.mouseY), model.display); } } } onClicked: { wallpapersGrid.currentIndex = index wallpapersGrid.forceActiveFocus(); cfg_Image = model.path } onExited: Tooltip.hideText() - - Component.onCompleted: { - if (cfg_Image == model.path) { - makeCurrentTimer.pendingIndex = model.index - makeCurrentTimer.restart() - } - } } diff --git a/wallpapers/image/imagepackage/contents/ui/config.qml b/wallpapers/image/imagepackage/contents/ui/config.qml index bc0185ca..bc2f6bbb 100644 --- a/wallpapers/image/imagepackage/contents/ui/config.qml +++ b/wallpapers/image/imagepackage/contents/ui/config.qml @@ -1,364 +1,360 @@ /* * Copyright 2013 Marco Martin * Copyright 2014 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 1.0 as QtControls import QtQuick.Dialogs 1.1 as QtDialogs import QtQuick.Layouts 1.0 //We need units from it import org.kde.plasma.core 2.0 as Plasmacore import org.kde.plasma.wallpapers.image 2.0 as Wallpaper import org.kde.kquickcontrolsaddons 2.0 ColumnLayout { id: root property alias cfg_Color: colorDialog.color property string cfg_Image property int cfg_FillMode property var cfg_SlidePaths: "" property int cfg_SlideInterval: 0 signal restoreIndex(int count) function saveConfig() { root.restoreIndex(imageWallpaper.wallpaperModel.count) imageWallpaper.commitDeletion(); } SystemPalette { id: syspal } Wallpaper.Image { id: imageWallpaper width: wallpaper.configuration.width height: wallpaper.configuration.height onSlidePathsChanged: cfg_SlidePaths = slidePaths } onCfg_SlidePathsChanged: { imageWallpaper.slidePaths = cfg_SlidePaths } property int hoursIntervalValue: Math.floor(cfg_SlideInterval / 3600) property int minutesIntervalValue: Math.floor(cfg_SlideInterval % 3600) / 60 property int secondsIntervalValue: cfg_SlideInterval % 3600 % 60 //Rectangle { color: "orange"; x: formAlignment; width: formAlignment; height: 20 } TextMetrics { id: textMetrics text: "00" } Row { //x: formAlignment - positionLabel.paintedWidth spacing: units.largeSpacing / 2 QtControls.Label { id: positionLabel width: formAlignment - units.largeSpacing anchors { verticalCenter: resizeComboBox.verticalCenter } text: i18nd("plasma_applet_org.kde.image", "Positioning:") horizontalAlignment: Text.AlignRight } QtControls.ComboBox { id: resizeComboBox property int textLength: 24 width: theme.mSize(theme.defaultFont).width * textLength model: [ { 'label': i18nd("plasma_applet_org.kde.image", "Scaled and Cropped"), 'fillMode': Image.PreserveAspectCrop }, { 'label': i18nd("plasma_applet_org.kde.image","Scaled"), 'fillMode': Image.Stretch }, { 'label': i18nd("plasma_applet_org.kde.image","Scaled, Keep Proportions"), 'fillMode': Image.PreserveAspectFit }, { 'label': i18nd("plasma_applet_org.kde.image", "Centered"), 'fillMode': Image.Pad }, { 'label': i18nd("plasma_applet_org.kde.image","Tiled"), 'fillMode': Image.Tile } ] textRole: "label" onCurrentIndexChanged: cfg_FillMode = model[currentIndex]["fillMode"] Component.onCompleted: setMethod(); function setMethod() { for (var i = 0; i < model.length; i++) { if (model[i]["fillMode"] == wallpaper.configuration.FillMode) { resizeComboBox.currentIndex = i; var tl = model[i]["label"].length; //resizeComboBox.textLength = Math.max(resizeComboBox.textLength, tl+5); } } } } } QtDialogs.ColorDialog { id: colorDialog modality: Qt.WindowModal showAlphaChannel: false title: i18nd("plasma_applet_org.kde.image", "Select Background Color") } Row { id: colorRow spacing: units.largeSpacing / 2 QtControls.Label { width: formAlignment - units.largeSpacing anchors.verticalCenter: colorButton.verticalCenter horizontalAlignment: Text.AlignRight text: i18nd("plasma_applet_org.kde.image", "Background Color:") } QtControls.Button { id: colorButton width: units.gridUnit * 3 text: " " // needed to it gets a proper height... onClicked: colorDialog.open() Rectangle { id: colorRect anchors.centerIn: parent width: parent.width - 2 * units.smallSpacing height: theme.mSize(theme.defaultFont).height color: colorDialog.color } } } Component { id: foldersComponent ColumnLayout { anchors.fill: parent Connections { target: root onHoursIntervalValueChanged: hoursInterval.value = root.hoursIntervalValue onMinutesIntervalValueChanged: minutesInterval.value = root.minutesIntervalValue onSecondsIntervalValueChanged: secondsInterval.value = root.secondsIntervalValue } //FIXME: there should be only one spinbox: QtControls spinboxes are still too limited for it tough RowLayout { Layout.fillWidth: true spacing: units.largeSpacing / 2 QtControls.Label { Layout.minimumWidth: formAlignment - units.largeSpacing anchors.verticalCenter: parent.verticalCenter horizontalAlignment: Text.AlignRight text: i18nd("plasma_applet_org.kde.image","Change every:") } QtControls.SpinBox { id: hoursInterval anchors.verticalCenter: parent.verticalCenter Layout.minimumWidth: textMetrics.width + units.gridUnit width: units.gridUnit * 3 decimals: 0 value: root.hoursIntervalValue minimumValue: 0 maximumValue: 24 onValueChanged: cfg_SlideInterval = hoursInterval.value * 3600 + minutesInterval.value * 60 + secondsInterval.value } QtControls.Label { anchors.verticalCenter: parent.verticalCenter text: i18nd("plasma_applet_org.kde.image","Hours") } Item { Layout.preferredWidth: units.gridUnit } QtControls.SpinBox { id: minutesInterval anchors.verticalCenter: parent.verticalCenter Layout.minimumWidth: textMetrics.width + units.gridUnit width: units.gridUnit * 3 decimals: 0 value: root.minutesIntervalValue minimumValue: 0 maximumValue: 60 onValueChanged: cfg_SlideInterval = hoursInterval.value * 3600 + minutesInterval.value * 60 + secondsInterval.value } QtControls.Label { anchors.verticalCenter: parent.verticalCenter text: i18nd("plasma_applet_org.kde.image","Minutes") } Item { Layout.preferredWidth: units.gridUnit } QtControls.SpinBox { id: secondsInterval anchors.verticalCenter: parent.verticalCenter Layout.minimumWidth: textMetrics.width + units.gridUnit width: units.gridUnit * 3 decimals: 0 value: root.secondsIntervalValue minimumValue: root.hoursIntervalValue === 0 && root.minutesIntervalValue === 0 ? 1 : 0 maximumValue: 60 onValueChanged: cfg_SlideInterval = hoursInterval.value * 3600 + minutesInterval.value * 60 + secondsInterval.value } QtControls.Label { anchors.verticalCenter: parent.verticalCenter text: i18nd("plasma_applet_org.kde.image","Seconds") } } QtControls.ScrollView { Layout.fillHeight: true; Layout.fillWidth: true frameVisible: true ListView { id: slidePathsView anchors.margins: 4 model: imageWallpaper.slidePaths delegate: QtControls.Label { text: modelData width: slidePathsView.width height: Math.max(paintedHeight, removeButton.height); QtControls.ToolButton { id: removeButton anchors { verticalCenter: parent.verticalCenter right: parent.right } iconName: "list-remove" onClicked: imageWallpaper.removeSlidePath(modelData); } } } } } } Component { id: thumbnailsComponent QtControls.ScrollView { anchors.fill: parent frameVisible: true highlightOnFocus: true; Component.onCompleted: { //replace the current binding on the scrollbar that makes it visible when content doesn't fit //otherwise we adjust gridSize when we hide the vertical scrollbar and //due to layouting that can make everything adjust which changes the contentWidth/height which //changes our scrollbars and we continue being stuck in a loop //looks better to not have everything resize anyway. //BUG: 336301 __verticalScrollBar.visible = true } GridView { id: wallpapersGrid model: imageWallpaper.wallpaperModel currentIndex: -1 focus: true cellWidth: Math.floor(wallpapersGrid.width / Math.max(Math.floor(wallpapersGrid.width / (units.gridUnit*12)), 3)) cellHeight: cellWidth / (imageWallpaper.width / imageWallpaper.height) anchors.margins: 4 boundsBehavior: Flickable.StopAtBounds delegate: WallpaperDelegate { color: cfg_Color } + onCountChanged: { + wallpapersGrid.currentIndex = imageWallpaper.wallpaperModel.indexOf(cfg_Image); + wallpapersGrid.positionViewAtIndex(wallpapersGrid.currentIndex, GridView.Visible) + } + Connections { target: root onRestoreIndex: { wallpapersGrid.currentIndex = wallpapersGrid.currentIndex - count } } - Timer { - id: makeCurrentTimer - interval: 100 - repeat: false - property string pendingIndex - onTriggered: { - wallpapersGrid.currentIndex = pendingIndex - wallpapersGrid.forceActiveFocus(); - } - } - Keys.onPressed: { if (count < 1) { return; } if (event.key == Qt.Key_Home) { currentIndex = 0; } else if (event.key == Qt.Key_End) { currentIndex = count - 1; } } Keys.onLeftPressed: moveCurrentIndexLeft() Keys.onRightPressed: moveCurrentIndexRight() Keys.onUpPressed: moveCurrentIndexUp() Keys.onDownPressed: moveCurrentIndexDown() Connections { target: imageWallpaper - onCustomWallpaperPicked: wallpapersGrid.currentIndex = 0 + onCustomWallpaperPicked: { + wallpapersGrid.currentIndex = 0 + } } } } } Loader { Layout.fillWidth: true Layout.fillHeight: true sourceComponent: (configDialog.currentWallpaper == "org.kde.image") ? thumbnailsComponent : foldersComponent } RowLayout { id: buttonsRow anchors { right: parent.right } QtControls.Button { visible: (configDialog.currentWallpaper == "org.kde.slideshow") iconName: "list-add" text: i18nd("plasma_applet_org.kde.image","Add Folder") onClicked: imageWallpaper.showAddSlidePathsDialog() } QtControls.Button { visible: (configDialog.currentWallpaper == "org.kde.image") iconName: "document-open-folder" text: i18nd("plasma_applet_org.kde.image","Open...") onClicked: imageWallpaper.showFileDialog(); } QtControls.Button { iconName: "get-hot-new-stuff" text: i18nd("plasma_applet_org.kde.image","Get New Wallpapers...") onClicked: imageWallpaper.getNewWallpaper(); } } } diff --git a/wallpapers/image/imagepackage/platformcontents/phone/ui/WallpaperDelegate.qml b/wallpapers/image/imagepackage/platformcontents/phone/ui/WallpaperDelegate.qml index e46a2c71..bfb52b06 100644 --- a/wallpapers/image/imagepackage/platformcontents/phone/ui/WallpaperDelegate.qml +++ b/wallpapers/image/imagepackage/platformcontents/phone/ui/WallpaperDelegate.qml @@ -1,140 +1,129 @@ /* * Copyright 2013 Marco Martin * Copyright 2014 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls.Private 1.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents MouseArea { id: wallpaperDelegate width: wallpapersGrid.cellWidth height: wallpapersGrid.cellHeight property bool selected: (wallpapersGrid.currentIndex == index) - onSelectedChanged: { - cfg_Image = model.path - } - hoverEnabled: true //note: this *doesn't* use system colors since it represent a //skeymorphic photograph rather than a widget Rectangle { id: background color: "white" anchors { fill: parent margins: units.smallSpacing } opacity: 0.8 Rectangle { color: cfg_Color anchors { fill: parent margins: units.smallSpacing * 2 } QIconItem { anchors.centerIn: parent width: units.iconSizes.large height: width icon: "view-preview" visible: !walliePreview.visible } QPixmapItem { id: walliePreview anchors.fill: parent visible: model.screenshot != null smooth: true pixmap: model.screenshot fillMode: { if (cfg_FillMode == Image.Stretch) { return QPixmapItem.Stretch; } else if (cfg_FillMode == Image.PreserveAspectFit) { return QPixmapItem.PreserveAspectFit; } else if (cfg_FillMode == Image.PreserveAspectCrop) { return QPixmapItem.PreserveAspectCrop; } else if (cfg_FillMode == Image.Tile) { return QPixmapItem.Tile; } else if (cfg_FillMode == Image.TileVertically) { return QPixmapItem.TileVertically; } else if (cfg_FillMode == Image.TileHorizontally) { return QPixmapItem.TileHorizontally; } return QPixmapItem.Pad; } } PlasmaComponents.ToolButton { anchors { top: parent.top right: parent.right margins: units.smallSpacing } iconSource: "list-remove" tooltip: i18nd("plasma_applet_org.kde.image", "Remove wallpaper") flat: false visible: model.removable onClicked: imageWallpaper.removeWallpaper(model.packageName) } } } Rectangle { opacity: selected ? 1.0 : 0 anchors.fill: background border.width: units.smallSpacing * 2 border.color: syspal.highlight color: "transparent" Behavior on opacity { PropertyAnimation { duration: units.longDuration easing.type: Easing.OutQuad } } } Timer { interval: 1000 // FIXME TODO: Use platform value for tooltip activation delay. running: wallpaperDelegate.containsMouse && !pressed && model.display && model.author onTriggered: { Tooltip.showText(wallpaperDelegate, Qt.point(wallpaperDelegate.mouseX, wallpaperDelegate.mouseY), i18nd("plasma_applet_org.kde.image", "%1 by %2", model.display, model.author)); } } onClicked: { wallpapersGrid.currentIndex = index cfg_Image = model.path } onExited: Tooltip.hideText() - - Component.onCompleted: { - if (cfg_Image == model.path) { - makeCurrentTimer.pendingIndex = model.index - makeCurrentTimer.restart() - } - } } diff --git a/wallpapers/image/imagepackage/platformcontents/phone/ui/config.qml b/wallpapers/image/imagepackage/platformcontents/phone/ui/config.qml index 3f309ae0..9900104e 100644 --- a/wallpapers/image/imagepackage/platformcontents/phone/ui/config.qml +++ b/wallpapers/image/imagepackage/platformcontents/phone/ui/config.qml @@ -1,93 +1,89 @@ /* * Copyright 2013 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 //We need units from it import org.kde.plasma.core 2.0 as Plasmacore import org.kde.plasma.wallpapers.image 2.0 as Wallpaper import org.kde.kquickcontrolsaddons 2.0 import QtQuick.Controls 1.0 as QtControls Item { id: root anchors { top: parent.top left: parent.left right: parent.right bottom: parent.bottom } property string cfg_Image Wallpaper.Image { id: imageWallpaper width: wallpaper.configuration.width height: wallpaper.configuration.height } //Rectangle { color: "orange"; x: formAlignment; width: formAlignment; height: 20 } QtControls.ScrollView { anchors.fill: parent frameVisible: true GridView { id: wallpapersGrid model: imageWallpaper.wallpaperModel currentIndex: -1 cellWidth: Math.floor(wallpapersGrid.width / Math.max(Math.floor(wallpapersGrid.width / (units.gridUnit*12)), 3)) cellHeight: cellWidth / (imageWallpaper.width / imageWallpaper.height) anchors.margins: 4 boundsBehavior: Flickable.DragAndOvershootBounds delegate: WallpaperDelegate {} - Timer { - id: makeCurrentTimer - interval: 100 - repeat: false - property string pendingIndex - onTriggered: { - wallpapersGrid.currentIndex = pendingIndex - } + + onCountChanged: { + wallpapersGrid.currentIndex = imageWallpaper.wallpaperModel.indexOf(cfg_Image); + wallpapersGrid.positionViewAtIndex(wallpapersGrid.currentIndex, GridView.Visible) } Connections { target: imageWallpaper onCustomWallpaperPicked: wallpapersGrid.currentIndex = 0 } } } QtControls.Button { anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter } iconName: "list-add" text: i18nd("plasma_applet_org.kde.image","Add Custom Wallpaper") onClicked: customWallpaperLoader.source = Qt.resolvedUrl("customwallpaper.qml") } Loader { id: customWallpaperLoader anchors.fill: parent } } diff --git a/wallpapers/image/imagepackage/platformcontents/touch/ui/WallpaperDelegate.qml b/wallpapers/image/imagepackage/platformcontents/touch/ui/WallpaperDelegate.qml index c0ff81b1..68470f7d 100644 --- a/wallpapers/image/imagepackage/platformcontents/touch/ui/WallpaperDelegate.qml +++ b/wallpapers/image/imagepackage/platformcontents/touch/ui/WallpaperDelegate.qml @@ -1,90 +1,79 @@ /* * Copyright 2013 Marco Martin * Copyright 2014 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents MouseArea { id: wallpaperDelegate width: wallpapersGrid.delegateWidth height: wallpapersGrid.delegateHeight property bool selected: (wallpapersGrid.currentIndex == index) - onSelectedChanged: { - cfg_Image = model.path - } - hoverEnabled: true PlasmaCore.FrameSvgItem { id: frameSvg imagePath: "widgets/media-delegate" prefix: (wallpapersGrid.currentIndex - (wallpapersGrid.currentPage*wallpapersGrid.pageSize)) == index ? "picture-selected" : "picture" width: (wallpapersGrid.currentIndex - (wallpapersGrid.currentPage*wallpapersGrid.pageSize)) == index ? parent.width+5 : parent.width-16 height: (wallpapersGrid.currentIndex - (wallpapersGrid.currentPage*wallpapersGrid.pageSize)) == index ? parent.height+5 : parent.height-16 anchors { left: parent.left right: parent.right bottomMargin: 8 } Behavior on width { NumberAnimation { duration: 250 easing.type: Easing.InOutQuad } } Behavior on height { NumberAnimation { duration: 250 easing.type: Easing.InOutQuad } } QPixmapItem { id: walliePreview anchors { fill: parent leftMargin: parent.margins.left topMargin: parent.margins.top rightMargin: parent.margins.right bottomMargin: parent.margins.bottom } visible: model.screenshot != null smooth: true pixmap: model.screenshot fillMode: QPixmapItem.Stretch } } onClicked: { wallpapersGrid.currentIndex = (wallpapersGrid.currentPage*wallpapersGrid.pageSize) + index cfg_Image = model.path } - - Component.onCompleted: { - if (cfg_Image == model.path) { - makeCurrentTimer.pendingIndex = model.index - makeCurrentTimer.restart() - } - } } diff --git a/wallpapers/image/imagepackage/platformcontents/touch/ui/config.qml b/wallpapers/image/imagepackage/platformcontents/touch/ui/config.qml index a805056f..969f6651 100644 --- a/wallpapers/image/imagepackage/platformcontents/touch/ui/config.qml +++ b/wallpapers/image/imagepackage/platformcontents/touch/ui/config.qml @@ -1,81 +1,76 @@ /* * Copyright 2013 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 //We need units from it import org.kde.plasma.core 2.0 as Plasmacore import org.kde.plasma.wallpapers.image 2.0 as Wallpaper import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.mobilecomponents 0.2 as MobileComponets Item { id: root anchors { top: parent.top left: parent.left right: parent.right bottom: parent.bottom } property string cfg_Image Wallpaper.Image { id: imageWallpaper width: wallpaper.configuration.width height: wallpaper.configuration.height } //Rectangle { color: "orange"; x: formAlignment; width: formAlignment; height: 20 } MobileComponets.IconGrid { id: wallpapersGrid model: imageWallpaper.wallpaperModel property int currentIndex: -1 onCurrentIndexChanged: { currentPage = Math.max(0, Math.floor(currentIndex/pageSize)) } anchors { fill: parent top: parent.top bottom: parent.bottom left: parent.left right: parent.right } delegateWidth: Math.floor(wallpapersGrid.width / Math.max(Math.floor(wallpapersGrid.width / (units.gridUnit*12)), 3)) delegateHeight: delegateWidth / 1.6 delegate: WallpaperDelegate {} - Timer { - id: makeCurrentTimer - interval: 100 - repeat: false - property string pendingIndex - onTriggered: { - wallpapersGrid.currentIndex = pendingIndex - wallpapersGrid.positionViewAtIndex(pendingIndex, ListView.Beginning) - } + + onCountChanged: { + wallpapersGrid.currentIndex = imageWallpaper.wallpaperModel.indexOf(cfg_Image); + wallpapersGrid.positionViewAtIndex(wallpapersGrid.currentIndex, GridView.Visible) } Connections { target: imageWallpaper - onCustomWallpaperPicked: wallpapersGrid.currentIndex = 0 - } + onCustomWallpaperPicked: wallpapersGrid.currentIndex = 0 + } } }