From fff2e564671e199be71140d379e0d2d50c5cec20 Mon Sep 17 00:00:00 2001 From: Uyanide Date: Tue, 17 Feb 2026 23:25:35 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20wip:=20=E2=99=BB=EF=B8=8F=20refa?= =?UTF-8?q?ctor:=20chekkupointo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 - Tests/CMakeLists.txt | 21 +- Tests/tst_configmgr.cpp | 32 +-- Tests/tst_imagemodel.cpp | 62 +++--- WallReel/Core/CMakeLists.txt | 21 +- .../{configmgr.cpp => Config/manager.cpp} | 73 +++--- .../{configmgr.hpp => Config/manager.hpp} | 127 +++++------ .../Core/{imagedata.cpp => Image/data.cpp} | 16 +- .../Core/{imagedata.hpp => Image/data.hpp} | 10 +- .../Core/{imagemodel.cpp => Image/model.cpp} | 51 +++-- .../Core/{imagemodel.hpp => Image/model.hpp} | 26 ++- .../{imageprovider.cpp => Image/provider.cpp} | 10 +- .../{imageprovider.hpp => Image/provider.hpp} | 14 +- WallReel/Core/{palette => Palette}/data.hpp | 8 +- .../Core/{palette => Palette}/manager.cpp | 2 +- .../Core/{palette => Palette}/manager.hpp | 12 +- .../Core/{palette => Palette}/predefined.hpp | 4 + .../Core/{utils => Utils}/colorextractor.hpp | 0 WallReel/Core/{utils => Utils}/misc.hpp | 4 + .../Core/{utils => Utils}/texttemplate.hpp | 4 + WallReel/Core/appoptions.cpp | 115 ++++++++++ WallReel/Core/appoptions.hpp | 35 +++ WallReel/Core/{utils => }/logger.cpp | 14 +- WallReel/Core/{utils => }/logger.hpp | 23 +- WallReel/Core/wallpaperservice.cpp | 30 ++- WallReel/Core/wallpaperservice.hpp | 20 +- WallReel/main.cpp | 207 ++++-------------- 27 files changed, 494 insertions(+), 451 deletions(-) rename WallReel/Core/{configmgr.cpp => Config/manager.cpp} (78%) rename WallReel/Core/{configmgr.hpp => Config/manager.hpp} (76%) rename WallReel/Core/{imagedata.cpp => Image/data.cpp} (79%) rename WallReel/Core/{imagedata.hpp => Image/data.hpp} (77%) rename WallReel/Core/{imagemodel.cpp => Image/model.cpp} (72%) rename WallReel/Core/{imagemodel.hpp => Image/model.hpp} (83%) rename WallReel/Core/{imageprovider.cpp => Image/provider.cpp} (54%) rename WallReel/Core/{imageprovider.hpp => Image/provider.hpp} (56%) rename WallReel/Core/{palette => Palette}/data.hpp (82%) rename WallReel/Core/{palette => Palette}/manager.cpp (97%) rename WallReel/Core/{palette => Palette}/manager.hpp (71%) rename WallReel/Core/{palette => Palette}/predefined.hpp (96%) rename WallReel/Core/{utils => Utils}/colorextractor.hpp (100%) rename WallReel/Core/{utils => Utils}/misc.hpp (98%) rename WallReel/Core/{utils => Utils}/texttemplate.hpp (98%) create mode 100644 WallReel/Core/appoptions.cpp create mode 100644 WallReel/Core/appoptions.hpp rename WallReel/Core/{utils => }/logger.cpp (90%) rename WallReel/Core/{utils => }/logger.hpp (71%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dff1e76..8303361 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,10 +64,6 @@ set_target_properties(${EXECUTABLE_NAME} PROPERTIES ) target_link_libraries(${EXECUTABLE_NAME} PRIVATE - Qt6::Quick - Qt6::Widgets - Qt6::QuickControls2 - Qt6::Concurrent ${CORELIB_NAME} ${UILIB_NAME} ) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index fe77169..159d5bb 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,7 +1,7 @@ project(Tests LANGUAGES CXX) -find_package(Qt6 REQUIRED COMPONENTS Core Test) +find_package(Qt6 REQUIRED COMPONENTS Test) add_executable(tst_configmgr tst_configmgr.cpp @@ -15,26 +15,11 @@ add_test(NAME tst_configmgr COMMAND tst_configmgr) add_test(NAME tst_imagemodel COMMAND tst_imagemodel) target_link_libraries(tst_configmgr PRIVATE - Qt6::Core Qt6::Test - Qt6::Gui - wallreel-core + ${CORELIB_NAME} ) target_link_libraries(tst_imagemodel PRIVATE - Qt6::Core Qt6::Test - Qt6::Gui - 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 + ${CORELIB_NAME} ) diff --git a/Tests/tst_configmgr.cpp b/Tests/tst_configmgr.cpp index 91a674e..267bba1 100644 --- a/Tests/tst_configmgr.cpp +++ b/Tests/tst_configmgr.cpp @@ -8,7 +8,9 @@ #include #include -#include "configmgr.hpp" +#include "Config/manager.hpp" + +using namespace WallReel::Core; class TestConfigMgr : public QObject { Q_OBJECT @@ -67,7 +69,7 @@ void TestConfigMgr::testDefaults() { // Empty config file writeConfig(QJsonObject()); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); // Check Style Defaults QCOMPARE(config.getImageWidth(), 320); @@ -144,7 +146,7 @@ void TestConfigMgr::testFullConfigParsing() { root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); // Assertions QCOMPARE(config.getWallpaperConfig().dirs.size(), 1); @@ -184,7 +186,7 @@ void TestConfigMgr::testInvalidConfigValues() { root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); // Should retain defaults QCOMPARE(config.getImageWidth(), 320); @@ -208,7 +210,7 @@ void TestConfigMgr::testWallpaperScanRecursive() { root["wallpaper"] = wallpaperObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QStringList wallpapers = config.getWallpapers(); QCOMPARE(wallpapers.size(), 2); @@ -235,7 +237,7 @@ void TestConfigMgr::testWallpaperScanNonRecursive() { root["wallpaper"] = wallpaperObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QStringList wallpapers = config.getWallpapers(); QCOMPARE(wallpapers.size(), 1); @@ -262,7 +264,7 @@ void TestConfigMgr::testWallpaperExcludes() { root["wallpaper"] = wallpaperObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QStringList wallpapers = config.getWallpapers(); QCOMPARE(wallpapers.size(), 1); @@ -281,7 +283,7 @@ void TestConfigMgr::testExplicitPaths() { root["wallpaper"] = wallpaperObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QStringList wallpapers = config.getWallpapers(); QCOMPARE(wallpapers.size(), 1); @@ -308,7 +310,7 @@ void TestConfigMgr::testImageExtensions() { root["wallpaper"] = wallpaperObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QStringList wallpapers = config.getWallpapers(); @@ -332,7 +334,7 @@ void TestConfigMgr::testSortTypes() { root["sort"] = sortObj; 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().reverse, false); } @@ -344,7 +346,7 @@ void TestConfigMgr::testSortTypes() { sortObj["reverse"] = true; root["sort"] = sortObj; 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().reverse, true); } @@ -355,7 +357,7 @@ void TestConfigMgr::testSortTypes() { sortObj["type"] = "size"; root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QCOMPARE(config.getSortConfig().type, Config::SortType::Size); } // 4. Date sort @@ -365,7 +367,7 @@ void TestConfigMgr::testSortTypes() { sortObj["type"] = "date"; root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QCOMPARE(config.getSortConfig().type, Config::SortType::Date); } // 5. Invalid sort -> fallback to default (Name) @@ -375,7 +377,7 @@ void TestConfigMgr::testSortTypes() { sortObj["type"] = "invalid_blah"; root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); // Default initialized in Config constructor is Name // But warning is logged QCOMPARE(config.getSortConfig().type, Config::SortType::Name); @@ -387,7 +389,7 @@ void TestConfigMgr::testSortTypes() { sortObj["type"] = "DaTe"; root["sort"] = sortObj; writeConfig(root); - Config config(m_tempDir.path(), {}, m_configPath); + Config::Manager config(m_tempDir.path(), {}, m_configPath); QCOMPARE(config.getSortConfig().type, Config::SortType::Date); } } diff --git a/Tests/tst_imagemodel.cpp b/Tests/tst_imagemodel.cpp index 60b1077..585f14c 100644 --- a/Tests/tst_imagemodel.cpp +++ b/Tests/tst_imagemodel.cpp @@ -3,9 +3,11 @@ #include #include -#include "configmgr.hpp" -#include "imagemodel.hpp" -#include "imageprovider.hpp" +#include "Config/manager.hpp" +#include "Image/model.hpp" +#include "Image/provider.hpp" + +using namespace WallReel::Core; class TestImageModel : public QObject { Q_OBJECT @@ -23,7 +25,7 @@ class TestImageModel : public QObject { QString m_pathC; void createTestFiles(); - void waitForModel(ImageModel* model); + void waitForModel(Image::Model* model); }; // clang-format off @@ -115,11 +117,11 @@ void TestImageModel::createTestFiles() { } } -void TestImageModel::waitForModel(ImageModel* model) { +void TestImageModel::waitForModel(Image::Model* model) { if (!model->isLoading()) { return; } - QSignalSpy spy(model, &ImageModel::isLoadingChanged); + QSignalSpy spy(model, &Image::Model::isLoadingChanged); while (model->isLoading()) { if (!spy.wait(5000)) { qWarning() << "Timeout waiting for model to load"; @@ -133,8 +135,8 @@ void TestImageModel::testSortName() { sortConfig.type = Config::SortType::Name; sortConfig.reverse = false; - ImageProvider provider; - ImageModel model(provider, sortConfig, QSize(100, 100)); + Image::Provider provider; + Image::Model model(provider, sortConfig, QSize(100, 100)); QStringList paths = {m_pathB, m_pathA, m_pathC}; // Unordered input model.loadAndProcess(paths); @@ -143,9 +145,9 @@ void TestImageModel::testSortName() { QCOMPARE(model.rowCount(), 3); // Expected: a.gif, b.gif, c.gif - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "a.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "b.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif"); // Reverse sortConfig.reverse = true; @@ -154,9 +156,9 @@ void TestImageModel::testSortName() { QCOMPARE(model.rowCount(), 3); // Expected: c.gif, b.gif, a.gif - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "b.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "a.gif"); } void TestImageModel::testSortDate() { @@ -164,8 +166,8 @@ void TestImageModel::testSortDate() { sortConfig.type = Config::SortType::Date; sortConfig.reverse = false; - ImageProvider provider; - ImageModel model(provider, sortConfig, QSize(100, 100)); + Image::Provider provider; + Image::Model model(provider, sortConfig, QSize(100, 100)); QStringList paths = {m_pathA, m_pathC, m_pathB}; model.loadAndProcess(paths); @@ -174,17 +176,17 @@ void TestImageModel::testSortDate() { QCOMPARE(model.rowCount(), 3); // Expected: c (old), a (mid), b (new) - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "b.gif"); // Reverse (Newest first) sortConfig.reverse = true; model.sortUpdate(); - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "b.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif"); } void TestImageModel::testSortSize() { @@ -192,8 +194,8 @@ void TestImageModel::testSortSize() { sortConfig.type = Config::SortType::Size; sortConfig.reverse = false; - ImageProvider provider; - ImageModel model(provider, sortConfig, QSize(100, 100)); + Image::Provider provider; + Image::Model model(provider, sortConfig, QSize(100, 100)); QStringList paths = {m_pathB, m_pathC, m_pathA}; model.loadAndProcess(paths); @@ -201,17 +203,17 @@ void TestImageModel::testSortSize() { QCOMPARE(model.rowCount(), 3); - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "c.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "b.gif"); // Reverse sortConfig.reverse = true; model.sortUpdate(); - QCOMPARE(model.data(model.index(0), ImageModel::NameRole).toString(), "b.gif"); - QCOMPARE(model.data(model.index(1), ImageModel::NameRole).toString(), "a.gif"); - QCOMPARE(model.data(model.index(2), ImageModel::NameRole).toString(), "c.gif"); + QCOMPARE(model.data(model.index(0), Image::Model::NameRole).toString(), "b.gif"); + QCOMPARE(model.data(model.index(1), Image::Model::NameRole).toString(), "a.gif"); + QCOMPARE(model.data(model.index(2), Image::Model::NameRole).toString(), "c.gif"); } QTEST_MAIN(TestImageModel) diff --git a/WallReel/Core/CMakeLists.txt b/WallReel/Core/CMakeLists.txt index 64cb752..444bdbb 100644 --- a/WallReel/Core/CMakeLists.txt +++ b/WallReel/Core/CMakeLists.txt @@ -2,24 +2,25 @@ qt_add_qml_module(${CORELIB_NAME} URI ${COREMODULE_URI} VERSION ${MODULE_VERSION_MAJOR}.${MODULE_VERSION_MINOR} SOURCES - imagedata.hpp imagedata.cpp - utils/logger.hpp utils/logger.cpp - utils/misc.hpp - configmgr.hpp configmgr.cpp - imagemodel.hpp imagemodel.cpp - imageprovider.hpp imageprovider.cpp + Image/data.hpp Image/data.cpp + Image/model.hpp Image/model.cpp + Image/provider.hpp Image/provider.cpp + Palette/data.hpp + Palette/manager.hpp Palette/manager.cpp + Config/manager.hpp Config/manager.cpp + logger.hpp logger.cpp wallpaperservice.hpp wallpaperservice.cpp - palette/data.hpp - palette/manager.hpp palette/manager.cpp + appoptions.hpp appoptions.cpp ) -target_link_libraries(${CORELIB_NAME} PRIVATE +target_link_libraries(${CORELIB_NAME} PUBLIC Qt6::Quick Qt6::Widgets Qt6::QuickControls2 Qt6::Concurrent ) -target_include_directories(${CORELIB_NAME} PRIVATE +target_include_directories(${CORELIB_NAME} PUBLIC ${CMAKE_BINARY_DIR}/generated + ${CMAKE_CURRENT_LIST_DIR} ) diff --git a/WallReel/Core/configmgr.cpp b/WallReel/Core/Config/manager.cpp similarity index 78% rename from WallReel/Core/configmgr.cpp rename to WallReel/Core/Config/manager.cpp index dca62dd..a4db166 100644 --- a/WallReel/Core/configmgr.cpp +++ b/WallReel/Core/Config/manager.cpp @@ -1,4 +1,4 @@ -#include "configmgr.hpp" +#include "manager.hpp" #include #include @@ -8,43 +8,40 @@ #include #include -#include "utils/logger.hpp" -#include "utils/misc.hpp" -using namespace GeneralLogger; +#include "Utils/misc.hpp" +#include "logger.hpp" -const QString Config::s_DefaultConfigFileName = "config.json"; - -Config::Config( +WallReel::Core::Config::Manager::Manager( const QString& configDir, const QStringList& searchDirs, const QString& configPath, QObject* parent) : QObject(parent), m_configDir(configDir) { if (configPath.isEmpty()) { - info(QString("Configuration directory: %1").arg(configDir)); + Logger::info(QString("Configuration directory: %1").arg(configDir)); _loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName); } else { _loadConfig(configPath); } 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) { m_wallpaperConfig.dirs.append({dir, false}); } } - debug("Loading wallpapers ..."); + Logger::debug("Loading wallpapers ..."); _loadWallpapers(); } -Config::~Config() { +WallReel::Core::Config::Manager::~Manager() { } -void Config::_loadConfig(const QString& configPath) { - info(QString("Loading configuration from: %1").arg(configPath)); +void WallReel::Core::Config::Manager::_loadConfig(const QString& configPath) { + Logger::info(QString("Loading configuration from: %1").arg(configPath)); QFile configFile(configPath); 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; } QByteArray configData = configFile.readAll(); @@ -52,7 +49,7 @@ void Config::_loadConfig(const QString& configPath) { QJsonDocument jsonDoc = QJsonDocument::fromJson(configData); if (jsonDoc.isNull() || !jsonDoc.isObject()) { - critical(QString("Invalid JSON format in config file")); + Logger::critical(QString("Invalid JSON format in config file")); return; } @@ -65,7 +62,7 @@ void Config::_loadConfig(const QString& configPath) { _loadSortConfig(jsonObj); } -void Config::_loadWallpaperConfig(const QJsonObject& root) { +void WallReel::Core::Config::Manager::_loadWallpaperConfig(const QJsonObject& root) { if (!root.contains("wallpaper") || !root["wallpaper"].isObject()) { return; } @@ -74,7 +71,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) { if (config.contains("paths") && config["paths"].isArray()) { for (const auto& item : config["paths"].toArray()) { 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(); if (obj.contains("path") && obj["path"].isString()) { WallpaperConfigItems::WallpaperDirConfigItem dirConfig; - dirConfig.path = ::expandPath(obj["path"].toString()); + dirConfig.path = Utils::expandPath(obj["path"].toString()); if (obj.contains("recursive") && obj["recursive"].isBool()) { dirConfig.recursive = obj["recursive"].toBool(); } else { @@ -102,7 +99,7 @@ void Config::_loadWallpaperConfig(const QJsonObject& root) { if (item.isString()) { auto regex = QRegularExpression(item.toString()); 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 { 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()) { return; } @@ -137,7 +134,7 @@ void Config::_loadPaletteConfig(const QJsonObject& root) { if (color.isValid()) { colorConfig.value = color; } 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()) { @@ -145,7 +142,7 @@ void Config::_loadPaletteConfig(const QJsonObject& root) { if (color.isValid()) { colorConfig.value = color; } 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()) { @@ -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()) { 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()) { 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()) { return; } @@ -270,7 +267,7 @@ void Config::_loadSortConfig(const QJsonObject& root) { } else if (type == "size") { m_sortConfig.type = SortType::Size; } 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(); QSet 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)) { 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)) { - if (checkDir(dirConfig.path)) { + if (Utils::checkDir(dirConfig.path)) { std::function scanDir; scanDir = [&](const QDir& d) { QStringList files = d.entryList(QDir::Files | QDir::NoDotAndDotDot); for (const QString& file : std::as_const(files)) { QString filePath = d.filePath(file); - paths.insert(expandPath(filePath)); + paths.insert(Utils::expandPath(filePath)); } if (dirConfig.recursive) { 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)) { scanDir(QDir(d.filePath(subDir))); } @@ -313,17 +310,17 @@ void Config::_loadWallpapers() { }; scanDir(QDir(dirConfig.path)); } 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; for (const auto& exclude : std::as_const(m_wallpaperConfig.excludes)) { for (const QString& path : std::as_const(paths)) { if (exclude.match(path).hasMatch()) { 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()); for (const QString& path : paths) { - if (checkImageFile(path)) { + if (Utils::checkImageFile(path)) { m_wallpapers.append(path); } 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())); } diff --git a/WallReel/Core/configmgr.hpp b/WallReel/Core/Config/manager.hpp similarity index 76% rename from WallReel/Core/configmgr.hpp rename to WallReel/Core/Config/manager.hpp index ce5bc6d..32795ef 100644 --- a/WallReel/Core/configmgr.hpp +++ b/WallReel/Core/Config/manager.hpp @@ -1,8 +1,6 @@ #ifndef WALLREEL_CONFIGMGR_HPP #define WALLREEL_CONFIGMGR_HPP -#include - #include #include #include @@ -44,7 +42,67 @@ // date: older before newer // 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 dirs; + QList excludes; +}; + +struct PaletteConfigItems { + struct PaletteColorConfigItem { + QString name; + QColor value; + }; + + struct PaletteConfigItem { + QString name; + QList colors; + }; + + QList palettes; +}; + +struct ActionConfigItems { + + QHash 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_PROPERTY(int imageWidth READ getImageWidth CONSTANT) @@ -54,69 +112,13 @@ class Config : public QObject { Q_PROPERTY(int windowHeight READ getWindowHeight CONSTANT) public: - enum class SortType : int { - None = 0, // "none" - Name, // "name" - Date, // "date" - Size, // "size" - }; - - struct WallpaperConfigItems { - struct WallpaperDirConfigItem { - QString path; - bool recursive; - }; - - QStringList paths; - QList dirs; - QList excludes; - }; - - struct PaletteConfigItems { - struct PaletteColorConfigItem { - QString name; - QColor value; - }; - - struct PaletteConfigItem { - QString name; - QList colors; - }; - - QList palettes; - }; - - struct ActionConfigItems { - - QHash 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( + Manager( const QString& configDir, const QStringList& searchDirs = {}, const QString& configPath = "", // Override the default config path QObject* parent = nullptr); - ~Config(); + ~Manager(); 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; } - static const QString s_DefaultConfigFileName; const QString m_configDir; private: @@ -168,4 +169,6 @@ class Config : public QObject { QStringList m_wallpapers; }; +} // namespace WallReel::Core::Config + #endif // WALLREEL_CONFIGMGR_HPP diff --git a/WallReel/Core/imagedata.cpp b/WallReel/Core/Image/data.cpp similarity index 79% rename from WallReel/Core/imagedata.cpp rename to WallReel/Core/Image/data.cpp index 9d1ded5..3f3f325 100644 --- a/WallReel/Core/imagedata.cpp +++ b/WallReel/Core/Image/data.cpp @@ -1,13 +1,11 @@ -#include "imagedata.hpp" +#include "data.hpp" #include -#include "utils/logger.hpp" +#include "../logger.hpp" -using namespace GeneralLogger; - -ImageData* ImageData::create(const QString& path, const QSize& size) { - ImageData* ret = new ImageData(path, size); +WallReel::Core::Image::Data* WallReel::Core::Image::Data::create(const QString& path, const QSize& size) { + Data* ret = new Data(path, size); if (!ret->isValid()) { delete ret; return nullptr; @@ -15,11 +13,11 @@ ImageData* ImageData::create(const QString& path, const QSize& size) { return ret; } -ImageData::ImageData(const QString& path, const QSize& targetSize) +WallReel::Core::Image::Data::Data(const QString& path, const QSize& targetSize) : m_file(path) { QImageReader reader(path); 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; } @@ -39,7 +37,7 @@ ImageData::ImageData(const QString& path, const QSize& targetSize) } 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; } diff --git a/WallReel/Core/imagedata.hpp b/WallReel/Core/Image/data.hpp similarity index 77% rename from WallReel/Core/imagedata.hpp rename to WallReel/Core/Image/data.hpp index 429a365..9e90a89 100644 --- a/WallReel/Core/imagedata.hpp +++ b/WallReel/Core/Image/data.hpp @@ -4,15 +4,17 @@ #include #include -class ImageData { +namespace WallReel::Core::Image { + +class Data { QString m_id; QFileInfo m_file; QImage m_image; - ImageData(const QString& path, const QSize& size); + Data(const QString& path, const QSize& size); 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; } @@ -33,4 +35,6 @@ class ImageData { private: }; +} // namespace WallReel::Core::Image + #endif // WALLREEL_IMAGEDATA_HPP diff --git a/WallReel/Core/imagemodel.cpp b/WallReel/Core/Image/model.cpp similarity index 72% rename from WallReel/Core/imagemodel.cpp rename to WallReel/Core/Image/model.cpp index eaeb854..ec40e0e 100644 --- a/WallReel/Core/imagemodel.cpp +++ b/WallReel/Core/Image/model.cpp @@ -1,13 +1,12 @@ - -#include "imagemodel.hpp" +#include "model.hpp" #include #include -#include "imagedata.hpp" +#include "data.hpp" -ImageModel::ImageModel( - ImageProvider& provider, +WallReel::Core::Image::Model::Model( + Provider& provider, const Config::SortConfigItems& sortConfig, QSize thumbnailSize, QObject* parent) @@ -17,9 +16,9 @@ ImageModel::ImageModel( m_thumbnailSize(thumbnailSize) { connect( &m_watcher, - &QFutureWatcher::finished, + &QFutureWatcher::finished, this, - &ImageModel::_onProcessingFinished); + &Model::_onProcessingFinished); connect( &m_progressUpdateTimer, &QTimer::timeout, @@ -29,21 +28,21 @@ ImageModel::ImageModel( }); } -ImageModel::~ImageModel() { +WallReel::Core::Image::Model::~Model() { m_watcher.cancel(); m_watcher.waitForFinished(); qDeleteAll(m_data); m_data.clear(); } -int ImageModel::rowCount(const QModelIndex& parent) const { +int WallReel::Core::Image::Model::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } 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()) { 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) { return; } @@ -72,10 +71,10 @@ void ImageModel::loadAndProcess(const QStringList& paths) { m_processedCount = 0; m_progressUpdateTimer.start(s_ProgressUpdateIntervalMs); - const auto thumbnailSize = m_thumbnailSize; - const auto counterPtr = &m_processedCount; - QFuture future = QtConcurrent::mapped(paths, [thumbnailSize, counterPtr](const QString& path) { - auto data = ImageData::create(path, thumbnailSize); + const auto thumbnailSize = m_thumbnailSize; + const auto counterPtr = &m_processedCount; + QFuture future = QtConcurrent::mapped(paths, [thumbnailSize, counterPtr](const QString& path) { + auto data = Data::create(path, thumbnailSize); counterPtr->fetch_add(1, std::memory_order_relaxed); return data; }); @@ -83,18 +82,18 @@ void ImageModel::loadAndProcess(const QStringList& paths) { emit totalCountChanged(); } -void ImageModel::stop() { +void WallReel::Core::Image::Model::stop() { if (m_isLoading) { m_watcher.cancel(); } } -void ImageModel::_onProgressValueChanged(int value) { +void WallReel::Core::Image::Model::_onProgressValueChanged(int value) { Q_UNUSED(value); emit progressChanged(); } -void ImageModel::_onProcessingFinished() { +void WallReel::Core::Image::Model::_onProcessingFinished() { auto results = m_watcher.future().results(); for (auto& data : results) { 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 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) { return false; } @@ -127,8 +126,8 @@ void ImageModel::sortUpdate() { return false; } - ImageData* first = reverse ? b : a; - ImageData* second = reverse ? a : b; + Data* first = reverse ? b : a; + Data* second = reverse ? a : b; switch (type) { case Config::SortType::Name: @@ -150,7 +149,7 @@ void ImageModel::sortUpdate() { 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()) { 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(); m_provider.clear(); qDeleteAll(m_data); @@ -175,7 +174,7 @@ void ImageModel::_clearData() { endResetModel(); } -void ImageModel::selectImage(int index) { +void WallReel::Core::Image::Model::selectImage(int index) { if (index < 0 || index >= m_data.count()) { 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()) { return; } diff --git a/WallReel/Core/imagemodel.hpp b/WallReel/Core/Image/model.hpp similarity index 83% rename from WallReel/Core/imagemodel.hpp rename to WallReel/Core/Image/model.hpp index 7987a2d..4d39ccf 100644 --- a/WallReel/Core/imagemodel.hpp +++ b/WallReel/Core/Image/model.hpp @@ -6,10 +6,12 @@ #include #include -#include "configmgr.hpp" -#include "imageprovider.hpp" +#include "Config/manager.hpp" +#include "provider.hpp" -class ImageModel : public QAbstractListModel { +namespace WallReel::Core::Image { + +class Model : public QAbstractListModel { Q_OBJECT Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged) @@ -31,13 +33,13 @@ class ImageModel : public QAbstractListModel { }; } - ImageModel( - ImageProvider& provider, + Model( + Provider& provider, const Config::SortConfigItems& sortConfig, QSize thumbnailSize, QObject* parent = nullptr); - ~ImageModel(); + ~Model(); bool isLoading() const { return m_isLoading; } @@ -68,21 +70,21 @@ class ImageModel : public QAbstractListModel { void isLoadingChanged(); void progressChanged(); void totalCountChanged(); - void imageSelected(const ImageData& imageData); - void imagePreviewed(const ImageData& imageData); + void imageSelected(const Data& imageData); + void imagePreviewed(const Data& imageData); private slots: void _onProgressValueChanged(int value); void _onProcessingFinished(); private: - ImageProvider& m_provider; + Provider& m_provider; const Config::SortConfigItems& m_sortConfig; QSize m_thumbnailSize; - QVector m_data; + QVector m_data; - QFutureWatcher m_watcher; + QFutureWatcher m_watcher; bool m_isLoading = false; std::atomic m_processedCount{0}; @@ -91,4 +93,6 @@ class ImageModel : public QAbstractListModel { static constexpr int s_IsLoadingUpdateIntervalMs = 50; }; +} // namespace WallReel::Core::Image + #endif // WALLREEL_IMAGEMODEL_HPP diff --git a/WallReel/Core/imageprovider.cpp b/WallReel/Core/Image/provider.cpp similarity index 54% rename from WallReel/Core/imageprovider.cpp rename to WallReel/Core/Image/provider.cpp index 2131123..d108d82 100644 --- a/WallReel/Core/imageprovider.cpp +++ b/WallReel/Core/Image/provider.cpp @@ -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); if (!m_images.contains(id)) { return QImage(); } - ImageData* data = m_images[id]; + Data* data = m_images[id]; if (size) { *size = data->getImage().size(); } return data->getImage(); } -void ImageProvider::insert(ImageData* data) { +void WallReel::Core::Image::Provider::insert(Data* data) { QMutexLocker locker(&m_mutex); m_images.insert(data->getId(), data); } -void ImageProvider::clear() { +void WallReel::Core::Image::Provider::clear() { QMutexLocker locker(&m_mutex); m_images.clear(); } diff --git a/WallReel/Core/imageprovider.hpp b/WallReel/Core/Image/provider.hpp similarity index 56% rename from WallReel/Core/imageprovider.hpp rename to WallReel/Core/Image/provider.hpp index 6329d81..db2a1fd 100644 --- a/WallReel/Core/imageprovider.hpp +++ b/WallReel/Core/Image/provider.hpp @@ -5,23 +5,27 @@ #include #include -#include "imagedata.hpp" +#include "data.hpp" -class ImageProvider : public QQuickImageProvider { +namespace WallReel::Core::Image { + +class Provider : public QQuickImageProvider { Q_OBJECT public: - ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) {} + Provider() : QQuickImageProvider(QQuickImageProvider::Image) {} QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize) override; - void insert(ImageData* data); + void insert(Data* data); void clear(); private: QMutex m_mutex; - QHash m_images; + QHash m_images; }; +} // namespace WallReel::Core::Image + #endif // WALLREEL_IMAGEPROVIDER_HPP diff --git a/WallReel/Core/palette/data.hpp b/WallReel/Core/Palette/data.hpp similarity index 82% rename from WallReel/Core/palette/data.hpp rename to WallReel/Core/Palette/data.hpp index 59e00e4..c13b687 100644 --- a/WallReel/Core/palette/data.hpp +++ b/WallReel/Core/Palette/data.hpp @@ -6,6 +6,8 @@ #include #include +namespace WallReel::Core::Palette { + struct ColorItem { Q_GADGET Q_PROPERTY(QString name MEMBER name CONSTANT) @@ -37,7 +39,9 @@ struct PaletteItem { } }; -Q_DECLARE_METATYPE(ColorItem) -Q_DECLARE_METATYPE(PaletteItem) +} // namespace WallReel::Core::Palette + +Q_DECLARE_METATYPE(WallReel::Core::Palette::ColorItem) +Q_DECLARE_METATYPE(WallReel::Core::Palette::PaletteItem) #endif // WALLREEL_PALETTE_DATA_HPP diff --git a/WallReel/Core/palette/manager.cpp b/WallReel/Core/Palette/manager.cpp similarity index 97% rename from WallReel/Core/palette/manager.cpp rename to WallReel/Core/Palette/manager.cpp index 7c780cc..3e957a1 100644 --- a/WallReel/Core/palette/manager.cpp +++ b/WallReel/Core/Palette/manager.cpp @@ -2,7 +2,7 @@ #include "predefined.hpp" -PaletteManager::PaletteManager( +WallReel::Core::Palette::Manager::Manager( const Config::PaletteConfigItems& config, QObject* parent) : QObject(parent) { // The new ones overrides the old ones, use a hashtable to track diff --git a/WallReel/Core/palette/manager.hpp b/WallReel/Core/Palette/manager.hpp similarity index 71% rename from WallReel/Core/palette/manager.hpp rename to WallReel/Core/Palette/manager.hpp index 9c0fa11..fca4cf1 100644 --- a/WallReel/Core/palette/manager.hpp +++ b/WallReel/Core/Palette/manager.hpp @@ -1,16 +1,18 @@ #ifndef WALLREEL_PALETTE_MANAGER_HPP #define WALLREEL_PALETTE_MANAGER_HPP -#include "../configmgr.hpp" +#include "Config/manager.hpp" #include "data.hpp" -class PaletteManager : public QObject { +namespace WallReel::Core::Palette { + +class Manager : public QObject { Q_OBJECT Q_PROPERTY(QList availablePalettes READ availablePalettes CONSTANT) public: - PaletteManager(const Config::PaletteConfigItems& config, - QObject* parent = nullptr); + Manager(const Config::PaletteConfigItems& config, + QObject* parent = nullptr); const QList& availablePalettes() const { return m_palettes; @@ -27,4 +29,6 @@ class PaletteManager : public QObject { QList m_palettes; }; +} // namespace WallReel::Core::Palette + #endif // WALLREEL_PALETTE_MANAGER_HPP diff --git a/WallReel/Core/palette/predefined.hpp b/WallReel/Core/Palette/predefined.hpp similarity index 96% rename from WallReel/Core/palette/predefined.hpp rename to WallReel/Core/Palette/predefined.hpp index d7589f4..4d2b1eb 100644 --- a/WallReel/Core/palette/predefined.hpp +++ b/WallReel/Core/Palette/predefined.hpp @@ -3,6 +3,8 @@ #include "data.hpp" +namespace WallReel::Core::Palette { + inline const QList preDefinedPalettes = { { @@ -85,4 +87,6 @@ inline const QList preDefinedPalettes = { }, }; +} // namespace WallReel::Core::Palette + #endif // WALLREEL_PALETTES_PREDEFINED_HPP diff --git a/WallReel/Core/utils/colorextractor.hpp b/WallReel/Core/Utils/colorextractor.hpp similarity index 100% rename from WallReel/Core/utils/colorextractor.hpp rename to WallReel/Core/Utils/colorextractor.hpp diff --git a/WallReel/Core/utils/misc.hpp b/WallReel/Core/Utils/misc.hpp similarity index 98% rename from WallReel/Core/utils/misc.hpp rename to WallReel/Core/Utils/misc.hpp index 12ae249..3658337 100644 --- a/WallReel/Core/utils/misc.hpp +++ b/WallReel/Core/Utils/misc.hpp @@ -11,6 +11,8 @@ #include "version.h" +namespace WallReel::Core::Utils { + /** * @brief Defer execution of a callable until the end of the current scope. * @@ -130,4 +132,6 @@ inline QString getConfigDir() { return configDir; } +} // namespace WallReel::Core::Utils + #endif // WALLREEL_MISC_HPP diff --git a/WallReel/Core/utils/texttemplate.hpp b/WallReel/Core/Utils/texttemplate.hpp similarity index 98% rename from WallReel/Core/utils/texttemplate.hpp rename to WallReel/Core/Utils/texttemplate.hpp index d045516..b866fca 100644 --- a/WallReel/Core/utils/texttemplate.hpp +++ b/WallReel/Core/Utils/texttemplate.hpp @@ -5,6 +5,8 @@ #include #include +namespace WallReel::Core::Utils { + /** * @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; } +} // namespace WallReel::Core::Utils + #endif // TEXTTEMPLATE_HPP diff --git a/WallReel/Core/appoptions.cpp b/WallReel/Core/appoptions.cpp new file mode 100644 index 0000000..a1d0dd3 --- /dev/null +++ b/WallReel/Core/appoptions.cpp @@ -0,0 +1,115 @@ +#include "appoptions.hpp" + +#include +#include +#include + +#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 diff --git a/WallReel/Core/appoptions.hpp b/WallReel/Core/appoptions.hpp new file mode 100644 index 0000000..e127ad1 --- /dev/null +++ b/WallReel/Core/appoptions.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +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 diff --git a/WallReel/Core/utils/logger.cpp b/WallReel/Core/logger.cpp similarity index 90% rename from WallReel/Core/utils/logger.cpp rename to WallReel/Core/logger.cpp index 387dd8e..3adf80b 100644 --- a/WallReel/Core/utils/logger.cpp +++ b/WallReel/Core/logger.cpp @@ -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) { delete s_logStream; s_logStream = new QTextStream(stream); @@ -81,7 +81,7 @@ void Logger::init(FILE* stream) { qInstallMessageHandler(messageOutput); } -void Logger::setLogLevel(QtMsgType level) { +void WallReel::Core::Logger::setLogLevel(QtMsgType level) { switch (level) { case QtDebugMsg: 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)); } -void GeneralLogger::debug(const QString& msg) { +void WallReel::Core::Logger::debug(const QString& msg) { qCDebug(logMain).noquote() << msg; } -void GeneralLogger::info(const QString& msg) { +void WallReel::Core::Logger::info(const QString& msg) { qCInfo(logMain).noquote() << msg; } -void GeneralLogger::warn(const QString& msg) { +void WallReel::Core::Logger::warn(const QString& msg) { qCWarning(logMain).noquote() << msg; } -void GeneralLogger::critical(const QString& msg) { +void WallReel::Core::Logger::critical(const QString& msg) { qCCritical(logMain).noquote() << msg; } diff --git a/WallReel/Core/utils/logger.hpp b/WallReel/Core/logger.hpp similarity index 71% rename from WallReel/Core/utils/logger.hpp rename to WallReel/Core/logger.hpp index 17c0b42..3fff574 100644 --- a/WallReel/Core/utils/logger.hpp +++ b/WallReel/Core/logger.hpp @@ -7,20 +7,17 @@ Q_DECLARE_LOGGING_CATEGORY(logMain) -namespace GeneralLogger { - -void debug(const QString& msg); - -void info(const QString& msg); - -void warn(const QString& msg); - -void critical(const QString& msg); - -} // namespace GeneralLogger - +namespace WallReel::Core { class Logger { 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. * @@ -42,4 +39,6 @@ class Logger { static void quiet(); }; +} // namespace WallReel::Core + #endif // WALLREEL_LOGGER_HPP diff --git a/WallReel/Core/wallpaperservice.cpp b/WallReel/Core/wallpaperservice.cpp index 206e962..46b1b8c 100644 --- a/WallReel/Core/wallpaperservice.cpp +++ b/WallReel/Core/wallpaperservice.cpp @@ -3,12 +3,10 @@ #include #include -#include "utils/logger.hpp" -#include "utils/texttemplate.hpp" +#include "Utils/texttemplate.hpp" +#include "logger.hpp" -using namespace GeneralLogger; - -WallpaperService::WallpaperService( +WallReel::Core::WallpaperService::WallpaperService( const Config::ActionConfigItems& actionConfig, QObject* parent) : 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_previewDebounceTimer->start(); } -void WallpaperService::select(const ImageData& imageData) { +void WallReel::Core::WallpaperService::select(const Image::Data& imageData) { 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; } _doSelect(imageData); } -void WallpaperService::restore() { +void WallReel::Core::WallpaperService::restore() { 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; } _doRestore(); } -void WallpaperService::_doPreview(const ImageData& imageData) { +void WallReel::Core::WallpaperService::_doPreview(const Image::Data& imageData) { QString path = imageData.getFullPath(); if (path.isEmpty()) { @@ -86,7 +84,7 @@ void WallpaperService::_doPreview(const ImageData& imageData) { {"path", path}, {"name", imageData.getFileName()}, }; - auto command = renderTemplate(m_actionConfig.onPreview, variables); + auto command = Utils::renderTemplate(m_actionConfig.onPreview, variables); if (command.isEmpty()) { return; } @@ -98,7 +96,7 @@ void WallpaperService::_doPreview(const ImageData& imageData) { 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(); if (path.isEmpty()) { @@ -113,19 +111,19 @@ void WallpaperService::_doSelect(const ImageData& imageData) { {"path", path}, {"name", imageData.getFileName()}, }; - auto command = renderTemplate(m_actionConfig.onSelected, variables); + auto command = Utils::renderTemplate(m_actionConfig.onSelected, variables); if (command.isEmpty()) { return; } m_selectProcess->start("sh", QStringList() << "-c" << command); } -void WallpaperService::_doRestore() { +void WallReel::Core::WallpaperService::_doRestore() { if (m_actionConfig.onRestore.isEmpty()) { 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()) { return; } diff --git a/WallReel/Core/wallpaperservice.hpp b/WallReel/Core/wallpaperservice.hpp index ca641d2..aac6c0f 100644 --- a/WallReel/Core/wallpaperservice.hpp +++ b/WallReel/Core/wallpaperservice.hpp @@ -4,8 +4,10 @@ #include #include -#include "configmgr.hpp" -#include "imagedata.hpp" +#include "Config/manager.hpp" +#include "Image/data.hpp" + +namespace WallReel::Core { class WallpaperService : public QObject { Q_OBJECT @@ -16,9 +18,9 @@ class WallpaperService : public QObject { QObject* parent = nullptr); public slots: - void preview(const ImageData& imageData); // execute after 500ms of inactivity - void select(const ImageData& imageData); // execute immediately, ignore if already running - void restore(); // execute immediately, ignore if already running + void preview(const Image::Data& imageData); // execute after 500ms of inactivity + void select(const Image::Data& imageData); // execute immediately, ignore if already running + void restore(); // execute immediately, ignore if already running signals: void previewCompleted(); @@ -26,16 +28,18 @@ class WallpaperService : public QObject { void restoreCompleted(); private: - void _doPreview(const ImageData& imageData); - void _doSelect(const ImageData& imageData); + void _doPreview(const Image::Data& imageData); + void _doSelect(const Image::Data& imageData); void _doRestore(); const Config::ActionConfigItems& m_actionConfig; QTimer* m_previewDebounceTimer; - const ImageData* m_pendingImageData; + const Image::Data* m_pendingImageData; QProcess* m_previewProcess; QProcess* m_selectProcess; QProcess* m_restoreProcess; }; +} // namespace WallReel::Core + #endif // WALLREEL_WALLPAPERSERVICE_HPP diff --git a/WallReel/main.cpp b/WallReel/main.cpp index e97209b..f036258 100644 --- a/WallReel/main.cpp +++ b/WallReel/main.cpp @@ -1,149 +1,29 @@ -#include - #include -#include -#include #include #include -#include -#include -#include "Core/configmgr.hpp" -#include "Core/imagemodel.hpp" -#include "Core/imageprovider.hpp" -#include "Core/palette/data.hpp" -#include "Core/palette/manager.hpp" -#include "Core/utils/logger.hpp" -#include "Core/utils/misc.hpp" +#include "Core/Config/manager.hpp" +#include "Core/Image/model.hpp" +#include "Core/Image/provider.hpp" +#include "Core/Palette/data.hpp" +#include "Core/Palette/manager.hpp" +#include "Core/Utils/misc.hpp" +#include "Core/appoptions.hpp" +#include "Core/logger.hpp" #include "Core/wallpaperservice.hpp" #include "version.h" -/** - * @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; +using namespace WallReel::Core; int main(int argc, char* argv[]) { + AppOptions s_options; + QApplication a(argc, argv); a.setApplicationName(APP_NAME); a.setApplicationVersion(APP_VERSION); Logger::init(); - s_options.parseArgs(&a); + s_options.parseArgs(a); if (s_options.doReturn) { return s_options.errorText.isEmpty() ? 0 : 1; @@ -151,50 +31,33 @@ int main(int argc, char* argv[]) { QQmlApplicationEngine engine; - ImageProvider* imageProvider = new ImageProvider(); + auto* imageProvider = new Image::Provider(); engine.addImageProvider(QLatin1String("processed"), imageProvider); - auto config = new Config( - ::getConfigDir(), + auto config = new Config::Manager( + Utils::getConfigDir(), s_options.appendDirs, s_options.configPath, imageProvider); - - auto paletteMgr = new PaletteManager( - config->getPaletteConfig(), - &a); - engine.rootContext()->setContextProperty("PaletteManager", paletteMgr); - qRegisterMetaType(); - qRegisterMetaType(); - - 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( COREMODULE_URI, MODULE_VERSION_MAJOR, MODULE_VERSION_MINOR, "Config", config); + + auto paletteMgr = new Palette::Manager( + config->getPaletteConfig(), + &a); + engine.rootContext()->setContextProperty("PaletteManager", paletteMgr); + qRegisterMetaType("PaletteItem"); + qRegisterMetaType("ColorItem"); + + auto imageModel = new Image::Model( + *imageProvider, + config->getSortConfig(), + config->getFocusImageSize(), + config); qmlRegisterSingletonInstance( COREMODULE_URI, MODULE_VERSION_MAJOR, @@ -202,6 +65,20 @@ int main(int argc, char* argv[]) { "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( &engine, &QQmlApplicationEngine::objectCreationFailed,