🚧 wip: ♻️ refactor: chekkupointo

This commit is contained in:
2026-02-17 23:25:35 +01:00
parent 9622c5b1fe
commit fff2e56467
27 changed files with 494 additions and 451 deletions
-4
View File
@@ -64,10 +64,6 @@ set_target_properties(${EXECUTABLE_NAME} PROPERTIES
) )
target_link_libraries(${EXECUTABLE_NAME} PRIVATE target_link_libraries(${EXECUTABLE_NAME} PRIVATE
Qt6::Quick
Qt6::Widgets
Qt6::QuickControls2
Qt6::Concurrent
${CORELIB_NAME} ${CORELIB_NAME}
${UILIB_NAME} ${UILIB_NAME}
) )
+3 -18
View File
@@ -1,7 +1,7 @@
project(Tests LANGUAGES CXX) project(Tests LANGUAGES CXX)
find_package(Qt6 REQUIRED COMPONENTS Core Test) find_package(Qt6 REQUIRED COMPONENTS Test)
add_executable(tst_configmgr add_executable(tst_configmgr
tst_configmgr.cpp tst_configmgr.cpp
@@ -15,26 +15,11 @@ add_test(NAME tst_configmgr COMMAND tst_configmgr)
add_test(NAME tst_imagemodel COMMAND tst_imagemodel) add_test(NAME tst_imagemodel COMMAND tst_imagemodel)
target_link_libraries(tst_configmgr PRIVATE target_link_libraries(tst_configmgr PRIVATE
Qt6::Core
Qt6::Test Qt6::Test
Qt6::Gui ${CORELIB_NAME}
wallreel-core
) )
target_link_libraries(tst_imagemodel PRIVATE target_link_libraries(tst_imagemodel PRIVATE
Qt6::Core
Qt6::Test Qt6::Test
Qt6::Gui ${CORELIB_NAME}
Qt6::Quick
wallreel-core
)
target_include_directories(tst_configmgr PRIVATE
${CMAKE_SOURCE_DIR}/WallReel/Core
${CMAKE_BINARY_DIR}/generated
)
target_include_directories(tst_imagemodel PRIVATE
${CMAKE_SOURCE_DIR}/WallReel/Core
${CMAKE_BINARY_DIR}/generated
) )
+17 -15
View File
@@ -8,7 +8,9 @@
#include <QTemporaryDir> #include <QTemporaryDir>
#include <QTest> #include <QTest>
#include "configmgr.hpp" #include "Config/manager.hpp"
using namespace WallReel::Core;
class TestConfigMgr : public QObject { class TestConfigMgr : public QObject {
Q_OBJECT Q_OBJECT
@@ -67,7 +69,7 @@ void TestConfigMgr::testDefaults() {
// Empty config file // Empty config file
writeConfig(QJsonObject()); writeConfig(QJsonObject());
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
// Check Style Defaults // Check Style Defaults
QCOMPARE(config.getImageWidth(), 320); QCOMPARE(config.getImageWidth(), 320);
@@ -144,7 +146,7 @@ void TestConfigMgr::testFullConfigParsing() {
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
// Assertions // Assertions
QCOMPARE(config.getWallpaperConfig().dirs.size(), 1); QCOMPARE(config.getWallpaperConfig().dirs.size(), 1);
@@ -184,7 +186,7 @@ void TestConfigMgr::testInvalidConfigValues() {
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
// Should retain defaults // Should retain defaults
QCOMPARE(config.getImageWidth(), 320); QCOMPARE(config.getImageWidth(), 320);
@@ -208,7 +210,7 @@ void TestConfigMgr::testWallpaperScanRecursive() {
root["wallpaper"] = wallpaperObj; root["wallpaper"] = wallpaperObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QStringList wallpapers = config.getWallpapers(); QStringList wallpapers = config.getWallpapers();
QCOMPARE(wallpapers.size(), 2); QCOMPARE(wallpapers.size(), 2);
@@ -235,7 +237,7 @@ void TestConfigMgr::testWallpaperScanNonRecursive() {
root["wallpaper"] = wallpaperObj; root["wallpaper"] = wallpaperObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QStringList wallpapers = config.getWallpapers(); QStringList wallpapers = config.getWallpapers();
QCOMPARE(wallpapers.size(), 1); QCOMPARE(wallpapers.size(), 1);
@@ -262,7 +264,7 @@ void TestConfigMgr::testWallpaperExcludes() {
root["wallpaper"] = wallpaperObj; root["wallpaper"] = wallpaperObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QStringList wallpapers = config.getWallpapers(); QStringList wallpapers = config.getWallpapers();
QCOMPARE(wallpapers.size(), 1); QCOMPARE(wallpapers.size(), 1);
@@ -281,7 +283,7 @@ void TestConfigMgr::testExplicitPaths() {
root["wallpaper"] = wallpaperObj; root["wallpaper"] = wallpaperObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QStringList wallpapers = config.getWallpapers(); QStringList wallpapers = config.getWallpapers();
QCOMPARE(wallpapers.size(), 1); QCOMPARE(wallpapers.size(), 1);
@@ -308,7 +310,7 @@ void TestConfigMgr::testImageExtensions() {
root["wallpaper"] = wallpaperObj; root["wallpaper"] = wallpaperObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QStringList wallpapers = config.getWallpapers(); QStringList wallpapers = config.getWallpapers();
@@ -332,7 +334,7 @@ void TestConfigMgr::testSortTypes() {
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QCOMPARE(config.getSortConfig().type, Config::SortType::None); QCOMPARE(config.getSortConfig().type, Config::SortType::None);
QCOMPARE(config.getSortConfig().reverse, false); QCOMPARE(config.getSortConfig().reverse, false);
} }
@@ -344,7 +346,7 @@ void TestConfigMgr::testSortTypes() {
sortObj["reverse"] = true; sortObj["reverse"] = true;
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QCOMPARE(config.getSortConfig().type, Config::SortType::Name); QCOMPARE(config.getSortConfig().type, Config::SortType::Name);
QCOMPARE(config.getSortConfig().reverse, true); QCOMPARE(config.getSortConfig().reverse, true);
} }
@@ -355,7 +357,7 @@ void TestConfigMgr::testSortTypes() {
sortObj["type"] = "size"; sortObj["type"] = "size";
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QCOMPARE(config.getSortConfig().type, Config::SortType::Size); QCOMPARE(config.getSortConfig().type, Config::SortType::Size);
} }
// 4. Date sort // 4. Date sort
@@ -365,7 +367,7 @@ void TestConfigMgr::testSortTypes() {
sortObj["type"] = "date"; sortObj["type"] = "date";
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QCOMPARE(config.getSortConfig().type, Config::SortType::Date); QCOMPARE(config.getSortConfig().type, Config::SortType::Date);
} }
// 5. Invalid sort -> fallback to default (Name) // 5. Invalid sort -> fallback to default (Name)
@@ -375,7 +377,7 @@ void TestConfigMgr::testSortTypes() {
sortObj["type"] = "invalid_blah"; sortObj["type"] = "invalid_blah";
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
// Default initialized in Config constructor is Name // Default initialized in Config constructor is Name
// But warning is logged // But warning is logged
QCOMPARE(config.getSortConfig().type, Config::SortType::Name); QCOMPARE(config.getSortConfig().type, Config::SortType::Name);
@@ -387,7 +389,7 @@ void TestConfigMgr::testSortTypes() {
sortObj["type"] = "DaTe"; sortObj["type"] = "DaTe";
root["sort"] = sortObj; root["sort"] = sortObj;
writeConfig(root); writeConfig(root);
Config config(m_tempDir.path(), {}, m_configPath); Config::Manager config(m_tempDir.path(), {}, m_configPath);
QCOMPARE(config.getSortConfig().type, Config::SortType::Date); QCOMPARE(config.getSortConfig().type, Config::SortType::Date);
} }
} }
+32 -30
View File
@@ -3,9 +3,11 @@
#include <QTemporaryDir> #include <QTemporaryDir>
#include <QtTest> #include <QtTest>
#include "configmgr.hpp" #include "Config/manager.hpp"
#include "imagemodel.hpp" #include "Image/model.hpp"
#include "imageprovider.hpp" #include "Image/provider.hpp"
using namespace WallReel::Core;
class TestImageModel : public QObject { class TestImageModel : public QObject {
Q_OBJECT Q_OBJECT
@@ -23,7 +25,7 @@ class TestImageModel : public QObject {
QString m_pathC; QString m_pathC;
void createTestFiles(); void createTestFiles();
void waitForModel(ImageModel* model); void waitForModel(Image::Model* model);
}; };
// clang-format off // clang-format off
@@ -115,11 +117,11 @@ void TestImageModel::createTestFiles() {
} }
} }
void TestImageModel::waitForModel(ImageModel* model) { void TestImageModel::waitForModel(Image::Model* model) {
if (!model->isLoading()) { if (!model->isLoading()) {
return; return;
} }
QSignalSpy spy(model, &ImageModel::isLoadingChanged); QSignalSpy spy(model, &Image::Model::isLoadingChanged);
while (model->isLoading()) { while (model->isLoading()) {
if (!spy.wait(5000)) { if (!spy.wait(5000)) {
qWarning() << "Timeout waiting for model to load"; qWarning() << "Timeout waiting for model to load";
@@ -133,8 +135,8 @@ void TestImageModel::testSortName() {
sortConfig.type = Config::SortType::Name; sortConfig.type = Config::SortType::Name;
sortConfig.reverse = false; sortConfig.reverse = false;
ImageProvider provider; Image::Provider provider;
ImageModel model(provider, sortConfig, QSize(100, 100)); Image::Model model(provider, sortConfig, QSize(100, 100));
QStringList paths = {m_pathB, m_pathA, m_pathC}; // Unordered input QStringList paths = {m_pathB, m_pathA, m_pathC}; // Unordered input
model.loadAndProcess(paths); model.loadAndProcess(paths);
@@ -143,9 +145,9 @@ void TestImageModel::testSortName() {
QCOMPARE(model.rowCount(), 3); QCOMPARE(model.rowCount(), 3);
// Expected: a.gif, b.gif, c.gif // Expected: a.gif, b.gif, c.gif
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "a.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "b.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif");
// Reverse // Reverse
sortConfig.reverse = true; sortConfig.reverse = true;
@@ -154,9 +156,9 @@ void TestImageModel::testSortName() {
QCOMPARE(model.rowCount(), 3); QCOMPARE(model.rowCount(), 3);
// Expected: c.gif, b.gif, a.gif // Expected: c.gif, b.gif, a.gif
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "b.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "a.gif");
} }
void TestImageModel::testSortDate() { void TestImageModel::testSortDate() {
@@ -164,8 +166,8 @@ void TestImageModel::testSortDate() {
sortConfig.type = Config::SortType::Date; sortConfig.type = Config::SortType::Date;
sortConfig.reverse = false; sortConfig.reverse = false;
ImageProvider provider; Image::Provider provider;
ImageModel model(provider, sortConfig, QSize(100, 100)); Image::Model model(provider, sortConfig, QSize(100, 100));
QStringList paths = {m_pathA, m_pathC, m_pathB}; QStringList paths = {m_pathA, m_pathC, m_pathB};
model.loadAndProcess(paths); model.loadAndProcess(paths);
@@ -174,17 +176,17 @@ void TestImageModel::testSortDate() {
QCOMPARE(model.rowCount(), 3); QCOMPARE(model.rowCount(), 3);
// Expected: c (old), a (mid), b (new) // Expected: c (old), a (mid), b (new)
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "b.gif");
// Reverse (Newest first) // Reverse (Newest first)
sortConfig.reverse = true; sortConfig.reverse = true;
model.sortUpdate(); model.sortUpdate();
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "b.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif");
} }
void TestImageModel::testSortSize() { void TestImageModel::testSortSize() {
@@ -192,8 +194,8 @@ void TestImageModel::testSortSize() {
sortConfig.type = Config::SortType::Size; sortConfig.type = Config::SortType::Size;
sortConfig.reverse = false; sortConfig.reverse = false;
ImageProvider provider; Image::Provider provider;
ImageModel model(provider, sortConfig, QSize(100, 100)); Image::Model model(provider, sortConfig, QSize(100, 100));
QStringList paths = {m_pathB, m_pathC, m_pathA}; QStringList paths = {m_pathB, m_pathC, m_pathA};
model.loadAndProcess(paths); model.loadAndProcess(paths);
@@ -201,17 +203,17 @@ void TestImageModel::testSortSize() {
QCOMPARE(model.rowCount(), 3); QCOMPARE(model.rowCount(), 3);
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "b.gif");
// Reverse // Reverse
sortConfig.reverse = true; sortConfig.reverse = true;
model.sortUpdate(); model.sortUpdate();
QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "b.gif"); QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "b.gif");
QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif");
QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif");
} }
QTEST_MAIN(TestImageModel) QTEST_MAIN(TestImageModel)
+11 -10
View File
@@ -2,24 +2,25 @@ qt_add_qml_module(${CORELIB_NAME}
URI ${COREMODULE_URI} URI ${COREMODULE_URI}
VERSION ${MODULE_VERSION_MAJOR}.${MODULE_VERSION_MINOR} VERSION ${MODULE_VERSION_MAJOR}.${MODULE_VERSION_MINOR}
SOURCES SOURCES
imagedata.hpp imagedata.cpp Image/data.hpp Image/data.cpp
utils/logger.hpp utils/logger.cpp Image/model.hpp Image/model.cpp
utils/misc.hpp Image/provider.hpp Image/provider.cpp
configmgr.hpp configmgr.cpp Palette/data.hpp
imagemodel.hpp imagemodel.cpp Palette/manager.hpp Palette/manager.cpp
imageprovider.hpp imageprovider.cpp Config/manager.hpp Config/manager.cpp
logger.hpp logger.cpp
wallpaperservice.hpp wallpaperservice.cpp wallpaperservice.hpp wallpaperservice.cpp
palette/data.hpp appoptions.hpp appoptions.cpp
palette/manager.hpp palette/manager.cpp
) )
target_link_libraries(${CORELIB_NAME} PRIVATE target_link_libraries(${CORELIB_NAME} PUBLIC
Qt6::Quick Qt6::Quick
Qt6::Widgets Qt6::Widgets
Qt6::QuickControls2 Qt6::QuickControls2
Qt6::Concurrent Qt6::Concurrent
) )
target_include_directories(${CORELIB_NAME} PRIVATE target_include_directories(${CORELIB_NAME} PUBLIC
${CMAKE_BINARY_DIR}/generated ${CMAKE_BINARY_DIR}/generated
${CMAKE_CURRENT_LIST_DIR}
) )
@@ -1,4 +1,4 @@
#include "configmgr.hpp" #include "manager.hpp"
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
@@ -8,43 +8,40 @@
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QStandardPaths> #include <QStandardPaths>
#include "utils/logger.hpp" #include "Utils/misc.hpp"
#include "utils/misc.hpp" #include "logger.hpp"
using namespace GeneralLogger;
const QString Config::s_DefaultConfigFileName = "config.json"; WallReel::Core::Config::Manager::Manager(
Config::Config(
const QString& configDir, const QString& configDir,
const QStringList& searchDirs, const QStringList& searchDirs,
const QString& configPath, const QString& configPath,
QObject* parent) QObject* parent)
: QObject(parent), m_configDir(configDir) { : QObject(parent), m_configDir(configDir) {
if (configPath.isEmpty()) { if (configPath.isEmpty()) {
info(QString("Configuration directory: %1").arg(configDir)); Logger::info(QString("Configuration directory: %1").arg(configDir));
_loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName); _loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName);
} else { } else {
_loadConfig(configPath); _loadConfig(configPath);
} }
if (!searchDirs.isEmpty()) { if (!searchDirs.isEmpty()) {
info(QString("Additional search directories: %1").arg(searchDirs.join(", "))); Logger::info(QString("Additional search directories: %1").arg(searchDirs.join(", ")));
for (const auto& dir : searchDirs) { for (const auto& dir : searchDirs) {
m_wallpaperConfig.dirs.append({dir, false}); m_wallpaperConfig.dirs.append({dir, false});
} }
} }
debug("Loading wallpapers ..."); Logger::debug("Loading wallpapers ...");
_loadWallpapers(); _loadWallpapers();
} }
Config::~Config() { WallReel::Core::Config::Manager::~Manager() {
} }
void Config::_loadConfig(const QString& configPath) { void WallReel::Core::Config::Manager::_loadConfig(const QString& configPath) {
info(QString("Loading configuration from: %1").arg(configPath)); Logger::info(QString("Loading configuration from: %1").arg(configPath));
QFile configFile(configPath); QFile configFile(configPath);
if (!configFile.open(QIODevice::ReadOnly)) { if (!configFile.open(QIODevice::ReadOnly)) {
critical(QString("Failed to open config file: %1").arg(configPath)); Logger::critical(QString("Failed to open config file: %1").arg(configPath));
return; return;
} }
QByteArray configData = configFile.readAll(); QByteArray configData = configFile.readAll();
@@ -52,7 +49,7 @@ void Config::_loadConfig(const QString& configPath) {
QJsonDocument jsonDoc = QJsonDocument::fromJson(configData); QJsonDocument jsonDoc = QJsonDocument::fromJson(configData);
if (jsonDoc.isNull() || !jsonDoc.isObject()) { if (jsonDoc.isNull() || !jsonDoc.isObject()) {
critical(QString("Invalid JSON format in config file")); Logger::critical(QString("Invalid JSON format in config file"));
return; return;
} }
@@ -65,7 +62,7 @@ void Config::_loadConfig(const QString& configPath) {
_loadSortConfig(jsonObj); _loadSortConfig(jsonObj);
} }
void Config::_loadWallpaperConfig(const QJsonObject& root) { void WallReel::Core::Config::Manager::_loadWallpaperConfig(const QJsonObject& root) {
if (!root.contains("wallpaper") || !root["wallpaper"].isObject()) { if (!root.contains("wallpaper") || !root["wallpaper"].isObject()) {
return; return;
} }
@@ -74,7 +71,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) {
if (config.contains("paths") && config["paths"].isArray()) { if (config.contains("paths") && config["paths"].isArray()) {
for (const auto& item : config["paths"].toArray()) { for (const auto& item : config["paths"].toArray()) {
if (item.isString()) { if (item.isString()) {
m_wallpaperConfig.paths.append(::expandPath(item.toString())); m_wallpaperConfig.paths.append(Utils::expandPath(item.toString()));
} }
} }
} }
@@ -85,7 +82,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) {
QJsonObject obj = item.toObject(); QJsonObject obj = item.toObject();
if (obj.contains("path") && obj["path"].isString()) { if (obj.contains("path") && obj["path"].isString()) {
WallpaperConfigItems::WallpaperDirConfigItem dirConfig; WallpaperConfigItems::WallpaperDirConfigItem dirConfig;
dirConfig.path = ::expandPath(obj["path"].toString()); dirConfig.path = Utils::expandPath(obj["path"].toString());
if (obj.contains("recursive") && obj["recursive"].isBool()) { if (obj.contains("recursive") && obj["recursive"].isBool()) {
dirConfig.recursive = obj["recursive"].toBool(); dirConfig.recursive = obj["recursive"].toBool();
} else { } else {
@@ -102,7 +99,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) {
if (item.isString()) { if (item.isString()) {
auto regex = QRegularExpression(item.toString()); auto regex = QRegularExpression(item.toString());
if (!regex.isValid()) { if (!regex.isValid()) {
warn(QString("Invalid regular expression in config: %1").arg(item.toString())); Logger::warn(QString("Invalid regular expression in config: %1").arg(item.toString()));
} else { } else {
m_wallpaperConfig.excludes.append(regex); m_wallpaperConfig.excludes.append(regex);
} }
@@ -111,7 +108,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) {
} }
} }
void Config::_loadPaletteConfig(const QJsonObject& root) { void WallReel::Core::Config::Manager::_loadPaletteConfig(const QJsonObject& root) {
if (!root.contains("palettes") || !root["palettes"].isArray()) { if (!root.contains("palettes") || !root["palettes"].isArray()) {
return; return;
} }
@@ -137,7 +134,7 @@ void Config::_loadPaletteConfig(const QJsonObject& root) {
if (color.isValid()) { if (color.isValid()) {
colorConfig.value = color; colorConfig.value = color;
} else { } else {
warn(QString("Invalid color string in config: %1").arg(colorObj["value"].toString())); Logger::warn(QString("Invalid color string in config: %1").arg(colorObj["value"].toString()));
} }
} }
} else if (colorItem.isString()) { } else if (colorItem.isString()) {
@@ -145,7 +142,7 @@ void Config::_loadPaletteConfig(const QJsonObject& root) {
if (color.isValid()) { if (color.isValid()) {
colorConfig.value = color; colorConfig.value = color;
} else { } else {
warn(QString("Invalid color string in config: %1").arg(colorItem.toString())); Logger::warn(QString("Invalid color string in config: %1").arg(colorItem.toString()));
} }
} }
if (colorConfig.value.isValid()) { if (colorConfig.value.isValid()) {
@@ -158,7 +155,7 @@ void Config::_loadPaletteConfig(const QJsonObject& root) {
} }
} }
void Config::_loadActionConfig(const QJsonObject& root) { void WallReel::Core::Config::Manager::_loadActionConfig(const QJsonObject& root) {
if (!root.contains("action") || !root["action"].isObject()) { if (!root.contains("action") || !root["action"].isObject()) {
return; return;
} }
@@ -213,7 +210,7 @@ void Config::_loadActionConfig(const QJsonObject& root) {
} }
} }
void Config::_loadStyleConfig(const QJsonObject& root) { void WallReel::Core::Config::Manager::_loadStyleConfig(const QJsonObject& root) {
if (!root.contains("style") || !root["style"].isObject()) { if (!root.contains("style") || !root["style"].isObject()) {
return; return;
} }
@@ -251,7 +248,7 @@ void Config::_loadStyleConfig(const QJsonObject& root) {
} }
} }
void Config::_loadSortConfig(const QJsonObject& root) { void WallReel::Core::Config::Manager::_loadSortConfig(const QJsonObject& root) {
if (!root.contains("sort") || !root["sort"].isObject()) { if (!root.contains("sort") || !root["sort"].isObject()) {
return; return;
} }
@@ -270,7 +267,7 @@ void Config::_loadSortConfig(const QJsonObject& root) {
} else if (type == "size") { } else if (type == "size") {
m_sortConfig.type = SortType::Size; m_sortConfig.type = SortType::Size;
} else { } else {
warn(QString("Unknown sort type: %1").arg(type)); Logger::warn(QString("Unknown sort type: %1").arg(type));
} }
} }
} }
@@ -282,30 +279,30 @@ void Config::_loadSortConfig(const QJsonObject& root) {
} }
} }
void Config::_loadWallpapers() { void WallReel::Core::Config::Manager::_loadWallpapers() {
m_wallpapers.clear(); m_wallpapers.clear();
QSet<QString> paths; QSet<QString> paths;
debug(QString("Loading wallpapers from %1 specified paths...").arg(m_wallpaperConfig.paths.size())); Logger::debug(QString("Loading wallpapers from %1 specified paths...").arg(m_wallpaperConfig.paths.size()));
for (const QString& path : std::as_const(m_wallpaperConfig.paths)) { for (const QString& path : std::as_const(m_wallpaperConfig.paths)) {
paths.insert(path); paths.insert(path);
} }
debug(QString("Loading wallpapers from %1 specified directories...").arg(m_wallpaperConfig.dirs.size())); Logger::debug(QString("Loading wallpapers from %1 specified directories...").arg(m_wallpaperConfig.dirs.size()));
for (const auto& dirConfig : std::as_const(m_wallpaperConfig.dirs)) { for (const auto& dirConfig : std::as_const(m_wallpaperConfig.dirs)) {
if (checkDir(dirConfig.path)) { if (Utils::checkDir(dirConfig.path)) {
std::function<void(const QDir&)> scanDir; std::function<void(const QDir&)> scanDir;
scanDir = [&](const QDir& d) { scanDir = [&](const QDir& d) {
QStringList files = d.entryList(QDir::Files | QDir::NoDotAndDotDot); QStringList files = d.entryList(QDir::Files | QDir::NoDotAndDotDot);
for (const QString& file : std::as_const(files)) { for (const QString& file : std::as_const(files)) {
QString filePath = d.filePath(file); QString filePath = d.filePath(file);
paths.insert(expandPath(filePath)); paths.insert(Utils::expandPath(filePath));
} }
if (dirConfig.recursive) { if (dirConfig.recursive) {
QStringList subDirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot); QStringList subDirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
debug(QString("Scanning directory '%1' for subdirectories... Found %2").arg(d.absolutePath()).arg(subDirs.size())); Logger::debug(QString("Scanning directory '%1' for subdirectories... Found %2").arg(d.absolutePath()).arg(subDirs.size()));
for (const QString& subDir : std::as_const(subDirs)) { for (const QString& subDir : std::as_const(subDirs)) {
scanDir(QDir(d.filePath(subDir))); scanDir(QDir(d.filePath(subDir)));
} }
@@ -313,17 +310,17 @@ void Config::_loadWallpapers() {
}; };
scanDir(QDir(dirConfig.path)); scanDir(QDir(dirConfig.path));
} else { } else {
warn(QString("Directory '%1' does not exist").arg(dirConfig.path)); Logger::warn(QString("Directory '%1' does not exist").arg(dirConfig.path));
} }
} }
debug(QString("Excluding %1 specified paths...").arg(m_wallpaperConfig.excludes.size())); Logger::debug(QString("Excluding %1 specified paths...").arg(m_wallpaperConfig.excludes.size()));
QStringList toRemove; QStringList toRemove;
for (const auto& exclude : std::as_const(m_wallpaperConfig.excludes)) { for (const auto& exclude : std::as_const(m_wallpaperConfig.excludes)) {
for (const QString& path : std::as_const(paths)) { for (const QString& path : std::as_const(paths)) {
if (exclude.match(path).hasMatch()) { if (exclude.match(path).hasMatch()) {
toRemove.append(path); toRemove.append(path);
debug(QString("Excluded path '%1' matched by regex '%2'").arg(path).arg(exclude.pattern())); Logger::debug(QString("Excluded path '%1' matched by regex '%2'").arg(path).arg(exclude.pattern()));
} }
} }
} }
@@ -333,12 +330,12 @@ void Config::_loadWallpapers() {
m_wallpapers.reserve(paths.size()); m_wallpapers.reserve(paths.size());
for (const QString& path : paths) { for (const QString& path : paths) {
if (checkImageFile(path)) { if (Utils::checkImageFile(path)) {
m_wallpapers.append(path); m_wallpapers.append(path);
} else { } else {
warn(QString("File '%1' is not recognized as a valid image file").arg(path)); Logger::warn(QString("File '%1' is not recognized as a valid image file").arg(path));
} }
} }
info(QString("Found %1 files").arg(paths.size())); Logger::info(QString("Found %1 files").arg(paths.size()));
} }
@@ -1,8 +1,6 @@
#ifndef WALLREEL_CONFIGMGR_HPP #ifndef WALLREEL_CONFIGMGR_HPP
#define WALLREEL_CONFIGMGR_HPP #define WALLREEL_CONFIGMGR_HPP
#include <qregularexpression.h>
#include <QColor> #include <QColor>
#include <QObject> #include <QObject>
#include <QRegularExpression> #include <QRegularExpression>
@@ -44,7 +42,67 @@
// date: older before newer // date: older before newer
// size: smaller before larger // size: smaller before larger
class Config : public QObject { namespace WallReel::Core::Config {
static const QString s_DefaultConfigFileName = "config.json";
enum class SortType : int {
None = 0, // "none"
Name, // "name"
Date, // "date"
Size, // "size"
};
struct WallpaperConfigItems {
struct WallpaperDirConfigItem {
QString path;
bool recursive;
};
QStringList paths;
QList<WallpaperDirConfigItem> dirs;
QList<QRegularExpression> excludes;
};
struct PaletteConfigItems {
struct PaletteColorConfigItem {
QString name;
QColor value;
};
struct PaletteConfigItem {
QString name;
QList<PaletteColorConfigItem> colors;
};
QList<PaletteConfigItem> palettes;
};
struct ActionConfigItems {
QHash<QString, QString> saveState;
QString onSelected;
QString onPreview;
QString onRestore;
int previewDebounceTime = 300; // milliseconds
bool printSelected = false;
bool printPreview = false;
};
struct StyleConfigItems {
double imageFocusScale = 1.5;
int imageWidth = 320;
int imageHeight = 200;
int windowWidth = 750;
int windowHeight = 500;
};
struct SortConfigItems {
SortType type = SortType::Name;
bool reverse = false;
};
class Manager : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int imageWidth READ getImageWidth CONSTANT) Q_PROPERTY(int imageWidth READ getImageWidth CONSTANT)
@@ -54,69 +112,13 @@ class Config : public QObject {
Q_PROPERTY(int windowHeight READ getWindowHeight CONSTANT) Q_PROPERTY(int windowHeight READ getWindowHeight CONSTANT)
public: public:
enum class SortType : int { Manager(
None = 0, // "none"
Name, // "name"
Date, // "date"
Size, // "size"
};
struct WallpaperConfigItems {
struct WallpaperDirConfigItem {
QString path;
bool recursive;
};
QStringList paths;
QList<WallpaperDirConfigItem> dirs;
QList<QRegularExpression> excludes;
};
struct PaletteConfigItems {
struct PaletteColorConfigItem {
QString name;
QColor value;
};
struct PaletteConfigItem {
QString name;
QList<PaletteColorConfigItem> colors;
};
QList<PaletteConfigItem> palettes;
};
struct ActionConfigItems {
QHash<QString, QString> saveState;
QString onSelected;
QString onPreview;
QString onRestore;
int previewDebounceTime = 300; // milliseconds
bool printSelected = false;
bool printPreview = false;
};
struct StyleConfigItems {
double imageFocusScale = 1.5;
int imageWidth = 320;
int imageHeight = 200;
int windowWidth = 750;
int windowHeight = 500;
};
struct SortConfigItems {
SortType type = SortType::Name;
bool reverse = false;
};
Config(
const QString& configDir, const QString& configDir,
const QStringList& searchDirs = {}, const QStringList& searchDirs = {},
const QString& configPath = "", // Override the default config path const QString& configPath = "", // Override the default config path
QObject* parent = nullptr); QObject* parent = nullptr);
~Config(); ~Manager();
const QStringList& getWallpapers() const { return m_wallpapers; } const QStringList& getWallpapers() const { return m_wallpapers; }
@@ -146,7 +148,6 @@ class Config : public QObject {
return QSize{m_styleConfig.imageWidth, m_styleConfig.imageHeight} * m_styleConfig.imageFocusScale; return QSize{m_styleConfig.imageWidth, m_styleConfig.imageHeight} * m_styleConfig.imageFocusScale;
} }
static const QString s_DefaultConfigFileName;
const QString m_configDir; const QString m_configDir;
private: private:
@@ -168,4 +169,6 @@ class Config : public QObject {
QStringList m_wallpapers; QStringList m_wallpapers;
}; };
} // namespace WallReel::Core::Config
#endif // WALLREEL_CONFIGMGR_HPP #endif // WALLREEL_CONFIGMGR_HPP
@@ -1,13 +1,11 @@
#include "imagedata.hpp" #include "data.hpp"
#include <QImageReader> #include <QImageReader>
#include "utils/logger.hpp" #include "../logger.hpp"
using namespace GeneralLogger; WallReel::Core::Image::Data* WallReel::Core::Image::Data::create(const QString& path, const QSize& size) {
Data* ret = new Data(path, size);
ImageData* ImageData::create(const QString& path, const QSize& size) {
ImageData* ret = new ImageData(path, size);
if (!ret->isValid()) { if (!ret->isValid()) {
delete ret; delete ret;
return nullptr; return nullptr;
@@ -15,11 +13,11 @@ ImageData* ImageData::create(const QString& path, const QSize& size) {
return ret; return ret;
} }
ImageData::ImageData(const QString& path, const QSize& targetSize) WallReel::Core::Image::Data::Data(const QString& path, const QSize& targetSize)
: m_file(path) { : m_file(path) {
QImageReader reader(path); QImageReader reader(path);
if (!reader.canRead()) { if (!reader.canRead()) {
warn(QString("Failed to load image from path: %1").arg(path)); Logger::warn(QString("Failed to load image from path: %1").arg(path));
return; return;
} }
@@ -39,7 +37,7 @@ ImageData::ImageData(const QString& path, const QSize& targetSize)
} }
if (!reader.read(&m_image)) { if (!reader.read(&m_image)) {
warn(QString("Failed to load image from path: %1").arg(path)); Logger::warn(QString("Failed to load image from path: %1").arg(path));
return; return;
} }
@@ -4,15 +4,17 @@
#include <QFileInfo> #include <QFileInfo>
#include <QImage> #include <QImage>
class ImageData { namespace WallReel::Core::Image {
class Data {
QString m_id; QString m_id;
QFileInfo m_file; QFileInfo m_file;
QImage m_image; QImage m_image;
ImageData(const QString& path, const QSize& size); Data(const QString& path, const QSize& size);
public: public:
static ImageData* create(const QString& path, const QSize& size); static Data* create(const QString& path, const QSize& size);
const QImage& getImage() const { return m_image; } const QImage& getImage() const { return m_image; }
@@ -33,4 +35,6 @@ class ImageData {
private: private:
}; };
} // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEDATA_HPP #endif // WALLREEL_IMAGEDATA_HPP
@@ -1,13 +1,12 @@
#include "model.hpp"
#include "imagemodel.hpp"
#include <QFuture> #include <QFuture>
#include <QtConcurrent> #include <QtConcurrent>
#include "imagedata.hpp" #include "data.hpp"
ImageModel::ImageModel( WallReel::Core::Image::Model::Model(
ImageProvider& provider, Provider& provider,
const Config::SortConfigItems& sortConfig, const Config::SortConfigItems& sortConfig,
QSize thumbnailSize, QSize thumbnailSize,
QObject* parent) QObject* parent)
@@ -17,9 +16,9 @@ ImageModel::ImageModel(
m_thumbnailSize(thumbnailSize) { m_thumbnailSize(thumbnailSize) {
connect( connect(
&m_watcher, &m_watcher,
&QFutureWatcher<ImageData*>::finished, &QFutureWatcher<Data*>::finished,
this, this,
&ImageModel::_onProcessingFinished); &Model::_onProcessingFinished);
connect( connect(
&m_progressUpdateTimer, &m_progressUpdateTimer,
&QTimer::timeout, &QTimer::timeout,
@@ -29,21 +28,21 @@ ImageModel::ImageModel(
}); });
} }
ImageModel::~ImageModel() { WallReel::Core::Image::Model::~Model() {
m_watcher.cancel(); m_watcher.cancel();
m_watcher.waitForFinished(); m_watcher.waitForFinished();
qDeleteAll(m_data); qDeleteAll(m_data);
m_data.clear(); m_data.clear();
} }
int ImageModel::rowCount(const QModelIndex& parent) const { int WallReel::Core::Image::Model::rowCount(const QModelIndex& parent) const {
if (parent.isValid()) { if (parent.isValid()) {
return 0; return 0;
} }
return m_data.count(); return m_data.count();
} }
QVariant ImageModel::data(const QModelIndex& index, int role) const { QVariant WallReel::Core::Image::Model::data(const QModelIndex& index, int role) const {
if (!index.isValid() || index.row() >= m_data.count()) { if (!index.isValid() || index.row() >= m_data.count()) {
return QVariant(); return QVariant();
} }
@@ -61,7 +60,7 @@ QVariant ImageModel::data(const QModelIndex& index, int role) const {
} }
} }
void ImageModel::loadAndProcess(const QStringList& paths) { void WallReel::Core::Image::Model::loadAndProcess(const QStringList& paths) {
if (m_isLoading) { if (m_isLoading) {
return; return;
} }
@@ -72,10 +71,10 @@ void ImageModel::loadAndProcess(const QStringList& paths) {
m_processedCount = 0; m_processedCount = 0;
m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs); m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs);
const auto thumbnailSize = m_thumbnailSize; const auto thumbnailSize = m_thumbnailSize;
const auto counterPtr = &m_processedCount; const auto counterPtr = &m_processedCount;
QFuture<ImageData*> future = QtConcurrent::mapped(paths, [thumbnailSize, counterPtr](const QString& path) { QFuture<Data*> future = QtConcurrent::mapped(paths, [thumbnailSize, counterPtr](const QString& path) {
auto data = ImageData::create(path, thumbnailSize); auto data = Data::create(path, thumbnailSize);
counterPtr->fetch_add(1, std::memory_order_relaxed); counterPtr->fetch_add(1, std::memory_order_relaxed);
return data; return data;
}); });
@@ -83,18 +82,18 @@ void ImageModel::loadAndProcess(const QStringList& paths) {
emit totalCountChanged(); emit totalCountChanged();
} }
void ImageModel::stop() { void WallReel::Core::Image::Model::stop() {
if (m_isLoading) { if (m_isLoading) {
m_watcher.cancel(); m_watcher.cancel();
} }
} }
void ImageModel::_onProgressValueChanged(int value) { void WallReel::Core::Image::Model::_onProgressValueChanged(int value) {
Q_UNUSED(value); Q_UNUSED(value);
emit progressChanged(); emit progressChanged();
} }
void ImageModel::_onProcessingFinished() { void WallReel::Core::Image::Model::_onProcessingFinished() {
auto results = m_watcher.future().results(); auto results = m_watcher.future().results();
for (auto& data : results) { for (auto& data : results) {
if (data && data->isValid()) { if (data && data->isValid()) {
@@ -116,10 +115,10 @@ void ImageModel::_onProcessingFinished() {
}); });
} }
void ImageModel::sortUpdate() { void WallReel::Core::Image::Model::sortUpdate() {
const auto type = m_sortConfig.type; const auto type = m_sortConfig.type;
const auto reverse = m_sortConfig.reverse; const auto reverse = m_sortConfig.reverse;
std::sort(m_data.begin(), m_data.end(), [type, reverse](ImageData* a, ImageData* b) { std::sort(m_data.begin(), m_data.end(), [type, reverse](Data* a, Data* b) {
if (!a || !b) { if (!a || !b) {
return false; return false;
} }
@@ -127,8 +126,8 @@ void ImageModel::sortUpdate() {
return false; return false;
} }
ImageData* first = reverse ? b : a; Data* first = reverse ? b : a;
ImageData* second = reverse ? a : b; Data* second = reverse ? a : b;
switch (type) { switch (type) {
case Config::SortType::Name: case Config::SortType::Name:
@@ -150,7 +149,7 @@ void ImageModel::sortUpdate() {
endResetModel(); endResetModel();
} }
QVariant ImageModel::dataAt(int index, const QString& roleName) const { QVariant WallReel::Core::Image::Model::dataAt(int index, const QString& roleName) const {
if (index < 0 || index >= m_data.count()) { if (index < 0 || index >= m_data.count()) {
return QVariant(); return QVariant();
} }
@@ -167,7 +166,7 @@ QVariant ImageModel::dataAt(int index, const QString& roleName) const {
} }
} }
void ImageModel::_clearData() { void WallReel::Core::Image::Model::_clearData() {
beginResetModel(); beginResetModel();
m_provider.clear(); m_provider.clear();
qDeleteAll(m_data); qDeleteAll(m_data);
@@ -175,7 +174,7 @@ void ImageModel::_clearData() {
endResetModel(); endResetModel();
} }
void ImageModel::selectImage(int index) { void WallReel::Core::Image::Model::selectImage(int index) {
if (index < 0 || index >= m_data.count()) { if (index < 0 || index >= m_data.count()) {
return; return;
} }
@@ -185,7 +184,7 @@ void ImageModel::selectImage(int index) {
} }
} }
void ImageModel::previewImage(int index) { void WallReel::Core::Image::Model::previewImage(int index) {
if (index < 0 || index >= m_data.count()) { if (index < 0 || index >= m_data.count()) {
return; return;
} }
@@ -6,10 +6,12 @@
#include <QTimer> #include <QTimer>
#include <atomic> #include <atomic>
#include "configmgr.hpp" #include "Config/manager.hpp"
#include "imageprovider.hpp" #include "provider.hpp"
class ImageModel : public QAbstractListModel { namespace WallReel::Core::Image {
class Model : public QAbstractListModel {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged)
@@ -31,13 +33,13 @@ class ImageModel : public QAbstractListModel {
}; };
} }
ImageModel( Model(
ImageProvider& provider, Provider& provider,
const Config::SortConfigItems& sortConfig, const Config::SortConfigItems& sortConfig,
QSize thumbnailSize, QSize thumbnailSize,
QObject* parent = nullptr); QObject* parent = nullptr);
~ImageModel(); ~Model();
bool isLoading() const { return m_isLoading; } bool isLoading() const { return m_isLoading; }
@@ -68,21 +70,21 @@ class ImageModel : public QAbstractListModel {
void isLoadingChanged(); void isLoadingChanged();
void progressChanged(); void progressChanged();
void totalCountChanged(); void totalCountChanged();
void imageSelected(const ImageData& imageData); void imageSelected(const Data& imageData);
void imagePreviewed(const ImageData& imageData); void imagePreviewed(const Data& imageData);
private slots: private slots:
void _onProgressValueChanged(int value); void _onProgressValueChanged(int value);
void _onProcessingFinished(); void _onProcessingFinished();
private: private:
ImageProvider& m_provider; Provider& m_provider;
const Config::SortConfigItems& m_sortConfig; const Config::SortConfigItems& m_sortConfig;
QSize m_thumbnailSize; QSize m_thumbnailSize;
QVector<ImageData*> m_data; QVector<Data*> m_data;
QFutureWatcher<ImageData*> m_watcher; QFutureWatcher<Data*> m_watcher;
bool m_isLoading = false; bool m_isLoading = false;
std::atomic<int> m_processedCount{0}; std::atomic<int> m_processedCount{0};
@@ -91,4 +93,6 @@ class ImageModel : public QAbstractListModel {
static constexpr int s_IsLoadingUpdateIntervalMs = 50; static constexpr int s_IsLoadingUpdateIntervalMs = 50;
}; };
} // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEMODEL_HPP #endif // WALLREEL_IMAGEMODEL_HPP
@@ -1,24 +1,24 @@
#include "imageprovider.hpp" #include "provider.hpp"
QImage ImageProvider::requestImage(const QString& id, QSize* size, const QSize& requestedSize) { QImage WallReel::Core::Image::Provider::requestImage(const QString& id, QSize* size, const QSize& requestedSize) {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
if (!m_images.contains(id)) { if (!m_images.contains(id)) {
return QImage(); return QImage();
} }
ImageData* data = m_images[id]; Data* data = m_images[id];
if (size) { if (size) {
*size = data->getImage().size(); *size = data->getImage().size();
} }
return data->getImage(); return data->getImage();
} }
void ImageProvider::insert(ImageData* data) { void WallReel::Core::Image::Provider::insert(Data* data) {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
m_images.insert(data->getId(), data); m_images.insert(data->getId(), data);
} }
void ImageProvider::clear() { void WallReel::Core::Image::Provider::clear() {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
m_images.clear(); m_images.clear();
} }
@@ -5,23 +5,27 @@
#include <QMutex> #include <QMutex>
#include <QQuickImageProvider> #include <QQuickImageProvider>
#include "imagedata.hpp" #include "data.hpp"
class ImageProvider : public QQuickImageProvider { namespace WallReel::Core::Image {
class Provider : public QQuickImageProvider {
Q_OBJECT Q_OBJECT
public: public:
ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) {} Provider() : QQuickImageProvider(QQuickImageProvider::Image) {}
QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize) override; QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize) override;
void insert(ImageData* data); void insert(Data* data);
void clear(); void clear();
private: private:
QMutex m_mutex; QMutex m_mutex;
QHash<QString, ImageData*> m_images; QHash<QString, Data*> m_images;
}; };
} // namespace WallReel::Core::Image
#endif // WALLREEL_IMAGEPROVIDER_HPP #endif // WALLREEL_IMAGEPROVIDER_HPP
@@ -6,6 +6,8 @@
#include <QObject> #include <QObject>
#include <QString> #include <QString>
namespace WallReel::Core::Palette {
struct ColorItem { struct ColorItem {
Q_GADGET Q_GADGET
Q_PROPERTY(QString name MEMBER name CONSTANT) Q_PROPERTY(QString name MEMBER name CONSTANT)
@@ -37,7 +39,9 @@ struct PaletteItem {
} }
}; };
Q_DECLARE_METATYPE(ColorItem) } // namespace WallReel::Core::Palette
Q_DECLARE_METATYPE(PaletteItem)
Q_DECLARE_METATYPE(WallReel::Core::Palette::ColorItem)
Q_DECLARE_METATYPE(WallReel::Core::Palette::PaletteItem)
#endif // WALLREEL_PALETTE_DATA_HPP #endif // WALLREEL_PALETTE_DATA_HPP
@@ -2,7 +2,7 @@
#include "predefined.hpp" #include "predefined.hpp"
PaletteManager::PaletteManager( WallReel::Core::Palette::Manager::Manager(
const Config::PaletteConfigItems& config, const Config::PaletteConfigItems& config,
QObject* parent) : QObject(parent) { QObject* parent) : QObject(parent) {
// The new ones overrides the old ones, use a hashtable to track // The new ones overrides the old ones, use a hashtable to track
@@ -1,16 +1,18 @@
#ifndef WALLREEL_PALETTE_MANAGER_HPP #ifndef WALLREEL_PALETTE_MANAGER_HPP
#define WALLREEL_PALETTE_MANAGER_HPP #define WALLREEL_PALETTE_MANAGER_HPP
#include "../configmgr.hpp" #include "Config/manager.hpp"
#include "data.hpp" #include "data.hpp"
class PaletteManager : public QObject { namespace WallReel::Core::Palette {
class Manager : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QList<PaletteItem> availablePalettes READ availablePalettes CONSTANT) Q_PROPERTY(QList<PaletteItem> availablePalettes READ availablePalettes CONSTANT)
public: public:
PaletteManager(const Config::PaletteConfigItems& config, Manager(const Config::PaletteConfigItems& config,
QObject* parent = nullptr); QObject* parent = nullptr);
const QList<PaletteItem>& availablePalettes() const { const QList<PaletteItem>& availablePalettes() const {
return m_palettes; return m_palettes;
@@ -27,4 +29,6 @@ class PaletteManager : public QObject {
QList<PaletteItem> m_palettes; QList<PaletteItem> m_palettes;
}; };
} // namespace WallReel::Core::Palette
#endif // WALLREEL_PALETTE_MANAGER_HPP #endif // WALLREEL_PALETTE_MANAGER_HPP
@@ -3,6 +3,8 @@
#include "data.hpp" #include "data.hpp"
namespace WallReel::Core::Palette {
inline const QList<PaletteItem> preDefinedPalettes = { inline const QList<PaletteItem> preDefinedPalettes = {
{ {
@@ -85,4 +87,6 @@ inline const QList<PaletteItem> preDefinedPalettes = {
}, },
}; };
} // namespace WallReel::Core::Palette
#endif // WALLREEL_PALETTES_PREDEFINED_HPP #endif // WALLREEL_PALETTES_PREDEFINED_HPP
@@ -11,6 +11,8 @@
#include "version.h" #include "version.h"
namespace WallReel::Core::Utils {
/** /**
* @brief Defer execution of a callable until the end of the current scope. * @brief Defer execution of a callable until the end of the current scope.
* *
@@ -130,4 +132,6 @@ inline QString getConfigDir() {
return configDir; return configDir;
} }
} // namespace WallReel::Core::Utils
#endif // WALLREEL_MISC_HPP #endif // WALLREEL_MISC_HPP
@@ -5,6 +5,8 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QString> #include <QString>
namespace WallReel::Core::Utils {
/** /**
* @brief Replaces {{ key }} style placeholders in a template string with corresponding values from a map. * @brief Replaces {{ key }} style placeholders in a template string with corresponding values from a map.
* *
@@ -135,4 +137,6 @@ inline QStringList extractTemplateKeys(const QString& templateStr) {
return keys; return keys;
} }
} // namespace WallReel::Core::Utils
#endif // TEXTTEMPLATE_HPP #endif // TEXTTEMPLATE_HPP
+115
View File
@@ -0,0 +1,115 @@
#include "appoptions.hpp"
#include <QApplication>
#include <QCommandLineOption>
#include <QTextStream>
#include "Utils/misc.hpp"
#include "logger.hpp"
#include "version.h"
namespace WallReel::Core {
// -v --version
void AppOptions::printVersion() {
QTextStream out(stdout);
out << APP_NAME << " version " << APP_VERSION << Qt::endl;
doReturn = true;
}
// -h --help
void AppOptions::printHelp() {
QTextStream out(stdout);
QString helpText = parser.helpText();
auto lines = helpText.split('\n');
for (auto& line : lines) {
if (line.contains("--help-all")) {
// Remove the --help-all option line added by Qt by default
continue;
}
out << line << Qt::endl;
}
doReturn = true;
}
// Print error message and help
void AppOptions::printError() {
if (!errorText.isEmpty()) {
QTextStream out(stderr);
out << errorText << Qt::endl;
printHelp();
}
doReturn = true;
}
AppOptions::AppOptions() = default;
void AppOptions::parseArgs(QApplication& app) {
parser.setApplicationDescription("A small wallpaper utility made with Qt");
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption versionOption = parser.addVersionOption();
QCommandLineOption verboseOption(QStringList() << "V" << "verbose", "Set log level to DEBUG (default is INFO)");
parser.addOption(verboseOption);
QCommandLineOption quietOption(QStringList() << "q" << "quiet", "Suppress all log output");
parser.addOption(quietOption);
QCommandLineOption appendDirOption(QStringList() << "d" << "append-dir", "Append an additional wallpaper search directory", "dir");
parser.addOption(appendDirOption);
QCommandLineOption configFileOption(QStringList() << "c" << "config-file", "Specify a custom configuration file", "file");
parser.addOption(configFileOption);
// Not parser.process(a->arguments()) because we want to handle exit logics ourselves.
// parser.process(...) will do something like exit(...) that will terminate
// the application brutally and produce unwanted warnings.
if (!parser.parse(app.arguments())) {
errorText = parser.errorText();
doReturn = true;
return;
}
if (parser.isSet(versionOption)) {
printVersion();
return;
}
if (parser.isSet(helpOption)) {
printHelp();
return;
}
if (parser.isSet(verboseOption)) {
Logger::setLogLevel(QtDebugMsg);
} else if (parser.isSet(quietOption)) {
Logger::quiet();
} else {
// Default to INFO level
Logger::setLogLevel(QtDebugMsg);
}
for (const QString& dir : parser.values(appendDirOption)) {
if (Utils::checkDir(dir)) {
appendDirs.append(dir);
} else {
errorText = QString("Error: Directory does not exist or is not accessible: %1").arg(dir);
printError();
return;
}
}
if (parser.isSet(configFileOption)) {
QString path = parser.value(configFileOption);
if (Utils::checkFile(path)) {
configPath = path;
} else {
errorText = QString("Error: Config file does not exist or is not accessible: %1").arg(path);
printError();
return;
}
}
}
} // namespace WallReel::Core
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <QCommandLineParser>
#include <QStringList>
class QApplication;
namespace WallReel::Core {
/**
* @brief A class to handle application options.
*/
class AppOptions {
QCommandLineParser parser;
// -v --version
void printVersion();
// -h --help
void printHelp();
// Print error message and help
void printError();
public:
QString configPath;
QStringList appendDirs;
QString errorText;
bool doReturn = false; ///< Indicates whether the application should exit after parsing arguments.
AppOptions();
void parseArgs(QApplication& app);
};
} // namespace WallReel::Core
@@ -71,7 +71,7 @@ static void messageOutput(QtMsgType type, const QMessageLogContext& context, con
} }
} }
void Logger::init(FILE* stream) { void WallReel::Core::Logger::init(FILE* stream) {
if (stream) { if (stream) {
delete s_logStream; delete s_logStream;
s_logStream = new QTextStream(stream); s_logStream = new QTextStream(stream);
@@ -81,7 +81,7 @@ void Logger::init(FILE* stream) {
qInstallMessageHandler(messageOutput); qInstallMessageHandler(messageOutput);
} }
void Logger::setLogLevel(QtMsgType level) { void WallReel::Core::Logger::setLogLevel(QtMsgType level) {
switch (level) { switch (level) {
case QtDebugMsg: case QtDebugMsg:
QLoggingCategory::setFilterRules(QString("%1.debug=true").arg(APP_NAME)); QLoggingCategory::setFilterRules(QString("%1.debug=true").arg(APP_NAME));
@@ -101,23 +101,23 @@ void Logger::setLogLevel(QtMsgType level) {
} }
} }
void Logger::quiet() { void WallReel::Core::Logger::quiet() {
QLoggingCategory::setFilterRules(QString("%1.debug=false\n%1.info=false\n%1.warning=false\n%1.critical=false\n%1.fatal=false").arg(APP_NAME)); QLoggingCategory::setFilterRules(QString("%1.debug=false\n%1.info=false\n%1.warning=false\n%1.critical=false\n%1.fatal=false").arg(APP_NAME));
} }
void GeneralLogger::debug(const QString& msg) { void WallReel::Core::Logger::debug(const QString& msg) {
qCDebug(logMain).noquote() << msg; qCDebug(logMain).noquote() << msg;
} }
void GeneralLogger::info(const QString& msg) { void WallReel::Core::Logger::info(const QString& msg) {
qCInfo(logMain).noquote() << msg; qCInfo(logMain).noquote() << msg;
} }
void GeneralLogger::warn(const QString& msg) { void WallReel::Core::Logger::warn(const QString& msg) {
qCWarning(logMain).noquote() << msg; qCWarning(logMain).noquote() << msg;
} }
void GeneralLogger::critical(const QString& msg) { void WallReel::Core::Logger::critical(const QString& msg) {
qCCritical(logMain).noquote() << msg; qCCritical(logMain).noquote() << msg;
} }
@@ -7,20 +7,17 @@
Q_DECLARE_LOGGING_CATEGORY(logMain) Q_DECLARE_LOGGING_CATEGORY(logMain)
namespace GeneralLogger { namespace WallReel::Core {
void debug(const QString& msg);
void info(const QString& msg);
void warn(const QString& msg);
void critical(const QString& msg);
} // namespace GeneralLogger
class Logger { class Logger {
public: public:
static void debug(const QString& msg);
static void info(const QString& msg);
static void warn(const QString& msg);
static void critical(const QString& msg);
/** /**
* @brief Initialize the logger and set the output stream. * @brief Initialize the logger and set the output stream.
* *
@@ -42,4 +39,6 @@ class Logger {
static void quiet(); static void quiet();
}; };
} // namespace WallReel::Core
#endif // WALLREEL_LOGGER_HPP #endif // WALLREEL_LOGGER_HPP
+14 -16
View File
@@ -3,12 +3,10 @@
#include <QColor> #include <QColor>
#include <iostream> #include <iostream>
#include "utils/logger.hpp" #include "Utils/texttemplate.hpp"
#include "utils/texttemplate.hpp" #include "logger.hpp"
using namespace GeneralLogger; WallReel::Core::WallpaperService::WallpaperService(
WallpaperService::WallpaperService(
const Config::ActionConfigItems& actionConfig, const Config::ActionConfigItems& actionConfig,
QObject* parent) QObject* parent)
: QObject(parent), m_actionConfig(actionConfig) { : QObject(parent), m_actionConfig(actionConfig) {
@@ -50,28 +48,28 @@ WallpaperService::WallpaperService(
}); });
} }
void WallpaperService::preview(const ImageData& imageData) { void WallReel::Core::WallpaperService::preview(const Image::Data& imageData) {
m_pendingImageData = &imageData; m_pendingImageData = &imageData;
m_previewDebounceTimer->start(); m_previewDebounceTimer->start();
} }
void WallpaperService::select(const ImageData& imageData) { void WallReel::Core::WallpaperService::select(const Image::Data& imageData) {
if (m_selectProcess->state() != QProcess::NotRunning) { if (m_selectProcess->state() != QProcess::NotRunning) {
warn("Previous select command is still running. Ignoring new command."); Logger::warn("Previous select command is still running. Ignoring new command.");
return; return;
} }
_doSelect(imageData); _doSelect(imageData);
} }
void WallpaperService::restore() { void WallReel::Core::WallpaperService::restore() {
if (m_restoreProcess->state() != QProcess::NotRunning) { if (m_restoreProcess->state() != QProcess::NotRunning) {
warn("Previous restore command is still running. Ignoring new command."); Logger::warn("Previous restore command is still running. Ignoring new command.");
return; return;
} }
_doRestore(); _doRestore();
} }
void WallpaperService::_doPreview(const ImageData& imageData) { void WallReel::Core::WallpaperService::_doPreview(const Image::Data& imageData) {
QString path = imageData.getFullPath(); QString path = imageData.getFullPath();
if (path.isEmpty()) { if (path.isEmpty()) {
@@ -86,7 +84,7 @@ void WallpaperService::_doPreview(const ImageData& imageData) {
{"path", path}, {"path", path},
{"name", imageData.getFileName()}, {"name", imageData.getFileName()},
}; };
auto command = renderTemplate(m_actionConfig.onPreview, variables); auto command = Utils::renderTemplate(m_actionConfig.onPreview, variables);
if (command.isEmpty()) { if (command.isEmpty()) {
return; return;
} }
@@ -98,7 +96,7 @@ void WallpaperService::_doPreview(const ImageData& imageData) {
m_previewProcess->start("sh", QStringList() << "-c" << command); m_previewProcess->start("sh", QStringList() << "-c" << command);
} }
void WallpaperService::_doSelect(const ImageData& imageData) { void WallReel::Core::WallpaperService::_doSelect(const Image::Data& imageData) {
QString path = imageData.getFullPath(); QString path = imageData.getFullPath();
if (path.isEmpty()) { if (path.isEmpty()) {
@@ -113,19 +111,19 @@ void WallpaperService::_doSelect(const ImageData& imageData) {
{"path", path}, {"path", path},
{"name", imageData.getFileName()}, {"name", imageData.getFileName()},
}; };
auto command = renderTemplate(m_actionConfig.onSelected, variables); auto command = Utils::renderTemplate(m_actionConfig.onSelected, variables);
if (command.isEmpty()) { if (command.isEmpty()) {
return; return;
} }
m_selectProcess->start("sh", QStringList() << "-c" << command); m_selectProcess->start("sh", QStringList() << "-c" << command);
} }
void WallpaperService::_doRestore() { void WallReel::Core::WallpaperService::_doRestore() {
if (m_actionConfig.onRestore.isEmpty()) { if (m_actionConfig.onRestore.isEmpty()) {
return; return;
} }
const QString command = renderTemplate(m_actionConfig.onRestore, m_actionConfig.saveState); const QString command = Utils::renderTemplate(m_actionConfig.onRestore, m_actionConfig.saveState);
if (command.isEmpty()) { if (command.isEmpty()) {
return; return;
} }
+12 -8
View File
@@ -4,8 +4,10 @@
#include <QProcess> #include <QProcess>
#include <QTimer> #include <QTimer>
#include "configmgr.hpp" #include "Config/manager.hpp"
#include "imagedata.hpp" #include "Image/data.hpp"
namespace WallReel::Core {
class WallpaperService : public QObject { class WallpaperService : public QObject {
Q_OBJECT Q_OBJECT
@@ -16,9 +18,9 @@ class WallpaperService : public QObject {
QObject* parent = nullptr); QObject* parent = nullptr);
public slots: public slots:
void preview(const ImageData& imageData); // execute after 500ms of inactivity void preview(const Image::Data& imageData); // execute after 500ms of inactivity
void select(const ImageData& imageData); // execute immediately, ignore if already running void select(const Image::Data& imageData); // execute immediately, ignore if already running
void restore(); // execute immediately, ignore if already running void restore(); // execute immediately, ignore if already running
signals: signals:
void previewCompleted(); void previewCompleted();
@@ -26,16 +28,18 @@ class WallpaperService : public QObject {
void restoreCompleted(); void restoreCompleted();
private: private:
void _doPreview(const ImageData& imageData); void _doPreview(const Image::Data& imageData);
void _doSelect(const ImageData& imageData); void _doSelect(const Image::Data& imageData);
void _doRestore(); void _doRestore();
const Config::ActionConfigItems& m_actionConfig; const Config::ActionConfigItems& m_actionConfig;
QTimer* m_previewDebounceTimer; QTimer* m_previewDebounceTimer;
const ImageData* m_pendingImageData; const Image::Data* m_pendingImageData;
QProcess* m_previewProcess; QProcess* m_previewProcess;
QProcess* m_selectProcess; QProcess* m_selectProcess;
QProcess* m_restoreProcess; QProcess* m_restoreProcess;
}; };
} // namespace WallReel::Core
#endif // WALLREEL_WALLPAPERSERVICE_HPP #endif // WALLREEL_WALLPAPERSERVICE_HPP
+42 -165
View File
@@ -1,149 +1,29 @@
#include <qobject.h>
#include <QApplication> #include <QApplication>
#include <QCommandLineParser>
#include <QDir>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext> #include <QQmlContext>
#include <QStandardPaths>
#include <QTextStream>
#include "Core/configmgr.hpp" #include "Core/Config/manager.hpp"
#include "Core/imagemodel.hpp" #include "Core/Image/model.hpp"
#include "Core/imageprovider.hpp" #include "Core/Image/provider.hpp"
#include "Core/palette/data.hpp" #include "Core/Palette/data.hpp"
#include "Core/palette/manager.hpp" #include "Core/Palette/manager.hpp"
#include "Core/utils/logger.hpp" #include "Core/Utils/misc.hpp"
#include "Core/utils/misc.hpp" #include "Core/appoptions.hpp"
#include "Core/logger.hpp"
#include "Core/wallpaperservice.hpp" #include "Core/wallpaperservice.hpp"
#include "version.h" #include "version.h"
/** using namespace WallReel::Core;
* @brief A static & single-instance class to handle application options.
*
*/
static class AppOptions {
QCommandLineParser parser{};
// The following 3 functions handle specific command line options
// and mark doReturn as true to indicate that the application should exit
// after parsing arguments.
// -v --version
void printVersion() {
QTextStream out(stdout);
out << APP_NAME << " version " << APP_VERSION << Qt::endl;
doReturn = true;
}
// -h --help
void printHelp() {
QTextStream out(stdout);
QString helpText = parser.helpText();
auto lines = helpText.split('\n');
for (auto& line : lines) {
if (line.contains("--help-all")) {
// Remove the --help-all option line added by Qt by default
continue;
}
out << line << Qt::endl;
}
doReturn = true;
}
// Print error message and help
void printError() {
if (!errorText.isEmpty()) {
QTextStream out(stderr);
out << errorText << Qt::endl;
printHelp();
}
doReturn = true;
}
public:
QString configPath = "";
QStringList appendDirs;
QString errorText = "";
bool doReturn = false; ///< Indicates whether the application should exit after parsing arguments.
void parseArgs(QApplication* a) {
parser.setApplicationDescription("A small wallpaper utility made with Qt");
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption versionOption = parser.addVersionOption();
QCommandLineOption verboseOption(QStringList() << "V" << "verbose", "Set log level to DEBUG (default is INFO)");
parser.addOption(verboseOption);
QCommandLineOption quietOption(QStringList() << "q" << "quiet", "Suppress all log output");
parser.addOption(quietOption);
QCommandLineOption appendDirOption(QStringList() << "d" << "append-dir", "Append an additional wallpaper search directory", "dir");
parser.addOption(appendDirOption);
QCommandLineOption configFileOption(QStringList() << "c" << "config-file", "Specify a custom configuration file", "file");
parser.addOption(configFileOption);
// Not parser.process(a->arguments()) because we want to handle exit logics ourselves.
// parser.process(...) will do something like exit(...) that will terminate
// the application brutally and produce unwanted warnings.
if (!parser.parse(a->arguments())) {
errorText = parser.errorText();
doReturn = true;
return;
}
if (parser.isSet(versionOption)) {
printVersion();
return;
}
if (parser.isSet(helpOption)) {
printHelp();
return;
}
if (parser.isSet(verboseOption)) {
Logger::setLogLevel(QtDebugMsg);
} else if (parser.isSet(quietOption)) {
Logger::quiet();
} else {
// Default to INFO level
Logger::setLogLevel(QtDebugMsg);
}
for (const QString& dir : parser.values(appendDirOption)) {
if (checkDir(dir)) {
appendDirs.append(dir);
} else {
errorText = QString("Error: Directory does not exist or is not accessible: %1").arg(dir);
printError();
return;
}
}
if (parser.isSet(configFileOption)) {
QString path = parser.value(configFileOption);
if (checkFile(path)) {
configPath = path;
} else {
errorText = QString("Error: Config file does not exist or is not accessible: %1").arg(path);
printError();
return;
}
}
}
} s_options;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
AppOptions s_options;
QApplication a(argc, argv); QApplication a(argc, argv);
a.setApplicationName(APP_NAME); a.setApplicationName(APP_NAME);
a.setApplicationVersion(APP_VERSION); a.setApplicationVersion(APP_VERSION);
Logger::init(); Logger::init();
s_options.parseArgs(&a); s_options.parseArgs(a);
if (s_options.doReturn) { if (s_options.doReturn) {
return s_options.errorText.isEmpty() ? 0 : 1; return s_options.errorText.isEmpty() ? 0 : 1;
@@ -151,50 +31,33 @@ int main(int argc, char* argv[]) {
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
ImageProvider* imageProvider = new ImageProvider(); auto* imageProvider = new Image::Provider();
engine.addImageProvider(QLatin1String("processed"), imageProvider); engine.addImageProvider(QLatin1String("processed"), imageProvider);
auto config = new Config( auto config = new Config::Manager(
::getConfigDir(), Utils::getConfigDir(),
s_options.appendDirs, s_options.appendDirs,
s_options.configPath, s_options.configPath,
imageProvider); imageProvider);
auto paletteMgr = new PaletteManager(
config->getPaletteConfig(),
&a);
engine.rootContext()->setContextProperty("PaletteManager", paletteMgr);
qRegisterMetaType<PaletteItem>();
qRegisterMetaType<ColorItem>();
auto imageModel = new ImageModel(
*imageProvider,
config->getSortConfig(),
config->getFocusImageSize(),
config);
auto wallpaperService = new WallpaperService(
config->getActionConfig(),
config);
QObject::connect(
imageModel,
&ImageModel::imageSelected,
wallpaperService,
&WallpaperService::select);
QObject::connect(
imageModel,
&ImageModel::imagePreviewed,
wallpaperService,
&WallpaperService::preview);
qmlRegisterSingletonInstance( qmlRegisterSingletonInstance(
COREMODULE_URI, COREMODULE_URI,
MODULE_VERSION_MAJOR, MODULE_VERSION_MAJOR,
MODULE_VERSION_MINOR, MODULE_VERSION_MINOR,
"Config", "Config",
config); config);
auto paletteMgr = new Palette::Manager(
config->getPaletteConfig(),
&a);
engine.rootContext()->setContextProperty("PaletteManager", paletteMgr);
qRegisterMetaType<Palette::PaletteItem>("PaletteItem");
qRegisterMetaType<Palette::ColorItem>("ColorItem");
auto imageModel = new Image::Model(
*imageProvider,
config->getSortConfig(),
config->getFocusImageSize(),
config);
qmlRegisterSingletonInstance( qmlRegisterSingletonInstance(
COREMODULE_URI, COREMODULE_URI,
MODULE_VERSION_MAJOR, MODULE_VERSION_MAJOR,
@@ -202,6 +65,20 @@ int main(int argc, char* argv[]) {
"ImageModel", "ImageModel",
imageModel); imageModel);
auto wallpaperService = new WallpaperService(
config->getActionConfig(),
config);
QObject::connect(
imageModel,
&Image::Model::imageSelected,
wallpaperService,
&WallpaperService::select);
QObject::connect(
imageModel,
&Image::Model::imagePreviewed,
wallpaperService,
&WallpaperService::preview);
QObject::connect( QObject::connect(
&engine, &engine,
&QQmlApplicationEngine::objectCreationFailed, &QQmlApplicationEngine::objectCreationFailed,