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