23 #include "config-plasma.h"
33 #include <QThreadPool>
37 #include <kservicetypetrader.h>
38 #include <kstandarddirs.h>
47 #include "plasma/private/dataengineconsumer_p.h"
48 #include "plasma/private/packages_p.h"
49 #include "plasma/private/wallpaper_p.h"
54 class SaveImageThread :
public QRunnable
60 SaveImageThread(
const QImage &image,
const QString &filePath)
63 m_filePath = filePath;
68 m_image.save(m_filePath);
72 LoadImageThread::LoadImageThread(
const QString &filePath)
74 m_filePath = filePath;
77 void LoadImageThread::run()
80 image.load(m_filePath);
84 class WallpaperWithPaint :
public Wallpaper
87 WallpaperWithPaint(
QObject *parent,
const QVariantList &args)
92 virtual void paint(QPainter *painter,
const QRectF &exposedRect)
95 d->script->paint(painter, exposedRect);
103 : d(new WallpaperPrivate(KService::serviceByStorageId(QString()), this))
105 setParent(parentObject);
109 : d(new WallpaperPrivate(KService::serviceByStorageId(args.count() > 0 ?
110 args[0].
toString() : QString()), this))
115 QVariantList &mutableArgs =
const_cast<QVariantList &
>(args);
116 if (!mutableArgs.isEmpty()) {
117 mutableArgs.removeFirst();
120 setParent(parentObject);
131 d->script->setUrls(urls);
134 foreach (
const KUrl &url, urls) {
142 if (!d->initialized) {
143 d->pendingUrls = urls;
144 }
else if (d->script) {
145 d->script->setUrls(urls);
147 QMetaObject::invokeMethod(
this,
"addUrls", Q_ARG(KUrl::List, urls));
154 if (!formFactor.isEmpty()) {
155 constraint.append(
"[X-Plasma-FormFactors] ~~ '").append(formFactor).append(
"'");
158 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Wallpaper", constraint);
159 return KPluginInfo::fromServices(offers);
164 QString constraint = QString(
"'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
165 if (!formFactor.isEmpty()) {
166 constraint.append(
"[X-Plasma-FormFactors] ~~ '").append(formFactor).append(
"'");
169 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Wallpaper", constraint);
170 kDebug() << offers.count() << constraint;
171 return KPluginInfo::fromServices(offers);
176 return d->wallpaperDescription.isValid() &&
177 d->wallpaperDescription.service()->hasMimeType(mimetype);
182 if (wallpaperName.isEmpty()) {
186 QString constraint = QString(
"[X-KDE-PluginInfo-Name] == '%1'").arg(wallpaperName);
187 KService::List offers = KServiceTypeTrader::self()->query(
"Plasma/Wallpaper", constraint);
189 if (offers.isEmpty()) {
190 kDebug() <<
"offers is empty for " << wallpaperName;
194 KService::Ptr offer = offers.first();
195 QVariantList allArgs;
196 allArgs << offer->storageId() << args;
198 if (!offer->property(
"X-Plasma-API").toString().isEmpty()) {
199 kDebug() <<
"we have a script using the"
200 << offer->property(
"X-Plasma-API").toString() <<
"API";
204 KPluginLoader plugin(*offer);
214 kDebug() <<
"Couldn't load wallpaper \"" << wallpaperName <<
"\"! reason given: " << error;
222 if (!info.isValid()) {
225 return load(info.pluginName(), args);
235 if (!WallpaperPrivate::s_packageStructure) {
236 WallpaperPrivate::s_packageStructure =
new WallpaperPackage();
239 return WallpaperPrivate::s_packageStructure;
244 if (!d->wallpaperDescription.isValid()) {
245 return i18n(
"Unknown Wallpaper");
248 return d->wallpaperDescription.name();
253 if (!d->wallpaperDescription.isValid()) {
257 return d->wallpaperDescription.icon();
262 if (!d->wallpaperDescription.isValid()) {
266 return d->wallpaperDescription.pluginName();
276 if (!d->wallpaperDescription.isValid()) {
277 return QList<KServiceAction>();
280 return d->wallpaperDescription.service()->actions();
285 return d->boundingRect;
290 return d->initialized;
297 if (d->targetSize != boundingRect.size()) {
298 d->targetSize = boundingRect.size();
305 if (d->mode.name() == mode) {
309 d->mode = KServiceAction();
310 if (!mode.isEmpty()) {
313 foreach (
const KServiceAction &action, modes) {
314 if (action.name() == mode) {
325 d->initialized =
true;
326 if (!d->pendingUrls.isEmpty()) {
328 d->pendingUrls.clear();
336 d->script->initWallpaper(config);
343 d->script->save(config);
350 return d->script->createConfigurationInterface(parent);
359 return d->script->mouseMoveEvent(event);
366 return d->script->mousePressEvent(event);
373 return d->script->mouseReleaseEvent(event);
380 return d->script->wheelEvent(event);
386 return d->dataEngine(name);
391 return d->needsConfig;
400 if (d->needsConfig == needsConfig) {
404 d->needsConfig = needsConfig;
410 return d->cacheRendering;
415 d->cacheRendering = useCache;
421 if (method != d->lastResizeMethod) {
422 d->lastResizeMethod = method;
429 return d->lastResizeMethod;
434 if (targetSize != d->targetSize) {
442 return d->targetSize;
448 if (image.isNull()) {
452 d->renderWallpaper(QString(), image, size, resizeMethod, color);
458 if (sourceImagePath.isEmpty() || !QFile::exists(sourceImagePath)) {
463 d->renderWallpaper(sourceImagePath, QImage(), size, resizeMethod, color);
466 void WallpaperPrivate::renderWallpaper(
const QString &sourceImagePath,
const QImage &image,
const QSize &size,
470 if (lastResizeMethod != resizeMethod) {
471 lastResizeMethod = resizeMethod;
472 emit q->renderHintsChanged();
475 if (cacheRendering) {
476 QFileInfo info(sourceImagePath);
477 QString cache = cacheKey(sourceImagePath, size, resizeMethod, color);
478 if (findInCache(cache, info.lastModified().toTime_t())) {
483 WallpaperRenderRequest request;
484 renderToken = request.token;
485 request.requester = q;
486 request.providedImage = image;
487 request.file = sourceImagePath;
489 request.resizeMethod = resizeMethod;
490 request.color = color;
491 WallpaperRenderThread::render(request);
495 WallpaperPrivate::WallpaperPrivate(KService::Ptr service, Wallpaper *wallpaper) :
497 wallpaperDescription(service),
500 lastResizeMethod(Wallpaper::ScaledResize),
502 cacheRendering(false),
505 scriptInitialized(false),
507 needsPreviewDuringConfiguration(false)
509 if (wallpaperDescription.isValid()) {
510 QString api = wallpaperDescription.property(
"X-Plasma-API").toString();
512 if (!api.isEmpty()) {
513 const QString path = KStandardDirs::locate(
"data",
514 "plasma/wallpapers/" + wallpaperDescription.pluginName() +
'/');
517 structure->setPath(path);
518 package = new Package(path, structure);
522 kDebug() <<
"Could not create a" << api <<
"ScriptEngine for the"
523 << wallpaperDescription.name() <<
"Wallpaper.";
531 QString WallpaperPrivate::cacheKey(
const QString &sourceImagePath,
const QSize &size,
532 int resizeMethod,
const QColor &color)
const
534 const QString
id = QString(
"%5_%3_%4_%1x%2")
535 .arg(size.width()).arg(size.height()).arg(color.name())
536 .arg(resizeMethod).arg(sourceImagePath);
540 QString WallpaperPrivate::cachePath(
const QString &key)
const
542 return KGlobal::dirs()->locateLocal(
"cache",
"plasma-wallpapers/" + key +
".png");
545 void WallpaperPrivate::newRenderCompleted(
const WallpaperRenderRequest &request,
const QImage &image)
547 kDebug() << request.token << renderToken;
548 if (request.token != renderToken) {
553 if (cacheRendering) {
554 q->insertIntoCache(cacheKey(request.file, request.size, request.resizeMethod, request.color), image);
558 emit q->renderCompleted(image);
563 void WallpaperPrivate::setupScriptSupport()
566 kDebug() <<
"setting up script support, package is in" <<
package->
path()
571 if (!translationsPath.isEmpty()) {
574 KGlobal::dirs()->addResourceDir(
"locale", translationsPath);
579 void WallpaperPrivate::initScript()
581 if (script && !scriptInitialized) {
582 setupScriptSupport();
584 scriptInitialized =
true;
588 bool WallpaperPrivate::findInCache(
const QString &key,
unsigned int lastModified)
590 if (cacheRendering) {
591 QString cache = cachePath(key);
592 if (QFile::exists(cache)) {
593 if (lastModified > 0) {
594 QFileInfo info(cache);
595 if (info.lastModified().toTime_t() < lastModified) {
600 LoadImageThread *loadImageT =
new LoadImageThread(cache);
601 q->connect(loadImageT, SIGNAL(done(QImage)), q, SIGNAL(
renderCompleted(QImage)));
602 QThreadPool::globalInstance()->start(loadImageT);
613 if (d->cacheRendering) {
614 QString cache = d->cachePath(key);
615 if (QFile::exists(cache)) {
616 if (lastModified > 0) {
617 QFileInfo info(cache);
618 if (info.lastModified().toTime_t() < lastModified) {
638 if (d->cacheRendering) {
639 if (image.isNull()) {
640 #ifndef PLASMA_NO_KIO
641 KIO::file_delete(d->cachePath(key));
643 QFile f(d->cachePath(key));
647 QThreadPool::globalInstance()->start(
new SaveImageThread(image, d->cachePath(key)));
664 return d->previewing;
674 return d->needsPreviewDuringConfiguration;
679 d->needsPreviewDuringConfiguration = preview;
689 #include "wallpaper.moc"
690 #include "private/wallpaper_p.moc"