feat: defer preview command until states are captured

This commit is contained in:
2026-03-01 05:08:58 +01:00
parent 1e9c175dd5
commit bf2f3d57c7
11 changed files with 232 additions and 187 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ qt_add_qml_module(${CORELIB_NAME}
Config/data.hpp Config/data.hpp
Config/manager.hpp Config/manager.cpp Config/manager.hpp Config/manager.cpp
logger.hpp logger.cpp logger.hpp logger.cpp
Service/manager.hpp Service/manager.hpp Service/manager.cpp
Service/wallpaper.hpp Service/wallpaper.cpp Service/wallpaper.hpp Service/wallpaper.cpp
appoptions.hpp appoptions.cpp appoptions.hpp appoptions.cpp
) )
+1
View File
@@ -141,6 +141,7 @@ struct StyleConfigItems {
struct CacheConfigItems { struct CacheConfigItems {
bool saveSortMethod = true; bool saveSortMethod = true;
bool savePalette = true; bool savePalette = true;
int maxImageEntries = 1000;
static const QString defaultSortType; static const QString defaultSortType;
static const QString defaultSortDescending; static const QString defaultSortDescending;
+10
View File
@@ -28,6 +28,11 @@ Manager::Manager(
const QString& configPath, const QString& configPath,
QObject* parent) QObject* parent)
: QObject(parent), m_configDir(configDir) { : QObject(parent), m_configDir(configDir) {
connect(this, &Manager::stateCaptured, this, [this]() {
m_stateCaptured = true;
WR_INFO("State capture completed");
});
// Load configPath if not empty, otherwise load from default location (configDir + s_DefaultConfigFileName) // Load configPath if not empty, otherwise load from default location (configDir + s_DefaultConfigFileName)
if (configPath.isEmpty()) { if (configPath.isEmpty()) {
WR_INFO(QString("Configuration directory: %1").arg(m_configDir.absolutePath())); WR_INFO(QString("Configuration directory: %1").arg(m_configDir.absolutePath()));
@@ -384,6 +389,11 @@ void Manager::_loadWallpapers() {
} }
void Manager::captureState() { void Manager::captureState() {
if (m_stateCaptured) {
WR_DEBUG("State already captured, skipping capture");
emit stateCaptured();
}
if (m_pendingCaptures > 0) { if (m_pendingCaptures > 0) {
WR_WARN("State capture already in progress, ignoring new capture request"); WR_WARN("State capture already in progress, ignoring new capture request");
return; return;
+3
View File
@@ -59,6 +59,8 @@ class Manager : public QObject {
const CacheConfigItems& getCacheConfig() const { return m_cacheConfig; } const CacheConfigItems& getCacheConfig() const { return m_cacheConfig; }
bool isStateCaptured() const { return m_stateCaptured; }
QSize getFocusImageSize() const { QSize getFocusImageSize() const {
return QSize{m_styleConfig.imageWidth, m_styleConfig.imageHeight} * m_styleConfig.imageFocusScale; return QSize{m_styleConfig.imageWidth, m_styleConfig.imageHeight} * m_styleConfig.imageFocusScale;
} }
@@ -95,6 +97,7 @@ class Manager : public QObject {
QStringList m_wallpapers; QStringList m_wallpapers;
int m_pendingCaptures = 0; int m_pendingCaptures = 0;
bool m_stateCaptured = false; // changed and accessed in main thread, no lock needed
}; };
} // namespace WallReel::Core::Config } // namespace WallReel::Core::Config
+1
View File
@@ -25,6 +25,7 @@ WallReel::Core::Image::Data::Data(const QString& path, const QSize& targetSize,
m_id = cacheMgr.cacheKey(m_file, m_targetSize); m_id = cacheMgr.cacheKey(m_file, m_targetSize);
m_cachedFile = cacheMgr.getImage(m_id, [this]() { return computeImage(); }); m_cachedFile = cacheMgr.getImage(m_id, [this]() { return computeImage(); });
m_dominantColor = cacheMgr.getColor(m_id, [this]() { return computeDominantColor(loadImage()); }); m_dominantColor = cacheMgr.getColor(m_id, [this]() { return computeDominantColor(loadImage()); });
m_isValid = m_cachedFile.isFile() && m_dominantColor.isValid();
} }
QImage WallReel::Core::Image::Data::loadImage() const { QImage WallReel::Core::Image::Data::loadImage() const {
+3 -1
View File
@@ -54,6 +54,8 @@ class Data {
QColor m_dominantColor; ///< Dominant color of the image, used for palette matching QColor m_dominantColor; ///< Dominant color of the image, used for palette matching
QHash<QString, QString> m_colorCache; ///< Cache for palette color matching results, key is palette name, value is matched color name QHash<QString, QString> m_colorCache; ///< Cache for palette color matching results, key is palette name, value is matched color name
bool m_isValid = false;
QImage computeImage() const; QImage computeImage() const;
QColor computeDominantColor(const QImage& image) const; QColor computeDominantColor(const QImage& image) const;
@@ -75,7 +77,7 @@ class Data {
QUrl getUrl() const { return QUrl::fromLocalFile(m_cachedFile.absoluteFilePath()); } QUrl getUrl() const { return QUrl::fromLocalFile(m_cachedFile.absoluteFilePath()); }
bool isValid() const { return m_cachedFile.exists(); } bool isValid() const { return m_isValid; }
QString getFullPath() const { return m_file.absoluteFilePath(); } QString getFullPath() const { return m_file.absoluteFilePath(); }
+9 -3
View File
@@ -251,6 +251,12 @@ class Carousel : public QObject {
} }
}); });
// Defer preview until state captured
connect(m_configMgr,
&Config::Manager::stateCaptured,
m_serviceMgr,
&Service::Manager::onStateCaptured);
// Quit on selected // Quit on selected
if (m_configMgr->getActionConfig().quitOnSelected) { if (m_configMgr->getActionConfig().quitOnSelected) {
QObject::connect( QObject::connect(
@@ -286,12 +292,12 @@ class Carousel : public QObject {
setSortDescending(m_cacheMgr->getSetting( setSortDescending(m_cacheMgr->getSetting(
Cache::SettingsType::LastSortDescending, Cache::SettingsType::LastSortDescending,
[]() { return Config::CacheConfigItems::defaultSortDescending; }) == "true"); []() { return Config::CacheConfigItems::defaultSortDescending; }) == "true");
connect(this, &Carousel::sortTypeChanged, this, [this]() { connect(app, &QApplication::aboutToQuit, this, [this]() {
m_cacheMgr->storeSetting( m_cacheMgr->storeSetting(
Cache::SettingsType::LastSortType, Cache::SettingsType::LastSortType,
Config::sortTypeToString(m_imageMgr->sortType())); Config::sortTypeToString(m_imageMgr->sortType()));
}); });
connect(this, &Carousel::sortDescendingChanged, this, [this]() { connect(app, &QApplication::aboutToQuit, this, [this]() {
m_cacheMgr->storeSetting( m_cacheMgr->storeSetting(
Cache::SettingsType::LastSortDescending, Cache::SettingsType::LastSortDescending,
m_imageMgr->sortDescending() ? "true" : "false"); m_imageMgr->sortDescending() ? "true" : "false");
@@ -301,7 +307,7 @@ class Carousel : public QObject {
requestSelectPalette(m_cacheMgr->getSetting( requestSelectPalette(m_cacheMgr->getSetting(
Cache::SettingsType::LastSelectedPalette, Cache::SettingsType::LastSelectedPalette,
[]() { return Config::CacheConfigItems::defaultSelectedPalette; })); []() { return Config::CacheConfigItems::defaultSelectedPalette; }));
connect(this, &Carousel::selectedPaletteChanged, this, [this]() { connect(app, &QApplication::aboutToQuit, this, [this]() {
m_cacheMgr->storeSetting( m_cacheMgr->storeSetting(
Cache::SettingsType::LastSelectedPalette, Cache::SettingsType::LastSelectedPalette,
m_paletteMgr->getSelectedPaletteName()); m_paletteMgr->getSelectedPaletteName());
+164
View File
@@ -0,0 +1,164 @@
#include "manager.hpp"
#include "Utils/texttemplate.hpp"
#include "logger.hpp"
WALLREEL_DECLARE_SENDER("ServiceManager")
namespace WallReel::Core::Service {
Manager::Manager(
const Config::ActionConfigItems& actionConfig,
Image::Manager& imageManager,
Palette::Manager& paletteManager,
QObject* parent) : m_actionConfig(actionConfig), m_imageManager(imageManager), m_paletteManager(paletteManager) {
m_wallpaperService = new WallpaperService(m_actionConfig.previewDebounceTime, this);
// Forward signals
// Direct signal 2 signal connection
connect(m_wallpaperService, &WallpaperService::previewCompleted, this, &Manager::previewCompleted);
// Signal 2 slot connection to handle processing state
connect(m_wallpaperService, &WallpaperService::selectCompleted, this, &Manager::_onSelectCompleted);
connect(m_wallpaperService, &WallpaperService::restoreCompleted, this, &Manager::_onRestoreCompleted);
}
void Manager::onStateCaptured() {
m_stateCaptured = true;
if (!m_pendingPreviewId.isEmpty()) {
WR_DEBUG("State captured, executing pending preview for id " + m_pendingPreviewId);
const QString pending = m_pendingPreviewId;
m_pendingPreviewId.clear();
previewWallpaper(pending);
}
}
void Manager::selectWallpaper(const QString& id) {
WR_DEBUG("Select action triggered for id " + id);
if (m_isProcessing) {
WR_DEBUG("Already processing an select action, ignoring new request");
return;
}
m_isProcessing = true;
emit isProcessingChanged();
const auto* data = m_imageManager.imageAt(id);
if (!data || !data->isValid()) {
WR_WARN(QString("No valid image data at id %1. Skipping select action.").arg(id));
m_isProcessing = false;
emit isProcessingChanged();
emit selectCompleted();
}
const auto command = _renderCommand(m_actionConfig.onSelected, _generateVariables(*data));
m_wallpaperService->select(command);
}
void Manager::restore() {
WR_DEBUG("Restore action triggered");
if (m_isProcessing) {
WR_DEBUG("Already processing an restore action, ignoring new request");
return;
}
if (!m_stateCaptured) {
WR_DEBUG("State not captured yet, skipping restore action");
emit restoreCompleted();
return;
}
m_isProcessing = true;
emit isProcessingChanged();
m_wallpaperService->restore(_renderCommand(m_actionConfig.onRestore, m_actionConfig.savedState));
}
void Manager::cancel() {
WR_DEBUG("Cancel action triggered");
m_wallpaperService->stopAll();
emit cancelCompleted();
}
void Manager::previewWallpaper(const QString& id) {
if (!m_stateCaptured) {
WR_DEBUG("State not captured yet, deferring preview for id " + id);
m_pendingPreviewId = id;
emit previewCompleted();
return;
}
WR_DEBUG("Preview action triggered for id " + id);
const auto* data = m_imageManager.imageAt(id);
if (!data || !data->isValid()) {
WR_WARN(QString("No valid image data at id %1. Skipping preview action.").arg(id));
emit previewCompleted();
return;
}
m_wallpaperService->preview(_renderCommand(m_actionConfig.onPreview, _generateVariables(*data)));
}
void Manager::restoreOnQuit() {
if (m_hasSelected) {
Logger::debug("ServiceManager", "Quit with selected wallpaper, no need to restore");
return;
}
Logger::debug("ServiceManager", "Restore on quit");
m_wallpaperService->stopAll();
QEventLoop loop;
connect(m_wallpaperService, &WallpaperService::restoreCompleted, &loop, &QEventLoop::quit);
// Call restore after the event loop starts
QTimer::singleShot(0, this, &Manager::restore);
loop.exec();
}
void Manager::_onSelectCompleted() {
Logger::debug("ServiceManager", "Select completed");
_onProcessCompleted();
m_hasSelected = true;
emit selectCompleted();
}
void Manager::_onRestoreCompleted() {
Logger::debug("ServiceManager", "Restore completed");
_onProcessCompleted();
emit restoreCompleted();
}
void Manager::_onProcessCompleted() {
m_isProcessing = false;
emit isProcessingChanged();
}
QString Manager::_renderCommand(const QString& templateStr, const QHash<QString, QString>& variables) const {
return Utils::renderTemplate(templateStr, variables);
}
QHash<QString, QString> Manager::_generateVariables(const Image::Data& imageData) const {
auto palette = m_paletteManager.getSelectedPaletteName();
if (palette.isEmpty()) {
palette = "null";
}
auto color = m_paletteManager.getCurrentColorName();
if (color.isEmpty()) {
color = "null";
}
auto hex = m_paletteManager.getCurrentColorHex();
if (hex.isEmpty()) {
hex = "null";
}
QHash<QString, QString> ret{
{"path", imageData.getFullPath()},
{"name", imageData.getFileName()},
{"size", QString::number(imageData.getSize())},
{"palette", palette},
{"colorName", color},
{"colorHex", hex},
{"domColorHex", imageData.getDominantColor().name()},
};
ret.insert(m_actionConfig.savedState);
return ret;
}
} // namespace WallReel::Core::Service
+18 -82
View File
@@ -8,7 +8,6 @@
#include "Image/manager.hpp" #include "Image/manager.hpp"
#include "Palette/manager.hpp" #include "Palette/manager.hpp"
#include "Service/wallpaper.hpp" #include "Service/wallpaper.hpp"
#include "logger.hpp"
namespace WallReel::Core::Service { namespace WallReel::Core::Service {
@@ -22,16 +21,7 @@ class Manager : public QObject {
const Config::ActionConfigItems& actionConfig, const Config::ActionConfigItems& actionConfig,
Image::Manager& imageManager, Image::Manager& imageManager,
Palette::Manager& paletteManager, Palette::Manager& paletteManager,
QObject* parent = nullptr) : m_actionConfig(actionConfig), m_imageManager(imageManager), m_paletteManager(paletteManager) { QObject* parent = nullptr);
m_wallpaperService = new WallpaperService(m_actionConfig, m_paletteManager, this);
// Forward signals
// Direct signal 2 signal connection
connect(m_wallpaperService, &WallpaperService::previewCompleted, this, &Manager::previewCompleted);
// Signal 2 slot connection to handle processing state
connect(m_wallpaperService, &WallpaperService::selectCompleted, this, &Manager::_onSelectCompleted);
connect(m_wallpaperService, &WallpaperService::restoreCompleted, this, &Manager::_onRestoreCompleted);
}
bool isProcessing() const { return m_isProcessing; } bool isProcessing() const { return m_isProcessing; }
@@ -39,86 +29,25 @@ class Manager : public QObject {
public slots: public slots:
void selectWallpaper(const QString& id) { void onStateCaptured();
Logger::debug("ServiceManager", QString("Select wallpaper with id %1").arg(id));
if (m_isProcessing) {
Logger::debug("ServiceManager", "Already processing an select action, ignoring new request");
return;
}
m_isProcessing = true;
emit isProcessingChanged();
const auto* data = m_imageManager.imageAt(id);
if (data) {
m_wallpaperService->select(*data);
} else {
Logger::warn("ServiceManager", QString("No image data at id %1. Skipping select action.").arg(id));
m_isProcessing = false;
emit isProcessingChanged();
emit selectCompleted();
}
}
void restore() { void selectWallpaper(const QString& id);
Logger::debug("ServiceManager", "Restore states");
if (m_isProcessing) {
Logger::debug("ServiceManager", "Already processing an restore action, ignoring new request");
return;
}
m_isProcessing = true;
emit isProcessingChanged();
m_wallpaperService->restore();
}
void cancel() { void restore();
Logger::debug("ServiceManager", "Cancel action");
m_wallpaperService->stopAll();
emit cancelCompleted();
}
void previewWallpaper(const QString& id) { void cancel();
Logger::debug("ServiceManager", "Preview wallpaper");
const auto* data = m_imageManager.imageAt(id);
if (data) {
m_wallpaperService->preview(*data);
} else {
Logger::warn("ServiceManager", "No image data at id " + id + ". Skipping preview action.");
emit previewCompleted();
}
}
void restoreOnQuit() { void previewWallpaper(const QString& id);
if (m_hasSelected) {
Logger::debug("ServiceManager", "Quit with selected wallpaper, no need to restore"); void restoreOnQuit();
return;
}
Logger::debug("ServiceManager", "Restore on quit");
m_wallpaperService->stopAll();
QEventLoop loop;
connect(m_wallpaperService, &WallpaperService::restoreCompleted, &loop, &QEventLoop::quit);
// Call restore after the event loop starts
QTimer::singleShot(0, m_wallpaperService, &WallpaperService::restore);
loop.exec();
}
private slots: private slots:
void _onSelectCompleted() { void _onSelectCompleted();
Logger::debug("ServiceManager", "Select completed");
_onProcessCompleted();
m_hasSelected = true;
emit selectCompleted();
}
void _onRestoreCompleted() { void _onRestoreCompleted();
Logger::debug("ServiceManager", "Restore completed");
_onProcessCompleted();
emit restoreCompleted();
}
void _onProcessCompleted() { void _onProcessCompleted();
m_isProcessing = false;
emit isProcessingChanged();
}
signals: signals:
void isProcessingChanged(); void isProcessingChanged();
@@ -127,6 +56,10 @@ class Manager : public QObject {
void restoreCompleted(); void restoreCompleted();
void cancelCompleted(); void cancelCompleted();
private:
QString _renderCommand(const QString& templateStr, const QHash<QString, QString>& variables) const;
QHash<QString, QString> _generateVariables(const Image::Data& imageData) const;
private: private:
WallpaperService* m_wallpaperService; WallpaperService* m_wallpaperService;
const Config::ActionConfigItems& m_actionConfig; const Config::ActionConfigItems& m_actionConfig;
@@ -135,6 +68,9 @@ class Manager : public QObject {
bool m_isProcessing = false; bool m_isProcessing = false;
bool m_hasSelected = false; bool m_hasSelected = false;
bool m_stateCaptured = false;
QString m_pendingPreviewId;
}; };
} // namespace WallReel::Core::Service } // namespace WallReel::Core::Service
+14 -82
View File
@@ -1,25 +1,20 @@
#include "Service/wallpaper.hpp" #include "Service/wallpaper.hpp"
#include <QColor> #include <QColor>
#include <iostream>
#include "Utils/texttemplate.hpp"
#include "logger.hpp" #include "logger.hpp"
WALLREEL_DECLARE_SENDER("WallpaperService") WALLREEL_DECLARE_SENDER("WallpaperService")
namespace WallReel::Core::Service { namespace WallReel::Core::Service {
WallpaperService::WallpaperService( WallpaperService::WallpaperService(int previewDebounceTime, QObject* parent)
const Config::ActionConfigItems& actionConfig, : QObject(parent) {
const Palette::Manager& paletteManager,
QObject* parent)
: QObject(parent), m_actionConfig(actionConfig), m_paletteManager(paletteManager) {
m_previewDebounceTimer = new QTimer(this); m_previewDebounceTimer = new QTimer(this);
m_previewDebounceTimer->setSingleShot(true); m_previewDebounceTimer->setSingleShot(true);
m_previewDebounceTimer->setInterval(m_actionConfig.previewDebounceTime); m_previewDebounceTimer->setInterval(previewDebounceTime);
connect(m_previewDebounceTimer, &QTimer::timeout, this, [this]() { connect(m_previewDebounceTimer, &QTimer::timeout, this, [this]() {
_doPreview(*m_pendingImageData); _doPreview(m_pendingPreviewCommand);
}); });
m_previewProcess = new QProcess(this); m_previewProcess = new QProcess(this);
@@ -67,71 +62,29 @@ void WallpaperService::stopAll() {
m_previewDebounceTimer->stop(); m_previewDebounceTimer->stop();
} }
void WallpaperService::preview(const Image::Data& imageData) { void WallpaperService::preview(const QString& command) {
m_pendingImageData = &imageData; m_pendingPreviewCommand = command;
m_previewDebounceTimer->start(); m_previewDebounceTimer->start();
} }
void WallpaperService::select(const Image::Data& imageData) { void WallpaperService::select(const QString& command) {
if (m_selectProcess->state() != QProcess::NotRunning) { if (m_selectProcess->state() != QProcess::NotRunning) {
WR_WARN("Previous select command is still running. Ignoring new command."); WR_WARN("Previous select command is still running. Ignoring new command.");
return; return;
} }
WR_DEBUG(QString("Select wallpaper: %1").arg(imageData.getFullPath())); _doSelect(command);
_doSelect(imageData);
} }
void WallpaperService::restore() { void WallpaperService::restore(const QString& command) {
if (m_restoreProcess->state() != QProcess::NotRunning) { if (m_restoreProcess->state() != QProcess::NotRunning) {
WR_WARN("Previous restore command is still running. Ignoring new command."); WR_WARN("Previous restore command is still running. Ignoring new command.");
return; return;
} }
WR_DEBUG("Restore state"); WR_DEBUG("Restore state");
_doRestore(); _doRestore(command);
} }
QHash<QString, QString> WallpaperService::_generateVariables(const Image::Data& imageData) { void WallpaperService::_doPreview(const QString& command) {
auto palette = m_paletteManager.getSelectedPaletteName();
if (palette.isEmpty()) {
palette = "null";
}
auto color = m_paletteManager.getCurrentColorName();
if (color.isEmpty()) {
color = "null";
}
auto hex = m_paletteManager.getCurrentColorHex();
if (hex.isEmpty()) {
hex = "null";
}
QHash<QString, QString> ret{
{"path", imageData.getFullPath()},
{"name", imageData.getFileName()},
{"size", QString::number(imageData.getSize())},
{"palette", palette},
{"colorName", color},
{"colorHex", hex},
{"domColorHex", imageData.getDominantColor().name()},
};
ret.insert(m_actionConfig.savedState);
return ret;
}
void WallpaperService::_doPreview(const Image::Data& imageData) {
QString path = imageData.getFullPath();
if (path.isEmpty()) {
WR_WARN("No valid image path for preview. Skipping preview action.");
emit previewCompleted();
return;
}
if (m_actionConfig.printPreview) {
std::cout << path.toStdString() << std::endl;
}
const auto variables = _generateVariables(imageData);
auto command = Utils::renderTemplate(m_actionConfig.onPreview, variables);
if (command.isEmpty()) { if (command.isEmpty()) {
WR_DEBUG("No preview command configured. Skipping preview action."); WR_DEBUG("No preview command configured. Skipping preview action.");
emit previewCompleted(); emit previewCompleted();
@@ -146,21 +99,7 @@ void WallpaperService::_doPreview(const Image::Data& imageData) {
m_previewProcess->start("sh", QStringList() << "-c" << command); m_previewProcess->start("sh", QStringList() << "-c" << command);
} }
void WallpaperService::_doSelect(const Image::Data& imageData) { void WallpaperService::_doSelect(const QString& command) {
QString path = imageData.getFullPath();
if (path.isEmpty()) {
WR_WARN("No valid image path for select. Skipping select action.");
emit selectCompleted();
return;
}
if (m_actionConfig.printSelected) {
std::cout << path.toStdString() << std::endl;
}
const auto variables = _generateVariables(imageData);
auto command = Utils::renderTemplate(m_actionConfig.onSelected, variables);
if (command.isEmpty()) { if (command.isEmpty()) {
WR_DEBUG("No select command configured. Skipping select action."); WR_DEBUG("No select command configured. Skipping select action.");
emit selectCompleted(); emit selectCompleted();
@@ -170,16 +109,9 @@ void WallpaperService::_doSelect(const Image::Data& imageData) {
m_selectProcess->start("sh", QStringList() << "-c" << command); m_selectProcess->start("sh", QStringList() << "-c" << command);
} }
void WallpaperService::_doRestore() { void WallpaperService::_doRestore(const QString& command) {
if (m_actionConfig.onRestore.isEmpty()) {
WR_DEBUG("No restore command configured. Skipping restore action.");
emit restoreCompleted();
return;
}
const QString command = Utils::renderTemplate(m_actionConfig.onRestore, m_actionConfig.savedState);
if (command.isEmpty()) { if (command.isEmpty()) {
WR_DEBUG("Restore command is empty after rendering. Skipping restore action."); WR_DEBUG("Restore command is empty. Skipping restore action.");
emit restoreCompleted(); emit restoreCompleted();
return; return;
} }
+8 -18
View File
@@ -4,27 +4,20 @@
#include <QProcess> #include <QProcess>
#include <QTimer> #include <QTimer>
#include "Config/data.hpp"
#include "Image/data.hpp"
#include "Palette/manager.hpp"
namespace WallReel::Core::Service { namespace WallReel::Core::Service {
class WallpaperService : public QObject { class WallpaperService : public QObject {
Q_OBJECT Q_OBJECT
public: public:
WallpaperService( WallpaperService(int previewDebounceTime, QObject* parent = nullptr);
const Config::ActionConfigItems& actionConfig,
const Palette::Manager& paletteManager,
QObject* parent = nullptr);
void stopAll(); void stopAll();
public slots: public slots:
void preview(const Image::Data& imageData); // execute after 500ms of inactivity void preview(const QString& command); // execute after 500ms of inactivity
void select(const Image::Data& imageData); // execute immediately, ignore if already running void select(const QString& command); // execute immediately, ignore if already running
void restore(); // execute immediately, ignore if already running void restore(const QString& command); // execute immediately, ignore if already running
signals: signals:
void previewCompleted(); void previewCompleted();
@@ -32,15 +25,12 @@ class WallpaperService : public QObject {
void restoreCompleted(); void restoreCompleted();
private: private:
void _doPreview(const Image::Data& imageData); void _doPreview(const QString& command);
void _doSelect(const Image::Data& imageData); void _doSelect(const QString& command);
void _doRestore(); void _doRestore(const QString& command);
QHash<QString, QString> _generateVariables(const Image::Data& imageData);
const Config::ActionConfigItems& m_actionConfig;
const Palette::Manager& m_paletteManager;
QTimer* m_previewDebounceTimer; QTimer* m_previewDebounceTimer;
const Image::Data* m_pendingImageData; QString m_pendingPreviewCommand;
QProcess* m_previewProcess; QProcess* m_previewProcess;
QProcess* m_selectProcess; QProcess* m_selectProcess;
QProcess* m_restoreProcess; QProcess* m_restoreProcess;