commit cec3b5da
Now loads pictures in the background
Changed files
| M | CMakeLists.txt before |
| M | imagemodel.cpp before |
| M | imagemodel.h before |
| A | thumbnailworker.cpp |
| A | thumbnailworker.h |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea1e767..3eba63e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,8 @@ qt_add_executable(ImageBrowser
mainwindow.h
imagemodel.cpp
imagemodel.h
+ thumbnailworker.cpp
+ thumbnailworker.h
)
target_link_libraries(ImageBrowser PRIVATE Qt6::Widgets)
\ No newline at end of file
diff --git a/imagemodel.cpp b/imagemodel.cpp
index f22f119..b6fd272 100644
--- a/imagemodel.cpp
+++ b/imagemodel.cpp
@@ -1,4 +1,5 @@
#include "imagemodel.h"
+#include "thumbnailworker.h"
#include <QDir>
#include <QImageReader>
@@ -7,6 +8,16 @@
ImageModel::ImageModel(QObject *parent)
: QAbstractListModel(parent)
{
+ m_threadPool.setMaxThreadCount(QThread::idealThreadCount());
+
+ // Simple gray placeholder
+ m_placeholder = QPixmap(128, 128);
+ m_placeholder.fill(Qt::lightGray);
+}
+
+ImageModel::~ImageModel()
+{
+ m_threadPool.waitForDone();
}
void ImageModel::setDirectory(const QString &path)
@@ -24,17 +35,23 @@ void ImageModel::setDirectory(const QString &path)
dir.setNameFilters(filters);
dir.setFilter(QDir::Files);
- for (const QFileInfo &file : dir.entryInfoList())
+ const auto files = dir.entryInfoList();
+
+ int row = 0;
+ for (const QFileInfo &file : files)
{
- QImageReader reader(file.absoluteFilePath());
- reader.setAutoTransform(true);
+ m_items.append({file.absoluteFilePath(), m_placeholder, false});
+
+ // Create worker
+ auto *worker = new ThumbnailWorker(file.absoluteFilePath(), row);
- QImage image = reader.read();
- QPixmap thumb = QPixmap::fromImage(
- image.scaled(128, 128, Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
+ connect(worker, &ThumbnailWorker::finished,
+ this, &ImageModel::thumbnailReady,
+ Qt::QueuedConnection);
- m_items.append({file.absoluteFilePath(), thumb});
+ m_threadPool.start(worker);
+
+ row++;
}
endResetModel();
@@ -68,3 +85,15 @@ QVariant ImageModel::data(const QModelIndex &index, int role) const
return {};
}
+
+void ImageModel::thumbnailReady(int row, const QPixmap &pixmap)
+{
+ if (row < 0 || row >= m_items.size())
+ return;
+
+ m_items[row].thumbnail = pixmap;
+ m_items[row].loaded = true;
+
+ QModelIndex idx = index(row);
+ emit dataChanged(idx, idx, {Qt::DecorationRole});
+}
diff --git a/imagemodel.h b/imagemodel.h
index 3915a94..ab11e6d 100644
--- a/imagemodel.h
+++ b/imagemodel.h
@@ -3,6 +3,9 @@
#include <QAbstractListModel>
#include <QPixmap>
#include <QVector>
+#include <QThreadPool>
+
+class ThumbnailWorker;
class ImageModel : public QAbstractListModel
{
@@ -10,6 +13,7 @@ class ImageModel : public QAbstractListModel
public:
explicit ImageModel(QObject *parent = nullptr);
+ ~ImageModel();
void setDirectory(const QString &path);
QString filePath(const QModelIndex &index) const;
@@ -17,12 +21,17 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
+ void thumbnailReady(int row, const QPixmap &pixmap);
+
private:
struct Item
{
QString path;
QPixmap thumbnail;
+ bool loaded = false;
};
QVector<Item> m_items;
+ QThreadPool m_threadPool;
+ QPixmap m_placeholder;
};
diff --git a/thumbnailworker.cpp b/thumbnailworker.cpp
new file mode 100644
index 0000000..f02d710
--- /dev/null
+++ b/thumbnailworker.cpp
@@ -0,0 +1,27 @@
+#include "thumbnailworker.h"
+#include <QImageReader>
+
+ThumbnailWorker::ThumbnailWorker(const QString &path, int row)
+ : m_path(path), m_row(row)
+{
+ setAutoDelete(true);
+}
+
+void ThumbnailWorker::run()
+{
+ QImageReader reader(m_path);
+ reader.setAutoTransform(true);
+
+ QImage image = reader.read();
+ QPixmap thumb;
+
+ if (!image.isNull())
+ {
+ thumb = QPixmap::fromImage(
+ image.scaled(128, 128,
+ Qt::KeepAspectRatio,
+ Qt::SmoothTransformation));
+ }
+
+ emit finished(m_row, thumb);
+}
diff --git a/thumbnailworker.h b/thumbnailworker.h
new file mode 100644
index 0000000..13df897
--- /dev/null
+++ b/thumbnailworker.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <QRunnable>
+#include <QObject>
+#include <QPixmap>
+
+class ThumbnailWorker : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ ThumbnailWorker(const QString &path, int row);
+
+ void run() override;
+
+signals:
+ void finished(int row, const QPixmap &pixmap);
+
+private:
+ QString m_path;
+ int m_row;
+};