refactor: state machine

This commit is contained in:
2025-08-08 04:17:15 +02:00
parent 490f924bcc
commit 7398e61f00
4 changed files with 133 additions and 39 deletions
+3 -2
View File
@@ -4,7 +4,8 @@
"~/Pictures/116327446_p0.jpg" "~/Pictures/116327446_p0.jpg"
], ],
"dirs": [ "dirs": [
"~/.config/backgrounds" "~/.config/backgrounds",
"/run/media/kolkas/移硬1T/逆流茶会/"
], ],
"excludes": [ "excludes": [
"~/.config/backgrounds/nao-stars-crop-adjust-flop.jpg", "~/.config/backgrounds/nao-stars-crop-adjust-flop.jpg",
@@ -21,7 +22,7 @@
"image_focus_width": 480, "image_focus_width": 480,
"window_width": 750, "window_width": 750,
"window_height": 500, "window_height": 500,
"no_loading_screen": false "no_loading_screen": true
}, },
"sort": { "sort": {
"type": "name", "type": "name",
+1 -1
View File
@@ -1,7 +1,7 @@
/* /*
* @Author: Uyanide pywang0608@foxmail.com * @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 01:22:53 * @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. * @Description: Animated carousel widget for displaying and selecting images.
*/ */
#include "images_carousel.h" #include "images_carousel.h"
+114 -30
View File
@@ -1,7 +1,7 @@
/* /*
* @Author: Uyanide pywang0608@foxmail.com * @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 00:37:58 * @Date: 2025-08-05 00:37:58
* @LastEditTime: 2025-08-08 02:25:20 * @LastEditTime: 2025-08-08 04:04:17
* @Description: MainWindow implementation. * @Description: MainWindow implementation.
*/ */
#include "main_window.h" #include "main_window.h"
@@ -44,13 +44,6 @@ void MainWindow::_setupUI() {
this, this,
&MainWindow::_onImageFocused); &MainWindow::_onImageFocused);
connect(this, &MainWindow::stop, m_carousel, &ImagesCarousel::onStop); 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); m_carouselIndex = ui->stackedWidget->addWidget(m_carousel);
// create loading indicator // create loading indicator
@@ -76,11 +69,11 @@ void MainWindow::_setupUI() {
connect(ui->confirmButton, connect(ui->confirmButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&MainWindow::onConfirm); &MainWindow::_onConfirmPressed);
connect(ui->cancelButton, connect(ui->cancelButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&MainWindow::onCancel); &MainWindow::_onCancelPressed);
ui->confirmButton->setFocusPolicy(Qt::NoFocus); ui->confirmButton->setFocusPolicy(Qt::NoFocus);
ui->cancelButton->setFocusPolicy(Qt::NoFocus); ui->cancelButton->setFocusPolicy(Qt::NoFocus);
@@ -89,23 +82,123 @@ void MainWindow::_setupUI() {
void MainWindow::keyPressEvent(QKeyEvent *event) { void MainWindow::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Escape) { if (event->key() == Qt::Key_Escape) {
onCancel(); _onCancelPressed();
} else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { return;
onConfirm();
} }
// if loadingScreen is enabled and loading is in progress, ignore other keys if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
else if (!m_config.getStyleConfig().noLoadingScreen && m_isLoading) { _onConfirmPressed();
event->ignore(); return;
} else if (event->key() == Qt::Key_Space || event->key() == Qt::Key_Tab || event->key() == Qt::Key_Right) { }
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(); m_carousel->focusNextImage();
} else if (event->key() == Qt::Key_Left) { break;
case Qt::Key_Left:
m_carousel->focusPrevImage(); m_carousel->focusPrevImage();
} else { break;
default:
QMainWindow::keyPressEvent(event); 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) { void MainWindow::wheelEvent(QWheelEvent *event) {
if (m_state != Ready && m_config.getStyleConfig().noLoadingScreen) {
event->ignore();
return;
}
if (event->angleDelta().y() > 0) { if (event->angleDelta().y() > 0) {
m_carousel->focusPrevImage(); m_carousel->focusPrevImage();
} else if (event->angleDelta().y() < 0) { } else if (event->angleDelta().y() < 0) {
@@ -116,10 +209,6 @@ void MainWindow::wheelEvent(QWheelEvent *event) {
} }
void MainWindow::onConfirm() { void MainWindow::onConfirm() {
if (m_isLoading) {
warn("Loading is still in progress, please wait until it finishes.");
return;
}
close(); close();
const auto path = m_carousel->getCurrentImagePath(); const auto path = m_carousel->getCurrentImagePath();
if (path.isEmpty()) { if (path.isEmpty()) {
@@ -144,20 +233,15 @@ void MainWindow::onConfirm() {
} }
void MainWindow::onCancel() { 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) { void MainWindow::_onImageFocused(const QString &path, const int index, const int count) {
ui->topLabel->setText(QString("%1 (%2/%3)").arg(splitNameFromPath(path)).arg(index + 1).arg(count)); ui->topLabel->setText(QString("%1 (%2/%3)").arg(splitNameFromPath(path)).arg(index + 1).arg(count));
} }
void MainWindow::_onLoadingStarted(const qsizetype amount) { void MainWindow::_onLoadingStarted(const qsizetype amount) {
m_isLoading = true; m_state = Loading;
if (m_config.getStyleConfig().noLoadingScreen) { if (m_config.getStyleConfig().noLoadingScreen) {
return; return;
} }
@@ -168,5 +252,5 @@ void MainWindow::_onLoadingStarted(const qsizetype amount) {
void MainWindow::_onLoadingCompleted(const qsizetype amount) { void MainWindow::_onLoadingCompleted(const qsizetype amount) {
info(QString("Loading completed, loaded %1 images").arg(amount)); info(QString("Loading completed, loaded %1 images").arg(amount));
ui->stackedWidget->setCurrentIndex(m_carouselIndex); ui->stackedWidget->setCurrentIndex(m_carouselIndex);
m_isLoading = false; m_state = Ready;
} }
+11 -2
View File
@@ -1,7 +1,7 @@
/* /*
* @Author: Uyanide pywang0608@foxmail.com * @Author: Uyanide pywang0608@foxmail.com
* @Date: 2025-08-05 00:37:58 * @Date: 2025-08-05 00:37:58
* @LastEditTime: 2025-08-08 02:11:57 * @LastEditTime: 2025-08-08 03:37:24
* @Description: MainWindow implementation. * @Description: MainWindow implementation.
*/ */
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
@@ -44,13 +44,22 @@ class MainWindow : public QMainWindow {
void _onLoadingStarted(const qsizetype amount); void _onLoadingStarted(const qsizetype amount);
void _onLoadingCompleted(const qsizetype amount); void _onLoadingCompleted(const qsizetype amount);
void _onCancelPressed();
void _onConfirmPressed();
private: private:
enum _State {
Init,
Loading,
Stopping,
Ready,
} m_state = Init;
Ui::MainWindow *ui; Ui::MainWindow *ui;
ImagesCarousel *m_carousel = nullptr; ImagesCarousel *m_carousel = nullptr;
LoadingIndicator *m_loadingIndicator = nullptr; LoadingIndicator *m_loadingIndicator = nullptr;
int m_carouselIndex, m_loadingIndicatorIndex; int m_carouselIndex, m_loadingIndicatorIndex;
const Config &m_config; const Config &m_config;
bool m_isLoading = false;
signals: signals:
void stop(); void stop();