From 6c06d1e9d1b6d083213d757f98b0b9d8a1ea0a5d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 10 Jan 2024 12:29:10 -0500 Subject: [PATCH] Remove types from attributes table --- include/ui/customattributestable.h | 4 +- src/mainwindow.cpp | 6 +- src/ui/customattributesdialog.cpp | 2 +- src/ui/customattributestable.cpp | 169 ++++++++++++++++------------- src/ui/eventframes.cpp | 1 + 5 files changed, 102 insertions(+), 80 deletions(-) diff --git a/include/ui/customattributestable.h b/include/ui/customattributestable.h index 8c702470..42836765 100644 --- a/include/ui/customattributestable.h +++ b/include/ui/customattributestable.h @@ -16,7 +16,7 @@ public: QMap getAttributes() const; void setAttributes(const QMap attributes); - void addAttribute(QString key, QJsonValue value); + void addNewAttribute(QString key, QJsonValue value); bool deleteSelectedAttributes(); void setDefaultAttribute(QString key, QJsonValue value); @@ -29,7 +29,7 @@ signals: private: QTableWidget *table; - void addAttribute(QString key, QJsonValue value, bool init); + int addAttribute(QString key, QJsonValue value); void resizeVertically(); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index adc6ad76..a2be7950 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -256,7 +256,11 @@ 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->editor, &Editor::updateCustomMapHeaderValues); + connect(ui->customAttributesTable, &CustomAttributesTable::edited, [this]() { + logInfo("TODO"); + this->markMapEdited(); + this->editor->updateCustomMapHeaderValues(); + }); this->loadUserSettings(); diff --git a/src/ui/customattributesdialog.cpp b/src/ui/customattributesdialog.cpp index b20ebba2..8c3dce3f 100644 --- a/src/ui/customattributesdialog.cpp +++ b/src/ui/customattributesdialog.cpp @@ -89,7 +89,7 @@ void CustomAttributesDialog::addNewAttribute() { } const QString key = ui->lineEdit_Name->text(); - this->table->addAttribute(key, value); + this->table->addNewAttribute(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 547e908c..611e3135 100644 --- a/src/ui/customattributestable.cpp +++ b/src/ui/customattributestable.cpp @@ -7,10 +7,19 @@ #include #include #include -#include +#include + +enum Column { + Key, + Value, + Count +}; // 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: Take control of Delete key? +// TODO: Edit history? CustomAttributesTable::CustomAttributesTable(QWidget *parent) : QFrame(parent) { @@ -31,8 +40,8 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) : layout->addWidget(buttonsFrame); this->table = new QTableWidget(this); - this->table->setColumnCount(3); - this->table->setHorizontalHeaderLabels(QStringList({"Type", "Key", "Value"})); + this->table->setColumnCount(Column::Count); + this->table->setHorizontalHeaderLabels(QStringList({"Key", "Value"})); this->table->horizontalHeader()->setStretchLastSection(true); this->table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); this->table->horizontalHeader()->setVisible(false); @@ -40,14 +49,15 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) : layout->addWidget(this->table); layout->addStretch(1); + // Connect the "Add" button connect(addButton, &QPushButton::clicked, [this]() { - bool ok; CustomAttributesDialog dialog(this); if (dialog.exec() == QDialog::Accepted) { emit this->edited(); } }); + // Connect the "Delete" button connect(deleteButton, &QPushButton::clicked, [this]() { if (this->deleteSelectedAttributes()) { emit this->edited(); @@ -57,6 +67,14 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) : connect(this->table, &QTableWidget::cellChanged, [this]() { emit this->edited(); }); + + // Key cells are uneditable, but users should be allowed to select one and press delete to remove the row. + // Adding the "Selectable" flag to the Key cell changes its appearance to match the Value cell, which + // makes it confusing that you can't edit the Key cell. To keep the uneditable appearance and allow + // deleting rows by selecting Key cells, we select the full row when a Key cell is selected. + connect(this->table, &QTableWidget::cellClicked, [this](int row, int column) { + if (column == Column::Key) this->table->selectRow(row); + }); } CustomAttributesTable::~CustomAttributesTable() @@ -87,96 +105,95 @@ QMap CustomAttributesTable::getAttributes() const { QMap fields; for (int row = 0; row < this->table->rowCount(); row++) { QString key = ""; - QTableWidgetItem *typeItem = this->table->item(row, 0); - QTableWidgetItem *keyItem = this->table->item(row, 1); - QTableWidgetItem *valueItem = this->table->item(row, 2); - + QTableWidgetItem *keyItem = this->table->item(row, Column::Key); if (keyItem) key = keyItem->text(); - if (key.isEmpty() || !typeItem || !valueItem) + if (key.isEmpty()) continue; // Read from the table data which JSON type to save the value as - QJsonValue::Type type = static_cast(typeItem->data(Qt::UserRole).toInt()); + QJsonValue::Type type = static_cast(keyItem->data(Qt::UserRole).toInt()); + QJsonValue value; - switch (type) - { - case QJsonValue::String: - value = QJsonValue(valueItem->text()); + switch (type) { + case QJsonValue::String: { + value = QJsonValue(this->table->item(row, Column::Value)->text()); break; - case QJsonValue::Double: - value = QJsonValue(valueItem->text().toInt()); + } case QJsonValue::Double: { + auto spinBox = static_cast(this->table->cellWidget(row, Column::Value)); + value = QJsonValue(spinBox->value()); break; - case QJsonValue::Bool: - value = QJsonValue(valueItem->checkState() == Qt::Checked); + } case QJsonValue::Bool: { + value = QJsonValue(this->table->item(row, Column::Value)->checkState() == Qt::Checked); break; - default: + } default: { // All other types will just be preserved - value = valueItem->data(Qt::UserRole).toJsonValue(); + value = this->table->item(row, Column::Value)->data(Qt::UserRole).toJsonValue(); break; - } + }} fields[key] = value; } return fields; } -void CustomAttributesTable::setAttributes(const QMap attributes) { - this->table->setRowCount(0); - for (auto it = attributes.cbegin(); it != attributes.cend(); it++) - this->addAttribute(it.key(), it.value(), true); +int CustomAttributesTable::addAttribute(QString key, QJsonValue value) { + const QSignalBlocker blocker(this->table); + QJsonValue::Type type = value.type(); + + // Add new row + int rowIndex = this->table->rowCount(); + this->table->insertRow(rowIndex); + + // Add key name to table + auto keyItem = new QTableWidgetItem(key); + keyItem->setFlags(Qt::ItemIsEnabled); + keyItem->setData(Qt::UserRole, type); // Record the type for writing to the file + keyItem->setTextAlignment(Qt::AlignCenter); + this->table->setItem(rowIndex, Column::Key, keyItem); + + // Add value to table + switch (type) { + case QJsonValue::String: { + // Add a regular cell item for editing text + this->table->setItem(rowIndex, Column::Value, new QTableWidgetItem(ParseUtil::jsonToQString(value))); + break; + } case QJsonValue::Double: { + // Add a spin box for editing number values + auto spinBox = new QSpinBox(this->table); + spinBox->setValue(ParseUtil::jsonToInt(value)); + connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this]() { emit this->edited(); }); + this->table->setCellWidget(rowIndex, Column::Value, spinBox); + break; + } case QJsonValue::Bool: { + // Add a checkable cell item for editing bools + auto valueItem = new QTableWidgetItem(""); + valueItem->setCheckState(value.toBool() ? Qt::Checked : Qt::Unchecked); + valueItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + this->table->setItem(rowIndex, Column::Value, valueItem); + break; + } default: { + // Arrays, objects, or null/undefined values cannot be edited + auto valueItem = new QTableWidgetItem("This value cannot be edited from this table"); + valueItem->setFlags(Qt::NoItemFlags); + valueItem->setData(Qt::UserRole, value); // Preserve the value for writing to the file + this->table->setItem(rowIndex, Column::Value, valueItem); + break; + }} + + 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)); 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; - QJsonValue::Type type = value.type(); - switch (type) - { - case QJsonValue::String: - case QJsonValue::Double: - valueItem = new QTableWidgetItem(ParseUtil::jsonToQString(value)); - break; - case QJsonValue::Bool: - valueItem = new QTableWidgetItem(""); - valueItem->setCheckState(value.toBool() ? Qt::Checked : Qt::Unchecked); - valueItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - break; - default: - valueItem = new QTableWidgetItem("This value cannot be edited from this table"); - valueItem->setFlags(Qt::ItemIsSelectable); - valueItem->setData(Qt::UserRole, value); // Preserve the value for writing to the file - break; - } - - static const QHash typeToName = { - {QJsonValue::Bool, "Bool"}, - {QJsonValue::Double, "Number"}, - {QJsonValue::String, "String"}, - {QJsonValue::Array, "Array"}, - {QJsonValue::Object, "Object"}, - {QJsonValue::Null, "Null"}, - {QJsonValue::Undefined, "Null"}, - }; - QTableWidgetItem * typeItem = new QTableWidgetItem(typeToName[type]); - typeItem->setFlags(Qt::ItemIsEnabled); - typeItem->setData(Qt::UserRole, type); // Record the type for writing to the file - typeItem->setTextAlignment(Qt::AlignCenter); - - int rowIndex = this->table->rowCount(); - this->table->insertRow(rowIndex); - this->table->setItem(rowIndex, 0, typeItem); - this->table->setItem(rowIndex, 1, new QTableWidgetItem(key)); - this->table->setItem(rowIndex, 2, valueItem); - - if (!init) { - valueItem->setText(""); // Erase the "0" in new numbers - this->table->selectRow(rowIndex); - this->resizeVertically(); - } +// For programmatically populating the table +void CustomAttributesTable::setAttributes(const QMap attributes) { + this->table->setRowCount(0); // Clear old values + for (auto it = attributes.cbegin(); it != attributes.cend(); it++) + this->addAttribute(it.key(), it.value()); + this->resizeVertically(); } void CustomAttributesTable::setDefaultAttribute(QString key, QJsonValue value) { diff --git a/src/ui/eventframes.cpp b/src/ui/eventframes.cpp index 0b82d202..bbf2eb63 100644 --- a/src/ui/eventframes.cpp +++ b/src/ui/eventframes.cpp @@ -138,6 +138,7 @@ void EventFrame::connectSignals(MainWindow *) { this->custom_attributes->disconnect(); connect(this->custom_attributes, &CustomAttributesTable::edited, [this]() { this->event->setCustomValues(this->custom_attributes->getAttributes()); + this->event->modify(); }); }