00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "wallpaper.h"
00022
00023 #include <QColor>
00024 #include <QFile>
00025 #include <QFileInfo>
00026 #include <QImage>
00027
00028 #include <kdebug.h>
00029 #include <kglobal.h>
00030 #include <kservicetypetrader.h>
00031 #include <kstandarddirs.h>
00032
00033 #include <kio/job.h>
00034
00035 #include <version.h>
00036
00037 #include "plasma/private/dataengineconsumer_p.h"
00038 #include "plasma/private/packages_p.h"
00039 #include "plasma/private/wallpaper_p.h"
00040
00041 namespace Plasma
00042 {
00043
00044 WallpaperRenderThread WallpaperPrivate::s_renderer;
00045 PackageStructure::Ptr WallpaperPrivate::s_packageStructure(0);
00046
00047 Wallpaper::Wallpaper(QObject * parentObject)
00048 : d(new WallpaperPrivate(KService::serviceByStorageId(QString()), this))
00049 {
00050 setParent(parentObject);
00051 connect(&WallpaperPrivate::s_renderer, SIGNAL(done(int,QImage,QString,QSize,int,QColor)),
00052 this, SLOT(renderCompleted(int,QImage,QString,QSize,int,QColor)));
00053 }
00054
00055 Wallpaper::Wallpaper(QObject *parentObject, const QVariantList &args)
00056 : d(new WallpaperPrivate(KService::serviceByStorageId(args.count() > 0 ?
00057 args[0].toString() : QString()), this))
00058 {
00059
00060
00061
00062 QVariantList &mutableArgs = const_cast<QVariantList &>(args);
00063 if (!mutableArgs.isEmpty()) {
00064 mutableArgs.removeFirst();
00065 }
00066
00067 setParent(parentObject);
00068 connect(&WallpaperPrivate::s_renderer, SIGNAL(done(int,QImage,QString,QSize,int,QColor)),
00069 this, SLOT(renderCompleted(int,QImage,QString,QSize,int,QColor)));
00070 }
00071
00072 Wallpaper::~Wallpaper()
00073 {
00074 delete d;
00075 }
00076
00077 KPluginInfo::List Wallpaper::listWallpaperInfo(const QString &formFactor)
00078 {
00079 QString constraint;
00080
00081 if (!formFactor.isEmpty()) {
00082 constraint.append("[X-Plasma-FormFactors] ~~ '").append(formFactor).append("'");
00083 }
00084
00085 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Wallpaper", constraint);
00086 return KPluginInfo::fromServices(offers);
00087 }
00088
00089 Wallpaper *Wallpaper::load(const QString &wallpaperName, const QVariantList &args)
00090 {
00091 if (wallpaperName.isEmpty()) {
00092 return 0;
00093 }
00094
00095 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(wallpaperName);
00096 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Wallpaper", constraint);
00097
00098 if (offers.isEmpty()) {
00099 kDebug() << "offers is empty for " << wallpaperName;
00100 return 0;
00101 }
00102
00103 KService::Ptr offer = offers.first();
00104 KPluginLoader plugin(*offer);
00105
00106 if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
00107 return 0;
00108 }
00109
00110 QVariantList allArgs;
00111 allArgs << offer->storageId() << args;
00112 QString error;
00113 Wallpaper *wallpaper = offer->createInstance<Plasma::Wallpaper>(0, allArgs, &error);
00114
00115 if (!wallpaper) {
00116 kDebug() << "Couldn't load wallpaper \"" << wallpaperName << "\"! reason given: " << error;
00117 }
00118
00119 return wallpaper;
00120 }
00121
00122 Wallpaper *Wallpaper::load(const KPluginInfo &info, const QVariantList &args)
00123 {
00124 if (!info.isValid()) {
00125 return 0;
00126 }
00127 return load(info.pluginName(), args);
00128 }
00129
00130 PackageStructure::Ptr Wallpaper::packageStructure(Wallpaper *paper)
00131 {
00132 if (paper) {
00133 PackageStructure::Ptr package(new WallpaperPackage(paper));
00134 return package;
00135 }
00136
00137 if (!WallpaperPrivate::s_packageStructure) {
00138 WallpaperPrivate::s_packageStructure = new WallpaperPackage();
00139 }
00140
00141 return WallpaperPrivate::s_packageStructure;
00142 }
00143
00144 QString Wallpaper::name() const
00145 {
00146 if (!d->wallpaperDescription.isValid()) {
00147 return i18n("Unknown Wallpaper");
00148 }
00149
00150 return d->wallpaperDescription.name();
00151 }
00152
00153 QString Wallpaper::icon() const
00154 {
00155 if (!d->wallpaperDescription.isValid()) {
00156 return QString();
00157 }
00158
00159 return d->wallpaperDescription.icon();
00160 }
00161
00162 QString Wallpaper::pluginName() const
00163 {
00164 if (!d->wallpaperDescription.isValid()) {
00165 return QString();
00166 }
00167
00168 return d->wallpaperDescription.pluginName();
00169 }
00170
00171 KServiceAction Wallpaper::renderingMode() const
00172 {
00173 return d->mode;
00174 }
00175
00176 QList<KServiceAction> Wallpaper::listRenderingModes() const
00177 {
00178 if (!d->wallpaperDescription.isValid()) {
00179 return QList<KServiceAction>();
00180 }
00181
00182 return d->wallpaperDescription.service()->actions();
00183 }
00184
00185 QRectF Wallpaper::boundingRect() const
00186 {
00187 return d->boundingRect;
00188 }
00189
00190 bool Wallpaper::isInitialized() const
00191 {
00192 return d->initialized;
00193 }
00194
00195 void Wallpaper::setBoundingRect(const QRectF &boundingRect)
00196 {
00197 QSizeF oldBoundingRectSize = d->boundingRect.size();
00198 d->boundingRect = boundingRect;
00199
00200 if (!d->targetSize.isValid() || d->targetSize == oldBoundingRectSize) {
00201 d->targetSize = boundingRect.size();
00202 emit renderHintsChanged();
00203 }
00204 }
00205
00206 void Wallpaper::setRenderingMode(const QString &mode)
00207 {
00208 if (d->mode.name() == mode) {
00209 return;
00210 }
00211
00212 d->mode = KServiceAction();
00213 if (!mode.isEmpty()) {
00214 QList<KServiceAction> modes = listRenderingModes();
00215
00216 foreach (const KServiceAction &action, modes) {
00217 if (action.name() == mode) {
00218 d->mode = action;
00219 break;
00220 }
00221 }
00222 }
00223 }
00224
00225 void Wallpaper::restore(const KConfigGroup &config)
00226 {
00227 init(config);
00228 d->initialized = true;
00229 }
00230
00231 void Wallpaper::init(const KConfigGroup &config)
00232 {
00233 Q_UNUSED(config);
00234 }
00235
00236 void Wallpaper::save(KConfigGroup &config)
00237 {
00238 Q_UNUSED(config);
00239 }
00240
00241 QWidget *Wallpaper::createConfigurationInterface(QWidget *parent)
00242 {
00243 Q_UNUSED(parent);
00244 return 0;
00245 }
00246
00247 void Wallpaper::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00248 {
00249 Q_UNUSED(event)
00250 }
00251
00252 void Wallpaper::mousePressEvent(QGraphicsSceneMouseEvent *event)
00253 {
00254 Q_UNUSED(event)
00255 }
00256
00257 void Wallpaper::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00258 {
00259 Q_UNUSED(event)
00260 }
00261
00262 void Wallpaper::wheelEvent(QGraphicsSceneWheelEvent *event)
00263 {
00264 Q_UNUSED(event)
00265 }
00266
00267 DataEngine *Wallpaper::dataEngine(const QString &name) const
00268 {
00269 return d->dataEngine(name);
00270 }
00271
00272 bool Wallpaper::configurationRequired() const
00273 {
00274 return d->needsConfig;
00275 }
00276
00277 void Wallpaper::setConfigurationRequired(bool needsConfig, const QString &reason)
00278 {
00279
00280
00281 Q_UNUSED(reason)
00282
00283 if (d->needsConfig == needsConfig) {
00284 return;
00285 }
00286
00287 d->needsConfig = needsConfig;
00288 emit configurationRequired(needsConfig);
00289 }
00290
00291 bool Wallpaper::isUsingRenderingCache() const
00292 {
00293 return d->cacheRendering;
00294 }
00295
00296 void Wallpaper::setUsingRenderingCache(bool useCache)
00297 {
00298 d->cacheRendering = useCache;
00299 }
00300
00301 void Wallpaper::setResizeMethodHint(Wallpaper::ResizeMethod resizeMethod)
00302 {
00303 d->lastResizeMethod = resizeMethod;
00304 emit renderHintsChanged();
00305 }
00306
00307 void Wallpaper::setTargetSizeHint(const QSizeF &targetSize)
00308 {
00309 d->targetSize = targetSize;
00310 emit renderHintsChanged();
00311 }
00312
00313 void Wallpaper::render(const QString &sourceImagePath, const QSize &size,
00314 Wallpaper::ResizeMethod resizeMethod, const QColor &color)
00315 {
00316 if (sourceImagePath.isEmpty() || !QFile::exists(sourceImagePath)) {
00317
00318 return;
00319 }
00320
00321 if (d->lastResizeMethod != resizeMethod) {
00322 d->lastResizeMethod = resizeMethod;
00323 emit renderHintsChanged();
00324 }
00325
00326 if (d->cacheRendering) {
00327 QFileInfo info(sourceImagePath);
00328 QString cache = d->cacheKey(sourceImagePath, size, resizeMethod, color);
00329 QImage img;
00330 if (findInCache(cache, img, info.lastModified().toTime_t())) {
00331 emit renderCompleted(img);
00332 return;
00333 }
00334 }
00335
00336 d->renderToken = WallpaperPrivate::s_renderer.render(sourceImagePath, size, resizeMethod, color);
00337
00338 }
00339
00340 QString WallpaperPrivate::cacheKey(const QString &sourceImagePath, const QSize &size,
00341 int resizeMethod, const QColor &color) const
00342 {
00343 const QString id = QString("%5_%3_%4_%1x%2")
00344 .arg(size.width()).arg(size.height()).arg(color.name())
00345 .arg(resizeMethod).arg(sourceImagePath);
00346 return id;
00347 }
00348
00349 QString WallpaperPrivate::cachePath(const QString &key) const
00350 {
00351 return KGlobal::dirs()->locateLocal("cache", "plasma-wallpapers/" + key + ".png");
00352 }
00353
00354 void WallpaperPrivate::renderCompleted(int token, const QImage &image,
00355 const QString &sourceImagePath, const QSize &size,
00356 int resizeMethod, const QColor &color)
00357 {
00358 if (token != renderToken) {
00359
00360 return;
00361 }
00362
00363 if (cacheRendering) {
00364 q->insertIntoCache(cacheKey(sourceImagePath, size, resizeMethod, color), image);
00365 }
00366
00367
00368 emit q->renderCompleted(image);
00369 }
00370
00371 bool Wallpaper::findInCache(const QString &key, QImage &image, unsigned int lastModified)
00372 {
00373 if (d->cacheRendering) {
00374 QString cache = d->cachePath(key);
00375 if (QFile::exists(cache)) {
00376 if (lastModified > 0) {
00377 QFileInfo info(cache);
00378 if (info.lastModified().toTime_t() < lastModified) {
00379 return false;
00380 }
00381 }
00382
00383 image.load(cache);
00384 return true;
00385 }
00386 }
00387
00388 return false;
00389 }
00390
00391 void Wallpaper::insertIntoCache(const QString& key, const QImage &image)
00392 {
00393
00394 if (key.isEmpty()) {
00395 return;
00396 }
00397
00398 if (d->cacheRendering) {
00399 if (image.isNull()) {
00400 KIO::file_delete(d->cachePath(key));
00401 } else {
00402 image.save(d->cachePath(key));
00403 }
00404 }
00405 }
00406
00407 }
00408
00409 #include "wallpaper.moc"