Add support for configuring featured art
This commit is contained in:
parent
914bf53cf1
commit
94aa711634
8 changed files with 145 additions and 10 deletions
|
@ -42,6 +42,8 @@ target_sources(Redai PRIVATE
|
|||
src/artdetailwindow.h
|
||||
src/artmodel.cpp
|
||||
src/artmodel.h
|
||||
src/featuredartmodel.cpp
|
||||
src/featuredartmodel.h
|
||||
src/imagelabel.cpp
|
||||
src/imagelabel.h
|
||||
src/main.cpp
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
|
||||
ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
||||
ArtConfigWindow::ArtConfigWindow(const QString &filename, const QString &definitionDirectory, const QString &assetDirectory, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowModality(Qt::WindowModality::WindowModal);
|
||||
|
@ -30,8 +30,11 @@ ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
|||
formLayoutWidget->setLayout(formLayout);
|
||||
mainLayout->addWidget(formLayoutWidget);
|
||||
|
||||
auto galleryScrollArea = new QScrollArea();
|
||||
formLayout->addWidget(galleryScrollArea);
|
||||
model = new FeaturedArtModel(definitionDirectory, assetDirectory);
|
||||
|
||||
auto galleryListView = new QListView();
|
||||
galleryListView->setModel(model);
|
||||
formLayout->addWidget(galleryListView);
|
||||
|
||||
m_newBannerEdit = new QLineEdit();
|
||||
formLayout->addRow(i18nc("@label:textbox", "New Banner"), m_newBannerEdit);
|
||||
|
@ -47,10 +50,11 @@ ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
|||
bottomButtonLayout->addWidget(cancelButton);
|
||||
bottomButtonLayout->addStretch(1);
|
||||
|
||||
auto saveButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-ok")), i18nc("@action:button", "Save"));
|
||||
saveButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-ok")), i18nc("@action:button", "Save"));
|
||||
connect(saveButton, &QPushButton::clicked, this, [this, filename] {
|
||||
saveData(filename);
|
||||
});
|
||||
saveButton->setEnabled(false);
|
||||
bottomButtonLayout->addWidget(saveButton);
|
||||
|
||||
if (QFile::exists(filename)) {
|
||||
|
@ -69,6 +73,16 @@ void ArtConfigWindow::loadData(const QString &filename)
|
|||
|
||||
m_newBannerEdit->setText(artJson[QStringLiteral("new-banner")].toString());
|
||||
m_commissionsOpen->setChecked(artJson[QStringLiteral("commissions")].toBool());
|
||||
|
||||
connect(model, &ArtModel::loadingFinished, this, [=] {
|
||||
saveButton->setEnabled(true);
|
||||
|
||||
QStringList featuredList;
|
||||
for (auto featuredId : artJson["featured"].toArray()) {
|
||||
featuredList.push_back(featuredId.toString());
|
||||
}
|
||||
model->setFeaturedItems(featuredList);
|
||||
});
|
||||
}
|
||||
|
||||
void ArtConfigWindow::saveData(const QString &filename)
|
||||
|
@ -79,6 +93,17 @@ void ArtConfigWindow::saveData(const QString &filename)
|
|||
object[QStringLiteral("new-banner")] = m_newBannerEdit->text();
|
||||
object[QStringLiteral("commissions")] = m_commissionsOpen->isChecked();
|
||||
|
||||
QJsonArray featuredArray;
|
||||
for (int i = 0; i < model->rowCount({}); i++) {
|
||||
const auto checkState = model->data(model->index(i, 0), Qt::CheckStateRole).value<Qt::CheckState>();
|
||||
if (checkState == Qt::Checked) {
|
||||
QFileInfo fileInfo(model->data(model->index(i, 1), Qt::DisplayRole).toString());
|
||||
featuredArray.push_back(fileInfo.baseName());
|
||||
}
|
||||
}
|
||||
|
||||
object["featured"] = featuredArray;
|
||||
|
||||
const QJsonDocument jsonDoc(object);
|
||||
|
||||
QFile file(filename);
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#include <QStringListModel>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "featuredartmodel.h"
|
||||
|
||||
class ArtConfigWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ArtConfigWindow(const QString &filename, QWidget *parent = nullptr);
|
||||
explicit ArtConfigWindow(const QString &filename, const QString &definitionDirectory, const QString &assetDirectory, QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
void loadData(const QString &filename);
|
||||
|
@ -25,4 +27,8 @@ private:
|
|||
|
||||
QLineEdit *m_newBannerEdit = nullptr;
|
||||
QCheckBox *m_commissionsOpen = nullptr;
|
||||
|
||||
FeaturedArtModel *model = nullptr;
|
||||
|
||||
QPushButton *saveButton = nullptr;
|
||||
};
|
|
@ -43,7 +43,7 @@ ArtModel::ArtModel(const QDir &definitionDirectory, const QDir &assetDirectory,
|
|||
endInsertRows();
|
||||
}
|
||||
|
||||
const std::function<ArtPiece(const PieceInformation &info)> loadPiece = [this](const PieceInformation &info) -> ArtPiece {
|
||||
const std::function<ArtPiece(const PieceInformation &info)> loadPiece = [](const PieceInformation &info) -> ArtPiece {
|
||||
ArtPiece p(info.definition, info.asset);
|
||||
|
||||
p.image.load(p.filename);
|
||||
|
@ -134,6 +134,8 @@ void ArtModel::finished()
|
|||
});
|
||||
|
||||
Q_EMIT dataChanged(index(0, 0), index(m_artPieces.size(), 0));
|
||||
|
||||
Q_EMIT loadingFinished();
|
||||
}
|
||||
|
||||
ArtPiece::ArtPiece(const QString &filename, const QString &assetFilename)
|
||||
|
|
|
@ -38,11 +38,15 @@ public:
|
|||
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
|
||||
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void loadingFinished();
|
||||
|
||||
protected:
|
||||
QVector<ArtPiece> m_artPieces;
|
||||
|
||||
private:
|
||||
void pieceFinished(int index);
|
||||
void finished();
|
||||
|
||||
QFutureWatcher<ArtPiece> *piecesFuture;
|
||||
|
||||
QVector<ArtPiece> m_artPieces;
|
||||
};
|
||||
|
|
71
src/featuredartmodel.cpp
Normal file
71
src/featuredartmodel.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "featuredartmodel.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
FeaturedArtModel::FeaturedArtModel(const QString &definitionDirectory, const QString &assetDirectory)
|
||||
: ArtModel(definitionDirectory, assetDirectory)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant FeaturedArtModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (index.column() == 0) {
|
||||
return ArtModel::data(FeaturedArtModel::index(index.row(), 2), role);
|
||||
} else {
|
||||
return ArtModel::data(FeaturedArtModel::index(index.row(), 0), role);
|
||||
}
|
||||
} else if (role == Qt::DecorationRole && index.column() == 0) {
|
||||
return ArtModel::data(FeaturedArtModel::index(index.row(), 1), role);
|
||||
} else if (role == Qt::CheckStateRole) {
|
||||
return checkedItems.contains(index) ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
|
||||
return ArtModel::data(index, role);
|
||||
}
|
||||
|
||||
Qt::ItemFlags FeaturedArtModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
const Qt::ItemFlags defaultFlags = ArtModel::flags(index);
|
||||
if (index.isValid()) {
|
||||
return defaultFlags | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
return defaultFlags;
|
||||
}
|
||||
|
||||
bool FeaturedArtModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() || role != Qt::CheckStateRole) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value == Qt::Checked) {
|
||||
checkedItems.insert(index);
|
||||
} else {
|
||||
checkedItems.remove(index);
|
||||
}
|
||||
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FeaturedArtModel::setFeaturedItems(QStringList featured)
|
||||
{
|
||||
for (const auto &id : featured) {
|
||||
for (int i = 0; i < m_artPieces.size(); i++) {
|
||||
ArtPiece &piece = m_artPieces[i];
|
||||
QFileInfo fileInfo(piece.jsonFilename);
|
||||
if (fileInfo.baseName() == id) {
|
||||
setData(index(i, 0), Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
src/featuredartmodel.h
Normal file
24
src/featuredartmodel.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "artmodel.h"
|
||||
|
||||
class FeaturedArtModel : public ArtModel
|
||||
{
|
||||
public:
|
||||
FeaturedArtModel(const QString &definitionDirectory, const QString &assetDirectory);
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
|
||||
void setFeaturedItems(QStringList featured);
|
||||
|
||||
private:
|
||||
QSet<QPersistentModelIndex> checkedItems;
|
||||
};
|
|
@ -25,8 +25,9 @@ MainWindow::MainWindow(const QDir &definitionDirectory, const QDir &assetDirecto
|
|||
auto manageMenu = menuBar->addMenu(i18nc("@title:menu Manage site", "Manage"));
|
||||
|
||||
auto editConfigAction = manageMenu->addAction(i18nc("@action:inmenu", "Edit Config..."));
|
||||
connect(editConfigAction, &QAction::triggered, this, [this, dataDirectory] {
|
||||
auto window = new ArtConfigWindow(dataDirectory.absoluteFilePath("art-config.json"), this);
|
||||
connect(editConfigAction, &QAction::triggered, this, [this, dataDirectory, definitionDirectory, assetDirectory] {
|
||||
auto window =
|
||||
new ArtConfigWindow(dataDirectory.absoluteFilePath("art-config.json"), definitionDirectory.absolutePath(), assetDirectory.absolutePath(), this);
|
||||
window->show();
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue