Concurrently load thumbnail images, improving startup times
This commit is contained in:
parent
861a8a14f2
commit
ad37574be9
3 changed files with 53 additions and 16 deletions
59
ArtModel.cpp
59
ArtModel.cpp
|
@ -4,13 +4,21 @@
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QImage>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
ArtModel::ArtModel(const QString& definitionDirectory, const QString& assetDirectory) : QAbstractTableModel() {
|
ArtModel::ArtModel(const QString& definitionDirectory, const QString& assetDirectory) : QAbstractTableModel() {
|
||||||
|
piecesFuture = new QFutureWatcher<ArtPiece>(this);
|
||||||
|
connect(piecesFuture, &QFutureWatcher<ArtPiece>::resultReadyAt, this, &ArtModel::pieceFinished);
|
||||||
|
connect(piecesFuture, &QFutureWatcher<ArtPiece>::finished, this, &ArtModel::finished);
|
||||||
|
|
||||||
|
struct PieceInformation {
|
||||||
|
QString definition;
|
||||||
|
QString asset;
|
||||||
|
};
|
||||||
|
QVector<PieceInformation> pieceList;
|
||||||
QDirIterator it(definitionDirectory);
|
QDirIterator it(definitionDirectory);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QFileInfo info(it.next());
|
QFileInfo info(it.next());
|
||||||
|
@ -18,22 +26,26 @@ ArtModel::ArtModel(const QString& definitionDirectory, const QString& assetDirec
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pieceList.push_back(PieceInformation{QString("%1/%2").arg(definitionDirectory).arg(info.baseName()), QString("%1/%2").arg(assetDirectory).arg(info.baseName())});
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(), m_artPieces.size(), m_artPieces.size() + 1);
|
beginInsertRows(QModelIndex(), m_artPieces.size(), m_artPieces.size() + 1);
|
||||||
|
|
||||||
ArtPiece p;
|
m_artPieces.push_back(ArtPiece{});
|
||||||
loadData(p, QString("%1/%2").arg(definitionDirectory).arg(info.baseName()), QString("%1/%2").arg(assetDirectory).arg(info.baseName()));
|
|
||||||
|
|
||||||
m_artPieces.push_back(p);
|
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(m_artPieces.begin(), m_artPieces.end(), [](ArtPiece& a, ArtPiece& b)
|
std::function<ArtPiece(const PieceInformation& info)> loadPiece = [this](const PieceInformation& info) -> ArtPiece {
|
||||||
{
|
ArtPiece p;
|
||||||
return a.date > b.date;
|
loadData(p, info.definition, info.asset);
|
||||||
});
|
|
||||||
|
|
||||||
dataChanged(index(0, 0), index(m_artPieces.size(), 0));
|
p.image.load(p.filename);
|
||||||
|
p.thumbnail = QPixmap::fromImage(p.image).scaled(100, 100, Qt::AspectRatioMode::KeepAspectRatio).toImage();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
piecesFuture->setFuture(QtConcurrent::mapped(pieceList, loadPiece));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ArtModel::rowCount(const QModelIndex &parent) const {
|
int ArtModel::rowCount(const QModelIndex &parent) const {
|
||||||
|
@ -65,10 +77,7 @@ QVariant ArtModel::data(const QModelIndex &index, int role) const {
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
QImage image;
|
return m_artPieces[index.row()].thumbnail;
|
||||||
image.load(m_artPieces[index.row()].filename);
|
|
||||||
|
|
||||||
return QPixmap::fromImage(image).scaled(100, 100, Qt::AspectRatioMode::KeepAspectRatio);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -113,7 +122,25 @@ void ArtModel::loadData(ArtPiece& piece, const QString& filename, const QString&
|
||||||
piece.date = QDate::fromString(artJson["date"].toString(), "yyyy");
|
piece.date = QDate::fromString(artJson["date"].toString(), "yyyy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (artJson.object().contains("title")) {
|
||||||
|
piece.title = artJson.object()["title"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
if(artJson.object().contains("alt_text")) {
|
if(artJson.object().contains("alt_text")) {
|
||||||
piece.hasAltText = true;
|
piece.hasAltText = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void ArtModel::pieceFinished(int row) {
|
||||||
|
m_artPieces[row] = piecesFuture->resultAt(row);
|
||||||
|
|
||||||
|
Q_EMIT dataChanged(index(row, 0), index(row + 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArtModel::finished() {
|
||||||
|
std::sort(m_artPieces.begin(), m_artPieces.end(), [](ArtPiece& a, ArtPiece& b)
|
||||||
|
{
|
||||||
|
return a.date > b.date;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_EMIT dataChanged(index(0, 0), index(m_artPieces.size(), 0));
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
#include <QImage>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
struct ArtPiece {
|
struct ArtPiece {
|
||||||
QString filename, jsonFilename;
|
QString filename, jsonFilename;
|
||||||
|
@ -9,6 +11,7 @@ struct ArtPiece {
|
||||||
QJsonObject object;
|
QJsonObject object;
|
||||||
|
|
||||||
QDate date;
|
QDate date;
|
||||||
|
QImage image, thumbnail;
|
||||||
|
|
||||||
bool hasAltText = false;
|
bool hasAltText = false;
|
||||||
};
|
};
|
||||||
|
@ -26,5 +29,10 @@ public:
|
||||||
private:
|
private:
|
||||||
void loadData(ArtPiece& piece, const QString& filename, const QString& assetFilename);
|
void loadData(ArtPiece& piece, const QString& filename, const QString& assetFilename);
|
||||||
|
|
||||||
|
void pieceFinished(int index);
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
QFutureWatcher<ArtPiece>* piecesFuture;
|
||||||
|
|
||||||
QList<ArtPiece> m_artPieces;
|
QList<ArtPiece> m_artPieces;
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@ find_package(Qt5 COMPONENTS
|
||||||
Core
|
Core
|
||||||
Gui
|
Gui
|
||||||
Widgets
|
Widgets
|
||||||
|
Concurrent
|
||||||
REQUIRED)
|
REQUIRED)
|
||||||
|
|
||||||
add_executable(Redai main.cpp MainWindow.cpp MainWindow.h ArtModel.cpp ArtModel.h ArtDetailWindow.cpp ArtDetailWindow.h imagelabel.cpp imagelabel.h)
|
add_executable(Redai main.cpp MainWindow.cpp MainWindow.h ArtModel.cpp ArtModel.h ArtDetailWindow.cpp ArtDetailWindow.h imagelabel.cpp imagelabel.h)
|
||||||
|
@ -17,5 +18,6 @@ target_link_libraries(Redai
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Gui
|
Qt5::Gui
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
|
Qt5::Concurrent
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue