From fa846c54baa100cb3122f27eefa32b4ac7f937d4 Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Tue, 7 Apr 2009 05:43:44 +0000 Subject: [PATCH] make the wallpaper packages a bit smarter svn path=/trunk/KDE/kdelibs/; revision=950409 --- private/packages.cpp | 133 +++++++++++++++++++++++++++++++++++++++++-- private/packages_p.h | 24 +++++++- 2 files changed, 148 insertions(+), 9 deletions(-) diff --git a/private/packages.cpp b/private/packages.cpp index 0115390e6..8ebc6cf1a 100644 --- a/private/packages.cpp +++ b/private/packages.cpp @@ -1,5 +1,5 @@ /****************************************************************************** -* Copyright 2007 by Aaron Seigo * +* Copyright 2007-2009 by Aaron Seigo * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * @@ -17,7 +17,12 @@ * Boston, MA 02110-1301, USA. * *******************************************************************************/ -#include "private/packages_p.h" +#include "plasma/private/packages_p.h" + +#include +#include // FLT_MAX + +#include #include #include @@ -26,13 +31,15 @@ #include +#include "plasma/private/wallpaper_p.h" + namespace Plasma { PlasmoidPackage::PlasmoidPackage(QObject *parent) : Plasma::PackageStructure(parent, QString("Plasmoid")) { - addDirectoryDefinition("images", "images", i18n("Images")); + addDirectoryDefinition("images", "images/", i18n("Images")); QStringList mimetypes; mimetypes << "image/svg+xml" << "image/png" << "image/jpeg"; setMimetypes("images", mimetypes); @@ -154,16 +161,130 @@ ThemePackage::ThemePackage(QObject *parent) setDefaultMimetypes(mimetypes); } -WallpaperPackage::WallpaperPackage(QObject *parent) - : PackageStructure(parent, "Background") +WallpaperPackage::WallpaperPackage(Wallpaper *paper, QObject *parent) + : PackageStructure(parent, "Background"), + m_paper(paper) { QStringList mimetypes; mimetypes << "image/svg" << "image/png" << "image/jpeg" << "image/jpg"; setDefaultMimetypes(mimetypes); - addDirectoryDefinition("images", "images", i18n("Images")); + addDirectoryDefinition("images", "images/", i18n("Images")); addFileDefinition("screenshot", "screenshot.png", i18n("Screenshot")); setAllowExternalPaths(true); + + if (m_paper) { + connect(m_paper, SIGNAL(destroyed(QObject*)), this, SLOT(paperDestroyed())); + } +} + +void WallpaperPackage::pathChanged() +{ + static bool guard = false; + + if (guard) { + return; + } + + guard = true; + + QFileInfo info(path()); + + if (info.isDir()) { + findBestPaper(); + } else { + // dirty trick to support having a file passed in instead of a directory + addFileDefinition("preferred", info.fileName(), i18n("Recommended wallpaper file")); + setContentsPrefix(QString()); + kDebug() << "changing" << path() << "to" << info.path(); + setPath(info.path()); + } + + guard = false; +} + +QSize WallpaperPackage::resSize(const QString &str) const +{ + int index = str.indexOf('x'); + if (index != -1) { + return QSize(str.left(index).toInt(), + str.mid(index + 1).toInt()); + } else { + return QSize(); + } +} + +void WallpaperPackage::findBestPaper() +{ + QStringList images = entryList("images"); + if (images.empty()) { + return; + } + + //kDebug() << "wanted" << size; + + // choose the nearest resolution + float best = FLT_MAX; + const QSize size = m_paper ? m_paper->boundingRect().size().toSize() : QSize(100000, 100000); + const Wallpaper::ResizeMethod method = m_paper ? m_paper->d->lastResizeMethod + : Wallpaper::ScaledResize; + + QString bestImage; + foreach (const QString &entry, images) { + QSize candidate = resSize(QFileInfo(entry).baseName()); + if (candidate == QSize()) { + continue; + } + + double dist = distance(candidate, size, method); + //kDebug() << "candidate" << candidate << "distance" << dist; + if (bestImage.isEmpty() || dist < best) { + bestImage = entry; + best = dist; + //kDebug() << "best" << bestImage; + if (dist == 0) { + break; + } + } + } + + //kDebug() << "best image" << bestImage; + addFileDefinition("preferred", path("images") + bestImage, i18n("Recommended wallpaper file")); +} + +float WallpaperPackage::distance(const QSize& size, const QSize& desired, + Plasma::Wallpaper::ResizeMethod method) const +{ + // compute difference of areas + float delta = size.width() * size.height() - + desired.width() * desired.height(); + // scale down to about 1.0 + delta /= ((desired.width() * desired.height())+(size.width() * size.height()))/2; + + + switch (method) { + case Plasma::Wallpaper::ScaledResize: { + // Consider first the difference in aspect ratio, + // then in areas. Prefer scaling down. + float deltaRatio = 1.0; + if (size.height() > 0 && desired.height() > 0) { + deltaRatio = float(size.width()) / float(size.height()) - + float(desired.width()) / float(desired.height()); + } + return fabs(deltaRatio) * 3.0 + (delta >= 0.0 ? delta : -delta + 5.0); + } + case Plasma::Wallpaper::ScaledAndCroppedResize: + // Difference of areas, slight preference to scale down + return delta >= 0.0 ? delta : -delta + 2.0; + default: + // Difference in areas + return fabs(delta); + } +} + +void WallpaperPackage::paperDestroyed() +{ + m_paper = 0; } } // namespace Plasma diff --git a/private/packages_p.h b/private/packages_p.h index bd4da7442..746c7c9e1 100644 --- a/private/packages_p.h +++ b/private/packages_p.h @@ -20,12 +20,15 @@ #ifndef LIBS_PLASMA_PACKAGES_P_H #define LIBS_PLASMA_PACKAGES_P_H -#include -#include "plasma.h" +#include "plasma/packagestructure.h" +#include "plasma/wallpaper.h" +#include "plasma/plasma.h" namespace Plasma { +class Wallpaper; + class PlasmoidPackage : public PackageStructure { Q_OBJECT @@ -49,7 +52,22 @@ class WallpaperPackage : public PackageStructure Q_OBJECT public: - explicit WallpaperPackage(QObject *parent = 0); + explicit WallpaperPackage(Wallpaper *paper = 0, QObject *parent = 0); + +protected: + void pathChanged(); + +private: + QSize resSize(const QString &str) const; + void findBestPaper(); + float distance(const QSize& size, const QSize& desired, + Plasma::Wallpaper::ResizeMethod method) const; + +private Q_SLOTS: + void paperDestroyed(); + +private: + Wallpaper *m_paper; }; PackageStructure::Ptr defaultPackageStructure(ComponentType type);