From 6438d332f7972b1aa76dad9f2b37e84c39a21329 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 10 Jan 2024 13:10:28 -0500 Subject: [PATCH] Handle custom key collisions --- forms/mainwindow.ui | 2 +- include/project.h | 2 +- include/ui/customattributestable.h | 19 +++++++---- src/editor.cpp | 2 +- src/mainwindow.cpp | 13 ++++---- src/ui/customattributesdialog.cpp | 4 +-- src/ui/customattributestable.cpp | 53 +++++++++++++++++++++++++----- src/ui/eventframes.cpp | 1 + 8 files changed, 70 insertions(+), 26 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index b7aa89b7..fff61cd4 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2383,7 +2383,7 @@ - + 0 diff --git a/include/project.h b/include/project.h index c7effcfb..ea8b03fb 100644 --- a/include/project.h +++ b/include/project.h @@ -132,7 +132,7 @@ public: bool readSpeciesIconPaths(); QMap speciesToIconPath; - QSet getTopLevelMapFields(); + static QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); bool loadLayout(MapLayout *); diff --git a/include/ui/customattributestable.h b/include/ui/customattributestable.h index 42836765..425b5f1f 100644 --- a/include/ui/customattributestable.h +++ b/include/ui/customattributestable.h @@ -16,20 +16,27 @@ public: QMap getAttributes() const; void setAttributes(const QMap attributes); - void addNewAttribute(QString key, QJsonValue value); - bool deleteSelectedAttributes(); + void addNewAttribute(const QString &key, QJsonValue value); - void setDefaultAttribute(QString key, QJsonValue value); - void unsetDefaultAttribute(QString key); + void setDefaultAttribute(const QString &key, QJsonValue value); + void unsetDefaultAttribute(const QString &key); - const QStringList restrictedKeyNames; // TODO: Populate + QSet keys() const; + QSet restrictedKeys() const; + void setRestrictedKeys(const QSet keys); signals: void edited(); private: QTableWidget *table; - int addAttribute(QString key, QJsonValue value); + + QSet m_keys; + QSet m_restrictedKeys; + + int addAttribute(const QString &key, QJsonValue value); + void removeAttribute(const QString &key); + bool deleteSelectedAttributes(); void resizeVertically(); }; diff --git a/src/editor.cpp b/src/editor.cpp index 7288474f..d9eea176 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1953,7 +1953,7 @@ void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback) void Editor::updateCustomMapHeaderValues() { - map->customHeaders = ui->customAttributesTable->getAttributes(); + map->customHeaders = ui->mapCustomAttributesTable->getAttributes(); emit editedMapData(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a2be7950..a7c6ed6e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -256,11 +256,6 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts); connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor); - connect(ui->customAttributesTable, &CustomAttributesTable::edited, [this]() { - logInfo("TODO"); - this->markMapEdited(); - this->editor->updateCustomMapHeaderValues(); - }); this->loadUserSettings(); @@ -306,6 +301,11 @@ void MainWindow::initEditor() { connect(this->ui->spinner_HealID, QOverload::of(&QSpinBox::valueChanged), [this](int value) { this->editor->selectedEventIndexChanged(value, Event::Group::Heal); }); + + connect(ui->mapCustomAttributesTable, &CustomAttributesTable::edited, [this]() { + this->markMapEdited(); + this->editor->updateCustomMapHeaderValues(); + }); } void MainWindow::initMiscHeapObjects() { @@ -519,6 +519,7 @@ bool MainWindow::openProject(QString dir) { this->closeSupplementaryWindows(); this->newMapDefaultsSet = false; + ui->mapCustomAttributesTable->setRestrictedKeys(Project::getTopLevelMapFields()); Scripting::init(this); bool already_open = isProjectOpen() && (editor->project->root == dir); @@ -851,7 +852,7 @@ void MainWindow::displayMapProperties() { ui->checkBox_AllowEscaping->setChecked(map->allowEscaping); ui->spinBox_FloorNumber->setValue(map->floorNumber); - ui->customAttributesTable->setAttributes(map->customHeaders); + ui->mapCustomAttributesTable->setAttributes(map->customHeaders); } void MainWindow::on_comboBox_Song_currentTextChanged(const QString &song) diff --git a/src/ui/customattributesdialog.cpp b/src/ui/customattributesdialog.cpp index 8c3dce3f..d7845b62 100644 --- a/src/ui/customattributesdialog.cpp +++ b/src/ui/customattributesdialog.cpp @@ -60,7 +60,7 @@ bool CustomAttributesDialog::verifyName() { } // Invalidate name if it would collide with an expected JSON field name - if (this->table->restrictedKeyNames.contains(name)) { + if (this->table->restrictedKeys().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); @@ -68,7 +68,7 @@ bool CustomAttributesDialog::verifyName() { } // Warn user if key name would overwrite an existing custom attribute - if (this->table->getAttributes().keys().contains(name)) { + if (this->table->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; diff --git a/src/ui/customattributestable.cpp b/src/ui/customattributestable.cpp index 611e3135..bc4dea2b 100644 --- a/src/ui/customattributestable.cpp +++ b/src/ui/customattributestable.cpp @@ -17,7 +17,7 @@ enum Column { // TODO: Tooltip-- "Custom fields will be added to the map.json file for the current map."? // TODO: Fix squishing when first element is added -// TODO: 'Overwriting' values adds a new attribute +// TODO: Fix Header table size on first open // TODO: Take control of Delete key? // TODO: Edit history? CustomAttributesTable::CustomAttributesTable(QWidget *parent) : @@ -81,7 +81,6 @@ 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++) { @@ -105,7 +104,7 @@ QMap CustomAttributesTable::getAttributes() const { QMap fields; for (int row = 0; row < this->table->rowCount(); row++) { QString key = ""; - QTableWidgetItem *keyItem = this->table->item(row, Column::Key); + auto keyItem = this->table->item(row, Column::Key); if (keyItem) key = keyItem->text(); if (key.isEmpty()) continue; @@ -135,14 +134,23 @@ QMap CustomAttributesTable::getAttributes() const { return fields; } -int CustomAttributesTable::addAttribute(QString key, QJsonValue value) { +int CustomAttributesTable::addAttribute(const QString &key, QJsonValue value) { const QSignalBlocker blocker(this->table); - QJsonValue::Type type = value.type(); + + // Certain key names cannot be used (if they would overwrite a field used outside this table) + if (this->m_restrictedKeys.contains(key)) + return -1; + + // Overwrite existing key (if present) + if (this->m_keys.remove(key)) + this->removeAttribute(key); // Add new row int rowIndex = this->table->rowCount(); this->table->insertRow(rowIndex); + QJsonValue::Type type = value.type(); + // Add key name to table auto keyItem = new QTableWidgetItem(key); keyItem->setFlags(Qt::ItemIsEnabled); @@ -159,6 +167,8 @@ int CustomAttributesTable::addAttribute(QString key, QJsonValue value) { } case QJsonValue::Double: { // Add a spin box for editing number values auto spinBox = new QSpinBox(this->table); + spinBox->setMinimum(INT_MIN); + spinBox->setMaximum(INT_MAX); spinBox->setValue(ParseUtil::jsonToInt(value)); connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this]() { emit this->edited(); }); this->table->setCellWidget(rowIndex, Column::Value, spinBox); @@ -178,13 +188,16 @@ int CustomAttributesTable::addAttribute(QString key, QJsonValue value) { this->table->setItem(rowIndex, Column::Value, valueItem); break; }} + this->m_keys.insert(key); return rowIndex; } // For the user adding an attribute by interacting with the table -void CustomAttributesTable::addNewAttribute(QString key, QJsonValue value) { - this->table->selectRow(this->addAttribute(key, value)); +void CustomAttributesTable::addNewAttribute(const QString &key, QJsonValue value) { + int row = this->addAttribute(key, value); + if (row < 0) return; + this->table->selectRow(row); this->resizeVertically(); } @@ -196,14 +209,24 @@ void CustomAttributesTable::setAttributes(const QMap attrib this->resizeVertically(); } -void CustomAttributesTable::setDefaultAttribute(QString key, QJsonValue value) { +void CustomAttributesTable::setDefaultAttribute(const QString &key, QJsonValue value) { // TODO } -void CustomAttributesTable::unsetDefaultAttribute(QString key) { +void CustomAttributesTable::unsetDefaultAttribute(const QString &key) { // TODO } +void CustomAttributesTable::removeAttribute(const QString &key) { + for (int row = 0; row < this->table->rowCount(); row++) { + auto keyItem = this->table->item(row, Column::Key); + if (keyItem && keyItem->text() == key) { + this->table->removeRow(row); + break; + } + } +} + bool CustomAttributesTable::deleteSelectedAttributes() { int rowCount = this->table->rowCount(); if (rowCount <= 0) @@ -229,3 +252,15 @@ bool CustomAttributesTable::deleteSelectedAttributes() { this->resizeVertically(); return true; } + +QSet CustomAttributesTable::keys() const { + return this->m_keys; +} + +QSet CustomAttributesTable::restrictedKeys() const { + return this->m_restrictedKeys; +} + +void CustomAttributesTable::setRestrictedKeys(const QSet keys) { + this->m_restrictedKeys = keys; +} diff --git a/src/ui/eventframes.cpp b/src/ui/eventframes.cpp index bbf2eb63..08eb2ec5 100644 --- a/src/ui/eventframes.cpp +++ b/src/ui/eventframes.cpp @@ -103,6 +103,7 @@ void EventFrame::setup() { void EventFrame::initCustomAttributesTable() { this->custom_attributes = new CustomAttributesTable(this); + this->custom_attributes->setRestrictedKeys(this->event->getExpectedFields()); this->custom_attributes->setAttributes(this->event->getCustomValues()); this->layout_contents->addWidget(this->custom_attributes); }