Add custom attributes dialog

This commit is contained in:
GriffinR 2024-01-09 17:03:07 -05:00
parent 84d3b4c55e
commit 2bf221c729
6 changed files with 326 additions and 22 deletions

View file

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CustomAttributesDialog</class>
<widget class="QDialog" name="CustomAttributesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>410</width>
<height>192</height>
</rect>
</property>
<property name="windowTitle">
<string>Add New Custom Attribute</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="centralwidget">
<layout class="QFormLayout" name="formLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_Name">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_Name">
<property name="toolTip">
<string>The key name for the new JSON field</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_Type">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="NoScrollComboBox" name="comboBox_Type">
<property name="toolTip">
<string>The data type for the new JSON field</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_Value">
<property name="text">
<string>Value</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QStackedWidget" name="stackedWidget_Value">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The value for the new JSON field</string>
</property>
<widget class="QWidget" name="page_String">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="lineEdit_Value"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Number">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="spinBox_Value"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Boolean">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_Value">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_Default">
<property name="text">
<string>Add to Defaults</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="checkBox_Default">
<property name="toolTip">
<string>If checked, this JSON field will be added to any new maps/events of this type, with the current value as its default</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NoScrollComboBox</class>
<extends>QComboBox</extends>
<header>noscrollcombobox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,31 @@
#ifndef CUSTOMATTRIBUTESDIALOG_H
#define CUSTOMATTRIBUTESDIALOG_H
#include <QDialog>
#include <QAbstractButton>
#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

View file

@ -16,14 +16,19 @@ public:
QMap<QString, QJsonValue> getAttributes() const; QMap<QString, QJsonValue> getAttributes() const;
void setAttributes(const QMap<QString, QJsonValue> attributes); void setAttributes(const QMap<QString, QJsonValue> attributes);
void addAttribute(QString key, QJsonValue value);
bool deleteSelectedAttributes(); bool deleteSelectedAttributes();
void setDefaultAttribute(QString key, QJsonValue value);
void unsetDefaultAttribute(QString key);
const QStringList restrictedKeyNames; // TODO: Populate
signals: signals:
void edited(); void edited();
private: private:
QTableWidget *table; QTableWidget *table;
QJsonValue pickType(bool * ok = nullptr);
void addAttribute(QString key, QJsonValue value, bool init); void addAttribute(QString key, QJsonValue value, bool init);
void resizeVertically(); void resizeVertically();
}; };

View file

@ -43,6 +43,7 @@ SOURCES += src/core/block.cpp \
src/scriptapi/apiutility.cpp \ src/scriptapi/apiutility.cpp \
src/scriptapi/scripting.cpp \ src/scriptapi/scripting.cpp \
src/ui/aboutporymap.cpp \ src/ui/aboutporymap.cpp \
src/ui/customattributesdialog.cpp \
src/ui/customscriptseditor.cpp \ src/ui/customscriptseditor.cpp \
src/ui/customscriptslistitem.cpp \ src/ui/customscriptslistitem.cpp \
src/ui/draggablepixmapitem.cpp \ src/ui/draggablepixmapitem.cpp \
@ -134,6 +135,7 @@ HEADERS += include/core/block.h \
include/lib/orderedmap.h \ include/lib/orderedmap.h \
include/lib/orderedjson.h \ include/lib/orderedjson.h \
include/ui/aboutporymap.h \ include/ui/aboutporymap.h \
include/ui/customattributesdialog.h \
include/ui/customscriptseditor.h \ include/ui/customscriptseditor.h \
include/ui/customscriptslistitem.h \ include/ui/customscriptslistitem.h \
include/ui/draggablepixmapitem.h \ include/ui/draggablepixmapitem.h \
@ -214,7 +216,8 @@ FORMS += forms/mainwindow.ui \
forms/colorpicker.ui \ forms/colorpicker.ui \
forms/projectsettingseditor.ui \ forms/projectsettingseditor.ui \
forms/customscriptseditor.ui \ forms/customscriptseditor.ui \
forms/customscriptslistitem.ui forms/customscriptslistitem.ui \
forms/customattributesdialog.ui
RESOURCES += \ RESOURCES += \
resources/images.qrc \ resources/images.qrc \

View file

@ -0,0 +1,96 @@
#include "customattributesdialog.h"
#include "ui_customattributesdialog.h"
#include <QMessageBox>
// 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<int>::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);
}

View file

@ -1,4 +1,5 @@
#include "customattributestable.h" #include "customattributestable.h"
#include "customattributesdialog.h"
#include "parseutil.h" #include "parseutil.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -41,9 +42,8 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) :
connect(addButton, &QPushButton::clicked, [this]() { connect(addButton, &QPushButton::clicked, [this]() {
bool ok; bool ok;
QJsonValue value = this->pickType(&ok); CustomAttributesDialog dialog(this);
if (ok) { if (dialog.exec() == QDialog::Accepted) {
this->addAttribute("", value, false);
emit this->edited(); emit this->edited();
} }
}); });
@ -63,6 +63,7 @@ CustomAttributesTable::~CustomAttributesTable()
{ {
} }
// TODO: Fix Header table size on first open
void CustomAttributesTable::resizeVertically() { void CustomAttributesTable::resizeVertically() {
int height = 0; int height = 0;
for (int i = 0; i < this->table->rowCount(); i++) { for (int i = 0; i < this->table->rowCount(); i++) {
@ -118,23 +119,6 @@ QMap<QString, QJsonValue> CustomAttributesTable::getAttributes() const {
return fields; return fields;
} }
QJsonValue CustomAttributesTable::pickType(bool * ok) {
static const QMap<QString, QJsonValue> 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<QString, QJsonValue> attributes) { void CustomAttributesTable::setAttributes(const QMap<QString, QJsonValue> attributes) {
this->table->setRowCount(0); this->table->setRowCount(0);
for (auto it = attributes.cbegin(); it != attributes.cend(); it++) for (auto it = attributes.cbegin(); it != attributes.cend(); it++)
@ -142,6 +126,10 @@ void CustomAttributesTable::setAttributes(const QMap<QString, QJsonValue> attrib
this->resizeVertically(); this->resizeVertically();
} }
void CustomAttributesTable::addAttribute(QString key, QJsonValue value) {
this->addAttribute(key, value, false);
}
void CustomAttributesTable::addAttribute(QString key, QJsonValue value, bool init) { void CustomAttributesTable::addAttribute(QString key, QJsonValue value, bool init) {
const QSignalBlocker blocker(this->table); const QSignalBlocker blocker(this->table);
QTableWidgetItem * valueItem; 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() { bool CustomAttributesTable::deleteSelectedAttributes() {
int rowCount = this->table->rowCount(); int rowCount = this->table->rowCount();
if (rowCount <= 0) if (rowCount <= 0)