From 2bf221c7299e0c275b443174e22d2f9676ac75e7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 9 Jan 2024 17:03:07 -0500 Subject: [PATCH] Add custom attributes dialog --- forms/customattributesdialog.ui | 173 ++++++++++++++++++++++++++++ include/ui/customattributesdialog.h | 31 +++++ include/ui/customattributestable.h | 7 +- porymap.pro | 5 +- src/ui/customattributesdialog.cpp | 96 +++++++++++++++ src/ui/customattributestable.cpp | 36 +++--- 6 files changed, 326 insertions(+), 22 deletions(-) create mode 100644 forms/customattributesdialog.ui create mode 100644 include/ui/customattributesdialog.h create mode 100644 src/ui/customattributesdialog.cpp diff --git a/forms/customattributesdialog.ui b/forms/customattributesdialog.ui new file mode 100644 index 00000000..b61d7150 --- /dev/null +++ b/forms/customattributesdialog.ui @@ -0,0 +1,173 @@ + + + CustomAttributesDialog + + + + 0 + 0 + 410 + 192 + + + + Add New Custom Attribute + + + + + + + 0 + + + 0 + + + + + Name + + + + + + + The key name for the new JSON field + + + true + + + + + + + Type + + + + + + + The data type for the new JSON field + + + + + + + Value + + + + + + + + 0 + 0 + + + + The value for the new JSON field + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + Add to Defaults + + + + + + + If checked, this JSON field will be added to any new maps/events of this type, with the current value as its default + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ + +
diff --git a/include/ui/customattributesdialog.h b/include/ui/customattributesdialog.h new file mode 100644 index 00000000..749a6691 --- /dev/null +++ b/include/ui/customattributesdialog.h @@ -0,0 +1,31 @@ +#ifndef CUSTOMATTRIBUTESDIALOG_H +#define CUSTOMATTRIBUTESDIALOG_H + +#include +#include + +#include "customattributestable.h" + +namespace Ui { +class CustomAttributesDialog; +} + +class CustomAttributesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CustomAttributesDialog(CustomAttributesTable *parent); + ~CustomAttributesDialog(); + +private: + Ui::CustomAttributesDialog *ui; + CustomAttributesTable *const table; + + void addNewAttribute(); + bool verifyName(); + void setNameEditHighlight(bool highlight); +}; + + +#endif // CUSTOMATTRIBUTESDIALOG_H diff --git a/include/ui/customattributestable.h b/include/ui/customattributestable.h index 421ac3bb..8c702470 100644 --- a/include/ui/customattributestable.h +++ b/include/ui/customattributestable.h @@ -16,14 +16,19 @@ public: QMap getAttributes() const; void setAttributes(const QMap attributes); + void addAttribute(QString key, QJsonValue value); bool deleteSelectedAttributes(); + void setDefaultAttribute(QString key, QJsonValue value); + void unsetDefaultAttribute(QString key); + + const QStringList restrictedKeyNames; // TODO: Populate + signals: void edited(); private: QTableWidget *table; - QJsonValue pickType(bool * ok = nullptr); void addAttribute(QString key, QJsonValue value, bool init); void resizeVertically(); }; diff --git a/porymap.pro b/porymap.pro index ddb3f621..3ed1480f 100644 --- a/porymap.pro +++ b/porymap.pro @@ -43,6 +43,7 @@ SOURCES += src/core/block.cpp \ src/scriptapi/apiutility.cpp \ src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ + src/ui/customattributesdialog.cpp \ src/ui/customscriptseditor.cpp \ src/ui/customscriptslistitem.cpp \ src/ui/draggablepixmapitem.cpp \ @@ -134,6 +135,7 @@ HEADERS += include/core/block.h \ include/lib/orderedmap.h \ include/lib/orderedjson.h \ include/ui/aboutporymap.h \ + include/ui/customattributesdialog.h \ include/ui/customscriptseditor.h \ include/ui/customscriptslistitem.h \ include/ui/draggablepixmapitem.h \ @@ -214,7 +216,8 @@ FORMS += forms/mainwindow.ui \ forms/colorpicker.ui \ forms/projectsettingseditor.ui \ forms/customscriptseditor.ui \ - forms/customscriptslistitem.ui + forms/customscriptslistitem.ui \ + forms/customattributesdialog.ui RESOURCES += \ resources/images.qrc \ diff --git a/src/ui/customattributesdialog.cpp b/src/ui/customattributesdialog.cpp new file mode 100644 index 00000000..b20ebba2 --- /dev/null +++ b/src/ui/customattributesdialog.cpp @@ -0,0 +1,96 @@ +#include "customattributesdialog.h" +#include "ui_customattributesdialog.h" + +#include + +// Preserve type selection for later dialogs +static int typeIndex = 0; + +CustomAttributesDialog::CustomAttributesDialog(CustomAttributesTable *parent) : + QDialog(parent), + ui(new Ui::CustomAttributesDialog), + table(parent) +{ + ui->setupUi(this); + + // Type combo box + static const QStringList types = {"String", "Number", "Boolean"}; + ui->comboBox_Type->addItems(types); + ui->comboBox_Type->setEditable(false); + connect(ui->comboBox_Type, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { + // When the value type is changed, update the value input widget + if (index >= 0 && index < types.length()){ + ui->stackedWidget_Value->setCurrentIndex(index); + typeIndex = index; + } + }); + ui->comboBox_Type->setCurrentIndex(typeIndex); + + // Clear the red highlight that may be set if user tries to finish with an invalid key name + connect(ui->lineEdit_Name, &QLineEdit::textChanged, [this](QString) { + this->setNameEditHighlight(false); + }); + + // Button box + connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton *button) { + auto buttonRole = ui->buttonBox->buttonRole(button); + if (buttonRole == QDialogButtonBox::AcceptRole && this->verifyName()) { + this->addNewAttribute(); + this->done(QDialog::Accepted); + } else if (buttonRole == QDialogButtonBox::RejectRole) { + this->done(QDialog::Rejected); + } + }); +} + +CustomAttributesDialog::~CustomAttributesDialog() { + delete ui; +} + +void CustomAttributesDialog::setNameEditHighlight(bool highlight) { + ui->lineEdit_Name->setStyleSheet(highlight ? "QLineEdit { background-color: rgba(255, 0, 0, 25%) }" : ""); +} + +bool CustomAttributesDialog::verifyName() { + const QString name = ui->lineEdit_Name->text(); + + if (name.isEmpty()) { + this->setNameEditHighlight(true); + return false; + } + + // Invalidate name if it would collide with an expected JSON field name + if (this->table->restrictedKeyNames.contains(name)) { + const QString msg = QString("The name '%1' is reserved, please choose a different name.").arg(name); + QMessageBox::critical(this, "Error", msg); + this->setNameEditHighlight(true); + return false; + } + + // Warn user if key name would overwrite an existing custom attribute + if (this->table->getAttributes().keys().contains(name)) { + const QString msg = QString("Overwrite value for existing attribute '%1'?").arg(name); + if (QMessageBox::warning(this, "Warning", msg, QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) + return false; + } + + return true; +} + +void CustomAttributesDialog::addNewAttribute() { + QJsonValue value; + const QString type = ui->comboBox_Type->currentText(); + if (type == "String") { + value = QJsonValue(ui->lineEdit_Value->text()); + } else if (type == "Number") { + value = QJsonValue(ui->spinBox_Value->value()); + } else if (type == "Boolean") { + value = QJsonValue(ui->checkBox_Value->isChecked()); + } + + const QString key = ui->lineEdit_Name->text(); + this->table->addAttribute(key, value); + + if (ui->checkBox_Default->isChecked()) + this->table->setDefaultAttribute(key, value); +} diff --git a/src/ui/customattributestable.cpp b/src/ui/customattributestable.cpp index a804c85b..547e908c 100644 --- a/src/ui/customattributestable.cpp +++ b/src/ui/customattributestable.cpp @@ -1,4 +1,5 @@ #include "customattributestable.h" +#include "customattributesdialog.h" #include "parseutil.h" #include #include @@ -41,9 +42,8 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) : connect(addButton, &QPushButton::clicked, [this]() { bool ok; - QJsonValue value = this->pickType(&ok); - if (ok) { - this->addAttribute("", value, false); + CustomAttributesDialog dialog(this); + if (dialog.exec() == QDialog::Accepted) { emit this->edited(); } }); @@ -63,6 +63,7 @@ CustomAttributesTable::~CustomAttributesTable() { } +// TODO: Fix Header table size on first open void CustomAttributesTable::resizeVertically() { int height = 0; for (int i = 0; i < this->table->rowCount(); i++) { @@ -118,23 +119,6 @@ QMap CustomAttributesTable::getAttributes() const { return fields; } -QJsonValue CustomAttributesTable::pickType(bool * ok) { - static const QMap valueTypes = { - {"String", QJsonValue(QString(""))}, - {"Number", QJsonValue(0)}, - {"Boolean", QJsonValue(false)}, - }; - static const QStringList typeNames = valueTypes.keys(); - static int defaultIndex = typeNames.indexOf("String"); - QString selection = QInputDialog::getItem(this, "", "Choose Value Type", typeNames, defaultIndex, false, ok); - - // Preserve selection for next time - int index = typeNames.indexOf(selection); - if (index >= 0) defaultIndex = index; - - return valueTypes.value(selection); -} - void CustomAttributesTable::setAttributes(const QMap attributes) { this->table->setRowCount(0); for (auto it = attributes.cbegin(); it != attributes.cend(); it++) @@ -142,6 +126,10 @@ void CustomAttributesTable::setAttributes(const QMap attrib this->resizeVertically(); } +void CustomAttributesTable::addAttribute(QString key, QJsonValue value) { + this->addAttribute(key, value, false); +} + void CustomAttributesTable::addAttribute(QString key, QJsonValue value, bool init) { const QSignalBlocker blocker(this->table); QTableWidgetItem * valueItem; @@ -191,6 +179,14 @@ void CustomAttributesTable::addAttribute(QString key, QJsonValue value, bool ini } } +void CustomAttributesTable::setDefaultAttribute(QString key, QJsonValue value) { + // TODO +} + +void CustomAttributesTable::unsetDefaultAttribute(QString key) { + // TODO +} + bool CustomAttributesTable::deleteSelectedAttributes() { int rowCount = this->table->rowCount(); if (rowCount <= 0)