Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/plugin-qt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
# SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later

add_subdirectory("thememanager")
add_subdirectory("wallpapercache")
add_subdirectory("wallpaperslideshow")
add_subdirectory("xsettings")
67 changes: 67 additions & 0 deletions src/plugin-qt/wallpapercache/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later

cmake_minimum_required(VERSION 3.16)

set(PLUGIN_NAME "plugin-qt-wallpapercache")

project(${PLUGIN_NAME})

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

include(GNUInstallDirs)
file(GLOB_RECURSE SRCS "*.h" "*.cpp")

find_package(PkgConfig REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui DBus)
pkg_check_modules(DtkCore REQUIRED dtk6core)
pkg_check_modules(DtkGui REQUIRED dtk6gui)

add_library(${PLUGIN_NAME} MODULE
${SRCS}
)

target_include_directories(${PLUGIN_NAME} PRIVATE
${DtkCore_INCLUDE_DIRS}
${DtkGui_INCLUDE_DIRS}
)

target_link_libraries(${PLUGIN_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::DBus
${DtkCore_LIBRARIES}
${DtkGui_LIBRARIES}
)

target_compile_options(${PLUGIN_NAME} PRIVATE
${DtkCore_CFLAGS_OTHER}
${DtkGui_CFLAGS_OTHER}
)

set(MISC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/misc)

install(TARGETS ${PLUGIN_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/deepin-service-manager/)
# Plugin descriptor for deepin-service-manager (system bus)
install(FILES ${MISC_DIR}/plugin-qt-wallpapercache.json DESTINATION share/deepin-service-manager/system/)
# D-Bus access control policy files
install(FILES
${MISC_DIR}/org.deepin.dde.WallpaperCache.conf
${MISC_DIR}/org.deepin.dde.ImageEffect1.conf
${MISC_DIR}/org.deepin.dde.ImageBlur1.conf
DESTINATION share/dbus-1/system.d/
)
# D-Bus activation service files (required for on-demand activation)
install(FILES
${MISC_DIR}/org.deepin.dde.WallpaperCache.service
${MISC_DIR}/org.deepin.dde.ImageEffect1.service
${MISC_DIR}/org.deepin.dde.ImageBlur1.service
DESTINATION share/dbus-1/system-services/
)
# systemd drop-in override (User, CacheDirectory, sandbox settings)
install(FILES
${MISC_DIR}/deepin-service-plugin@org.deepin.dde.WallpaperCache.service.d/override.conf
DESTINATION lib/systemd/system/deepin-service-plugin@org.deepin.dde.WallpaperCache.service.d/
)
247 changes: 247 additions & 0 deletions src/plugin-qt/wallpapercache/cachedwallpaper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "cachedwallpaper.h"
#include "scaleimagethread.h"
#include "imageeffectprocessor.h"

#include <QDebug>

Check warning on line 9 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDir>

Check warning on line 10 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFile>

Check warning on line 11 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFile> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QCryptographicHash>

Check warning on line 12 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QCryptographicHash> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFileInfo>

Check warning on line 13 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFileInfo> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDateTime>

Check warning on line 14 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDateTime> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QImageReader>

Check warning on line 15 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QImageReader> not found. Please note: Cppcheck does not need standard library headers to get proper results.

CachedWallpaper::CachedWallpaper()
{
QDir().mkpath(kBlurCacheDir);
}

CachedWallpaper::~CachedWallpaper()
{
m_cachedImages.clear();
}

CachedWallpaper *CachedWallpaper::instance()
{
static CachedWallpaper cachedWallpaper;
return &cachedWallpaper;
}

QStringList CachedWallpaper::getCachedImagePaths(const QString &originalPath, const QList<QSize> &sizes, bool isMd5Path)
{
QList<QSize> noCachedSizes;
QStringList results;

QString pathMd5 = ScaleImageThread::pathMd5(originalPath, isMd5Path);

if (m_cachedImages.contains(pathMd5)) {
const QMap<QString, QString> &map = m_cachedImages[pathMd5];
for (const QSize &size : sizes) {
QString strSize = ScaleImageThread::sizeToString(size);
if (map.contains(strSize)) {
results.append(map[strSize]);
} else {
noCachedSizes.append(size);
}
}
} else {
noCachedSizes = sizes;
}

if (!noCachedSizes.isEmpty()) {
qDebug() << "need handle image:" << originalPath << " sizes:" << noCachedSizes;
Q_EMIT needHandleImage(originalPath, noCachedSizes, isMd5Path);
}

return results;
}

void CachedWallpaper::cacheImage(const QString &originalPathMd5, const QString &size, const QString &processedPath)
{
qDebug() << "cache Image:" << processedPath;
m_cachedImages[originalPathMd5].insert(size, processedPath);
}

QString CachedWallpaper::getBlurImagePath(const QString &originalPath)
{
QString pathMd5 = QCryptographicHash::hash(originalPath.toUtf8(), QCryptographicHash::Md5).toHex();

QMutexLocker locker(&m_blurGenerateMutex);

auto it = m_blurImageCache.constFind(pathMd5);
if (it != m_blurImageCache.constEnd() && QFile::exists(it.value())) {
return it.value();
}

QString blurPath = generateBlurImage(pathMd5, originalPath);
if (!blurPath.isEmpty()) {
cacheBlurImage(pathMd5, blurPath);
return blurPath;
}

return QString();
}

void CachedWallpaper::cacheBlurImage(const QString &originalPathMd5, const QString &blurPath)
{
qDebug() << "cache blur image:" << blurPath;
m_blurImageCache[originalPathMd5] = blurPath;
}

QStringList CachedWallpaper::getProcessedImageWithBlur(const QString &originalPath, const QList<QSize> &sizes, bool needBlur)

Check warning on line 94 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getProcessedImageWithBlur' is never used.
{
QString sourcePath = originalPath;

if (needBlur) {
QString blurPath = getBlurImagePath(originalPath);
if (!blurPath.isEmpty()) {
sourcePath = blurPath;
}
}

QStringList results = getCachedImagePaths(sourcePath, sizes);
if (!results.isEmpty()) {
return results;
}

return QStringList() << sourcePath;
}

QString CachedWallpaper::blurOutputPath(const QString &pathMd5, const QString &originalPath)
{
QFileInfo fi(originalPath);
QString suffix = fi.suffix();
return QString("%1/%2%3").arg(kBlurCacheDir, pathMd5, suffix.isEmpty() ? "" : "." + suffix);
}

QString CachedWallpaper::generateBlurImage(const QString &pathMd5, const QString &originalPath)
{
QFileInfo originalFileInfo(originalPath);
QString outputFile = blurOutputPath(pathMd5, originalPath);

// Return cached file if up-to-date
QFileInfo outputFileInfo(outputFile);
if (outputFileInfo.exists()
&& outputFileInfo.lastModified() >= originalFileInfo.lastModified()
&& outputFileInfo.size() > 0) {
qDebug() << "Blur image already exists and up-to-date:" << outputFile;
return outputFile;
}

qDebug() << "Generating blur image:" << originalPath << "=>" << outputFile;

QImage blurredImage = ImageEffectProcessor::applyPixmixEffect(originalPath);
if (blurredImage.isNull()) {
qWarning() << "Failed to generate blur image:" << originalPath;
return QString();
}

if (!blurredImage.save(outputFile, QImageReader::imageFormat(originalPath), 100)) {
qWarning() << "Failed to save blur image:" << outputFile;
return QString();
}

// Match output mtime to input for cache freshness check
QFile timeFile(outputFile);
if (timeFile.open(QIODevice::ReadWrite)) {
timeFile.setFileTime(originalFileInfo.lastModified(), QFileDevice::FileModificationTime);
timeFile.close();
}

qDebug() << "Successfully generated blur image:" << outputFile;
return outputFile;
}

QStringList CachedWallpaper::getWallpaperListForScreen(const QString &originalPath, const QList<QSize> &sizes, bool needBlur)

Check warning on line 158 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getWallpaperListForScreen' is never used.
{
if (needBlur) {
QString blurPath = getBlurImagePath(originalPath);
if (!blurPath.isEmpty()) {
QStringList results = getCachedImagePaths(blurPath, sizes);
if (!results.isEmpty()) {
return results;
}
return QStringList() << blurPath;
}
qWarning() << "Blur processing failed for:" << originalPath << ", fallback to original";
}

QStringList results = getCachedImagePaths(originalPath, sizes);
if (!results.isEmpty()) {
return results;
}

return QStringList() << originalPath;
}

bool CachedWallpaper::deleteBlurImage(const QString &originalPath)
{
QString pathMd5 = QCryptographicHash::hash(originalPath.toUtf8(), QCryptographicHash::Md5).toHex();

auto it = m_blurImageCache.find(pathMd5);
if (it != m_blurImageCache.end()) {
QString blurPath = it.value();
m_blurImageCache.erase(it);
if (QFile::remove(blurPath)) {
qDebug() << "Deleted blur image:" << blurPath;
return true;
}
qWarning() << "Failed to delete blur image file:" << blurPath;
return false;
}

// Try to delete on-disk file even if not in memory cache
QString outputFile = blurOutputPath(pathMd5, originalPath);
if (QFile::remove(outputFile)) {
qDebug() << "Deleted blur image file:" << outputFile;
}
return true;
}

void CachedWallpaper::clearBlurCache()
{
m_blurImageCache.clear();

QDir cacheDir(kBlurCacheDir);
if (!cacheDir.exists()) {
return;
}

QFileInfoList files = cacheDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
int deletedCount = 0;
for (const QFileInfo &fileInfo : files) {
if (QFile::remove(fileInfo.absoluteFilePath())) {
deletedCount++;
} else {
qWarning() << "Failed to delete blur cache file:" << fileInfo.absoluteFilePath();
}
}
qDebug() << "Cleared blur cache, deleted" << deletedCount << "files";
}

bool CachedWallpaper::deleteEffectImage(const QString &originalPath, const QString &effect)

Check warning on line 225 in src/plugin-qt/wallpapercache/cachedwallpaper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'deleteEffectImage' is never used.
{
if (effect.isEmpty() || effect == "pixmix") {
return deleteBlurImage(originalPath);
}
qWarning() << "Unsupported effect for deletion:" << effect;
return false;
}

void CachedWallpaper::clearEffectCache(const QString &effect)
{
if (effect == "all") {
clearBlurCache();
return;
}

QString effectName = effect.isEmpty() ? "pixmix" : effect;
if (effectName == "pixmix") {
clearBlurCache();
} else {
qWarning() << "Unsupported effect for cache clearing:" << effectName;
}
}
61 changes: 61 additions & 0 deletions src/plugin-qt/wallpapercache/cachedwallpaper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef CACHED_WALLPAPER_H
#define CACHED_WALLPAPER_H

#include <QObject>
#include <QString>
#include <QMap>
#include <QSize>
#include <QMutex>

// Shared cache path constants
inline const QString kWallpaperCacheDir = QStringLiteral("/var/cache/dde-wallpaper-cache");
inline const QString kBlurCacheDir = kWallpaperCacheDir + QStringLiteral("/blur");

class CachedWallpaper : public QObject
{
Q_OBJECT

private:
explicit CachedWallpaper();
~CachedWallpaper();

signals:
void needHandleImage(const QString &originalPath, const QList<QSize> &size, bool isMd5Path);

public:
static CachedWallpaper *instance();
QStringList getCachedImagePaths(const QString &originalPath, const QList<QSize> &sizes, bool isMd5Path = false);
void cacheImage(const QString &originalPathMd5, const QString &size, const QString &processedPath);

// Blur wallpaper interfaces
QString getBlurImagePath(const QString &originalPath);
QStringList getProcessedImageWithBlur(const QString &originalPath, const QList<QSize> &sizes, bool needBlur = false);

// Unified wallpaper processing interface
QStringList getWallpaperListForScreen(const QString &originalPath, const QList<QSize> &sizes, bool needBlur = true);

// Blur image management interfaces
bool deleteBlurImage(const QString &originalPath);
bool deleteEffectImage(const QString &originalPath, const QString &effect);
void clearBlurCache();
void clearEffectCache(const QString &effect);

static QString blurOutputPath(const QString &pathMd5, const QString &originalPath);

private:
QString generateBlurImage(const QString &pathMd5, const QString &originalPath);
void cacheBlurImage(const QString &originalPathMd5, const QString &blurPath);

private:
// originalPath's md5; sizeToString;processedWallpaperPath
QMap<QString, QMap<QString, QString>> m_cachedImages;
// 模糊壁纸缓存: originalPath's md5; blurImagePath
QMap<QString, QString> m_blurImageCache;
QMutex m_blurGenerateMutex;
};

#endif // CACHED_WALLPAPER_H
Loading
Loading