• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Plasma

backgroundlistmodel.cpp

Go to the documentation of this file.
00001 /*
00002   Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
00003 
00004   This program is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008 */
00009 
00010 #include "backgroundlistmodel.h"
00011 
00012 #include <QFile>
00013 #include <QDir>
00014 
00015 #include <KDebug>
00016 #include <KFileMetaInfo>
00017 #include <KGlobal>
00018 #include <KIO/PreviewJob>
00019 #include <KProgressDialog>
00020 #include <KStandardDirs>
00021 
00022 #include <Plasma/Package>
00023 #include <Plasma/PackageStructure>
00024 
00025 #include "backgrounddelegate.h"
00026 #include "image.h"
00027 
00028 BackgroundListModel::BackgroundListModel(float ratio, Plasma::Wallpaper *listener, QObject *parent)
00029     : QAbstractListModel(parent),
00030       m_listener(listener),
00031       m_structureParent(listener),
00032       m_ratio(ratio),
00033       m_size(0,0),
00034       m_resizeMethod(Plasma::Wallpaper::ScaledResize)
00035 {
00036     connect(&m_dirwatch, SIGNAL(deleted(QString)), this, SLOT(removeBackground(QString)));
00037 }
00038 
00039 BackgroundListModel::~BackgroundListModel()
00040 {
00041     qDeleteAll(m_packages);
00042 }
00043 
00044 void BackgroundListModel::removeBackground(const QString &path)
00045 {
00046     QModelIndex index;
00047     while ((index = indexOf(path)).isValid()) {
00048         beginRemoveRows(QModelIndex(), index.row(), index.row());
00049         Plasma::Package *package = m_packages.at(index.row());
00050         m_packages.removeAt(index.row());
00051         delete package;
00052         endRemoveRows();
00053     }
00054 }
00055 
00056 void BackgroundListModel::reload()
00057 {
00058     reload(QStringList());
00059 }
00060 
00061 void BackgroundListModel::reload(const QStringList &selected)
00062 {
00063     const QStringList dirs = KGlobal::dirs()->findDirs("wallpaper", "");
00064     QList<Plasma::Package *> tmp;
00065 
00066     if (!m_packages.isEmpty()) {
00067         beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1);
00068         qDeleteAll(m_packages);
00069         m_packages.clear();
00070         endRemoveRows();
00071     }
00072 
00073     foreach (const QString &file, selected) {
00074         if (!contains(file) && QFile::exists(file)) {
00075             tmp << new Plasma::Package(file, Plasma::Wallpaper::packageStructure(m_structureParent));
00076         }
00077     }
00078 
00079     {
00080         const QStringList backgrounds = findAllBackgrounds(m_structureParent, this, dirs);
00081         foreach (const QString &background, backgrounds) {
00082             tmp << new Plasma::Package(background, Plasma::Wallpaper::packageStructure(m_structureParent));
00083         }
00084     }
00085 
00086     // add new files to dirwatch
00087     foreach (Plasma::Package *b, tmp) {
00088         if (!m_dirwatch.contains(b->path())) {
00089             m_dirwatch.addFile(b->path());
00090         }
00091     }
00092 
00093     if (!tmp.isEmpty()) {
00094         beginInsertRows(QModelIndex(), 0, tmp.size() - 1);
00095         m_packages = tmp;
00096         endInsertRows();
00097     }
00098 }
00099 
00100 QStringList BackgroundFinder::papersFound() const
00101 {
00102     return m_papersFound;
00103 }
00104 
00105 void BackgroundListModel::addBackground(const QString& path)
00106 {
00107     if (!contains(path)) {
00108         if (!m_dirwatch.contains(path)) {
00109             m_dirwatch.addFile(path);
00110         }
00111         beginInsertRows(QModelIndex(), 0, 0);
00112         Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent);
00113         Plasma::Package *pkg = new Plasma::Package(path, structure);
00114         m_packages.prepend(pkg);
00115         endInsertRows();
00116     }
00117 }
00118 
00119 QModelIndex BackgroundListModel::indexOf(const QString &path) const
00120 {
00121     for (int i = 0; i < m_packages.size(); i++) {
00122         // packages will end with a '/', but the path passed in may not
00123         QString package = m_packages[i]->path();
00124         if (package.at(package.length() - 1) == '/') {
00125             package.truncate(package.length() - 1);
00126         }
00127 
00128         if (path.startsWith(package)) {
00129             // FIXME: ugly hack to make a difference between local files in the same dir
00130             // package->path does not contain the actual file name
00131             if ((!m_packages[i]->structure()->contentsPrefix().isEmpty()) ||
00132                 (path == m_packages[i]->filePath("preferred"))) {
00133                 return index(i, 0);
00134             }
00135         }
00136     }
00137     return QModelIndex();
00138 }
00139 
00140 bool BackgroundListModel::contains(const QString &path) const
00141 {
00142     return indexOf(path).isValid();
00143 }
00144 
00145 int BackgroundListModel::rowCount(const QModelIndex &) const
00146 {
00147     return m_packages.size();
00148 }
00149 
00150 QSize BackgroundListModel::bestSize(Plasma::Package *package) const
00151 {
00152     if (m_sizeCache.contains(package)) {
00153         return m_sizeCache.value(package);
00154     }
00155 
00156     const QString image = package->filePath("preferred");
00157     if (image.isEmpty()) {
00158         return QSize();
00159     }
00160 
00161     KFileMetaInfo info(image, QString(), KFileMetaInfo::TechnicalInfo);
00162     QSize size(info.item("http://freedesktop.org/standards/xesam/1.0/core#width").value().toInt(),
00163                info.item("http://freedesktop.org/standards/xesam/1.0/core#height").value().toInt());
00164 
00165     //backup solution if strigi does not work
00166     if (size.width() == 0 || size.height() == 0) {
00167         kDebug() << "fall back to QImage, check your strigi";
00168         size = QImage(image).size();
00169     }
00170 
00171     const_cast<BackgroundListModel *>(this)->m_sizeCache.insert(package, size);
00172     return size;
00173 }
00174 
00175 QVariant BackgroundListModel::data(const QModelIndex &index, int role) const
00176 {
00177     if (!index.isValid()) {
00178         return QVariant();
00179     }
00180 
00181     if (index.row() >= m_packages.size()) {
00182         return QVariant();
00183     }
00184 
00185     Plasma::Package *b = package(index.row());
00186     if (!b) {
00187         return QVariant();
00188     }
00189 
00190     switch (role) {
00191     case Qt::DisplayRole: {
00192         QString title = b->metadata().name();
00193 
00194         if (title.isEmpty()) {
00195             return QFileInfo(b->filePath("preferred")).completeBaseName();
00196         }
00197 
00198         return title;
00199     }
00200     break;
00201 
00202     case BackgroundDelegate::ScreenshotRole: {
00203         if (m_previews.contains(b)) {
00204             return m_previews.value(b);
00205         }
00206 
00207         KUrl file(b->filePath("preferred"));
00208 
00209         if (file.isValid()) {
00210             KIO::PreviewJob* job = KIO::filePreview(KUrl::List() << file,
00211                                                     BackgroundDelegate::SCREENSHOT_SIZE,
00212                                                     BackgroundDelegate::SCREENSHOT_SIZE);
00213 
00214             connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
00215                     this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
00216             connect(job, SIGNAL(failed(const KFileItem&)),
00217                     this, SLOT(previewFailed(const KFileItem&)));
00218             const_cast<BackgroundListModel *>(this)->m_previewJobs.insert(file, QPersistentModelIndex(index));
00219         }
00220 
00221         QPixmap pix(BackgroundDelegate::SCREENSHOT_SIZE, BackgroundDelegate::SCREENSHOT_SIZE);
00222         pix.fill(Qt::transparent);
00223         const_cast<BackgroundListModel *>(this)->m_previews.insert(b, pix);
00224         return pix;
00225     }
00226     break;
00227 
00228     case BackgroundDelegate::AuthorRole:
00229         return b->metadata().author();
00230     break;
00231 
00232     case BackgroundDelegate::ResolutionRole:{
00233         QSize size = bestSize(b);
00234 
00235         if (size.isValid()) {
00236             return QString("%1x%2").arg(size.width()).arg(size.height());
00237         }
00238 
00239         return QString();
00240     }
00241     break;
00242 
00243     default:
00244         return QVariant();
00245     break;
00246     }
00247 }
00248 
00249 void BackgroundListModel::showPreview(const KFileItem &item, const QPixmap &preview)
00250 {
00251     QPersistentModelIndex index = m_previewJobs.value(item.url());
00252     m_previewJobs.remove(item.url());
00253 
00254     if (!index.isValid()) {
00255         return;
00256     }
00257 
00258     Plasma::Package *b = package(index.row());
00259     if (!b) {
00260         return;
00261     }
00262 
00263     m_previews.insert(b, preview);
00264     static_cast<Image*>(m_listener)->updateScreenshot(index);
00265 }
00266 
00267 void BackgroundListModel::previewFailed(const KFileItem &item)
00268 {
00269     m_previewJobs.remove(item.url());
00270 }
00271 
00272 Plasma::Package* BackgroundListModel::package(int index) const
00273 {
00274     return m_packages.at(index);
00275 }
00276 
00277 QStringList BackgroundListModel::findAllBackgrounds(Plasma::Wallpaper *structureParent,
00278                                                     const BackgroundListModel *container,
00279                                                     const QStringList &p)
00280 {
00281     //TODO: put this in a thread so that it can run in the background without blocking
00282     QEventLoop localEventLoop;
00283     BackgroundFinder finder(structureParent, container, p, &localEventLoop);
00284     connect(&finder, SIGNAL(finished()), &localEventLoop, SLOT(quit()));
00285     QTimer::singleShot(0, &finder, SLOT(start()));
00286     localEventLoop.exec();
00287     return finder.papersFound();
00288 }
00289 
00290 BackgroundFinder::BackgroundFinder(Plasma::Wallpaper *structureParent,
00291                                    const BackgroundListModel *container,
00292                                    const QStringList &paths,
00293                                    QEventLoop *eventLoop)
00294     : QObject(0),
00295       m_structureParent(structureParent),
00296       m_container(container),
00297       m_paths(paths),
00298       m_eventLoop(eventLoop)
00299 {
00300 }
00301 
00302 void BackgroundFinder::start()
00303 {
00304     KProgressDialog *progress = new KProgressDialog;
00305     progress->setAllowCancel(false);
00306     progress->setModal(true);
00307     progress->setLabelText(i18n("Finding images for the wallpaper slideshow."));
00308     progress->progressBar()->setRange(0, 0);
00309 
00310     QSet<QString> suffixes;
00311     suffixes << "png" << "jpeg" << "jpg" << "svg" << "svgz";
00312 
00313     QDir dir;
00314     dir.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::Readable);
00315 
00316     int count = 0;
00317     int allCount = 0;
00318     bool setLabel = true;
00319     while (!m_paths.isEmpty()) {
00320         QString path = m_paths.takeLast();
00321         //kDebug() << "doing" << path;
00322         dir.setPath(path);
00323         const QFileInfoList files = dir.entryInfoList();
00324         foreach (const QFileInfo &wp, files) {
00325             if (wp.isDir()) {
00326                 //kDebug() << "directory" << wp.fileName() << validPackages.contains(wp.fileName());
00327                 QString name = wp.fileName();
00328                 if (name == "." || name == "..") {
00329                     // do nothing
00330                 } else if(QFile::exists(wp.filePath() + "/metadata.desktop")) {
00331                     Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent);
00332                     Plasma::Package pkg(wp.filePath(), structure);
00333 
00334                     if (pkg.isValid() && (!m_container || !m_container->contains(pkg.path()))) {
00335                         if (setLabel) {
00336                             progress->setLabelText(i18n("Finding images for the wallpaper slideshow.") + "\n\n" +
00337                                                    i18n("Adding wallpaper package in %1", name));
00338                         }
00339 
00340                         ++count;
00341                         m_papersFound << pkg.path();
00342                         //kDebug() << "gots a" << wp.filePath();
00343                     } else {
00344                         m_paths.append(wp.filePath());
00345                     }
00346                 } else {
00347                     m_paths.append(wp.filePath());
00348                 }
00349             } else if (suffixes.contains(wp.suffix().toLower()) && (!m_container || !m_container->contains(wp.filePath()))) {
00350                 //kDebug() << "adding" << wp.filePath() << setLabel;
00351                 if (setLabel) {
00352                     progress->setLabelText(i18n("Finding images for the wallpaper slideshow.") + "\n\n" +
00353                                            i18n("Adding image %1", wp.filePath()));
00354                     setLabel = false;
00355                 }
00356                 //kDebug() << "     adding image file" << wp.filePath();
00357                 ++count;
00358                 m_papersFound << wp.filePath();
00359             }
00360 
00361             ++allCount;
00362             if (allCount % 10 == 0) {
00363                 m_eventLoop->processEvents(QEventLoop::ExcludeUserInputEvents);
00364                 if (progress->isVisible() && count % 10) {
00365                     setLabel = true;
00366                 }
00367             }
00368         }
00369     }
00370 
00371     delete progress;
00372     emit finished();
00373 }
00374 
00375 void BackgroundListModel::setWallpaperSize(QSize size)
00376 {
00377     m_size = size;
00378 }
00379 
00380 void BackgroundListModel::setResizeMethod(Plasma::Wallpaper::ResizeMethod resizeMethod)
00381 {
00382     m_resizeMethod = resizeMethod;
00383 }
00384 
00385 #include "backgroundlistmodel.moc"
00386 
00387 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •     Animators
  •     Applets
  •     Engines
  • Solid Modules
  • System Settings
  •   SystemSettingsView
Generated for API Reference by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal