Verified Commit f106e61c authored by Fushan Wen's avatar Fushan Wen 💬
Browse files

wallpapers/image: add dark wallpaper support for KPackage wallpapers

Dark wallpapers are put in contents/images_dark folder. The dark
wallpaper will be used when system color scheme is dark.

FEATURE: 207976
FIXED-IN: 5.26
parent 51cab794
Pipeline #199803 canceled with stage
in 47 seconds
......@@ -83,6 +83,8 @@ QQC2.StackView {
slideshowMode: wallpaper.configuration.SlideshowMode
slideshowFoldersFirst: wallpaper.configuration.SlideshowFoldersFirst
uncheckedSlides: wallpaper.configuration.UncheckedSlides
onColorSchemeChanged: Qt.callLater(loadImage);
}
onFillModeChanged: Qt.callLater(loadImage);
......
......@@ -28,7 +28,10 @@ void ImageFinder::run()
dir.setNameFilters(suffixes());
const auto filterCondition = [](const QFileInfo &info) {
return info.baseName() != QLatin1String("screenshot") && !info.absoluteFilePath().contains(QLatin1String("contents/images/"));
const QString path = info.absoluteFilePath();
return info.baseName() != QLatin1String("screenshot") && !path.contains(QLatin1String("contents/images/"))
&& !path.contains(QLatin1String("contents/images_dark/"));
};
int i;
......
......@@ -117,12 +117,12 @@ void PackageFinder::findPreferredImageInPackage(KPackage::Package &package, cons
}
// find preferred size
QString preferred;
{
const QStringList images = package.entryList("images");
auto findBestMatch = [&package, &tSize](const QByteArray &folder) {
QString preferred;
const QStringList images = package.entryList(folder);
if (images.empty()) {
return;
return preferred;
}
float best = std::numeric_limits<float>::max();
......@@ -141,10 +141,24 @@ void PackageFinder::findPreferredImageInPackage(KPackage::Package &package, cons
best = dist;
}
}
}
return preferred;
};
package.addDirectoryDefinition(QByteArrayLiteral("images_dark"), QStringLiteral("images_dark"), QStringLiteral("Dark Images"));
const QString preferred = findBestMatch(QByteArrayLiteral("images"));
const QString preferredDark = findBestMatch(QByteArrayLiteral("images_dark"));
package.removeDefinition("preferred");
package.addFileDefinition("preferred", QStringLiteral("images/") + preferred, i18n("Recommended wallpaper file"));
if (!preferredDark.isEmpty()) {
package.removeDefinition("preferredDark");
package.addFileDefinition("preferredDark",
QStringLiteral("images_dark%1").arg(QDir::separator()) + preferredDark,
QStringLiteral("Recommended dark wallpaper file"));
}
}
QString PackageFinder::packageDisplayName(const KPackage::Package &b)
......
......@@ -40,6 +40,7 @@ ImageBackend::ImageBackend(QObject *parent)
: QObject(parent)
, m_targetSize(qGuiApp->primaryScreen()->size() * qGuiApp->primaryScreen()->devicePixelRatio())
, m_slideFilterModel(new SlideFilterModel(this))
, m_isDarkColorScheme(isDarkColorScheme())
{
connect(&m_timer, &QTimer::timeout, this, &ImageBackend::nextSlide);
......@@ -62,6 +63,9 @@ void ImageBackend::componentComplete()
// to load the proper one afterwards etc etc
m_ready = true;
// Follow system color scheme
connect(qGuiApp, &QGuiApplication::paletteChanged, this, &ImageBackend::slotSystemPaletteChanged);
if (m_mode == SingleImage) {
setSingleImage();
} else if (m_mode == SlideShow) {
......@@ -250,6 +254,15 @@ SlideModel *ImageBackend::slideshowModel()
return m_slideshowModel;
}
bool ImageBackend::isDarkColorScheme(const QPalette &palette) const noexcept
{
// 192 is from kcm_colors
if (palette == QPalette()) {
return qGray(qGuiApp->palette().window().color().rgb()) < 192;
}
return qGray(palette.window().color().rgb()) < 192;
}
QAbstractItemModel *ImageBackend::slideFilterModel()
{
if (!m_slideFilterModel->sourceModel()) {
......@@ -469,6 +482,24 @@ void ImageBackend::backgroundsFound()
nextSlide();
}
void ImageBackend::slotSystemPaletteChanged(const QPalette &palette)
{
if (m_providerType != Provider::Package || m_usedInConfig) {
// Currently only KPackage supports adaptive wallpapers
return;
}
const bool dark = isDarkColorScheme(palette);
if (dark == m_isDarkColorScheme) {
return;
}
m_isDarkColorScheme = dark;
Q_EMIT colorSchemeChanged();
}
void ImageBackend::showFileDialog()
{
if (!m_dialog) {
......@@ -628,6 +659,14 @@ void ImageBackend::openModelImage() const
PackageFinder::findPreferredImageInPackage(package, m_targetSize);
url = QUrl::fromLocalFile(package.filePath("preferred"));
if (isDarkColorScheme()) {
const QUrl darkUrl = package.fileUrl("preferredDark");
if (!darkUrl.isEmpty()) {
url = darkUrl;
}
}
break;
}
}
......
......@@ -11,6 +11,7 @@
#pragma once
#include <QAbstractItemModel>
#include <QPalette>
#include <QQmlParserStatus>
#include <QSize>
#include <QTimer>
......@@ -142,6 +143,12 @@ Q_SIGNALS:
void uncheckedSlidesChanged();
void loadingChanged();
/**
* Emitted when system color scheme changes. The frontend is required to
* reload the wallpaper even if the image path is not changed.
*/
void colorSchemeChanged();
protected Q_SLOTS:
void showAddSlidePathsDialog();
void slotWallpaperBrowseCompleted();
......@@ -149,12 +156,22 @@ protected Q_SLOTS:
void addDirFromSelectionDialog();
void backgroundsFound();
/**
* Switches to dark-colored wallpaper if available when system color
* scheme is dark.
*
* @since 5.26
*/
void slotSystemPaletteChanged(const QPalette &palette);
protected:
void setSingleImage();
private:
SlideModel *slideshowModel();
inline bool isDarkColorScheme(const QPalette &palette = {}) const noexcept;
bool m_ready = false;
int m_delay = 10;
QUrl m_image;
......@@ -177,4 +194,6 @@ private:
SlideModel *m_slideshowModel = nullptr;
SlideFilterModel *m_slideFilterModel;
QFileDialog *m_dialog = nullptr;
bool m_isDarkColorScheme;
};
......@@ -6,7 +6,9 @@
#include "packageimageprovider.h"
#include <QGuiApplication>
#include <QImageReader>
#include <QPalette>
#include <QUrlQuery>
#include <KPackage/PackageLoader>
......@@ -75,7 +77,17 @@ void AsyncPackageImageResponseRunnable::run()
PackageFinder::findPreferredImageInPackage(package, m_requestedSize);
QImage image(package.filePath("preferred"));
QString path = package.filePath("preferred");
// 192 is from kcm_colors
if (qGray(qGuiApp->palette().window().color().rgb()) < 192) {
QString darkPath = package.filePath("preferredDark");
if (!darkPath.isEmpty()) {
path = darkPath;
}
}
QImage image(path);
if (!image.isNull() && m_requestedSize.isValid()) {
image = image.scaled(m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment