From 7398e61f007a5939eb6eb57842420dcf412b8970 Mon Sep 17 00:00:00 2001 From: Uyanide Date: Fri, 8 Aug 2025 04:17:15 +0200 Subject: [PATCH] refactor: state machine --- config.example.json | 5 +- src/images_carousel.cpp | 2 +- src/main_window.cpp | 152 +++++++++++++++++++++++++++++++--------- src/main_window.h | 13 +++- 4 files changed, 133 insertions(+), 39 deletions(-) diff --git a/config.example.json b/config.example.json index 2dc5a1b..2486d84 100644 --- a/config.example.json +++ b/config.example.json @@ -4,7 +4,8 @@ "~/Pictures/116327446_p0.jpg" ], "dirs": [ - "~/.config/backgrounds" + "~/.config/backgrounds", + "/run/media/kolkas/移硬1T/逆流茶会/" ], "excludes": [ "~/.config/backgrounds/nao-stars-crop-adjust-flop.jpg", @@ -21,7 +22,7 @@ "image_focus_width": 480, "window_width": 750, "window_height": 500, - "no_loading_screen": false + "no_loading_screen": true }, "sort": { "type": "name", diff --git a/src/images_carousel.cpp b/src/images_carousel.cpp index b0060d5..4244570 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-08 02:34:24 + * @LastEditTime: 2025-08-08 04:05:07 * @Description: Animated carousel widget for displaying and selecting images. */ #include "images_carousel.h" diff --git a/src/main_window.cpp b/src/main_window.cpp index 8dd52a7..5261b35 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-08 02:25:20 + * @LastEditTime: 2025-08-08 04:04:17 * @Description: MainWindow implementation. */ #include "main_window.h" @@ -44,13 +44,6 @@ void MainWindow::_setupUI() { this, &MainWindow::_onImageFocused); connect(this, &MainWindow::stop, m_carousel, &ImagesCarousel::onStop); - connect(m_carousel, &ImagesCarousel::stopped, this, - // &MainWindow::close); // instead of closing, we just stop the loading - [this]() { - _onLoadingCompleted(m_carousel->getLoadedImagesCount()); - m_carousel->focusCurrImage(); }, - // ensure this is called in the main thread - Qt::QueuedConnection); m_carouselIndex = ui->stackedWidget->addWidget(m_carousel); // create loading indicator @@ -76,11 +69,11 @@ void MainWindow::_setupUI() { connect(ui->confirmButton, &QPushButton::clicked, this, - &MainWindow::onConfirm); + &MainWindow::_onConfirmPressed); connect(ui->cancelButton, &QPushButton::clicked, this, - &MainWindow::onCancel); + &MainWindow::_onCancelPressed); ui->confirmButton->setFocusPolicy(Qt::NoFocus); ui->cancelButton->setFocusPolicy(Qt::NoFocus); @@ -89,23 +82,123 @@ void MainWindow::_setupUI() { void MainWindow::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { - onCancel(); - } else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - onConfirm(); + _onCancelPressed(); + return; } - // if loadingScreen is enabled and loading is in progress, ignore other keys - else if (!m_config.getStyleConfig().noLoadingScreen && m_isLoading) { - event->ignore(); - } else if (event->key() == Qt::Key_Space || event->key() == Qt::Key_Tab || event->key() == Qt::Key_Right) { - m_carousel->focusNextImage(); - } else if (event->key() == Qt::Key_Left) { - m_carousel->focusPrevImage(); - } else { - QMainWindow::keyPressEvent(event); + if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { + _onConfirmPressed(); + return; + } + + switch (m_state) { + case Init: + MainWindow::keyPressEvent(event); + break; + case Loading: + if (m_config.getStyleConfig().noLoadingScreen) { + switch (event->key()) { + case Qt::Key_Space: + case Qt::Key_Tab: + case Qt::Key_Right: + m_carousel->focusNextImage(); + break; + case Qt::Key_Left: + m_carousel->focusPrevImage(); + break; + default: + QMainWindow::keyPressEvent(event); + } + } else { + event->ignore(); + } + break; + case Ready: + switch (event->key()) { + case Qt::Key_Space: + case Qt::Key_Tab: + case Qt::Key_Right: + m_carousel->focusNextImage(); + break; + case Qt::Key_Left: + m_carousel->focusPrevImage(); + break; + default: + QMainWindow::keyPressEvent(event); + } + break; + default: + event->ignore(); + break; + } +} + +void MainWindow::_onCancelPressed() { + switch (m_state) { + case Loading: + // case loading screen is disabled, quit the app + if (m_config.getStyleConfig().noLoadingScreen) { + info("Stopping loading and quitting app."); + connect( + m_carousel, + &ImagesCarousel::stopped, + this, + &MainWindow::onCancel); + m_state = Stopping; + emit stop(); + } + // otherwise, stop loading and display the loaded images + else { + info("Stopping loading."); + connect( + m_carousel, + &ImagesCarousel::stopped, + this, + [this]() { + _onLoadingCompleted(m_carousel->getLoadedImagesCount()); + m_carousel->focusCurrImage(); + }); + m_state = Stopping; + emit stop(); + } + break; + case Ready: + info("Quitting app."); + onCancel(); + break; + default: + break; + } +} + +void MainWindow::_onConfirmPressed() { + switch (m_state) { + case Loading: + // case loading screen is disabled, confirm the selection + if (m_config.getStyleConfig().noLoadingScreen) { + info("Stopping loading and confirming selection."); + connect( + m_carousel, + &ImagesCarousel::stopped, + this, + &MainWindow::onConfirm); + m_state = Stopping; + emit stop(); + } + break; + case Ready: + info("Confirming selection."); + onConfirm(); + break; + default: + break; } } void MainWindow::wheelEvent(QWheelEvent *event) { + if (m_state != Ready && m_config.getStyleConfig().noLoadingScreen) { + event->ignore(); + return; + } if (event->angleDelta().y() > 0) { m_carousel->focusPrevImage(); } else if (event->angleDelta().y() < 0) { @@ -116,10 +209,6 @@ void MainWindow::wheelEvent(QWheelEvent *event) { } void MainWindow::onConfirm() { - if (m_isLoading) { - warn("Loading is still in progress, please wait until it finishes."); - return; - } close(); const auto path = m_carousel->getCurrentImagePath(); if (path.isEmpty()) { @@ -144,12 +233,7 @@ void MainWindow::onConfirm() { } void MainWindow::onCancel() { - if (m_isLoading) { - warn("Loading stopped by user, waiting all threads to finish..."); - emit stop(); - } else { - close(); - } + close(); } void MainWindow::_onImageFocused(const QString &path, const int index, const int count) { @@ -157,7 +241,7 @@ void MainWindow::_onImageFocused(const QString &path, const int index, const int } void MainWindow::_onLoadingStarted(const qsizetype amount) { - m_isLoading = true; + m_state = Loading; if (m_config.getStyleConfig().noLoadingScreen) { return; } @@ -168,5 +252,5 @@ void MainWindow::_onLoadingStarted(const qsizetype amount) { void MainWindow::_onLoadingCompleted(const qsizetype amount) { info(QString("Loading completed, loaded %1 images").arg(amount)); ui->stackedWidget->setCurrentIndex(m_carouselIndex); - m_isLoading = false; + m_state = Ready; } diff --git a/src/main_window.h b/src/main_window.h index f8c2465..037c310 100644 --- a/src/main_window.h +++ b/src/main_window.h @@ -1,7 +1,7 @@ /* * @Author: Uyanide pywang0608@foxmail.com * @Date: 2025-08-05 00:37:58 - * @LastEditTime: 2025-08-08 02:11:57 + * @LastEditTime: 2025-08-08 03:37:24 * @Description: MainWindow implementation. */ #ifndef MAINWINDOW_H @@ -44,13 +44,22 @@ class MainWindow : public QMainWindow { void _onLoadingStarted(const qsizetype amount); void _onLoadingCompleted(const qsizetype amount); + void _onCancelPressed(); + void _onConfirmPressed(); + private: + enum _State { + Init, + Loading, + Stopping, + Ready, + } m_state = Init; + Ui::MainWindow *ui; ImagesCarousel *m_carousel = nullptr; LoadingIndicator *m_loadingIndicator = nullptr; int m_carouselIndex, m_loadingIndicatorIndex; const Config &m_config; - bool m_isLoading = false; signals: void stop();