// SPDX-FileCopyrightText: 2023 Joshua Goins // // SPDX-License-Identifier: GPL-3.0-or-later #include "artdetailwindow.h" #include "imagelabel.h" #include #include #include #include #include #include #include #include #include #include #include #include ArtDetailWindow::ArtDetailWindow(const QString &filename, const QDir &assetDirectory, QWidget *parent) : QDialog(parent) { setMinimumWidth(800); setMinimumHeight(600); setWindowModality(Qt::WindowModality::WindowModal); setWindowTitle(filename); QFileInfo info(filename); const QString withoutExtension = info.completeBaseName(); auto mainLayout = new QHBoxLayout(); setLayout(mainLayout); auto formLayout = new QFormLayout(); auto formLayoutWidget = new QWidget(); formLayoutWidget->setMaximumWidth(450); formLayoutWidget->setLayout(formLayout); mainLayout->addWidget(formLayoutWidget); QImage image; image.load(assetDirectory.absoluteFilePath(QStringLiteral("%1.webp").arg(withoutExtension))); auto previewBox = new QGroupBox(i18nc("@title:group", "Preview")); mainLayout->addWidget(previewBox); auto previewLayout = new QVBoxLayout(); previewBox->setLayout(previewLayout); auto imageView = new ImageLabel(); imageView->setPixmap(QPixmap::fromImage(image)); previewLayout->addWidget(imageView); m_titleEdit = new QLineEdit(); formLayout->addRow(i18nc("@label:textbox", "Title"), m_titleEdit); m_knowExactDateBox = new QCheckBox(); connect(m_knowExactDateBox, &QCheckBox::toggled, this, [this](bool checked) { if (checked) { m_dateEdit->setDisplayFormat(QStringLiteral("yyyy-MM-dd")); } else { m_dateEdit->setDisplayFormat(QStringLiteral("yyyy")); } }); formLayout->addRow(i18nc("@option:check", "Know Exact Date?"), m_knowExactDateBox); m_dateEdit = new QDateEdit(); m_dateEdit->setCalendarPopup(true); formLayout->addRow(i18nc("@label:chooser", "Date"), m_dateEdit); m_altTextEdit = new QTextEdit(); m_altTextEdit->setAcceptRichText(false); formLayout->addRow(i18nc("@label:textbox", "Alt Text"), m_altTextEdit); m_descriptionEdit = new QTextEdit(); m_descriptionEdit->setAcceptRichText(false); formLayout->addRow(i18nc("@label:textbox", "Description"), m_descriptionEdit); m_nsfwBox = new QCheckBox(); formLayout->addRow(i18nc("@option:check", "Is NSFW?"), m_nsfwBox); m_mastodonUrlEdit = new QLineEdit(); formLayout->addRow(i18nc("@label:textbox", "Mastodon URL"), m_mastodonUrlEdit); m_pixivUrlEdit = new QLineEdit(); formLayout->addRow(i18nc("@label:textbox", "Pixiv URL"), m_pixivUrlEdit); m_newgroundsUrlEdit = new QLineEdit(); formLayout->addRow(i18nc("@label:textbox", "Newgrounds URL"), m_newgroundsUrlEdit); m_programEdit = new QLineEdit(); formLayout->addRow(i18nc("@label:textbox", "Program"), m_programEdit); auto charactersLayout = new QVBoxLayout(); formLayout->addRow(i18nc("@title:group", "Characters"), charactersLayout); auto characterList = new QListView(); m_characterListModel = new QStringListModel(); characterList->setModel(m_characterListModel); charactersLayout->addWidget(characterList); auto characterButtonLayout = new QHBoxLayout(); charactersLayout->addLayout(characterButtonLayout); auto addCharacterButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-add")), i18nc("@action:button", "Add")); connect(addCharacterButton, &QPushButton::clicked, this, [this] { m_characterListModel->setStringList(m_characterListModel->stringList() << QStringLiteral("New Character")); }); characterButtonLayout->addWidget(addCharacterButton); characterButtonLayout->addStretch(1); auto removeCharacterButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-remove")), i18nc("@action:button", "Remove")); connect(removeCharacterButton, &QPushButton::clicked, this, [this, characterList] { if (characterList->selectionModel()->hasSelection()) { const QString toRemove = characterList->selectionModel()->selectedRows()[0].data().toString(); auto tmp = m_characterListModel->stringList(); tmp.removeOne(toRemove); m_characterListModel->setStringList(tmp); } }); characterButtonLayout->addWidget(removeCharacterButton); auto tagLayout = new QVBoxLayout(); formLayout->addRow(i18nc("@title:group", "Tags"), tagLayout); auto tagsList = new QListView(); m_tagsListModel = new QStringListModel(); tagsList->setModel(m_tagsListModel); tagLayout->addWidget(tagsList); auto tagButtonLayout = new QHBoxLayout(); tagLayout->addLayout(tagButtonLayout); auto addTagButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-add")), i18nc("@action:button", "Add")); connect(addTagButton, &QPushButton::clicked, this, [this] { m_tagsListModel->setStringList(m_tagsListModel->stringList() << QStringLiteral("New Tag")); }); tagButtonLayout->addWidget(addTagButton); tagButtonLayout->addStretch(1); auto removeTagButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-remove")), i18nc("@action:button", "Remove")); connect(removeTagButton, &QPushButton::clicked, this, [this, tagsList] { if (tagsList->selectionModel()->hasSelection()) { const QString toRemove = tagsList->selectionModel()->selectedRows()[0].data().toString(); auto tmp = m_tagsListModel->stringList(); tmp.removeOne(toRemove); m_tagsListModel->setStringList(tmp); } }); tagButtonLayout->addWidget(removeTagButton); auto bottomButtonLayout = new QHBoxLayout(); formLayout->addRow(bottomButtonLayout); auto cancelButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-close")), i18nc("@action:button", "Cancel")); connect(cancelButton, &QPushButton::clicked, this, &ArtDetailWindow::close); bottomButtonLayout->addWidget(cancelButton); bottomButtonLayout->addStretch(1); auto saveButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-ok")), i18nc("@action:button", "Save")); connect(saveButton, &QPushButton::clicked, this, [this, filename] { saveData(filename); }); bottomButtonLayout->addWidget(saveButton); if (QFile::exists(filename)) { loadData(filename); } } void ArtDetailWindow::loadData(const QString &filename) { qDebug() << "Loading data from" << filename; QFile artFile(filename); artFile.open(QFile::ReadOnly); const QJsonDocument artJson = QJsonDocument::fromJson(artFile.readAll()); if (artJson.object().contains(QStringLiteral("title"))) { m_titleEdit->setText(artJson[QStringLiteral("title")].toString()); } if (artJson.object().contains(QStringLiteral("alt_text"))) { m_altTextEdit->setText(artJson[QStringLiteral("alt_text")].toString()); } if (artJson.object().contains(QStringLiteral("description"))) { m_descriptionEdit->setText(artJson[QStringLiteral("description")].toString()); } m_knowExactDateBox->setChecked(artJson[QStringLiteral("date")].toString().contains(QStringLiteral("-"))); if (m_knowExactDateBox->isChecked()) { m_dateEdit->setDate(QDate::fromString(artJson[QStringLiteral("date")].toString(), QStringLiteral("yyyy-MM-dd"))); m_dateEdit->setDisplayFormat(QStringLiteral("yyyy-MM-dd")); } else { m_dateEdit->setDate(QDate::fromString(artJson[QStringLiteral("date")].toString(), QStringLiteral("yyyy"))); m_dateEdit->setDisplayFormat(QStringLiteral("yyyy")); } if (artJson.object().contains(QStringLiteral("nsfw"))) { m_nsfwBox->setChecked(artJson[QStringLiteral("nsfw")].toBool()); } if (artJson.object().contains(QStringLiteral("mastodon_url"))) { m_mastodonUrlEdit->setText(artJson[QStringLiteral("mastodon_url")].toString()); } if (artJson.object().contains(QStringLiteral("pixiv_url"))) { m_pixivUrlEdit->setText(artJson[QStringLiteral("pixiv_url")].toString()); } if (artJson.object().contains(QStringLiteral("newgrounds_url"))) { m_newgroundsUrlEdit->setText(artJson[QStringLiteral("newgrounds_url")].toString()); } if (artJson.object().contains(QStringLiteral("program"))) { m_programEdit->setText(artJson[QStringLiteral("program")].toString()); } if (artJson.object().contains(QStringLiteral("characters"))) { QStringList list; for (const auto &character : artJson[QStringLiteral("characters")].toArray()) { list.append(character.toString()); } m_characterListModel->setStringList(list); } if (artJson.object().contains(QStringLiteral("tags"))) { QStringList list; for (const auto &tag : artJson[QStringLiteral("tags")].toArray()) { list.append(tag.toString()); } m_tagsListModel->setStringList(list); } } void ArtDetailWindow::saveData(const QString &filename) { qDebug() << "Saving data to" << filename; QJsonObject object; if (!m_titleEdit->text().isEmpty()) { object[QStringLiteral("title")] = m_titleEdit->text(); } if (!m_altTextEdit->document()->isEmpty()) { object[QStringLiteral("alt_text")] = m_altTextEdit->document()->toPlainText(); } if (!m_descriptionEdit->document()->isEmpty()) { object[QStringLiteral("description")] = m_descriptionEdit->document()->toPlainText(); } if (m_knowExactDateBox->isChecked()) { object[QStringLiteral("date")] = m_dateEdit->date().toString(QStringLiteral("yyyy-MM-dd")); } else { object[QStringLiteral("date")] = m_dateEdit->date().toString(QStringLiteral("yyyy")); } if (m_nsfwBox->isChecked()) { object[QStringLiteral("nsfw")] = m_nsfwBox->isChecked(); } if (!m_mastodonUrlEdit->text().isEmpty()) { object[QStringLiteral("mastodon_url")] = m_mastodonUrlEdit->text(); } if (!m_pixivUrlEdit->text().isEmpty()) { object[QStringLiteral("pixiv_url")] = m_pixivUrlEdit->text(); } if (!m_newgroundsUrlEdit->text().isEmpty()) { object[QStringLiteral("newgrounds_url")] = m_newgroundsUrlEdit->text(); } if (!m_programEdit->text().isEmpty()) { object[QStringLiteral("program")] = m_programEdit->text(); } auto tags = m_tagsListModel->stringList(); if (!tags.isEmpty()) { object[QStringLiteral("tags")] = QJsonArray::fromStringList(tags); } auto characters = m_characterListModel->stringList(); if (!characters.isEmpty()) { object[QStringLiteral("characters")] = QJsonArray::fromStringList(characters); } const QJsonDocument jsonDoc(object); QFile file(filename); file.open(QFile::WriteOnly); file.write(jsonDoc.toJson()); file.close(); close(); }