• Skip to content
  • Skip to link menu
KDE 4.2 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>
00032 #include <Plasma/PackageMetadata>
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     BackgroundPackageStructure(QObject *parent = 0);
00147 private:
00148     void addResolution(const char *res);
00149 };
00150 
00151 BackgroundPackageStructure::BackgroundPackageStructure(QObject *parent)
00152     : PackageStructure(parent, "Background")
00153 {
00154     QStringList mimetypes;
00155     mimetypes << "image/svg" << "image/png" << "image/jpeg" << "image/jpg";
00156     setDefaultMimetypes(mimetypes);
00157 
00158     addDirectoryDefinition("images", "images", i18n("Images"));
00159     addFileDefinition("screenshot", "screenshot.png", i18n("Screenshot"));
00160     setAllowExternalPaths(true);
00161 }
00162 
00163 
00164 
00165 BackgroundPackage::BackgroundPackage(const QString &path, float ratio)
00166     : Package(path, KSharedPtr<Plasma::PackageStructure>(new BackgroundPackageStructure(this))),
00167       m_path(path),
00168       m_ratio(ratio)
00169 {
00170 }
00171 
00172 QString BackgroundPackage::resString(const QSize &size) const
00173 {
00174     return QString::number(size.width()) + 'x' + QString::number(size.height());
00175 }
00176 
00177 QSize BackgroundPackage::resSize(const QString &str) const
00178 {
00179     int index = str.indexOf('x');
00180     if (index != -1) {
00181         return QSize(str.left(index).toInt(),
00182                      str.mid(index + 1).toInt());
00183     }
00184     else {
00185         return QSize();
00186     }
00187 }
00188 
00189 QString BackgroundPackage::findBackground(const QSize &size,
00190                                           ResizeMethod method) const
00191 {
00192     QStringList images = entryList("images");
00193     if (images.empty()) {
00194         return QString();
00195     }
00196 
00197     //kDebug() << "wanted" << size;
00198 
00199     // choose the nearest resolution
00200     float best = FLT_MAX;
00201     QString bestImage;
00202     foreach (const QString &entry, images) {
00203         QSize candidate = resSize(QFileInfo(entry).baseName());
00204         if (candidate == QSize()) {
00205             continue;
00206         }
00207 
00208         double dist = distance(candidate, size, method);
00209         //kDebug() << "candidate" << candidate << "distance" << dist;
00210         if (bestImage.isNull() || dist < best) {
00211             bestImage = filePath("images", entry);
00212             best = dist;
00213             //kDebug() << "best" << bestImage;
00214             if (dist == 0) {
00215                 break;
00216             }
00217         }
00218     }
00219 
00220     //kDebug() << "best image" << bestImage;
00221     return bestImage;
00222 }
00223 
00224 float BackgroundPackage::distance(const QSize& size,
00225                                    const QSize& desired,
00226                                    ResizeMethod method) const
00227 {
00228     // compute difference of areas
00229     float delta = size.width() * size.height() -
00230                   desired.width() * desired.height();
00231     // scale down to about 1.0
00232     delta /= ((desired.width() * desired.height())+(size.width() * size.height()))/2;
00233 
00234 
00235     switch (method) {
00236     case Scale: {
00237         // Consider first the difference in aspect ratio,
00238         // then in areas. Prefer scaling down.
00239         float deltaRatio = 1.0;
00240         if (size.height() > 0 && desired.height() > 0) {
00241             deltaRatio = float(size.width()) / float(size.height()) -
00242                          float(desired.width()) / float(desired.height());
00243         }
00244         return fabs(deltaRatio) * 3.0 + (delta >= 0.0 ? delta : -delta + 5.0);
00245     }
00246     case ScaleCrop:
00247         // Difference of areas, slight preference to scale down
00248         return delta >= 0.0 ? delta : -delta + 2.0;
00249     case Center:
00250     default:
00251         // Difference in areas
00252         return fabs(delta);
00253     }
00254 }
00255 
00256 QPixmap BackgroundPackage::screenshot() const
00257 {
00258     if (m_screenshot.isNull()) {
00259         QString screenshotPath = filePath("screenshot");
00260         if (!screenshotPath.isEmpty()) {
00261             QImage img = createScreenshot(screenshotPath, m_ratio);
00262             m_screenshot = QPixmap::fromImage(img);
00263         }
00264     }
00265 
00266     return m_screenshot;
00267 }
00268 
00269 bool BackgroundPackage::screenshotGenerationStarted() const
00270 {
00271     return true;
00272 }
00273 
00274 void BackgroundPackage::generateScreenshot(QPersistentModelIndex) const
00275 {
00276 }
00277 
00278 QString BackgroundPackage::title() const
00279 {
00280     Plasma::PackageMetadata md = metadata();
00281     QString title = md.name();
00282     if (title.isEmpty()) {
00283         title = md.pluginName();
00284         title.replace("_", " ");
00285     }
00286     return title;
00287 }
00288 
00289 QString BackgroundPackage::author() const
00290 {
00291     return metadata().author();
00292 }
00293 
00294 QString BackgroundPackage::email() const
00295 {
00296     return metadata().email();
00297 }
00298 
00299 QString BackgroundPackage::license() const
00300 {
00301     return metadata().license();
00302 }
00303 
00304 bool BackgroundPackage::isValid() const
00305 {
00306     return Package::isValid();
00307 }
00308 
00309 QString BackgroundPackage::path() const
00310 {
00311     return m_path;
00312 }
00313 
00314 
00315 BackgroundFile::BackgroundFile(const QString &file, float ratio)
00316 : m_file(file)
00317 , m_ratio(ratio)
00318 , m_resizer_started(false)
00319 {
00320 }
00321 
00322 BackgroundFile::~BackgroundFile()
00323 {
00324 }
00325 
00326 QString BackgroundFile::findBackground(const QSize &,
00327                                        ResizeMethod) const
00328 {
00329     return m_file;
00330 }
00331 
00332 QPixmap BackgroundFile::screenshot() const
00333 {
00334     return m_screenshot;
00335 }
00336 
00337 bool BackgroundFile::screenshotGenerationStarted() const
00338 {
00339     return m_resizer_started;
00340 }
00341 
00342 void BackgroundFile::generateScreenshot(QPersistentModelIndex index) const
00343 {
00344     ResizeThread *resizer = new ResizeThread(m_file, m_ratio);
00345     connect(resizer, SIGNAL(done(ThreadWeaver::Job *)),
00346             this, SLOT(updateScreenshot(ThreadWeaver::Job *)));
00347     m_resizer_started = true;
00348     resizer->start(index);
00349 }
00350 
00351 void BackgroundFile::updateScreenshot(ThreadWeaver::Job *job)
00352 {
00353     ResizeThread *resizer = static_cast<ResizeThread *>(job);
00354     m_screenshot = QPixmap::fromImage(resizer->result());
00355     emit screenshotDone(resizer->index());
00356     resizer->deleteLater();
00357 }
00358 
00359 //TODO: impl
00360 QString BackgroundFile::author() const
00361 {
00362     return QString();
00363 }
00364 
00365 QString BackgroundFile::title() const
00366 {
00367     return QFileInfo(m_file).completeBaseName();
00368 }
00369 
00370 //TODO: impl
00371 QString BackgroundFile::email() const
00372 {
00373     return QString();
00374 }
00375 
00376 //TODO: impl
00377 QString BackgroundFile::license() const
00378 {
00379     return QString();
00380 }
00381 
00382 //TODO: impl
00383 bool BackgroundFile::isValid() const
00384 {
00385     return true;
00386 }
00387 
00388 QString BackgroundFile::path() const
00389 {
00390     return m_file;
00391 }

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
Generated for API Reference by doxygen 1.5.7
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