Better type conversion custom event attributes

This commit is contained in:
GriffinR 2022-10-18 19:52:35 -04:00
parent 8e6585bbb2
commit 4c3a508534
7 changed files with 160 additions and 167 deletions

View file

@ -151,8 +151,8 @@ public:
virtual QSet<QString> getExpectedFields() = 0; virtual QSet<QString> getExpectedFields() = 0;
void readCustomValues(QJsonObject values); void readCustomValues(QJsonObject values);
void addCustomValuesTo(OrderedJson::object *obj); void addCustomValuesTo(OrderedJson::object *obj);
QMap<QString, QString> getCustomValues() { return this->customValues; } const QMap<QString, QJsonValue> getCustomValues() { return this->customValues; }
void setCustomValues(QMap<QString, QString> newCustomValues) { this->customValues = newCustomValues; } void setCustomValues(const QMap<QString, QJsonValue> newCustomValues) { this->customValues = newCustomValues; }
virtual void loadPixmap(Project *project) = 0; virtual void loadPixmap(Project *project) = 0;
@ -193,7 +193,7 @@ protected:
int spriteHeight = 16; int spriteHeight = 16;
bool usingSprite = false; bool usingSprite = false;
QMap<QString, QString> customValues; QMap<QString, QJsonValue> customValues;
QPixmap pixmap; QPixmap pixmap;
DraggablePixmapItem *pixmapItem = nullptr; DraggablePixmapItem *pixmapItem = nullptr;

View file

@ -12,11 +12,15 @@ public:
explicit CustomAttributesTable(Event *event, QWidget *parent = nullptr); explicit CustomAttributesTable(Event *event, QWidget *parent = nullptr);
~CustomAttributesTable(); ~CustomAttributesTable();
static const QMap<QString, QJsonValue> getAttributes(QTableWidget * table);
static QJsonValue pickType(QWidget * parent, bool * ok = nullptr);
static void addAttribute(QTableWidget * table, QString key, QJsonValue value, bool isNew = false);
static bool deleteSelectedAttributes(QTableWidget * table);
private: private:
Event *event; Event *event;
QTableWidget *table; QTableWidget *table;
void resizeVertically(); void resizeVertically();
QMap<QString, QString> getTableFields();
}; };
#endif // CUSTOMATTRIBUTESTABLE_H #endif // CUSTOMATTRIBUTESTABLE_H

View file

@ -38,13 +38,12 @@ void Event::setDefaultValues(Project *) {
this->setElevation(3); this->setElevation(3);
} }
// TODO: Don't assume string type
void Event::readCustomValues(QJsonObject values) { void Event::readCustomValues(QJsonObject values) {
this->customValues.clear(); this->customValues.clear();
QSet<QString> expectedFields = this->getExpectedFields(); QSet<QString> expectedFields = this->getExpectedFields();
for (QString key : values.keys()) { for (QString key : values.keys()) {
if (!expectedFields.contains(key)) { if (!expectedFields.contains(key)) {
this->customValues[key] = values[key].toString(); this->customValues[key] = values[key];
} }
} }
} }
@ -52,7 +51,7 @@ void Event::readCustomValues(QJsonObject values) {
void Event::addCustomValuesTo(OrderedJson::object *obj) { void Event::addCustomValuesTo(OrderedJson::object *obj) {
for (QString key : this->customValues.keys()) { for (QString key : this->customValues.keys()) {
if (!obj->contains(key)) { if (!obj->contains(key)) {
(*obj)[key] = this->customValues[key]; (*obj)[key] = OrderedJson::fromQJsonValue(this->customValues[key]);
} }
} }
} }

View file

@ -10,6 +10,7 @@
#include "editcommands.h" #include "editcommands.h"
#include "config.h" #include "config.h"
#include "scripting.h" #include "scripting.h"
#include "customattributestable.h"
#include <QCheckBox> #include <QCheckBox>
#include <QPainter> #include <QPainter>
#include <QMouseEvent> #include <QMouseEvent>
@ -1952,39 +1953,7 @@ void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback)
void Editor::updateCustomMapHeaderValues(QTableWidget *table) void Editor::updateCustomMapHeaderValues(QTableWidget *table)
{ {
QMap<QString, QJsonValue> fields; map->customHeaders = CustomAttributesTable::getAttributes(table);
for (int row = 0; row < table->rowCount(); row++) {
QString key = "";
QTableWidgetItem *typeItem = table->item(row, 0);
QTableWidgetItem *keyItem = table->item(row, 1);
QTableWidgetItem *valueItem = table->item(row, 2);
if (keyItem) key = keyItem->text();
if (key.isEmpty() || !typeItem || !valueItem)
continue;
// Read from the table data which JSON type to save the value as
QJsonValue::Type type = static_cast<QJsonValue::Type>(typeItem->data(Qt::UserRole).toInt());
QJsonValue value;
switch (type)
{
case QJsonValue::String:
value = QJsonValue(valueItem->text());
break;
case QJsonValue::Double:
value = QJsonValue(valueItem->text().toInt());
break;
case QJsonValue::Bool:
value = QJsonValue(valueItem->checkState() == Qt::Checked);
break;
default:
// All other types will just be preserved
value = valueItem->data(Qt::UserRole).toJsonValue();
break;
}
fields[key] = value;
}
map->customHeaders = fields;
emit editedMapData(); emit editedMapData();
} }

View file

@ -816,7 +816,7 @@ void MainWindow::displayMapProperties() {
ui->tableWidget_CustomHeaderFields->blockSignals(true); ui->tableWidget_CustomHeaderFields->blockSignals(true);
ui->tableWidget_CustomHeaderFields->setRowCount(0); ui->tableWidget_CustomHeaderFields->setRowCount(0);
for (auto it = map->customHeaders.begin(); it != map->customHeaders.end(); it++) for (auto it = map->customHeaders.begin(); it != map->customHeaders.end(); it++)
addCustomHeaderValue(it.key(), it.value()); CustomAttributesTable::addAttribute(ui->tableWidget_CustomHeaderFields, it.key(), it.value());
ui->tableWidget_CustomHeaderFields->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->tableWidget_CustomHeaderFields->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->tableWidget_CustomHeaderFields->blockSignals(false); ui->tableWidget_CustomHeaderFields->blockSignals(false);
} }
@ -2756,90 +2756,20 @@ void MainWindow::togglePreferenceSpecificUi() {
ui->actionOpen_Project_in_Text_Editor->setEnabled(true); ui->actionOpen_Project_in_Text_Editor->setEnabled(true);
} }
void MainWindow::addCustomHeaderValue(QString key, QJsonValue value, bool isNew) {
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;
}
const QHash<QJsonValue::Type, QString> 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->ui->tableWidget_CustomHeaderFields->rowCount();
this->ui->tableWidget_CustomHeaderFields->insertRow(rowIndex);
this->ui->tableWidget_CustomHeaderFields->setItem(rowIndex, 0, typeItem);
this->ui->tableWidget_CustomHeaderFields->setItem(rowIndex, 1, new QTableWidgetItem(key));
this->ui->tableWidget_CustomHeaderFields->setItem(rowIndex, 2, valueItem);
if (isNew) {
valueItem->setText(""); // Erase the "0" in new numbers
this->ui->tableWidget_CustomHeaderFields->selectRow(rowIndex);
this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
}
}
void MainWindow::on_pushButton_AddCustomHeaderField_clicked() void MainWindow::on_pushButton_AddCustomHeaderField_clicked()
{ {
const QMap<QString, QJsonValue> valueTypes = {
{"String", QJsonValue(QString(""))},
{"Number", QJsonValue(0)},
{"Boolean", QJsonValue(false)},
};
bool ok; bool ok;
QStringList typeNames = valueTypes.keys(); QJsonValue value = CustomAttributesTable::pickType(this, &ok);
QString selection = QInputDialog::getItem(this, "", "Choose Value Type", typeNames, typeNames.indexOf("String"), false, &ok); if (ok){
if (ok) CustomAttributesTable::addAttribute(this->ui->tableWidget_CustomHeaderFields, "", value, true);
addCustomHeaderValue("", valueTypes[selection], true); this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
}
} }
void MainWindow::on_pushButton_DeleteCustomHeaderField_clicked() void MainWindow::on_pushButton_DeleteCustomHeaderField_clicked()
{ {
int rowCount = this->ui->tableWidget_CustomHeaderFields->rowCount(); if (CustomAttributesTable::deleteSelectedAttributes(this->ui->tableWidget_CustomHeaderFields))
if (rowCount > 0) {
QModelIndexList indexList = ui->tableWidget_CustomHeaderFields->selectionModel()->selectedIndexes();
QList<QPersistentModelIndex> persistentIndexes;
for (QModelIndex index : indexList) {
QPersistentModelIndex persistentIndex(index);
persistentIndexes.append(persistentIndex);
}
for (QPersistentModelIndex index : persistentIndexes) {
this->ui->tableWidget_CustomHeaderFields->removeRow(index.row());
}
if (this->ui->tableWidget_CustomHeaderFields->rowCount() > 0) {
this->ui->tableWidget_CustomHeaderFields->selectRow(0);
}
this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields); this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
}
} }
void MainWindow::on_tableWidget_CustomHeaderFields_cellChanged(int, int) void MainWindow::on_tableWidget_CustomHeaderFields_cellChanged(int, int)

View file

@ -1,10 +1,12 @@
#include "customattributestable.h" #include "customattributestable.h"
#include "parseutil.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
#include <QPushButton> #include <QPushButton>
#include <QTableWidget> #include <QTableWidget>
#include <QLabel> #include <QLabel>
#include <QScrollBar> #include <QScrollBar>
#include <QInputDialog>
CustomAttributesTable::CustomAttributesTable(Event *event, QWidget *parent) : CustomAttributesTable::CustomAttributesTable(Event *event, QWidget *parent) :
QFrame(parent) QFrame(parent)
@ -28,52 +30,34 @@ CustomAttributesTable::CustomAttributesTable(Event *event, QWidget *parent) :
layout->addWidget(buttonsFrame); layout->addWidget(buttonsFrame);
this->table = new QTableWidget(this); this->table = new QTableWidget(this);
this->table->setColumnCount(2); this->table->setColumnCount(3);
this->table->setHorizontalHeaderLabels(QStringList({"Key", "Value"})); this->table->setHorizontalHeaderLabels(QStringList({"Type", "Key", "Value"}));
this->table->horizontalHeader()->setStretchLastSection(true); this->table->horizontalHeader()->setStretchLastSection(true);
layout->addWidget(this->table); layout->addWidget(this->table);
QMap<QString, QString> customValues = this->event->getCustomValues(); QMap<QString, QJsonValue> customValues = this->event->getCustomValues();
for (auto it = customValues.begin(); it != customValues.end(); it++) { for (auto it = customValues.begin(); it != customValues.end(); it++)
int rowIndex = this->table->rowCount(); CustomAttributesTable::addAttribute(this->table, it.key(), it.value());
this->table->insertRow(rowIndex);
this->table->setItem(rowIndex, 0, new QTableWidgetItem(it.key()));
this->table->setItem(rowIndex, 1, new QTableWidgetItem(it.value()));
}
connect(addButton, &QPushButton::clicked, [=]() { connect(addButton, &QPushButton::clicked, [=]() {
int rowIndex = this->table->rowCount(); bool ok;
this->table->insertRow(rowIndex); QJsonValue value = CustomAttributesTable::pickType(this, &ok);
this->table->selectRow(rowIndex); if (ok){
this->event->setCustomValues(this->getTableFields()); CustomAttributesTable::addAttribute(this->table, "", value, true);
this->resizeVertically(); this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
this->resizeVertically();
}
}); });
connect(deleteButton, &QPushButton::clicked, [=]() { connect(deleteButton, &QPushButton::clicked, [=]() {
int rowCount = this->table->rowCount(); if (CustomAttributesTable::deleteSelectedAttributes(this->table)) {
if (rowCount > 0) { this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
QModelIndexList indexList = this->table->selectionModel()->selectedIndexes();
QList<QPersistentModelIndex> persistentIndexes;
for (QModelIndex index : indexList) {
QPersistentModelIndex persistentIndex(index);
persistentIndexes.append(persistentIndex);
}
for (QPersistentModelIndex index : persistentIndexes) {
this->table->removeRow(index.row());
}
if (this->table->rowCount() > 0) {
this->table->selectRow(0);
}
this->event->setCustomValues(this->getTableFields());
this->resizeVertically(); this->resizeVertically();
} }
}); });
connect(this->table, &QTableWidget::cellChanged, [=]() { connect(this->table, &QTableWidget::cellChanged, [=]() {
this->event->setCustomValues(this->getTableFields()); this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
}); });
this->resizeVertically(); this->resizeVertically();
@ -83,20 +67,6 @@ CustomAttributesTable::~CustomAttributesTable()
{ {
} }
QMap<QString, QString> CustomAttributesTable::getTableFields() {
QMap<QString, QString> fields;
for (int row = 0; row < table->rowCount(); row++) {
QString keyStr = "";
QString valueStr = "";
QTableWidgetItem *key = table->item(row, 0);
QTableWidgetItem *value = table->item(row, 1);
if (key) keyStr = key->text();
if (value) valueStr = value->text();
fields[keyStr] = valueStr;
}
return fields;
}
void CustomAttributesTable::resizeVertically() { void CustomAttributesTable::resizeVertically() {
int horizontalHeaderHeight = this->table->horizontalHeader()->height(); int horizontalHeaderHeight = this->table->horizontalHeader()->height();
int rowHeight = 0; int rowHeight = 0;
@ -112,3 +82,125 @@ void CustomAttributesTable::resizeVertically() {
this->table->setMinimumHeight(totalHeight); this->table->setMinimumHeight(totalHeight);
this->table->setMaximumHeight(totalHeight); this->table->setMaximumHeight(totalHeight);
} }
const QMap<QString, QJsonValue> CustomAttributesTable::getAttributes(QTableWidget * table) {
QMap<QString, QJsonValue> fields;
if (!table) return fields;
for (int row = 0; row < table->rowCount(); row++) {
QString key = "";
QTableWidgetItem *typeItem = table->item(row, 0);
QTableWidgetItem *keyItem = table->item(row, 1);
QTableWidgetItem *valueItem = table->item(row, 2);
if (keyItem) key = keyItem->text();
if (key.isEmpty() || !typeItem || !valueItem)
continue;
// Read from the table data which JSON type to save the value as
QJsonValue::Type type = static_cast<QJsonValue::Type>(typeItem->data(Qt::UserRole).toInt());
QJsonValue value;
switch (type)
{
case QJsonValue::String:
value = QJsonValue(valueItem->text());
break;
case QJsonValue::Double:
value = QJsonValue(valueItem->text().toInt());
break;
case QJsonValue::Bool:
value = QJsonValue(valueItem->checkState() == Qt::Checked);
break;
default:
// All other types will just be preserved
value = valueItem->data(Qt::UserRole).toJsonValue();
break;
}
fields[key] = value;
}
return fields;
}
QJsonValue CustomAttributesTable::pickType(QWidget * parent, bool * ok) {
const QMap<QString, QJsonValue> valueTypes = {
{"String", QJsonValue(QString(""))},
{"Number", QJsonValue(0)},
{"Boolean", QJsonValue(false)},
};
QStringList typeNames = valueTypes.keys();
QString selection = QInputDialog::getItem(parent, "", "Choose Value Type", typeNames, typeNames.indexOf("String"), false, ok);
return valueTypes.value(selection);
}
void CustomAttributesTable::addAttribute(QTableWidget * table, QString key, QJsonValue value, bool isNew) {
if (!table) return;
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;
}
const QHash<QJsonValue::Type, QString> 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 = table->rowCount();
table->insertRow(rowIndex);
table->setItem(rowIndex, 0, typeItem);
table->setItem(rowIndex, 1, new QTableWidgetItem(key));
table->setItem(rowIndex, 2, valueItem);
if (isNew) {
valueItem->setText(""); // Erase the "0" in new numbers
table->selectRow(rowIndex);
}
}
bool CustomAttributesTable::deleteSelectedAttributes(QTableWidget * table) {
if (!table)
return false;
int rowCount = table->rowCount();
if (rowCount <= 0)
return false;
QModelIndexList indexList = table->selectionModel()->selectedIndexes();
QList<QPersistentModelIndex> persistentIndexes;
for (QModelIndex index : indexList) {
QPersistentModelIndex persistentIndex(index);
persistentIndexes.append(persistentIndex);
}
for (QPersistentModelIndex index : persistentIndexes) {
table->removeRow(index.row());
}
if (table->rowCount() > 0) {
table->selectRow(0);
}
return true;
}

View file

@ -85,9 +85,8 @@ void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
if (eventType == Event::Type::Warp) { if (eventType == Event::Type::Warp) {
WarpEvent *warp = dynamic_cast<WarpEvent *>(this->event); WarpEvent *warp = dynamic_cast<WarpEvent *>(this->event);
QString destMap = warp->getDestinationMap(); QString destMap = warp->getDestinationMap();
bool ok; int warpId = ParseUtil::gameStringToInt(warp->getDestinationWarpID());
int warpId = ParseUtil::gameStringToInt(warp->getDestinationWarpID(), &ok); emit editor->warpEventDoubleClicked(destMap, warpId, Event::Group::Warp);
if (ok) emit editor->warpEventDoubleClicked(destMap, warpId, Event::Group::Warp);
} }
else if (eventType == Event::Type::CloneObject) { else if (eventType == Event::Type::CloneObject) {
CloneObjectEvent *clone = dynamic_cast<CloneObjectEvent *>(this->event); CloneObjectEvent *clone = dynamic_cast<CloneObjectEvent *>(this->event);