diff --git a/CMakeLists.txt b/CMakeLists.txt index af9d2e7..4a96c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) src/images_carousel.h src/images_carousel.cpp src/designer/images_carousel.ui src/config.h src/config.cpp src/logger.h + src/loading_indicator.h src/loading_indicator.cpp src/designer/loading_indicator.ui ) # Define target properties for Android with Qt 6 as: # set_property(TARGET wallpaper_chooser APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR diff --git a/config.example.json b/config.example.json index 99a5744..481ab0f 100644 --- a/config.example.json +++ b/config.example.json @@ -4,7 +4,9 @@ "~/Pictures/116327446_p0.jpg" ], "dirs": [ - "~/.config/backgrounds" + "~/.config/backgrounds", + "/media/Beta/3-Anime/图集/绿色健康.2/绿色健康.2", + "/media/Beta/壁纸/库" ], "excludes": [ "~/.config/backgrounds/nao-stars-crop-adjust-flop.jpg", diff --git a/src/designer/loading_indicator.ui b/src/designer/loading_indicator.ui new file mode 100644 index 0000000..8cc12af --- /dev/null +++ b/src/designer/loading_indicator.ui @@ -0,0 +1,63 @@ + + + LoadingIndicator + + + + 0 + 0 + 795 + 653 + + + + + + + + 500 + 16777215 + + + + 24 + + + true + + + %v/%m + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/src/designer/main_window.ui b/src/designer/main_window.ui index 2e02358..4856ade 100644 --- a/src/designer/main_window.ui +++ b/src/designer/main_window.ui @@ -68,6 +68,16 @@ + + + + + 0 + 0 + + + + diff --git a/src/images_carousel.cpp b/src/images_carousel.cpp index 3083e0a..889ccbe 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 00:22:29 + * @LastEditTime: 2025-08-07 00:50:11 * @Description: Animated carousel widget for displaying and selecting images. */ #include "images_carousel.h" @@ -46,13 +46,9 @@ ImagesCarousel::ImagesCarousel(const double itemAspectRatio, // Load initial images connect(this, - &ImagesCarousel::imagesLoaded, + &ImagesCarousel::loadingCompleted, this, - [this]() { - _focusCurrImage(); - // exit(0); // for speed test - disconnect(this, &ImagesCarousel::imagesLoaded, this, nullptr); - }); + &ImagesCarousel::_onInitImagesLoaded); // Auto focus when scrolling m_scrollDebounceTimer = new QTimer(this); @@ -76,6 +72,15 @@ ImagesCarousel::ImagesCarousel(const double itemAspectRatio, }); } +void ImagesCarousel::_onInitImagesLoaded() { + disconnect(this, &ImagesCarousel::loadingCompleted, this, &ImagesCarousel::_onInitImagesLoaded); + if (m_loadedImages.isEmpty()) { + return; + } + m_currentIndex = 0; + _focusCurrImage(); +} + ImagesCarousel::~ImagesCarousel() { delete ui; // memory of items in m_loadedImages managed by Qt parent-child system @@ -91,6 +96,7 @@ void ImagesCarousel::appendImages(const QStringList& paths) { QMutexLocker locker(&m_imageCountMutex); m_imageCount += paths.size(); } + emit loadingStarted(paths.size()); for (const QString& path : paths) { ImageLoader* loader = new ImageLoader(path, this); QThreadPool::globalInstance()->start(loader); @@ -146,10 +152,11 @@ void ImagesCarousel::_insertImage(const ImageData* data) { m_loadedImages.insert(inserPos, item); m_imagesLayout->insertWidget(inserPos, item); + emit imageLoaded(m_loadedImages.size()); { QMutexLocker countLocker(&m_imageCountMutex); if (m_loadedImages.size() >= m_imageCount) { - emit imagesLoaded(); + emit loadingCompleted(m_loadedImages.size()); } } } @@ -266,6 +273,9 @@ void ImagesCarousel::_onItemClicked(int index) { // if (m_suppressAutoFocus) return; _unfocusCurrImage(); m_currentIndex = index; + if (index < 0 || index >= m_loadedImages.size()) { + return; // Out of bounds + } _focusCurrImage(); } diff --git a/src/images_carousel.h b/src/images_carousel.h index 00e0f59..6729f18 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:27:03 + * @LastEditTime: 2025-08-07 00:52:14 * @Description: Animated carousel widget for displaying and selecting images. */ #ifndef IMAGES_CAROUSEL_H @@ -144,6 +144,7 @@ class ImagesCarousel : public QWidget { void _unfocusCurrImage(); void _onScrollBarValueChanged(int value); void _onItemClicked(int index); + void _onInitImagesLoaded(); public: void @@ -168,7 +169,9 @@ class ImagesCarousel : public QWidget { signals: void imageFocused(const QString& path, const int index, const int count); - void imagesLoaded(); + void loadingStarted(const qsizetype amount); + void loadingCompleted(const qsizetype amount); + void imageLoaded(const qsizetype count); }; class ImagesCarouselScrollArea : public QScrollArea { diff --git a/src/loading_indicator.cpp b/src/loading_indicator.cpp new file mode 100644 index 0000000..053ef9e --- /dev/null +++ b/src/loading_indicator.cpp @@ -0,0 +1,16 @@ +/* + * @Author: Uyanide pywang0608@foxmail.com + * @Date: 2025-08-07 00:32:25 + * @LastEditTime: 2025-08-07 01:09:49 + * @Description: A loading indicator widget with a progress bar. + */ +#include "loading_indicator.h" + +LoadingIndicator::LoadingIndicator(QWidget *parent) : QWidget(parent), + ui(new Ui::LoadingIndicator) { + ui->setupUi(this); +} + +LoadingIndicator::~LoadingIndicator() { + delete ui; +} diff --git a/src/loading_indicator.h b/src/loading_indicator.h new file mode 100644 index 0000000..3f09a7c --- /dev/null +++ b/src/loading_indicator.h @@ -0,0 +1,33 @@ +/* + * @Author: Uyanide pywang0608@foxmail.com + * @Date: 2025-08-07 00:32:25 + * @LastEditTime: 2025-08-07 01:00:29 + * @Description: LoadingIndicator implementation. + */ +#ifndef LOADING_INDICATOR_H +#define LOADING_INDICATOR_H + +#include + +#include "ui_loading_indicator.h" + +namespace Ui { +class LoadingIndicator; +} + +class LoadingIndicator : public QWidget { + Q_OBJECT + + public: + explicit LoadingIndicator(QWidget *parent = nullptr); + ~LoadingIndicator(); + + void setMaximum(int max) { ui->progressBar->setMaximum(max); } + + void setValue(int value) { ui->progressBar->setValue(value); } + + private: + Ui::LoadingIndicator *ui; +}; + +#endif // LOADING_INDICATOR_H diff --git a/src/main_window.cpp b/src/main_window.cpp index edfddbf..5f63b21 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-06 02:16:25 + * @LastEditTime: 2025-08-07 01:08:55 * @Description: MainWindow implementation. */ #include "main_window.h" @@ -33,7 +33,8 @@ MainWindow::~MainWindow() { } void MainWindow::_setupUI() { - // insert images carousel + + // create images carousel m_carousel = new ImagesCarousel( m_config.getStyleAspectRatio(), m_config.getStyleImageWidth(), @@ -42,14 +43,40 @@ void MainWindow::_setupUI() { m_config.isSortReverse(), this); ui->mainLayout->insertWidget(2, m_carousel); - connect(m_carousel, &ImagesCarousel::imageFocused, this, &MainWindow::_onImageFocused); + connect(m_carousel, + &ImagesCarousel::imageFocused, + this, + &MainWindow::_onImageFocused); + m_carouselIndex = ui->stackedWidget->addWidget(m_carousel); + + // create loading indicator + m_loadingIndicator = new LoadingIndicator(this); + connect(m_carousel, + &ImagesCarousel::loadingStarted, + this, + &MainWindow::_onLoadingStarted); + connect(m_carousel, + &ImagesCarousel::loadingCompleted, + this, + &MainWindow::_onLoadingCompleted); + connect(m_carousel, + &ImagesCarousel::imageLoaded, + m_loadingIndicator, + &LoadingIndicator::setValue); + m_loadingIndicatorIndex = ui->stackedWidget->addWidget(m_loadingIndicator); // 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); + 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); @@ -110,4 +137,13 @@ void MainWindow::onCancel() { 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)); +} + +void MainWindow::_onLoadingStarted(const qsizetype amount) { + m_loadingIndicator->setMaximum(amount); + ui->stackedWidget->setCurrentIndex(m_loadingIndicatorIndex); +} + +void MainWindow::_onLoadingCompleted(const qsizetype amount) { + ui->stackedWidget->setCurrentIndex(m_carouselIndex); } \ No newline at end of file diff --git a/src/main_window.h b/src/main_window.h index ace1f4f..a4af628 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-06 02:13:47 + * @LastEditTime: 2025-08-07 01:08:12 * @Description: MainWindow implementation. */ #ifndef MAINWINDOW_H @@ -11,6 +11,7 @@ #include "config.h" #include "images_carousel.h" +#include "loading_indicator.h" QT_BEGIN_NAMESPACE @@ -40,10 +41,14 @@ class MainWindow : public QMainWindow { private slots: void _onImageFocused(const QString &path, const int index, const int count); + void _onLoadingStarted(const qsizetype amount); + void _onLoadingCompleted(const qsizetype amount); private: Ui::MainWindow *ui; - ImagesCarousel *m_carousel = nullptr; + ImagesCarousel *m_carousel = nullptr; + LoadingIndicator *m_loadingIndicator = nullptr; + int m_carouselIndex, m_loadingIndicatorIndex; const Config &m_config; }; #endif // MAINWINDOW_H