feat: configurable sizes

This commit is contained in:
2025-08-05 20:14:37 +02:00
parent 56d5e66d6f
commit 1100910f62
10 changed files with 256 additions and 152 deletions
+7
View File
@@ -14,5 +14,12 @@
},
"actions": {
"confirm": "~/.scripts/change-wallpaper.fish \"%1\""
},
"style": {
"aspect_ratio": 1.6,
"image_width": 320,
"image_focus_width": 480,
"window_width": 750,
"window_height": 500
}
}
+99 -40
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 01:34:52
* @LastEditTime: 2025-08-05 17:26:33
* @LastEditTime: 2025-08-05 20:11:11
* @Description: Configuration manager.
*/
#include "config.h"
@@ -19,22 +19,6 @@ 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) {
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::_loadConfig(const QString &configPath) {
QFile configFile(configPath);
if (!configFile.open(QIODevice::ReadOnly)) {
@@ -50,42 +34,117 @@ void Config::_loadConfig(const QString &configPath) {
return;
}
static const auto parseJsonArray = [](const QJsonObject &obj, const QString &key, QStringList &list) {
if (obj.contains(key) && obj[key].isArray()) {
QJsonArray array = obj[key].toArray();
for (const QJsonValue &value : array) {
if (value.isString()) {
list.append(::expandPath(value.toString()));
const auto jsonObj = jsonDoc.object();
struct ConfigMapping {
QString path;
QString key;
std::function<void(const QJsonValue &)> parser;
};
static const auto parseJsonArray = [](const QJsonValue &val, QStringList &list) {
if (val.isArray()) {
for (const auto &item : val.toArray()) {
if (item.isString()) {
list.append(::expandPath(item.toString()));
}
}
} else {
warn(QString("Key '%1' not found or not an array in config").arg(key));
}
};
const auto jsonObj = jsonDoc.object();
if (!jsonObj.contains("wallpaper") || !jsonObj["wallpaper"].isObject()) {
warn("Key 'wallpaper' not fount or not an object in config");
std::vector<ConfigMapping>
mappings = {
{"wallpaper.paths", "paths", [this](const QJsonValue &val) {
parseJsonArray(val, m_configItems.wallpaperPaths);
}},
{"wallpaper.dirs", "dirs", [this](const QJsonValue &val) {
parseJsonArray(val, m_configItems.wallpaperDirs);
}},
{"wallpaper.excludes", "excludes", [this](const QJsonValue &val) {
parseJsonArray(val, m_configItems.wallpaperExcludes);
}},
{"actions.confirm", "confirm", [this](const QJsonValue &val) {
if (val.isString()) {
m_configItems.actionsConfirm = ::expandPath(val.toString());
info(QString("Action confirm: %1").arg(m_configItems.actionsConfirm));
}
}},
{"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));
}
}},
{"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));
}
}},
{"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));
}
}},
{"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));
}
}},
{"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));
}
}},
};
// 统一解析
for (const auto &mapping : mappings) {
([&mapping, &jsonObj]() {
auto pathParts = mapping.path.split('.');
QJsonObject currentObj = jsonObj;
QJsonValue targetValue;
for (int i = 0; i < pathParts.size() - 1; ++i) {
if (currentObj.contains(pathParts[i]) && currentObj[pathParts[i]].isObject()) {
currentObj = currentObj[pathParts[i]].toObject();
} else {
const auto wallpaperObj = jsonObj.value("wallpaper").toObject();
parseJsonArray(wallpaperObj, "paths", m_configItems.wallpaperPaths);
parseJsonArray(wallpaperObj, "dirs", m_configItems.wallpaperDirs);
parseJsonArray(wallpaperObj, "excludes", m_configItems.wallpaperExcludes);
warn(QString("Path '%1' not found").arg(pathParts.mid(0, i + 1).join('.')));
return;
}
}
if (!jsonObj.contains("actions") || !jsonObj["actions"].isObject()) {
warn("Key 'actions' not found or not an object in config");
// 获取目标值
const QString &finalKey = pathParts.last();
if (currentObj.contains(finalKey)) {
mapping.parser(currentObj[finalKey]);
} else {
const auto actionsObj = jsonObj.value("actions").toObject();
if (actionsObj.contains("confirm") && actionsObj["confirm"].isString()) {
m_configItems.actionsConfirm = ::expandPath(actionsObj["confirm"].toString());
info(QString("Action on confirm: %1").arg(m_configItems.actionsConfirm));
} else {
warn("Key 'confirm' not found or not a string in 'actions'");
warn(QString("Key '%1' not found in '%2'").arg(finalKey).arg(mapping.path));
}
})();
}
}
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();
+17 -2
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 01:34:52
* @LastEditTime: 2025-08-05 17:26:25
* @LastEditTime: 2025-08-05 20:12:47
* @Description: Configuration manager.
*/
#ifndef CONFIG_H
@@ -27,6 +27,16 @@ class Config : public QObject {
[[nodiscard]] const QString& getActionsConfirm() const { return m_configItems.actionsConfirm; }
[[nodiscard]] double getStyleAspectRatio() const { return m_configItems.styleAspectRatio; }
[[nodiscard]] int getStyleImageWidth() const { return m_configItems.styleImageWidth; }
[[nodiscard]] int getStyleImageFocusWidth() const { return m_configItems.styleImageFocusWidth; }
[[nodiscard]] int getStyleWindowWidth() const { return m_configItems.styleWindowWidth; }
[[nodiscard]] int getStyleWindowHeight() const { return m_configItems.styleWindowHeight; }
static const QString s_DefaultConfigFileName;
private:
@@ -35,11 +45,16 @@ class Config : public QObject {
void _loadWallpapers();
private:
struct ConfigItems {
struct _ConfigItems {
QStringList wallpaperPaths;
QStringList wallpaperDirs;
QStringList wallpaperExcludes;
QString actionsConfirm;
double styleAspectRatio = 1.6;
int styleImageWidth = 320;
int styleImageFocusWidth = 480;
int styleWindowWidth = 800;
int styleWindowHeight = 600;
} m_configItems;
QStringList m_wallpapers;
+6
View File
@@ -10,6 +10,12 @@
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
+1 -19
View File
@@ -35,17 +35,7 @@
<set>QMainWindow::DockOption::AllowTabbedDocks|QMainWindow::DockOption::AnimatedDocks</set>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ImagesCarousel" name="carousel" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<layout class="QVBoxLayout" name="mainLayout">
<item>
<widget class="QWidget" name="actions" native="true">
<property name="minimumSize">
@@ -100,14 +90,6 @@
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>ImagesCarousel</class>
<extends>QWidget</extends>
<header>images_carousel.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+53 -52
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 01:22:53
* @LastEditTime: 2025-08-05 17:25:59
* @LastEditTime: 2025-08-05 20:06:23
* @Description: Animated carousel widget for displaying and selecting images.
*/
#include "images_carousel.h"
@@ -21,20 +21,27 @@
using namespace GeneralLogger;
ImagesCarousel::ImagesCarousel(QWidget* parent)
ImagesCarousel::ImagesCarousel(const double itemAspectRatio,
const int itemWidth,
const int itemFocusWidth,
QWidget* parent)
: QWidget(parent),
ui(new Ui::ImagesCarousel),
m_updateTimer(new QTimer(this)),
m_scrollAnimation(nullptr) {
m_scrollAnimation(nullptr),
m_itemWidth(itemWidth),
m_itemHeight(static_cast<int>(itemWidth / itemAspectRatio)),
m_itemFocusWidth(itemFocusWidth),
m_itemFocusHeight(static_cast<int>(itemFocusWidth / itemAspectRatio)) {
ui->setupUi(this);
connect(m_updateTimer, &QTimer::timeout, this, &ImagesCarousel::updateImages);
connect(m_updateTimer, &QTimer::timeout, this, &ImagesCarousel::_updateImages);
m_updateTimer->start(100);
}
ImagesCarousel::~ImagesCarousel() {
delete ui;
for (auto item : m_imageQueue) {
for (auto item : std::as_const(m_imageQueue)) {
delete item;
}
if (m_scrollAnimation) {
@@ -49,22 +56,26 @@ void ImagesCarousel::appendImage(const QString& path) {
}
ImageLoader::ImageLoader(const QString& path, ImagesCarousel* carousel)
: m_path(path), m_carousel(carousel) {
: m_path(path),
m_carousel(carousel),
m_initWidth(carousel->m_itemFocusWidth),
m_initHeight(carousel->m_itemFocusHeight) {
setAutoDelete(true);
}
void ImagesCarousel::addImageToQueue(const ImageData* data) {
void ImagesCarousel::_addImageToQueue(const ImageData* data) {
QMutexLocker locker(&m_queueMutex);
auto imageItem = new ImageItem(data,
s_itemWidth,
s_itemHeight,
s_itemFocusWidth,
s_itemFocusHeight,
auto imageItem = new ImageItem(
data,
m_itemWidth,
m_itemHeight,
m_itemFocusWidth,
m_itemFocusHeight,
this);
m_imageQueue.enqueue(imageItem);
}
void ImagesCarousel::updateImages() {
void ImagesCarousel::_updateImages() {
QMutexLocker locker(&m_queueMutex);
int processCount = 0;
@@ -72,30 +83,31 @@ void ImagesCarousel::updateImages() {
ImageItem* item = m_imageQueue.dequeue();
ui->scrollAreaWidgetContents->layout()->addWidget(item);
m_loadedImages.append(item);
// focus first image
if (m_loadedImages.size() == 1) {
item->focusImage();
item->setFocus(true);
} else {
item->unfocusImage();
item->setFocus(false);
}
processCount++;
}
}
void ImageLoader::run() {
auto data = new ImageData(m_path);
auto data = new ImageData(m_path, m_initWidth, m_initHeight);
QMetaObject::invokeMethod(m_carousel,
"addImageToQueue",
"_addImageToQueue",
Qt::QueuedConnection,
Q_ARG(const ImageData*, data));
}
ImageData::ImageData(const QString& p) : path(p) {
ImageData::ImageData(const QString& p, const int initWidth, const int initHeight) : path(p) {
path = p;
if (!pixmap.load(p)) {
warn(QString("Failed to load image from path: %1").arg(p));
}
// resize in "cover" mode
const QSize targetSize(ImagesCarousel::s_itemWidth, ImagesCarousel::s_itemHeight);
const QSize targetSize(initWidth, initHeight);
pixmap = pixmap.scaled(targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
// Crop to center
@@ -105,34 +117,34 @@ ImageData::ImageData(const QString& p) : path(p) {
}
void ImagesCarousel::focusNextImage() {
unfocusCurrImage();
_unfocusCurrImage();
if (m_loadedImages.size() <= 1) return;
m_currentIndex++;
if (m_currentIndex >= m_loadedImages.size()) {
m_currentIndex = 0;
}
focusCurrImage();
_focusCurrImage();
}
void ImagesCarousel::focusPrevImage() {
if (m_loadedImages.size() <= 1) return;
unfocusCurrImage();
_unfocusCurrImage();
m_currentIndex--;
if (m_currentIndex < 0) {
m_currentIndex = m_loadedImages.size() - 1;
}
focusCurrImage();
_focusCurrImage();
}
void ImagesCarousel::unfocusCurrImage() {
m_loadedImages[m_currentIndex]->unfocusImage();
void ImagesCarousel::_unfocusCurrImage() {
m_loadedImages[m_currentIndex]->setFocus(false);
}
void ImagesCarousel::focusCurrImage() {
m_loadedImages[m_currentIndex]->focusImage();
void ImagesCarousel::_focusCurrImage() {
m_loadedImages[m_currentIndex]->setFocus(true);
auto hScrollBar = ui->scrollArea->horizontalScrollBar();
int spacing = ui->scrollAreaWidgetContents->layout()->spacing();
int centerOffset = (s_itemWidth + spacing) * m_currentIndex + s_itemFocusWidth / 2 - spacing;
int centerOffset = (m_itemWidth + spacing) * m_currentIndex + m_itemFocusWidth / 2 - spacing;
int leftOffset = centerOffset - ui->scrollArea->width() / 2;
if (leftOffset < 0) {
leftOffset = 0;
@@ -162,12 +174,21 @@ ImageItem::ImageItem(const ImageData* data,
m_data(data),
m_itemSize(itemWidth, itemHeight),
m_itemFocusSize(itemFocusWidth, itemFocusHeight) {
setPixmap(data->pixmap);
setFixedSize(ImagesCarousel::s_itemWidth, ImagesCarousel::s_itemHeight);
setScaledContents(true);
setPixmap(data->pixmap);
setFixedSize(itemWidth, itemHeight);
}
void ImageItem::focusImage() {
ImageItem::~ImageItem() {
if (m_scaleAnimation) {
m_scaleAnimation->stop();
delete m_scaleAnimation;
m_scaleAnimation = nullptr;
}
delete m_data;
}
void ImageItem::setFocus(bool focus) {
if (m_scaleAnimation) {
m_scaleAnimation->stop();
delete m_scaleAnimation;
@@ -176,27 +197,7 @@ void ImageItem::focusImage() {
m_scaleAnimation = new QPropertyAnimation(this, "size");
m_scaleAnimation->setDuration(ImagesCarousel::s_animationDuration);
m_scaleAnimation->setStartValue(size());
m_scaleAnimation->setEndValue(m_itemFocusSize);
m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic);
connect(m_scaleAnimation,
&QPropertyAnimation::valueChanged,
this,
[this](const QVariant& value) {
setFixedSize(value.toSize());
});
m_scaleAnimation->start();
}
void ImageItem::unfocusImage() {
if (m_scaleAnimation) {
m_scaleAnimation->stop();
delete m_scaleAnimation;
m_scaleAnimation = nullptr;
}
m_scaleAnimation = new QPropertyAnimation(this, "size");
m_scaleAnimation->setDuration(ImagesCarousel::s_animationDuration);
m_scaleAnimation->setStartValue(size());
m_scaleAnimation->setEndValue(m_itemSize);
m_scaleAnimation->setEndValue(focus ? m_itemFocusSize : m_itemSize);
m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic);
connect(m_scaleAnimation,
&QPropertyAnimation::valueChanged,
+37 -17
View File
@@ -1,12 +1,14 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 01:22:53
* @LastEditTime: 2025-08-05 17:25:34
* @LastEditTime: 2025-08-05 19:47:43
* @Description: Animated carousel widget for displaying and selecting images.
*/
#ifndef IMAGES_CAROUSEL_H
#define IMAGES_CAROUSEL_H
#include <qtmetamacros.h>
#include <QKeyEvent>
#include <QLabel>
#include <QMutex>
@@ -22,15 +24,20 @@
class ImagesCarousel;
/**
* @brief Data structure to hold image information
* and can be safely created and passed between threads.
*/
struct ImageData {
QString path;
QPixmap pixmap;
ImageData() = default;
explicit ImageData(const QString& p);
explicit ImageData(const QString& p, const int initWidth, const int initHeight);
};
/**
* @brief Image label that displays an image
*/
class ImageItem : public QLabel {
Q_OBJECT
@@ -42,13 +49,14 @@ class ImageItem : public QLabel {
const int itemFocusHeight,
QWidget* parent = nullptr);
~ImageItem() override;
[[nodiscard]] const QString& getPath() const { return m_data->path; }
[[nodiscard]] const QPixmap& getPixmap() const { return m_data->pixmap; }
public slots:
void focusImage();
void unfocusImage();
public:
void setFocus(bool focus = true);
private:
const ImageData* m_data;
@@ -65,6 +73,8 @@ class ImageLoader : public QRunnable {
private:
QString m_path;
ImagesCarousel* m_carousel;
const int m_initWidth;
const int m_initHeight;
};
namespace Ui {
@@ -74,14 +84,15 @@ class ImagesCarousel;
class ImagesCarousel : public QWidget {
Q_OBJECT
friend void ImageLoader::run();
public:
explicit ImagesCarousel(QWidget* parent = nullptr);
explicit ImagesCarousel(const double itemAspectRatio,
const int itemWidth,
const int itemFocusWidth,
QWidget* parent = nullptr);
~ImagesCarousel();
static constexpr int s_itemWidth = 320;
static constexpr int s_itemHeight = 200;
static constexpr int s_itemFocusWidth = 480;
static constexpr int s_itemFocusHeight = 300;
static constexpr int s_animationDuration = 300;
[[nodiscard]] QString getCurrentImagePath() const {
@@ -91,16 +102,25 @@ class ImagesCarousel : public QWidget {
return m_loadedImages[m_currentIndex]->getPath();
}
const int m_itemWidth = 320;
const int m_itemHeight = 180;
const int m_itemFocusWidth = 480;
const int m_itemFocusHeight = 270;
public slots:
void addImageToQueue(const ImageData* data);
void appendImage(const QString& path);
void focusNextImage();
void focusPrevImage();
void unfocusCurrImage();
void focusCurrImage();
private slots:
void updateImages();
void _unfocusCurrImage();
public:
void appendImage(const QString& path);
private:
Q_INVOKABLE void _addImageToQueue(const ImageData* data);
void _focusCurrImage();
void _updateImages();
private:
Ui::ImagesCarousel* ui;
+5 -2
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 00:37:58
* @LastEditTime: 2025-08-05 17:34:37
* @LastEditTime: 2025-08-05 19:42:07
* @Description: Entry point.
*/
#include <qapplication.h>
@@ -11,6 +11,7 @@
#include <QStandardPaths>
#include <QTextStream>
#include "config.h"
#include "logger.h"
#include "main_window.h"
@@ -28,7 +29,9 @@ static QString getConfigDir() {
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w(::getConfigDir());
Config config(getConfigDir());
MainWindow w(config);
w.show();
return a.exec();
+21 -12
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 00:37:58
* @LastEditTime: 2025-08-05 17:40:35
* @LastEditTime: 2025-08-05 20:12:40
* @Description: MainWindow implementation.
*/
#include "main_window.h"
@@ -17,11 +17,8 @@
using namespace GeneralLogger;
MainWindow::MainWindow(const QString &configDir, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
m_config = new Config(configDir, {}, this);
MainWindow::MainWindow(const Config &config, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), m_config(config) {
ui->setupUi(this);
_setupUI();
}
@@ -31,13 +28,25 @@ MainWindow::~MainWindow() {
}
void MainWindow::_setupUI() {
// insert images carousel
m_carousel = new ImagesCarousel(
m_config.getStyleAspectRatio(),
m_config.getStyleImageWidth(),
m_config.getStyleImageFocusWidth(),
this);
ui->mainLayout->insertWidget(0, m_carousel);
// set window size
setMinimumSize(m_config.getStyleWindowWidth(), m_config.getStyleWindowHeight());
setMaximumSize(m_config.getStyleWindowWidth(), m_config.getStyleWindowHeight());
connect(ui->confirmButton, &QPushButton::clicked, this, &MainWindow::onConfirm);
connect(ui->cancelButton, &QPushButton::clicked, this, &MainWindow::onCancel);
ui->confirmButton->setFocusPolicy(Qt::NoFocus);
ui->cancelButton->setFocusPolicy(Qt::NoFocus);
for (const auto &image : m_config->getWallpapers()) {
ui->carousel->appendImage(image);
for (const auto &image : m_config.getWallpapers()) {
m_carousel->appendImage(image);
}
}
@@ -47,9 +56,9 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
} else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
onConfirm();
} else if (event->key() == Qt::Key_Space || event->key() == Qt::Key_Tab || event->key() == Qt::Key_Right) {
ui->carousel->focusNextImage();
m_carousel->focusNextImage();
} else if (event->key() == Qt::Key_Left) {
ui->carousel->focusPrevImage();
m_carousel->focusPrevImage();
} else {
QMainWindow::keyPressEvent(event);
}
@@ -57,13 +66,13 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
void MainWindow::onConfirm() {
close();
const auto path = ui->carousel->getCurrentImagePath();
const auto path = m_carousel->getCurrentImagePath();
if (path.isEmpty()) {
warn("No image selected");
return;
}
info(QString("Selected image: %1").arg(path));
const auto cmdOrig = m_config->getActionsConfirm();
const auto cmdOrig = m_config.getActionsConfirm();
if (cmdOrig.isEmpty()) {
warn("No action defined for confirmation");
return;
+5 -3
View File
@@ -1,7 +1,7 @@
/*
* @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 00:37:58
* @LastEditTime: 2025-08-05 17:23:41
* @LastEditTime: 2025-08-05 19:53:51
* @Description: MainWindow implementation.
*/
#ifndef MAINWINDOW_H
@@ -10,6 +10,7 @@
#include <QMainWindow>
#include "config.h"
#include "images_carousel.h"
QT_BEGIN_NAMESPACE
@@ -23,7 +24,7 @@ class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(const QString &configDir, QWidget *parent = nullptr);
MainWindow(const Config &config, QWidget *parent = nullptr);
~MainWindow();
public slots:
@@ -38,6 +39,7 @@ class MainWindow : public QMainWindow {
private:
Ui::MainWindow *ui;
Config *m_config;
ImagesCarousel *m_carousel = nullptr;
const Config &m_config;
};
#endif // MAINWINDOW_H