#include "ArtModel.h" #include #include #include #include #include #include #include #include ArtModel::ArtModel(const QString& definitionDirectory, const QString& assetDirectory) : QAbstractTableModel() { piecesFuture = new QFutureWatcher(this); connect(piecesFuture, &QFutureWatcher::resultReadyAt, this, &ArtModel::pieceFinished); connect(piecesFuture, &QFutureWatcher::finished, this, &ArtModel::finished); struct PieceInformation { QString definition; QString asset; }; QVector pieceList; QDirIterator it(definitionDirectory); while (it.hasNext()) { QFileInfo info(it.next()); if(!info.isFile()) { 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); m_artPieces.push_back(ArtPiece{}); endInsertRows(); } std::function loadPiece = [this](const PieceInformation& info) -> ArtPiece { ArtPiece p; loadData(p, info.definition, info.asset); 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 { return m_artPieces.size(); } int ArtModel::columnCount(const QModelIndex &parent) const { return 4; } QVariant ArtModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return {}; if (role == Qt::DisplayRole) { switch(index.column()) { case 0: return m_artPieces[index.row()].filename; case 1: return {}; case 2: return m_artPieces[index.row()].title; case 3: return m_artPieces[index.row()].hasAltText; } } else if (role == Qt::UserRole) { return m_artPieces[index.row()].object; } else if (role == Qt::DecorationRole) { switch(index.column()) { case 1: { return m_artPieces[index.row()].thumbnail; } break; case 3: return m_artPieces[index.row()].hasAltText ? QIcon::fromTheme("emblem-checked") : QIcon::fromTheme("emblem-error"); } } else if (role == Qt::UserRole + 1) { return m_artPieces[index.row()].jsonFilename; } return {}; } QVariant ArtModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Orientation::Horizontal && role == Qt::DisplayRole) { switch(section) { case 0: return "Filename"; case 1: return "Image"; case 2: return "Title"; case 3: return "Has Alt Text"; } } return QAbstractTableModel::headerData(section, orientation, role); } void ArtModel::loadData(ArtPiece& piece, const QString& filename, const QString& assetFilename) { piece.jsonFilename = filename + ".json"; piece.filename = assetFilename; QFile artFile(piece.jsonFilename); artFile.open(QFile::ReadOnly); QJsonDocument artJson = QJsonDocument::fromJson(artFile.readAll()); if(artJson["date"].toString().contains("-")) { piece.date = QDate::fromString(artJson["date"].toString(), "yyyy-MM-dd"); } else { 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")) { 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)); }