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/artdetailwindow.h
|
||||||
src/artmodel.cpp
|
src/artmodel.cpp
|
||||||
src/artmodel.h
|
src/artmodel.h
|
||||||
|
src/featuredartmodel.cpp
|
||||||
|
src/featuredartmodel.h
|
||||||
src/imagelabel.cpp
|
src/imagelabel.cpp
|
||||||
src/imagelabel.h
|
src/imagelabel.h
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
|
||||||
ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
ArtConfigWindow::ArtConfigWindow(const QString &filename, const QString &definitionDirectory, const QString &assetDirectory, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
setWindowModality(Qt::WindowModality::WindowModal);
|
setWindowModality(Qt::WindowModality::WindowModal);
|
||||||
|
@ -30,8 +30,11 @@ ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
||||||
formLayoutWidget->setLayout(formLayout);
|
formLayoutWidget->setLayout(formLayout);
|
||||||
mainLayout->addWidget(formLayoutWidget);
|
mainLayout->addWidget(formLayoutWidget);
|
||||||
|
|
||||||
auto galleryScrollArea = new QScrollArea();
|
model = new FeaturedArtModel(definitionDirectory, assetDirectory);
|
||||||
formLayout->addWidget(galleryScrollArea);
|
|
||||||
|
auto galleryListView = new QListView();
|
||||||
|
galleryListView->setModel(model);
|
||||||
|
formLayout->addWidget(galleryListView);
|
||||||
|
|
||||||
m_newBannerEdit = new QLineEdit();
|
m_newBannerEdit = new QLineEdit();
|
||||||
formLayout->addRow(i18nc("@label:textbox", "New Banner"), m_newBannerEdit);
|
formLayout->addRow(i18nc("@label:textbox", "New Banner"), m_newBannerEdit);
|
||||||
|
@ -47,10 +50,11 @@ ArtConfigWindow::ArtConfigWindow(const QString &filename, QWidget *parent)
|
||||||
bottomButtonLayout->addWidget(cancelButton);
|
bottomButtonLayout->addWidget(cancelButton);
|
||||||
bottomButtonLayout->addStretch(1);
|
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] {
|
connect(saveButton, &QPushButton::clicked, this, [this, filename] {
|
||||||
saveData(filename);
|
saveData(filename);
|
||||||
});
|
});
|
||||||
|
saveButton->setEnabled(false);
|
||||||
bottomButtonLayout->addWidget(saveButton);
|
bottomButtonLayout->addWidget(saveButton);
|
||||||
|
|
||||||
if (QFile::exists(filename)) {
|
if (QFile::exists(filename)) {
|
||||||
|
@ -69,6 +73,16 @@ void ArtConfigWindow::loadData(const QString &filename)
|
||||||
|
|
||||||
m_newBannerEdit->setText(artJson[QStringLiteral("new-banner")].toString());
|
m_newBannerEdit->setText(artJson[QStringLiteral("new-banner")].toString());
|
||||||
m_commissionsOpen->setChecked(artJson[QStringLiteral("commissions")].toBool());
|
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)
|
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("new-banner")] = m_newBannerEdit->text();
|
||||||
object[QStringLiteral("commissions")] = m_commissionsOpen->isChecked();
|
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);
|
const QJsonDocument jsonDoc(object);
|
||||||
|
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include "featuredartmodel.h"
|
||||||
|
|
||||||
class ArtConfigWindow : public QDialog
|
class ArtConfigWindow : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ArtConfigWindow(const QString &filename, QWidget *parent = nullptr);
|
explicit ArtConfigWindow(const QString &filename, const QString &definitionDirectory, const QString &assetDirectory, QWidget *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadData(const QString &filename);
|
void loadData(const QString &filename);
|
||||||
|
@ -25,4 +27,8 @@ private:
|
||||||
|
|
||||||
QLineEdit *m_newBannerEdit = nullptr;
|
QLineEdit *m_newBannerEdit = nullptr;
|
||||||
QCheckBox *m_commissionsOpen = nullptr;
|
QCheckBox *m_commissionsOpen = nullptr;
|
||||||
|
|
||||||
|
FeaturedArtModel *model = nullptr;
|
||||||
|
|
||||||
|
QPushButton *saveButton = nullptr;
|
||||||
};
|
};
|
|
@ -43,7 +43,7 @@ ArtModel::ArtModel(const QDir &definitionDirectory, const QDir &assetDirectory,
|
||||||
endInsertRows();
|
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);
|
ArtPiece p(info.definition, info.asset);
|
||||||
|
|
||||||
p.image.load(p.filename);
|
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 dataChanged(index(0, 0), index(m_artPieces.size(), 0));
|
||||||
|
|
||||||
|
Q_EMIT loadingFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArtPiece::ArtPiece(const QString &filename, const QString &assetFilename)
|
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 data(const QModelIndex &index, int role) const override;
|
||||||
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, 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:
|
private:
|
||||||
void pieceFinished(int index);
|
void pieceFinished(int index);
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
QFutureWatcher<ArtPiece> *piecesFuture;
|
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 manageMenu = menuBar->addMenu(i18nc("@title:menu Manage site", "Manage"));
|
||||||
|
|
||||||
auto editConfigAction = manageMenu->addAction(i18nc("@action:inmenu", "Edit Config..."));
|
auto editConfigAction = manageMenu->addAction(i18nc("@action:inmenu", "Edit Config..."));
|
||||||
connect(editConfigAction, &QAction::triggered, this, [this, dataDirectory] {
|
connect(editConfigAction, &QAction::triggered, this, [this, dataDirectory, definitionDirectory, assetDirectory] {
|
||||||
auto window = new ArtConfigWindow(dataDirectory.absoluteFilePath("art-config.json"), this);
|
auto window =
|
||||||
|
new ArtConfigWindow(dataDirectory.absoluteFilePath("art-config.json"), definitionDirectory.absolutePath(), assetDirectory.absolutePath(), this);
|
||||||
window->show();
|
window->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue