refactor: remove unnecessary list

This commit is contained in:
2025-12-01 01:41:55 +01:00
parent c93c58a988
commit bdb071bbdd
2 changed files with 66 additions and 53 deletions
+43 -37
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-12-01 00:58:12 * @LastEditTime: 2025-12-01 01:40:01
* @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"
@@ -14,11 +14,11 @@
#include <QMetaObject> #include <QMetaObject>
#include <QScrollArea> #include <QScrollArea>
#include <QScrollBar> #include <QScrollBar>
#include <QThreadPool>
#include <QVector> #include <QVector>
#include <algorithm>
#include <functional> #include <functional>
#include <iterator>
#include "image_item.h"
#include "logger.h" #include "logger.h"
#include "ui_images_carousel.h" #include "ui_images_carousel.h"
#include "utils.h" #include "utils.h"
@@ -87,7 +87,7 @@ void ImagesCarousel::_onImagesLoaded() {
} }
if (m_initialImagesLoaded) { if (m_initialImagesLoaded) {
// No images loaded // No images loaded
if (m_loadedImages.isEmpty()) { if (!getLoadedImagesCount()) {
return; return;
} }
// Focus the first image // Focus the first image
@@ -102,8 +102,6 @@ void ImagesCarousel::_onImagesLoaded() {
ImagesCarousel::~ImagesCarousel() { ImagesCarousel::~ImagesCarousel() {
delete ui; delete ui;
// memory of items in m_loadedImages managed by Qt parent-child system
// ...
if (m_scrollAnimation) { if (m_scrollAnimation) {
m_scrollAnimation->stop(); m_scrollAnimation->stop();
m_scrollAnimation->deleteLater(); m_scrollAnimation->deleteLater();
@@ -132,7 +130,6 @@ void ImagesCarousel::appendImages(const QStringList& paths) {
&ImagesCarousel::_processImageInsertQueue); &ImagesCarousel::_processImageInsertQueue);
m_imageInsertQueueTimer->start(); m_imageInsertQueueTimer->start();
} }
m_loadedImages.reserve(m_loadedImages.size() + paths.size());
emit loadingStarted(paths.size()); emit loadingStarted(paths.size());
for (const QString& path : paths) { for (const QString& path : paths) {
ImageLoader* loader = new ImageLoader(path, this); ImageLoader* loader = new ImageLoader(path, this);
@@ -162,7 +159,7 @@ void ImagesCarousel::_insertImageQueue(const ImageData* data) {
int ImagesCarousel::_insertImage(const ImageData* data) { int ImagesCarousel::_insertImage(const ImageData* data) {
// Increase loaded count regardless of success or failure // Increase loaded count regardless of success or failure
Defer defer([this]() { Defer defer([this]() {
emit imageLoaded(m_loadedImages.size()); emit imageLoaded(getLoadedImagesCount());
{ {
QMutexLocker countLocker(&m_countMutex); QMutexLocker countLocker(&m_countMutex);
if (++m_loadedImagesCount >= m_addedImagesCount) { if (++m_loadedImagesCount >= m_addedImagesCount) {
@@ -204,26 +201,26 @@ int ImagesCarousel::_insertImage(const ImageData* data) {
}; };
// insert into correct position based on sort type and direction // insert into correct position based on sort type and direction
qint64 insertPos = m_loadedImages.size(); qint64 insertPos = getLoadedImagesCount();
if (m_sortType != Config::SortType::None) { if (m_sortType != Config::SortType::None) {
auto cmp = cmpFuncs[static_cast<int>(m_sortType)]; auto cmp = cmpFuncs[static_cast<int>(m_sortType)];
auto reverse = m_sortReverse; auto reverse = m_sortReverse;
auto it = std::upper_bound( int left = 0, right = getLoadedImagesCount();
m_loadedImages.begin(), while (left < right) {
m_loadedImages.end(), int mid = left + (right - left) / 2;
item, if (reverse ? cmp(item, getImageItemAt(mid)) : cmp(getImageItemAt(mid), item)) {
[cmp, reverse](const ImageItem* a, const ImageItem* b) { right = mid;
return reverse ? cmp(b, a) : cmp(a, b); } else {
}); left = mid + 1;
}
insertPos = std::distance(m_loadedImages.begin(), it); }
insertPos = left;
} }
connect(item, connect(item,
&ImageItem::clicked, &ImageItem::clicked,
this, this,
&ImagesCarousel::_onItemClicked); &ImagesCarousel::_onItemClicked);
m_loadedImages.insert(insertPos, item);
m_imagesLayout->insertWidget(insertPos, item); m_imagesLayout->insertWidget(insertPos, item);
return insertPos; return insertPos;
} }
@@ -247,7 +244,7 @@ void ImagesCarousel::_processImageInsertQueue() {
// Update focusing index if any // Update focusing index if any
if (m_currentIndex >= 0) { if (m_currentIndex >= 0) {
m_currentIndex = currPos; m_currentIndex = currPos;
if (m_currentIndex < 0 || m_currentIndex >= m_loadedImages.size()) { if (m_currentIndex < 0 || m_currentIndex >= getLoadedImagesCount()) {
m_currentIndex = 0; m_currentIndex = 0;
} }
} }
@@ -283,46 +280,49 @@ void ImageLoader::run() {
} }
void ImagesCarousel::focusNextImage() { void ImagesCarousel::focusNextImage() {
const auto count = getLoadedImagesCount();
// If no focus, focus the first image // If no focus, focus the first image
if (m_currentIndex < 0) { if (m_currentIndex < 0) {
if (m_loadedImages.isEmpty()) return; if (!count) return;
m_currentIndex = 0; m_currentIndex = 0;
focusCurrImage(); focusCurrImage();
return; return;
} }
unfocusCurrImage(); unfocusCurrImage();
if (m_loadedImages.size() <= 1) return; if (count <= 1) return;
m_currentIndex++; m_currentIndex++;
if (m_currentIndex >= m_loadedImages.size()) { if (m_currentIndex >= count) {
m_currentIndex = 0; m_currentIndex = 0;
} }
focusCurrImage(); focusCurrImage();
} }
void ImagesCarousel::focusPrevImage() { void ImagesCarousel::focusPrevImage() {
const auto count = getLoadedImagesCount();
// If no focus, focus the last image // If no focus, focus the last image
if (m_currentIndex < 0) { if (m_currentIndex < 0) {
if (m_loadedImages.isEmpty()) return; if (!count) return;
m_currentIndex = m_loadedImages.size() - 1; m_currentIndex = count - 1;
focusCurrImage(); focusCurrImage();
return; return;
} }
if (m_loadedImages.size() <= 1) return; if (count <= 1) return;
unfocusCurrImage(); unfocusCurrImage();
m_currentIndex--; m_currentIndex--;
if (m_currentIndex < 0) { if (m_currentIndex < 0) {
m_currentIndex = m_loadedImages.size() - 1; m_currentIndex = count - 1;
} }
focusCurrImage(); focusCurrImage();
} }
void ImagesCarousel::unfocusCurrImage() { void ImagesCarousel::unfocusCurrImage() {
if (m_currentIndex < 0) return; if (m_currentIndex < 0) return;
if (m_currentIndex >= m_loadedImages.size()) { if (m_currentIndex >= getLoadedImagesCount()) {
warn(QString("Invalid index to unfocus: %1").arg(m_currentIndex)); warn(QString("Invalid index to unfocus: %1").arg(m_currentIndex));
return; return;
} }
m_loadedImages[m_currentIndex]->setFocus(false, m_animationEnabled); auto item = getImageItemAt(m_currentIndex);
if (item) item->setFocus(false, m_animationEnabled);
} }
int ImagesCarousel::_focusingLeftOffset(int index) { int ImagesCarousel::_focusingLeftOffset(int index) {
@@ -334,14 +334,19 @@ int ImagesCarousel::_focusingLeftOffset(int index) {
void ImagesCarousel::focusCurrImage() { void ImagesCarousel::focusCurrImage() {
// If no focus, do nothing // If no focus, do nothing
if (m_currentIndex < 0) return; if (m_currentIndex < 0) return;
if (m_currentIndex >= m_loadedImages.size()) { if (m_currentIndex >= getLoadedImagesCount()) {
warn(QString("Invalid index to focus: %1").arg(m_currentIndex)); warn(QString("Invalid index to focus: %1").arg(m_currentIndex));
return; return;
} }
m_loadedImages[m_currentIndex]->setFocus(true, m_animationEnabled); auto item = getImageItemAt(m_currentIndex);
emit imageFocused(m_loadedImages[m_currentIndex]->getFileFullPath(), if (!item) {
warn(QString("Failed to get item at index: %1").arg(m_currentIndex));
return;
}
item->setFocus(true, m_animationEnabled);
emit imageFocused(item->getFileFullPath(),
m_currentIndex, m_currentIndex,
m_loadedImages.size()); getLoadedImagesCount());
auto hScrollBar = ui->scrollArea->horizontalScrollBar(); auto hScrollBar = ui->scrollArea->horizontalScrollBar();
int leftOffset = _focusingLeftOffset(m_currentIndex); int leftOffset = _focusingLeftOffset(m_currentIndex);
if (leftOffset < 0) { if (leftOffset < 0) {
@@ -389,7 +394,7 @@ void ImagesCarousel::_onScrollBarValueChanged(int value) {
int itemOffset = m_itemWidth + ui->scrollAreaWidgetContents->layout()->spacing(); int itemOffset = m_itemWidth + ui->scrollAreaWidgetContents->layout()->spacing();
int index = centerOffset / itemOffset; int index = centerOffset / itemOffset;
if (index < 0 || index >= m_loadedImages.size()) { if (index < 0 || index >= getLoadedImagesCount()) {
return; // Out of bounds return; // Out of bounds
} }
if (index == m_currentIndex) { if (index == m_currentIndex) {
@@ -404,14 +409,15 @@ void ImagesCarousel::_onItemClicked(const QString& path) {
// if (m_suppressAutoFocus) return; // if (m_suppressAutoFocus) return;
unfocusCurrImage(); unfocusCurrImage();
// Most likely the clicked item is near the current index // Most likely the clicked item is near the current index
const auto count = getLoadedImagesCount();
for (int i = m_currentIndex, j = m_currentIndex + 1; for (int i = m_currentIndex, j = m_currentIndex + 1;
i >= 0 || j < m_loadedImages.size(); i >= 0 || j < count;
--i, ++j) { --i, ++j) {
if (i >= 0 && m_loadedImages[i]->getFileFullPath() == path) { if (i >= 0 && getImageItemAt(i)->getFileFullPath() == path) {
m_currentIndex = i; m_currentIndex = i;
break; break;
} }
if (j < m_loadedImages.size() && m_loadedImages[j]->getFileFullPath() == path) { if (j < count && getImageItemAt(j)->getFileFullPath() == path) {
m_currentIndex = j; m_currentIndex = j;
break; break;
} }
+19 -12
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-12-01 00:59:39 * @LastEditTime: 2025-12-01 01:36:04
* @Description: Animated carousel widget for displaying and selecting images. * @Description: Animated carousel widget for displaying and selecting images.
*/ */
#ifndef IMAGES_CAROUSEL_H #ifndef IMAGES_CAROUSEL_H
@@ -12,18 +12,13 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QLabel>
#include <QMutex> #include <QMutex>
#include <QObject>
#include <QPixmap>
#include <QPointer> #include <QPointer>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QQueue> #include <QQueue>
#include <QRunnable> #include <QRunnable>
#include <QScrollArea> #include <QScrollArea>
#include <QThreadPool>
#include <QTimer> #include <QTimer>
#include <QWidget>
#include "config.h" #include "config.h"
#include "image_item.h" #include "image_item.h"
@@ -70,15 +65,28 @@ class ImagesCarousel : public QWidget {
static constexpr int s_processBatchSize = 30; // items static constexpr int s_processBatchSize = 30; // items
[[nodiscard]] QString getCurrentImagePath() const { [[nodiscard]] QString getCurrentImagePath() const {
if (m_currentIndex < 0 || m_currentIndex >= m_loadedImages.size()) { if (m_currentIndex >= 0 && m_currentIndex < getLoadedImagesCount()) {
return ""; auto item = getImageItemAt(m_currentIndex);
if (item) {
return item->getFileFullPath();
} }
return m_loadedImages[m_currentIndex]->getFileFullPath(); }
return "";
} }
// Should always be called in the main thread // Should always be called in the main thread
[[nodiscard]] qsizetype getLoadedImagesCount() { [[nodiscard]] qsizetype getLoadedImagesCount() const {
return m_loadedImages.size(); return m_imagesLayout->count();
}
[[nodiscard]] ImageItem* getImageItemAt(int index) const {
if (index < 0 || index >= getLoadedImagesCount()) {
return nullptr;
}
return dynamic_cast<ImageItem*>(
m_imagesLayout
->itemAt(index)
->widget());
} }
[[nodiscard]] qsizetype getAddedImagesCount() { [[nodiscard]] qsizetype getAddedImagesCount() {
@@ -126,7 +134,6 @@ class ImagesCarousel : public QWidget {
ImagesCarouselScrollArea* m_scrollArea = nullptr; ImagesCarouselScrollArea* m_scrollArea = nullptr;
// Items and counters // Items and counters
QVector<ImageItem*> m_loadedImages; // m_loadedImages.size() may != m_loadedImagesCount
int m_loadedImagesCount = 0; // increase when _insertImage is called OR ImageLoader::run() is called with m_stopSign as true int m_loadedImagesCount = 0; // increase when _insertImage is called OR ImageLoader::run() is called with m_stopSign as true
int m_addedImagesCount = 0; // increase when appendImages called int m_addedImagesCount = 0; // increase when appendImages called
QMutex m_countMutex; // for m_loadedImagesCount and m_addedImagesCount QMutex m_countMutex; // for m_loadedImagesCount and m_addedImagesCount