commit 459bad0f
Cache folders while switching between them
Changed files
| M | src/imagemodel.cpp before |
| M | src/imagemodel.h before |
| M | src/mainwindow.cpp before |
| M | src/mainwindow.h before |
| M | src/preferencesdialog.cpp before |
| M | src/preferencesdialog.h before |
diff --git a/src/imagemodel.cpp b/src/imagemodel.cpp
index 3288ae0..622dbf6 100644
--- a/src/imagemodel.cpp
+++ b/src/imagemodel.cpp
@@ -9,7 +9,8 @@
ImageModel::ImageModel(QObject *parent)
: QAbstractListModel(parent)
{
- m_threadPool.setMaxThreadCount(QThread::idealThreadCount());
+ // Limit 1 thread for thumbnail loading to avoid excessive disk I/O on harddrives. SSDs are so fast the extra threads don't help much anyway.
+ m_threadPool.setMaxThreadCount(1); //QThread::idealThreadCount()
m_placeholder = QPixmap(128, 128);
m_placeholder.fill(Qt::lightGray);
@@ -24,12 +25,35 @@ ImageModel::~ImageModel()
m_threadPool.waitForDone();
}
+void ImageModel::setCacheMaxSize(int n)
+{
+ m_cacheMaxSize = std::max(0, n);
+ while (m_cacheOrder.size() > m_cacheMaxSize)
+ m_folderThumbnailCache.remove(m_cacheOrder.takeFirst());
+}
+
void ImageModel::setDirectory(const QString &path)
{
m_cancelFlag = true;
m_threadPool.waitForDone();
m_cancelFlag = false;
+ // Save current folder's thumbnails to cache before discarding them
+ if (!m_currentDir.isEmpty()) {
+ ThumbnailMap map;
+ for (const Item &item : m_items)
+ if (item.loaded && !item.isFolder)
+ map[item.path] = item.thumbnail;
+ if (!map.isEmpty()) {
+ if (!m_cacheOrder.contains(m_currentDir)) {
+ m_cacheOrder.append(m_currentDir);
+ if (m_cacheOrder.size() > m_cacheMaxSize)
+ m_folderThumbnailCache.remove(m_cacheOrder.takeFirst());
+ }
+ m_folderThumbnailCache[m_currentDir] = std::move(map);
+ }
+ }
+
beginResetModel();
m_items.clear();
m_pendingRows.clear();
@@ -61,9 +85,23 @@ void ImageModel::setDirectory(const QString &path)
const auto files = dir.entryInfoList();
+ // Restore cached thumbnails for this folder if available
+ const ThumbnailMap *cached = m_folderThumbnailCache.contains(path)
+ ? &m_folderThumbnailCache[path]
+ : nullptr;
+
for (const QFileInfo &file : files)
{
- m_items.append({file.absoluteFilePath(), file.fileName(), m_placeholder, false, false});
+ QPixmap thumb = m_placeholder;
+ bool loaded = false;
+ if (cached) {
+ auto it = cached->find(file.absoluteFilePath());
+ if (it != cached->end()) {
+ thumb = it.value();
+ loaded = true;
+ }
+ }
+ m_items.append({file.absoluteFilePath(), file.fileName(), thumb, loaded, false});
}
endResetModel();
diff --git a/src/imagemodel.h b/src/imagemodel.h
index 7586159..0be4ed7 100644
--- a/src/imagemodel.h
+++ b/src/imagemodel.h
@@ -5,6 +5,8 @@
#include <QVector>
#include <QThreadPool>
#include <QSet>
+#include <QHash>
+#include <QList>
#include <atomic>
#include <QIcon>
@@ -24,6 +26,7 @@ public:
QString currentDirectory() const;
void requestThumbnails(int firstRow, int lastRow);
+ void setCacheMaxSize(int n);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
@@ -42,6 +45,8 @@ private:
void queueRow(int row);
+ using ThumbnailMap = QHash<QString, QPixmap>;
+
QVector<Item> m_items;
QThreadPool m_threadPool;
QPixmap m_placeholder;
@@ -50,4 +55,9 @@ private:
std::atomic_bool m_cancelFlag{false};
QIcon m_folderIcon;
QString m_currentDir;
+
+ // Folder thumbnail cache (last N visited directories)
+ QHash<QString, ThumbnailMap> m_folderThumbnailCache;
+ QList<QString> m_cacheOrder;
+ int m_cacheMaxSize = 4;
};
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 312c92f..2086083 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -439,6 +439,8 @@ void MainWindow::loadPreferences()
m_imageView->setBackgroundColor(m_backgroundColorPreference);
m_lockDockingPreference = settings.value("lockDocking", false).toBool();
applyDockLocking(m_lockDockingPreference);
+ m_folderCacheSizePreference = settings.value("folderCacheSize", 4).toInt();
+ m_imageModel->setCacheMaxSize(m_folderCacheSizePreference);
if (settings.contains("windowGeometry"))
restoreGeometry(settings.value("windowGeometry").toByteArray());
if (settings.contains("windowState"))
@@ -450,6 +452,7 @@ void MainWindow::savePreferences()
QSettings settings("SagoImageBrowser", "SagoImageBrowser");
settings.setValue("backgroundColor", m_backgroundColorPreference);
settings.setValue("lockDocking", m_lockDockingPreference);
+ settings.setValue("folderCacheSize", m_folderCacheSizePreference);
settings.setValue("windowGeometry", saveGeometry());
settings.setValue("windowState", saveState());
}
@@ -459,6 +462,7 @@ void MainWindow::onPreferencesTriggered()
PreferencesDialog dialog(this);
dialog.setBackgroundColor(m_backgroundColorPreference);
dialog.setLockDocking(m_lockDockingPreference);
+ dialog.setCacheSize(m_folderCacheSizePreference);
bool shouldResetLayout = false;
connect(&dialog, &PreferencesDialog::resetLayoutRequested, this, [&shouldResetLayout]() {
@@ -471,6 +475,8 @@ void MainWindow::onPreferencesTriggered()
m_imageView->setBackgroundColor(m_backgroundColorPreference);
m_lockDockingPreference = dialog.getLockDocking();
applyDockLocking(m_lockDockingPreference);
+ m_folderCacheSizePreference = dialog.getCacheSize();
+ m_imageModel->setCacheMaxSize(m_folderCacheSizePreference);
savePreferences();
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 76bcf9e..39f127d 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -52,6 +52,7 @@ private:
QStackedWidget *m_stack;
QString m_backgroundColorPreference = "black";
+ int m_folderCacheSizePreference = 4;
QWidget *m_browserPage;
ImageViewWidget *m_imageView;
bool m_wasMaximized = false;
diff --git a/src/preferencesdialog.cpp b/src/preferencesdialog.cpp
index 32de6c5..a96b863 100644
--- a/src/preferencesdialog.cpp
+++ b/src/preferencesdialog.cpp
@@ -4,6 +4,7 @@
#include <QHBoxLayout>
#include <QLabel>
#include <QComboBox>
+#include <QSpinBox>
#include <QCheckBox>
#include <QPushButton>
#include <QGroupBox>
@@ -32,6 +33,17 @@ PreferencesDialog::PreferencesDialog(QWidget *parent)
bgColorLayout->addStretch();
groupLayout->addLayout(bgColorLayout);
+
+ QHBoxLayout *cacheSizeLayout = new QHBoxLayout;
+ QLabel *cacheSizeLabel = new QLabel("Folder thumbnail cache (folders):");
+ m_cacheSizeSpinBox = new QSpinBox;
+ m_cacheSizeSpinBox->setRange(1, 20);
+ m_cacheSizeSpinBox->setValue(4);
+ cacheSizeLayout->addWidget(cacheSizeLabel);
+ cacheSizeLayout->addWidget(m_cacheSizeSpinBox);
+ cacheSizeLayout->addStretch();
+ groupLayout->addLayout(cacheSizeLayout);
+
mainLayout->addWidget(imageGroup);
QGroupBox *layoutGroup = new QGroupBox("Layout", this);
@@ -76,6 +88,16 @@ void PreferencesDialog::setBackgroundColor(const QString &color)
m_backgroundColorCombo->setCurrentIndex(index);
}
+int PreferencesDialog::getCacheSize() const
+{
+ return m_cacheSizeSpinBox->value();
+}
+
+void PreferencesDialog::setCacheSize(int n)
+{
+ m_cacheSizeSpinBox->setValue(n);
+}
+
bool PreferencesDialog::getLockDocking() const
{
return m_lockDockingCheck->isChecked();
diff --git a/src/preferencesdialog.h b/src/preferencesdialog.h
index 391fc8d..a6b79cf 100644
--- a/src/preferencesdialog.h
+++ b/src/preferencesdialog.h
@@ -4,6 +4,7 @@
class QComboBox;
class QCheckBox;
+class QSpinBox;
class PreferencesDialog : public QDialog
{
@@ -15,6 +16,9 @@ public:
QString getBackgroundColor() const;
void setBackgroundColor(const QString &color);
+ int getCacheSize() const;
+ void setCacheSize(int n);
+
bool getLockDocking() const;
void setLockDocking(bool lock);
@@ -26,6 +30,7 @@ signals:
private:
QComboBox *m_backgroundColorCombo;
+ QSpinBox *m_cacheSizeSpinBox;
QCheckBox *m_lockDockingCheck;
QCheckBox *m_resetLayoutCheck;
};