diff --git a/config.example.json b/config.example.json index 4caeb9c..2dc5a1b 100644 --- a/config.example.json +++ b/config.example.json @@ -4,8 +4,7 @@ "~/Pictures/116327446_p0.jpg" ], "dirs": [ - "~/.config/backgrounds", - "/run/media/kolkas/移硬1T/逆流茶会/" + "~/.config/backgrounds" ], "excludes": [ "~/.config/backgrounds/nao-stars-crop-adjust-flop.jpg", @@ -13,7 +12,7 @@ "~/.config/backgrounds/README.md" ] }, - "actions": { + "action": { "confirm": "~/.scripts/change-wallpaper.sh \"%1\"" }, "style": { @@ -22,7 +21,7 @@ "image_focus_width": 480, "window_width": 750, "window_height": 500, - "no_loading_screen": true + "no_loading_screen": false }, "sort": { "type": "name", diff --git a/src/config.cpp b/src/config.cpp index 529592f..9949628 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 01:34:52 - * @LastEditTime: 2025-08-07 22:02:55 + * @LastEditTime: 2025-08-07 22:27:50 * @Description: Configuration manager. */ #include "config.h" @@ -19,6 +19,23 @@ using namespace GeneralLogger; static QString expandPath(const QString &path); +const QString Config::s_DefaultConfigFileName = "config.json"; + +Config::Config(const QString &configDir, const QStringList &searchDirs, QObject *parent) + : QObject(parent), m_configDir(configDir) { + info(QString("Loading configuration from: %1").arg(configDir)); + _loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName); + + info(QString("Additional search directories: %1").arg(searchDirs.join(", "))); + m_wallpaperConfig.dirs.append(searchDirs); + + info("Loading wallpapers ..."); + _loadWallpapers(); +} + +Config::~Config() { +} + void Config::_loadConfig(const QString &configPath) { QFile configFile(configPath); if (!configFile.open(QIODevice::ReadOnly)) { @@ -55,77 +72,77 @@ void Config::_loadConfig(const QString &configPath) { std::vector mappings = { {"wallpaper.paths", "paths", [this](const QJsonValue &val) { - parseJsonArray(val, m_configItems.wallpaperPaths); + parseJsonArray(val, m_wallpaperConfig.paths); }}, {"wallpaper.dirs", "dirs", [this](const QJsonValue &val) { - parseJsonArray(val, m_configItems.wallpaperDirs); + parseJsonArray(val, m_wallpaperConfig.dirs); }}, {"wallpaper.excludes", "excludes", [this](const QJsonValue &val) { - parseJsonArray(val, m_configItems.wallpaperExcludes); + parseJsonArray(val, m_wallpaperConfig.excludes); }}, - {"actions.confirm", "confirm", [this](const QJsonValue &val) { + {"action.confirm", "confirm", [this](const QJsonValue &val) { if (val.isString()) { - m_configItems.actionsConfirm = ::expandPath(val.toString()); - info(QString("Action confirm: %1").arg(m_configItems.actionsConfirm), GeneralLogger::STEP); + m_actionConfig.confirm = ::expandPath(val.toString()); + info(QString("Action confirm: %1").arg(m_actionConfig.confirm), GeneralLogger::STEP); } }}, {"style.aspect_ratio", "aspect_ratio", [this](const QJsonValue &val) { if (val.isDouble() && val.toDouble() > 0) { - m_configItems.styleAspectRatio = val.toDouble(); - info(QString("Aspect ratio: %1").arg(m_configItems.styleAspectRatio), GeneralLogger::STEP); + m_styleConfig.aspectRatio = val.toDouble(); + info(QString("Aspect ratio: %1").arg(m_styleConfig.aspectRatio), GeneralLogger::STEP); } }}, {"style.image_width", "image_width", [this](const QJsonValue &val) { if (val.isDouble() && val.toDouble() > 0) { - m_configItems.styleImageWidth = val.toInt(); - info(QString("Image width: %1").arg(m_configItems.styleImageWidth), GeneralLogger::STEP); + m_styleConfig.imageWidth = val.toInt(); + info(QString("Image width: %1").arg(m_styleConfig.imageWidth), GeneralLogger::STEP); } }}, {"style.image_focus_width", "image_focus_width", [this](const QJsonValue &val) { if (val.isDouble() && val.toDouble() > 0) { - m_configItems.styleImageFocusWidth = val.toInt(); - info(QString("Image focus width: %1").arg(m_configItems.styleImageFocusWidth), GeneralLogger::STEP); + m_styleConfig.imageFocusWidth = val.toInt(); + info(QString("Image focus width: %1").arg(m_styleConfig.imageFocusWidth), GeneralLogger::STEP); } }}, {"style.window_width", "window_width", [this](const QJsonValue &val) { if (val.isDouble() && val.toDouble() > 0) { - m_configItems.styleWindowWidth = val.toInt(); - info(QString("Window width: %1").arg(m_configItems.styleWindowWidth), GeneralLogger::STEP); + m_styleConfig.windowWidth = val.toInt(); + info(QString("Window width: %1").arg(m_styleConfig.windowWidth), GeneralLogger::STEP); } }}, {"style.window_height", "window_height", [this](const QJsonValue &val) { if (val.isDouble() && val.toDouble() > 0) { - m_configItems.styleWindowHeight = val.toInt(); - info(QString("Window height: %1").arg(m_configItems.styleWindowHeight), GeneralLogger::STEP); + m_styleConfig.windowHeight = val.toInt(); + info(QString("Window height: %1").arg(m_styleConfig.windowHeight), GeneralLogger::STEP); } }}, {"style.no_loading_screen", "no_loading_screen", [this](const QJsonValue &val) { if (val.isBool()) { - m_configItems.styleNoLoadingScreen = val.toBool(); - info(QString("No loading screen: %1").arg(m_configItems.styleNoLoadingScreen), GeneralLogger::STEP); + m_styleConfig.noLoadingScreen = val.toBool(); + info(QString("No loading screen: %1").arg(m_styleConfig.noLoadingScreen), GeneralLogger::STEP); } }}, {"sort.type", "type", [this](const QJsonValue &val) { if (val.isString()) { QString type = val.toString().toLower(); if (type == "none") { - m_configItems.sortType = SortType::None; + m_sortConfig.type = SortType::None; } else if (type == "name") { - m_configItems.sortType = SortType::Name; + m_sortConfig.type = SortType::Name; } else if (type == "date") { - m_configItems.sortType = SortType::Date; + m_sortConfig.type = SortType::Date; } else if (type == "size") { - m_configItems.sortType = SortType::Size; + m_sortConfig.type = SortType::Size; } else { warn(QString("Unknown sort type: %1").arg(type), GeneralLogger::STEP); } } - info(QString("Sort type: %1").arg(static_cast(m_configItems.sortType)), GeneralLogger::STEP); + info(QString("Sort type: %1").arg(static_cast(m_sortConfig.type)), GeneralLogger::STEP); }}, {"sort.reverse", "reverse", [this](const QJsonValue &val) { if (val.isBool()) { - m_configItems.sortReverse = val.toBool(); - info(QString("Sort reverse: %1").arg(m_configItems.sortReverse), GeneralLogger::STEP); + m_sortConfig.reverse = val.toBool(); + info(QString("Sort reverse: %1").arg(m_sortConfig.reverse), GeneralLogger::STEP); } }}, }; @@ -158,34 +175,18 @@ void Config::_loadConfig(const QString &configPath) { } } -const QString Config::s_DefaultConfigFileName = "config.json"; - -Config::Config(const QString &configDir, const QStringList &searchDirs, QObject *parent) : QObject(parent) { - info(QString("Loading configuration from: %1").arg(configDir)); - _loadConfig(configDir + QDir::separator() + s_DefaultConfigFileName); - - info(QString("Additional search directories: %1").arg(searchDirs.join(", "))); - m_configItems.wallpaperDirs.append(searchDirs); - - info("Loading wallpapers ..."); - _loadWallpapers(); -} - -Config::~Config() { -} - void Config::_loadWallpapers() { m_wallpapers.clear(); QSet paths; - info(QString("Loading wallpapers from %1 specified paths").arg(m_configItems.wallpaperPaths.size()), LogIndent::STEP); - for (const QString &path : m_configItems.wallpaperPaths) { + info(QString("Loading wallpapers from %1 specified paths").arg(m_wallpaperConfig.paths.size()), LogIndent::STEP); + for (const QString &path : m_wallpaperConfig.paths) { paths.insert(path); } - info(QString("Loading wallpapers from %1 specified directories").arg(m_configItems.wallpaperDirs.size()), LogIndent::STEP); - for (const QString &dirPath : m_configItems.wallpaperDirs) { + info(QString("Loading wallpapers from %1 specified directories").arg(m_wallpaperConfig.dirs.size()), LogIndent::STEP); + for (const QString &dirPath : m_wallpaperConfig.dirs) { QDir dir(dirPath); if (dir.exists()) { QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); @@ -198,8 +199,8 @@ void Config::_loadWallpapers() { } } - info(QString("Excluding %1 specified paths").arg(m_configItems.wallpaperExcludes.size()), LogIndent::STEP); - for (const QString &exclude : m_configItems.wallpaperExcludes) { + info(QString("Excluding %1 specified paths").arg(m_wallpaperConfig.excludes.size()), LogIndent::STEP); + for (const QString &exclude : m_wallpaperConfig.excludes) { paths.remove(exclude); } diff --git a/src/config.h b/src/config.h index 4604f66..e55c82d 100644 --- a/src/config.h +++ b/src/config.h @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 01:34:52 - * @LastEditTime: 2025-08-07 22:03:05 + * @LastEditTime: 2025-08-07 22:28:11 * @Description: Configuration manager. */ #ifndef CONFIG_H @@ -22,6 +22,30 @@ class Config : public QObject { Size, }; + struct WallpaperConfigItems { + QStringList paths; + QStringList dirs; + QStringList excludes; + }; + + struct ActionConfigItems { + QString confirm; + }; + + struct StyleConfigItems { + double aspectRatio = 1.6; + int imageWidth = 320; + int imageFocusWidth = 480; + int windowWidth = 750; + int windowHeight = 500; + bool noLoadingScreen = false; + }; + + struct SortConfigItems { + SortType type = SortType::Name; + bool reverse = false; + }; + Config(const QString& configDir, const QStringList& searchDirs = {}, QObject* parent = nullptr); ~Config(); @@ -32,46 +56,26 @@ class Config : public QObject { [[nodiscard]] qint64 getWallpaperCount() const { return m_wallpapers.size(); } - [[nodiscard]] const QString& getActionsConfirm() const { return m_configItems.actionsConfirm; } + [[nodiscard]] const WallpaperConfigItems& getWallpaperConfig() const { return m_wallpaperConfig; } - [[nodiscard]] double getStyleAspectRatio() const { return m_configItems.styleAspectRatio; } + [[nodiscard]] const ActionConfigItems& getActionConfig() const { return m_actionConfig; } - [[nodiscard]] int getStyleImageWidth() const { return m_configItems.styleImageWidth; } + [[nodiscard]] const StyleConfigItems& getStyleConfig() const { return m_styleConfig; } - [[nodiscard]] int getStyleImageFocusWidth() const { return m_configItems.styleImageFocusWidth; } - - [[nodiscard]] int getStyleWindowWidth() const { return m_configItems.styleWindowWidth; } - - [[nodiscard]] int getStyleWindowHeight() const { return m_configItems.styleWindowHeight; } - - [[nodiscard]] bool isStyleNoLoadingScreen() const { return m_configItems.styleNoLoadingScreen; } - - [[nodiscard]] SortType getSortType() const { return m_configItems.sortType; } - - [[nodiscard]] bool isSortReverse() const { return m_configItems.sortReverse; } + [[nodiscard]] const SortConfigItems& getSortConfig() const { return m_sortConfig; } static const QString s_DefaultConfigFileName; + const QString m_configDir; private: - void - _loadConfig(const QString& configPath); + void _loadConfig(const QString& configPath); void _loadWallpapers(); private: - struct _ConfigItems { - QStringList wallpaperPaths; - QStringList wallpaperDirs; - QStringList wallpaperExcludes; - QString actionsConfirm; - double styleAspectRatio = 1.6; - int styleImageWidth = 320; - int styleImageFocusWidth = 480; - int styleWindowWidth = 720; - int styleWindowHeight = 500; - bool styleNoLoadingScreen = false; - SortType sortType = SortType::None; - bool sortReverse = false; - } m_configItems; + WallpaperConfigItems m_wallpaperConfig; + ActionConfigItems m_actionConfig; + StyleConfigItems m_styleConfig; + SortConfigItems m_sortConfig; QStringList m_wallpapers; }; diff --git a/src/images_carousel.cpp b/src/images_carousel.cpp index f9e6951..05ce596 100644 --- a/src/images_carousel.cpp +++ b/src/images_carousel.cpp @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 01:22:53 - * @LastEditTime: 2025-08-07 22:06:44 + * @LastEditTime: 2025-08-07 22:17:41 * @Description: Animated carousel widget for displaying and selecting images. */ #include "images_carousel.h" @@ -25,20 +25,17 @@ using namespace GeneralLogger; -ImagesCarousel::ImagesCarousel(const double itemAspectRatio, - const int itemWidth, - const int itemFocusWidth, - const Config::SortType sortType, - const bool sortReverse, +ImagesCarousel::ImagesCarousel(const Config::StyleConfigItems& styleConfig, + const Config::SortConfigItems& sortConfig, QWidget* parent) : QWidget(parent), ui(new Ui::ImagesCarousel), - m_itemWidth(itemWidth), - m_itemHeight(static_cast(itemWidth / itemAspectRatio)), - m_itemFocusWidth(itemFocusWidth), - m_itemFocusHeight(static_cast(itemFocusWidth / itemAspectRatio)), - m_sortType(sortType), - m_sortReverse(sortReverse) { + m_itemWidth(styleConfig.imageWidth), + m_itemHeight(static_cast(m_itemWidth / styleConfig.aspectRatio)), + m_itemFocusWidth(styleConfig.imageFocusWidth), + m_itemFocusHeight(static_cast(styleConfig.imageFocusWidth / styleConfig.aspectRatio)), + m_sortType(sortConfig.type), + m_sortReverse(sortConfig.reverse) { ui->setupUi(this); m_scrollArea = dynamic_cast(ui->scrollArea); diff --git a/src/images_carousel.h b/src/images_carousel.h index 6729f18..0102ed3 100644 --- a/src/images_carousel.h +++ b/src/images_carousel.h @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 01:22:53 - * @LastEditTime: 2025-08-07 00:52:14 + * @LastEditTime: 2025-08-07 22:16:37 * @Description: Animated carousel widget for displaying and selecting images. */ #ifndef IMAGES_CAROUSEL_H @@ -111,11 +111,8 @@ class ImagesCarousel : public QWidget { friend void ImageLoader::run(); public: - explicit ImagesCarousel(const double itemAspectRatio, - const int itemWidth, - const int itemFocusWidth, - const Config::SortType sortType, - const bool sortReverse, + explicit ImagesCarousel(const Config::StyleConfigItems& styleConfig, + const Config::SortConfigItems& sortConfig, QWidget* parent = nullptr); ~ImagesCarousel(); diff --git a/src/logger.cpp b/src/logger.cpp index ba14d80..4731909 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,11 +1,13 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-07 01:12:37 - * @LastEditTime: 2025-08-07 21:21:45 + * @LastEditTime: 2025-08-07 22:24:27 * @Description: Implementation of logger. */ #include "logger.h" +#include + #ifndef GENERAL_LOGGER_DISABLED #include @@ -40,7 +42,7 @@ Logger::Logger(FILE* stream, &Logger::logSig, this, &Logger::_log, - Qt::QueuedConnection); + Qt::AutoConnection); } void Logger::_log( diff --git a/src/main.cpp b/src/main.cpp index de68efd..8e01aad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 00:37:58 - * @LastEditTime: 2025-08-07 21:38:26 + * @LastEditTime: 2025-08-07 22:21:29 * @Description: Entry point. */ #include @@ -12,6 +12,7 @@ #include #include "config.h" +#include "logger.h" #include "main_window.h" static QString getConfigDir() { @@ -26,6 +27,10 @@ static QString getConfigDir() { int main(int argc, char *argv[]) { QApplication a(argc, argv); +#ifndef GENERAL_LOGGER_DISABLED + Logger::instance(stderr, GeneralLogger::LogIndent::DETAIL, &a); +#endif // GENERAL_LOGGER_DISABLED + Config config(getConfigDir()); MainWindow w(config); diff --git a/src/main_window.cpp b/src/main_window.cpp index d1da534..85aa6e1 100644 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 00:37:58 - * @LastEditTime: 2025-08-07 22:03:58 + * @LastEditTime: 2025-08-07 22:15:47 * @Description: MainWindow implementation. */ #include "main_window.h" @@ -36,11 +36,8 @@ void MainWindow::_setupUI() { // create images carousel m_carousel = new ImagesCarousel( - m_config.getStyleAspectRatio(), - m_config.getStyleImageWidth(), - m_config.getStyleImageFocusWidth(), - m_config.getSortType(), - m_config.isSortReverse(), + m_config.getStyleConfig(), + m_config.getSortConfig(), this); ui->mainLayout->insertWidget(2, m_carousel); connect(m_carousel, @@ -66,8 +63,8 @@ void MainWindow::_setupUI() { m_loadingIndicatorIndex = ui->stackedWidget->addWidget(m_loadingIndicator); // set window size - setMinimumSize(m_config.getStyleWindowWidth(), m_config.getStyleWindowHeight()); - setMaximumSize(m_config.getStyleWindowWidth(), m_config.getStyleWindowHeight()); + setMinimumSize(m_config.getStyleConfig().windowWidth, m_config.getStyleConfig().windowHeight); + setMaximumSize(m_config.getStyleConfig().windowWidth, m_config.getStyleConfig().windowHeight); connect(ui->confirmButton, &QPushButton::clicked, @@ -115,7 +112,7 @@ void MainWindow::onConfirm() { return; } info(QString("Selected image: %1").arg(path)); - const auto cmdOrig = m_config.getActionsConfirm(); + const auto cmdOrig = m_config.getActionConfig().confirm; if (cmdOrig.isEmpty()) { warn("No action defined for confirmation"); return; @@ -140,7 +137,7 @@ void MainWindow::_onImageFocused(const QString &path, const int index, const int } void MainWindow::_onLoadingStarted(const qsizetype amount) { - if (m_config.isStyleNoLoadingScreen()) { + if (m_config.getStyleConfig().noLoadingScreen) { return; } m_loadingIndicator->setMaximum(amount);