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

Plasma

backgroundpackage.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 version 2,
00006  *   or (at your option) any later version.
00007  *
00008  *   This program is distributed in the hope that it will be useful,
00009  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *   GNU General Public License for more details
00012  *
00013  *   You should have received a copy of the GNU Library General Public
00014  *   License along with this program; if not, write to the
00015  *   Free Software Foundation, Inc.,
00016  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00017  */
00018 
00019 #include "backgroundpackage.h"
00020 #include <cmath>
00021 // <cmath> does not define fabs (by the standard, even if it does with gcc)
00022 #include <math.h>
00023 #include <float.h> // FLT_MAX
00024 
00025 #include <QFileInfo>
00026 #include <QPainter>
00027 #include <KDebug>
00028 #include <KLocalizedString>
00029 #include <KStandardDirs>
00030 #include <KSvgRenderer>
00031 #include <plasma/packagestructure.h>
00032 #include <plasma/packagemetadata.h>
00033 #include <ThreadWeaver/Weaver>
00034 
00035 using namespace Plasma;
00036 
00037 class ResizeThread : public ThreadWeaver::Job
00038 {
00039 public:
00040     ResizeThread(const QString &path, float ratio, QObject *parent = 0);
00041     virtual ~ResizeThread();
00042     
00043     virtual void start(QPersistentModelIndex index);
00044     virtual void run();
00045     
00046     QImage result() const;
00047     QPersistentModelIndex index() const;
00048     bool isInitialized() const;
00049 private:
00050     QString m_path;
00051     QImage m_result;
00052     float m_ratio;
00053     QPersistentModelIndex m_index;
00054 };
00055 
00056 ResizeThread::ResizeThread(const QString &path, float ratio, QObject *parent)
00057 : ThreadWeaver::Job(parent)
00058 , m_path(path)
00059 , m_ratio(ratio)
00060 {
00061 }
00062 
00063 ResizeThread::~ResizeThread() {
00064 }
00065 
00066 void ResizeThread::start(QPersistentModelIndex index)
00067 {
00068     m_index = index;
00069     ThreadWeaver::Weaver::instance()->enqueue(this);
00070 }
00071 
00072 bool ResizeThread::isInitialized() const
00073 {
00074     return m_index.isValid();
00075 }
00076 
00077 void ResizeThread::run()
00078 {
00079     m_result = Background::createScreenshot(m_path, m_ratio);
00080 }
00081 
00082 QImage ResizeThread::result() const
00083 {
00084     if (isFinished()) {
00085         return m_result;
00086     }
00087     else {
00088         return QImage();
00089     }
00090 }
00091 
00092 QPersistentModelIndex ResizeThread::index() const
00093 {
00094     return m_index;
00095 }
00096 
00097 Background::~Background()
00098 {
00099 }
00100 
00101 QImage Background::createScreenshot(const QString &path, float ratio)
00102 {
00103     if (path.endsWith("svg") || path.endsWith("svgz")) {
00104         KSvgRenderer renderer(path);
00105         QImage img(QSize(int(SCREENSHOT_HEIGHT * ratio), SCREENSHOT_HEIGHT),
00106                    QImage::Format_ARGB32_Premultiplied);
00107         img.fill(0);
00108         QPainter p(&img);
00109         renderer.render(&p);
00110         return img;
00111     }
00112     else {
00113         QImage img(path);
00114         if (!img.isNull()) {
00115             return img.scaled(int(SCREENSHOT_HEIGHT * ratio), 
00116                             SCREENSHOT_HEIGHT,
00117                             Qt::KeepAspectRatio);
00118         }
00119         else {
00120             return defaultScreenshot();
00121         }
00122     }
00123 
00124 }
00125 
00126 QImage Background::defaultScreenshot()
00127 {
00128     static QImage defaultScreenshotImage;
00129     
00130     if (defaultScreenshotImage.isNull()) {
00131         QImage img(QSize(SCREENSHOT_HEIGHT, SCREENSHOT_HEIGHT), QImage::Format_ARGB32_Premultiplied);
00132         img.fill(Qt::white);
00133         QPainter p(&img);
00134         p.drawText(QRect(0, 0, SCREENSHOT_HEIGHT, SCREENSHOT_HEIGHT), 
00135                    Qt::AlignHCenter | Qt::AlignVCenter,
00136                    "Preview\nnot\navailable");
00137         defaultScreenshotImage = img;
00138     }
00139     return defaultScreenshotImage;
00140 }
00141 
00142 
00143 class BackgroundPackageStructure : public PackageStructure
00144 {
00145 public:
00146     static const PackageStructure::Ptr self();
00147 private:
00148     BackgroundPackageStructure(); // should be used as a singleton
00149     void addResolution(const char *res);
00150 };
00151 
00152 BackgroundPackageStructure::BackgroundPackageStructure()
00153 : PackageStructure(0, "Background")
00154 {
00155     QStringList mimetypes;
00156     mimetypes << "image/svg" << "image/png" << "image/jpeg" << "image/jpg";
00157     setDefaultMimetypes(mimetypes);
00158 
00159     addDirectoryDefinition("images", "images", i18n("Images"));
00160     addFileDefinition("screenshot", "screenshot.png", i18n("Screenshot"));
00161 }
00162 
00163 
00164 const PackageStructure::Ptr BackgroundPackageStructure::self()
00165 {
00166     static BackgroundPackageStructure::Ptr instance(0);
00167 
00168     if (!instance) {
00169         instance = new BackgroundPackageStructure;
00170     }
00171 
00172     return instance;
00173 }
00174 
00175 
00176 
00177 BackgroundPackage::BackgroundPackage(const QString &path, float ratio)
00178 : Package(path, BackgroundPackageStructure::self())
00179 , m_path(path)
00180 , m_ratio(ratio)
00181 {
00182 }
00183 
00184 QString BackgroundPackage::resString(const QSize &size) const
00185 {
00186     return QString::number(size.width()) + 'x' + QString::number(size.height());
00187 }
00188 
00189 QSize BackgroundPackage::resSize(const QString &str) const
00190 {
00191     int index = str.indexOf('x');
00192     if (index != -1) {
00193         return QSize(str.left(index).toInt(), 
00194                      str.mid(index + 1).toInt());
00195     }
00196     else {
00197         return QSize();
00198     }
00199 }
00200 
00201 QString BackgroundPackage::findBackground(const QSize &size, 
00202                                           ResizeMethod method) const
00203 {
00204     QStringList images = entryList("images");
00205     if (images.empty()) {
00206         return QString();
00207     }
00208     
00209     // choose the nearest resolution
00210     float best = FLT_MAX;
00211     QString bestImage;
00212     foreach (const QString &entry, images) {
00213         QSize candidate = resSize(QFileInfo(entry).baseName());
00214         if (candidate == QSize()) {
00215             continue;
00216         }
00217         
00218         double dist = distance(candidate, size, method);
00219         kDebug() << "candidate" << candidate << "distance" << dist;
00220         if (bestImage.isNull() || dist < best) {
00221             bestImage = filePath("images", entry);
00222             best = dist;
00223             kDebug() << "best" << bestImage;
00224             if (dist == 0) {
00225                 break;
00226             }
00227         }
00228     }
00229     
00230     kDebug() << "best image" << bestImage;
00231     return bestImage;
00232 }
00233 
00234 float BackgroundPackage::distance(const QSize& size,
00235                                    const QSize& desired,
00236                                    ResizeMethod method) const
00237 {
00238     // compute difference of areas
00239     float delta = size.width() * size.height() -
00240                   desired.width() * desired.height();
00241     // scale down to about 1.0
00242     delta /= 1000000.0;
00243     
00244     switch (method) {
00245     case Scale: {
00246         // Consider first the difference in aspect ratio,
00247         // then in areas. Prefer scaling down.
00248         float deltaRatio = size.width() / size.height() -
00249                            desired.width() / desired.height();
00250         return fabs(deltaRatio) * 3.0 + 
00251             (delta >= 0.0 ? delta : -delta + 5.0);
00252     }
00253     case ScaleCrop:
00254         // Difference of areas, slight preference to scale down
00255         return delta >= 0.0 ? delta : -delta + 2.0;
00256     case Center:
00257     default:
00258         // Difference in areas
00259         return fabs(delta);
00260     }
00261 }
00262 
00263 QPixmap BackgroundPackage::screenshot() const
00264 {
00265     if (m_screenshot.isNull()) {
00266         QString screenshotPath = filePath("screenshot");
00267         if (!screenshotPath.isEmpty()) {
00268             QImage img = createScreenshot(screenshotPath, m_ratio);
00269             m_screenshot = QPixmap::fromImage(img);
00270         }
00271     }
00272     
00273     return m_screenshot;
00274 }
00275 
00276 bool BackgroundPackage::screenshotGenerationStarted() const
00277 {
00278     return true;
00279 }
00280 
00281 void BackgroundPackage::generateScreenshot(QPersistentModelIndex) const
00282 {
00283 }
00284 
00285 QString BackgroundPackage::title() const
00286 {
00287     QString title = metadata()->name();
00288     if (title.isEmpty()) {
00289         title = metadata()->pluginName();
00290         title.replace("_", " ");
00291     }
00292     return title;
00293 }
00294 
00295 QString BackgroundPackage::author() const
00296 {
00297     return metadata()->author();
00298 }
00299 
00300 QString BackgroundPackage::email() const
00301 {
00302     return metadata()->email();
00303 }
00304 
00305 QString BackgroundPackage::license() const
00306 {
00307     return metadata()->license();
00308 }
00309 
00310 bool BackgroundPackage::isValid() const
00311 {
00312     return Package::isValid();
00313 }
00314 
00315 QString BackgroundPackage::path() const
00316 {
00317     return m_path;
00318 }
00319 
00320 
00321 BackgroundFile::BackgroundFile(const QString &file, float ratio)
00322 : m_file(file)
00323 , m_ratio(ratio)
00324 , m_resizer_started(false)
00325 {
00326 }
00327 
00328 BackgroundFile::~BackgroundFile()
00329 {
00330 }
00331 
00332 QString BackgroundFile::findBackground(const QSize &,
00333                                        ResizeMethod) const
00334 {
00335     return m_file;
00336 }
00337 
00338 QPixmap BackgroundFile::screenshot() const
00339 {
00340     return m_screenshot;
00341 }
00342 
00343 bool BackgroundFile::screenshotGenerationStarted() const
00344 {
00345     return m_resizer_started;
00346 }
00347 
00348 void BackgroundFile::generateScreenshot(QPersistentModelIndex index) const
00349 {
00350     ResizeThread *resizer = new ResizeThread(m_file, m_ratio);
00351     connect(resizer, SIGNAL(done(ThreadWeaver::Job *)),
00352             this, SLOT(updateScreenshot(ThreadWeaver::Job *)));
00353     m_resizer_started = true;
00354     resizer->start(index);
00355 }
00356 
00357 void BackgroundFile::updateScreenshot(ThreadWeaver::Job *job)
00358 {
00359     ResizeThread *resizer = static_cast<ResizeThread *>(job);
00360     m_screenshot = QPixmap::fromImage(resizer->result());
00361     emit screenshotDone(resizer->index());
00362     resizer->deleteLater();
00363 }
00364 
00365 QString BackgroundFile::author() const
00366 {
00367     return QString();
00368 }
00369 
00370 QString BackgroundFile::title() const
00371 {
00372     return QFileInfo(m_file).baseName();
00373 }
00374 
00375 QString BackgroundFile::email() const
00376 {
00377     return QString();
00378 }
00379 
00380 QString BackgroundFile::license() const
00381 {
00382     return QString();
00383 }
00384 
00385 bool BackgroundFile::isValid() const
00386 {
00387     return true;
00388 }
00389 
00390 QString BackgroundFile::path() const
00391 {
00392     return m_file;
00393 }

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
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
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