1
#ifndef BACKGROUNDLISTMODEL_CPP
2
#define BACKGROUNDLISTMODEL_CPP
4
Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
12
#include "backgroundlistmodel.h"
16
#include <QThreadPool>
20
#include <KFileMetaInfo>
22
#include <KIO/PreviewJob>
23
#include <KProgressDialog>
24
#include <KStandardDirs>
26
#include <Plasma/Package>
27
#include <Plasma/PackageStructure>
29
#include "backgrounddelegate.h"
32
ImageSizeFinder::ImageSizeFinder(const QString &path, QObject *parent)
38
void ImageSizeFinder::run()
41
emit sizeFound(m_path, image.size());
45
BackgroundListModel::BackgroundListModel(Plasma::Wallpaper *listener, QObject *parent)
46
: QAbstractListModel(parent),
47
m_structureParent(listener),
49
m_resizeMethod(Plasma::Wallpaper::ScaledResize)
51
connect(&m_dirwatch, SIGNAL(deleted(QString)), this, SLOT(removeBackground(QString)));
52
m_previewUnavailablePix.fill(Qt::transparent);
53
//m_previewUnavailablePix = KIcon("unknown").pixmap(m_previewUnavailablePix.size());
56
BackgroundListModel::~BackgroundListModel()
58
qDeleteAll(m_packages);
61
void BackgroundListModel::removeBackground(const QString &path)
64
while ((index = indexOf(path)).isValid()) {
65
beginRemoveRows(QModelIndex(), index.row(), index.row());
66
Plasma::Package *package = m_packages.at(index.row());
67
m_packages.removeAt(index.row());
73
void BackgroundListModel::reload()
75
reload(QStringList());
78
void BackgroundListModel::reload(const QStringList &selected)
80
if (!m_packages.isEmpty()) {
81
beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1);
82
qDeleteAll(m_packages);
87
if (!selected.isEmpty()) {
88
processPaths(selected);
91
const QStringList dirs = KGlobal::dirs()->findDirs("wallpaper", "");
92
kDebug() << "going looking in" << dirs;
93
BackgroundFinder *finder = new BackgroundFinder(m_structureParent, dirs);
94
connect(finder, SIGNAL(backgroundsFound(QStringList,QString)), this, SLOT(backgroundsFound(QStringList,QString)));
95
m_findToken = finder->token();
99
void BackgroundListModel::backgroundsFound(const QStringList &paths, const QString &token)
101
if (token == m_findToken) {
106
void BackgroundListModel::processPaths(const QStringList &paths)
108
QList<Plasma::Package *> newPackages;
109
foreach (const QString &file, paths) {
110
if (!contains(file) && QFile::exists(file)) {
111
Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent);
112
Plasma::Package *package = new Plasma::Package(file, structure);
113
if (package->isValid()) {
114
newPackages << package;
121
// add new files to dirwatch
122
foreach (Plasma::Package *b, newPackages) {
123
if (!m_dirwatch.contains(b->path())) {
124
m_dirwatch.addFile(b->path());
128
if (!newPackages.isEmpty()) {
129
const int start = rowCount();
130
beginInsertRows(QModelIndex(), start, start + newPackages.size());
131
m_packages.append(newPackages);
134
//kDebug() << t.elapsed();
137
void BackgroundListModel::addBackground(const QString& path)
139
if (!contains(path)) {
140
if (!m_dirwatch.contains(path)) {
141
m_dirwatch.addFile(path);
143
beginInsertRows(QModelIndex(), 0, 0);
144
Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent);
145
Plasma::Package *pkg = new Plasma::Package(path, structure);
146
m_packages.prepend(pkg);
151
QModelIndex BackgroundListModel::indexOf(const QString &path) const
153
for (int i = 0; i < m_packages.size(); i++) {
154
// packages will end with a '/', but the path passed in may not
155
QString package = m_packages[i]->path();
156
if (package.at(package.length() - 1) == '/') {
157
package.truncate(package.length() - 1);
160
if (path.startsWith(package)) {
161
// FIXME: ugly hack to make a difference between local files in the same dir
162
// package->path does not contain the actual file name
163
if ((!m_packages[i]->structure()->contentsPrefixPaths().isEmpty()) ||
164
(path == m_packages[i]->filePath("preferred"))) {
169
return QModelIndex();
172
bool BackgroundListModel::contains(const QString &path) const
174
return indexOf(path).isValid();
177
int BackgroundListModel::rowCount(const QModelIndex &) const
179
return m_packages.size();
182
QSize BackgroundListModel::bestSize(Plasma::Package *package) const
184
if (m_sizeCache.contains(package)) {
185
return m_sizeCache.value(package);
188
const QString image = package->filePath("preferred");
189
if (image.isEmpty()) {
193
KFileMetaInfo info(image, QString(), KFileMetaInfo::TechnicalInfo);
194
QSize size(info.item("http://freedesktop.org/standards/xesam/1.0/core#width").value().toInt(),
195
info.item("http://freedesktop.org/standards/xesam/1.0/core#height").value().toInt());
196
//backup solution if strigi does not work
197
if (size.width() == 0 || size.height() == 0) {
198
// kDebug() << "fall back to QImage, check your strigi";
199
ImageSizeFinder *finder = new ImageSizeFinder(image);
200
connect(finder, SIGNAL(sizeFound(QString,QSize)), this,
201
SLOT(sizeFound(QString,QSize)));
202
QThreadPool::globalInstance()->start(finder);
203
size = QSize(-1, -1);
206
const_cast<BackgroundListModel *>(this)->m_sizeCache.insert(package, size);
210
void BackgroundListModel::sizeFound(const QString &path, const QSize &s)
212
QModelIndex index = indexOf(path);
213
if (index.isValid()) {
214
Plasma::Package *package = m_packages.at(index.row());
215
m_sizeCache.insert(package, s);
216
static_cast<Image *>(m_structureParent)->updateScreenshot(index);
220
QVariant BackgroundListModel::data(const QModelIndex &index, int role) const
222
if (!index.isValid()) {
226
if (index.row() >= m_packages.size()) {
230
Plasma::Package *b = package(index.row());
236
case Qt::DisplayRole: {
237
QString title = b->metadata().name();
239
if (title.isEmpty()) {
240
return QFileInfo(b->filePath("preferred")).completeBaseName();
247
case BackgroundDelegate::ScreenshotRole: {
248
if (m_previews.contains(b)) {
249
return m_previews.value(b);
252
KUrl file(b->filePath("preferred"));
253
if (!m_previewJobs.contains(file) && file.isValid()) {
255
list.append(KFileItem(file, QString(), 0));
256
KIO::PreviewJob* job = KIO::filePreview(list,
257
QSize(BackgroundDelegate::SCREENSHOT_SIZE,
258
BackgroundDelegate::SCREENSHOT_SIZE/1.6));
259
job->setIgnoreMaximumSize(true);
260
connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
261
this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
262
connect(job, SIGNAL(failed(const KFileItem&)),
263
this, SLOT(previewFailed(const KFileItem&)));
264
const_cast<BackgroundListModel *>(this)->m_previewJobs.insert(file, QPersistentModelIndex(index));
267
const_cast<BackgroundListModel *>(this)->m_previews.insert(b, m_previewUnavailablePix);
268
return m_previewUnavailablePix;
272
case BackgroundDelegate::AuthorRole:
273
return b->metadata().author();
276
case BackgroundDelegate::ResolutionRole:{
277
QSize size = bestSize(b);
279
if (size.isValid()) {
280
return QString("%1x%2").arg(size.width()).arg(size.height());
293
void BackgroundListModel::showPreview(const KFileItem &item, const QPixmap &preview)
295
QPersistentModelIndex index = m_previewJobs.value(item.url());
296
m_previewJobs.remove(item.url());
298
if (!index.isValid()) {
302
Plasma::Package *b = package(index.row());
307
m_previews.insert(b, preview);
308
//kDebug() << "preview size:" << preview.size();
309
static_cast<Image *>(m_structureParent)->updateScreenshot(index);
312
void BackgroundListModel::previewFailed(const KFileItem &item)
314
m_previewJobs.remove(item.url());
317
Plasma::Package* BackgroundListModel::package(int index) const
319
return m_packages.at(index);
322
void BackgroundListModel::setWallpaperSize(const QSize& size)
327
void BackgroundListModel::setResizeMethod(Plasma::Wallpaper::ResizeMethod resizeMethod)
329
m_resizeMethod = resizeMethod;
332
BackgroundFinder::BackgroundFinder(Plasma::Wallpaper *structureParent, const QStringList &paths)
333
: QThread(structureParent),
334
m_structure(Plasma::Wallpaper::packageStructure(structureParent)),
336
m_token(QUuid().toString())
340
BackgroundFinder::~BackgroundFinder()
345
QString BackgroundFinder::token() const
350
void BackgroundFinder::run()
354
QSet<QString> suffixes;
355
suffixes << "png" << "jpeg" << "jpg" << "svg" << "svgz";
357
QStringList papersFound;
358
//kDebug() << "starting with" << m_paths;
361
dir.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::Readable);
362
Plasma::Package pkg(QString(), m_structure);
365
for (i = 0; i < m_paths.count(); ++i) {
366
const QString path = m_paths.at(i);
367
//kDebug() << "doing" << path;
369
const QFileInfoList files = dir.entryInfoList();
370
foreach (const QFileInfo &wp, files) {
372
//kDebug() << "directory" << wp.fileName() << validPackages.contains(wp.fileName());
373
const QString name = wp.fileName();
374
if (name == "." || name == "..") {
379
const QString filePath = wp.filePath();
380
if (QFile::exists(filePath + "/metadata.desktop")) {
381
pkg.setPath(filePath);
383
papersFound << pkg.path();
385
//kDebug() << "gots a" << wp.filePath();
389
// add this to the directories we should be looking at
390
m_paths.append(filePath);
391
} else if (suffixes.contains(wp.suffix().toLower())) {
392
//kDebug() << " adding image file" << wp.filePath();
393
papersFound << wp.filePath();
398
//kDebug() << "background found!" << papersFound.size() << "in" << i << "dirs, taking" << t.elapsed() << "ms";
399
emit backgroundsFound(papersFound, m_token);
403
#include "backgroundlistmodel.moc"
406
#endif // BACKGROUNDLISTMODEL_CPP