From 98a5ff4a231e8a3768a0e4d79b2a55a904343085 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 31 Mar 2024 12:43:08 -0400 Subject: [PATCH 001/153] Initial Dialog Not building yet. Some sort of linking error --- qtfred/source_groups.cmake | 5 + .../mission/dialogs/VariableDialogModel.cpp | 0 .../src/mission/dialogs/VariableDialogModel.h | 21 + qtfred/src/ui/FredView.cpp | 6 + qtfred/src/ui/FredView.h | 1 + qtfred/src/ui/dialogs/VariableDialog.cpp | 189 ++++++++ qtfred/src/ui/dialogs/VariableDialog.h | 61 +++ qtfred/ui/VariableDialog.ui | 429 ++++++++++++++++++ 8 files changed, 712 insertions(+) create mode 100644 qtfred/src/mission/dialogs/VariableDialogModel.cpp create mode 100644 qtfred/src/mission/dialogs/VariableDialogModel.h create mode 100644 qtfred/src/ui/dialogs/VariableDialog.cpp create mode 100644 qtfred/src/ui/dialogs/VariableDialog.h create mode 100644 qtfred/ui/VariableDialog.ui diff --git a/qtfred/source_groups.cmake b/qtfred/source_groups.cmake index 7e3e41384c8..77e8c9f7f14 100644 --- a/qtfred/source_groups.cmake +++ b/qtfred/source_groups.cmake @@ -66,6 +66,8 @@ add_file_folder("Source/Mission/Dialogs" src/mission/dialogs/SelectionDialogModel.h src/mission/dialogs/ShieldSystemDialogModel.cpp src/mission/dialogs/ShieldSystemDialogModel.h + src/mission/dialogs/VariableDialogModel.cpp + src/mission/dialogs/VariableDialogModel.h src/mission/dialogs/WaypointEditorDialogModel.cpp src/mission/dialogs/WaypointEditorDialogModel.h ) @@ -130,6 +132,8 @@ add_file_folder("Source/UI/Dialogs" src/ui/dialogs/SelectionDialog.h src/ui/dialogs/ShieldSystemDialog.h src/ui/dialogs/ShieldSystemDialog.cpp + src/ui/dialogs/VariableDialog.cpp + src/ui/dialogs/VariableDialog.h src/ui/dialogs/VoiceActingManager.h src/ui/dialogs/VoiceActingManager.cpp src/ui/dialogs/WaypointEditorDialog.cpp @@ -201,6 +205,7 @@ add_file_folder("UI" ui/PlayerOrdersDialog.ui ui/ShipTextureReplacementDialog.ui ui/ShipTBLViewer.ui + ui/VariableDialog.ui ) add_file_folder("Resources" diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h new file mode 100644 index 00000000000..94ee93b5815 --- /dev/null +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -0,0 +1,21 @@ +#pragma once + +#include "globalincs/pstypes.h" + +#include "AbstractDialogModel.h" + +namespace fso { +namespace fred { +namespace dialogs { + +class VariableDialogModel : public AbstractDialogModel { + public: + VariableDialogModel(QObject* parent, EditorViewport* viewport); + + bool apply() override; + void reject() override; +}; + +} // namespace dialogs +} // namespace fred +} // namespace fso diff --git a/qtfred/src/ui/FredView.cpp b/qtfred/src/ui/FredView.cpp index 3b6fa4cf483..1ca3e5e7cbf 100644 --- a/qtfred/src/ui/FredView.cpp +++ b/qtfred/src/ui/FredView.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "mission/Editor.h" @@ -751,6 +752,11 @@ void FredView::on_actionLoadout_triggered(bool) { auto editorDialog = new dialogs::LoadoutDialog(this, _viewport); editorDialog->show(); } +void FredView::on_actionVariablesAndContainers_triggered(bool) { + auto editorDialog = new dialogs::VariableDialog(this, _viewport); + editorDialog->show(); +} + DialogButton FredView::showButtonDialog(DialogType type, const SCP_string& title, const SCP_string& message, diff --git a/qtfred/src/ui/FredView.h b/qtfred/src/ui/FredView.h index 573c5b06be1..b11bfbfa0a3 100644 --- a/qtfred/src/ui/FredView.h +++ b/qtfred/src/ui/FredView.h @@ -91,6 +91,7 @@ class FredView: public QMainWindow, public IDialogProvider { void on_actionCommand_Briefing_triggered(bool); void on_actionReinforcements_triggered(bool); void on_actionLoadout_triggered(bool); + void on_actionVariablesAndContainers_triggered(bool); void on_actionSelectionLock_triggered(bool enabled); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp new file mode 100644 index 00000000000..a7b95db8844 --- /dev/null +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -0,0 +1,189 @@ +#include "VariableDialog.h" +#include "ui_VariableDialog.h" + +#include +#include + +#include +#include +//#include + +namespace fso { +namespace fred { +namespace dialogs { + +VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) + : QDialog(parent), ui(new Ui::VariableDialog()), _model(new VariableDialogModel(this, viewport)), _viewport(viewport) +{ + this->setFocus(); + + // Major Changes, like Applying the model, rejecting changes and updating the UI. + connect(_model.get(), &AbstractDialogModel::modelChanged, this, &VariableDialog::updateUI); + connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); + connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); + + connect(ui->variablesTable, + QOverload::of(&QTableWidget::cellChanged), + this, + &VariableDialog::onVariablesTableUpdated); + + connect(ui->variablesTable, + QOverload::of(&QTableWidget::cellChanged), + this, + &VariableDialog::onContainersTableUpdated); + + connect(ui->variablesTable, + QOverload::of(&QTableWidget::cellChanged), + this, + &VariableDialog::onContainerContentsTableUpdated); + + connect(ui->addVariableButton, + &QPushButton::clicked, + this, + &VariableDialog::onAddVariableButtonPressed); + + connect(ui->deleteVariableButton, + &QPushButton::clicked, + this, + &VariableDialog::onDeleteVariableButtonPressed); + + connect(ui->setVariableAsStringRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetVariableAsStringRadioSelected); + + connect(ui->setVariableAsNumberRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetVariableAsNumberRadioSelected); + + connect(ui->saveContainerOnMissionCompletedRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSaveVariableOnMissionCompleteRadioSelected); + + connect(ui->saveVariableOnMissionCloseRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSaveVariableOnMissionCloseRadioSelected); + + connect(ui->setVariableAsEternalcheckbox, + &QCheckBox::clicked, + this, + &VariableDialog::onSaveVariableAsEternalCheckboxClicked); + + connect(ui->addContainerButton, + &QPushButton::clicked, + this, + &VariableDialog::onAddContainerButtonPressed); + + connect(ui->deleteContainerButton, + &QPushButton::clicked, + this, + &VariableDialog::onDeleteContainerButtonPressed); + + connect(ui->setContainerAsMapRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerAsMapRadioSelected); + + connect(ui->setContainerAsListRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerAsListRadioSelected); + + connect(ui->setContainerAsStringRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerAsStringRadioSelected); + + connect(ui->setContainerAsNumberRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerAsNumberRadio); + + connect(ui->saveContainerOnMissionCloseRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSaveContainerOnMissionClosedRadioSelected); + + connect(ui->saveContainerOnMissionCompletedRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSaveContainerOnMissionCompletedRadioSelected); + + + connect(ui->addContainerItemButton, + &QPushButton::clicked, + this, + &VariableDialog::onAddContainerItemButtonPressed); + + connect(ui->deleteContainerItemButton, + &QPushButton::clicked, + this, + &VariableDialog::onDeleteContainerItemButtonPressed); + + connect(ui->setContainerAsEternalCheckbox, + &QCheckBox::clicked, + this, + &VariableDialog::onSetContainerAsEternalCheckboxClicked); +} + + void VariableDialog::onVariablesTableUpdated() {} + void VariableDialog::onContainersTableUpdated() {} + void VariableDialog::onContainerContentsTableUpdated() {} + void VariableDialog::onAddVariableButtonPressed() {} + void VariableDialog::onDeleteVariableButtonPressed() {} + void VariableDialog::onSetVariableAsStringRadioSelected() {} + void VariableDialog::onSetVariableAsNumberRadioSelected() {} + void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() {} + void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} + void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} + + void VariableDialog::onAddContainerButtonPressed() {} + void VariableDialog::onDeleteContainerButtonPressed() {} + void VariableDialog::onSetContainerAsMapRadioSelected() {} + void VariableDialog::onSetContainerAsListRadioSelected() {} + void VariableDialog::onSetContainerAsStringRadioSelected() {} + void VariableDialog::onSetContainerAsNumberRadio() {} + void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} + void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} + void VariableDialog::onNetworkContainerCheckboxClicked() {} + void VariableDialog::onSetContainerAsEternalCheckboxClicked() {} + void VariableDialog::onAddContainerItemButtonPressed() {} + void VariableDialog::onDeleteContainerItemButtonPressed() {} + +/* +containersTable +containerContentsTable +addVariableButton +deleteVariableButton +setVariableAsStringRadio +setVariableAsNumberRadio +networkVariableCheckbox +saveVariableOnMissionCompletedRaio +saveVariableOnMissionCloseRadio +setVariableAsEternalcheckbox + +addContainerButton +deleteContainerButton +setContainerAsMapRadio +setContainerAsListRadio +setContainerAsStringRadio +setContainerAsNumberRadio +saveContainerOnMissionCloseRadio +saveContainerOnMissionCompletedRadio +networkContainerCheckbox +setContainerAsEternalCheckbox + */ + + + +VariableDialog::~VariableDialog(){}; // NOLINT + +void VariableDialog::updateUI(){}; + + +} // namespace dialogs +} // namespace fred +} // namespace fso \ No newline at end of file diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h new file mode 100644 index 00000000000..f3eec607aa6 --- /dev/null +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include + +namespace fso { +namespace fred { +namespace dialogs { + +namespace Ui { +class VariableDialog; +} + +class VariableDialog : public QDialog { + Q_OBJECT + + public: + explicit VariableDialog(FredView* parent, EditorViewport* viewport); + ~VariableDialog() override; + + private: + std::unique_ptr ui; + std::unique_ptr _model; + EditorViewport* _viewport; + + void updateUI(); + + void onVariablesTableUpdated(); + void onContainersTableUpdated(); + void onContainerContentsTableUpdated(); + void onAddVariableButtonPressed(); + void onDeleteVariableButtonPressed(); + void onSetVariableAsStringRadioSelected(); + void onSetVariableAsNumberRadioSelected(); + void onSaveVariableOnMissionCompleteRadioSelected(); + void onSaveVariableOnMissionCloseRadioSelected(); + void onSaveVariableAsEternalCheckboxClicked(); + + void onAddContainerButtonPressed(); + void onDeleteContainerButtonPressed(); + void onSetContainerAsMapRadioSelected(); + void onSetContainerAsListRadioSelected(); + void onSetContainerAsStringRadioSelected(); + void onSetContainerAsNumberRadio(); + void onSaveContainerOnMissionClosedRadioSelected(); + void onSaveContainerOnMissionCompletedRadioSelected(); + void onNetworkContainerCheckboxClicked(); + void onSetContainerAsEternalCheckboxClicked(); + void onAddContainerItemButtonPressed(); + void onDeleteContainerItemButtonPressed(); +}; + + + + + +} // namespace dialogs +} // namespace fred +} // namespace fso \ No newline at end of file diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui new file mode 100644 index 00000000000..b3e99e727a6 --- /dev/null +++ b/qtfred/ui/VariableDialog.ui @@ -0,0 +1,429 @@ + + + fso::fred::dialogs::VariableDialog + + + + 0 + 0 + 589 + 608 + + + + Fiction Viewer Editor + + + + + + + 0 + 325 + + + + Containers + + + + + 10 + 30 + 231 + 121 + + + + + + + 10 + 160 + 331 + 161 + + + + Contents + + + + + 10 + 30 + 221 + 121 + + + + + + + 240 + 30 + 81 + 121 + + + + + + + Add + + + + + + + + 8 + + + + Delete + + + + + + + + + + 250 + 30 + 81 + 121 + + + + + + + Add + + + + + + + + 8 + + + + Delete + + + + + + + + + 360 + 180 + 201 + 141 + + + + Options + + + + + 0 + 20 + 201 + 121 + + + + + + + Save on Mission Close + + + + + + + Save on Mission Completed + + + + + + + Network-Variable + + + + + + + Eternal + + + + + + + + + + 359 + 18 + 201 + 151 + + + + + + + Container Type + + + + + 0 + 20 + 201 + 52 + + + + + + + Map + + + + + + + List + + + + + + + + + + + Data Type + + + + + 0 + 20 + 201 + 52 + + + + + + + String + + + + + + + Number + + + + + + + + + + + + + + + + 0 + 230 + + + + Variables + + + + + 260 + 30 + 175 + 61 + + + + + + + Add Variable + + + + + + + Delete Variable and References + + + + + + + + + 260 + 100 + 301 + 121 + + + + Options + + + + + 0 + 20 + 301 + 101 + + + + + + + + + String + + + + + + + Number + + + + + + + Network-Variable + + + + + + + + + + + Save on Mission Close + + + + + + + Save on Mission Completed + + + + + + + Eternal + + + + + + + + + + + + 10 + 30 + 241 + 191 + + + + + + + + + QLayout::SetMaximumSize + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 12 + + + + Variables and Containers Editor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + From e7583ddab802dc097b706608088e30b19260778b Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 22 Dec 2023 18:41:06 -0500 Subject: [PATCH 002/153] start creating Model and helper structs --- .../mission/dialogs/VariableDialogModel.cpp | 7 +++++ .../src/mission/dialogs/VariableDialogModel.h | 31 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index e69de29bb2d..b40a90689f5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -0,0 +1,7 @@ +#include "VariableDialogModel.h" + +VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) + : AbstractDialogModel(parent, viewport) +{ + initializeData(); +} \ No newline at end of file diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 94ee93b5815..15a7923f60c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -8,12 +8,41 @@ namespace fso { namespace fred { namespace dialogs { +struct variable_info { + SCP_string name = ""; + bool container = false; + bool map = false; + bool string = true; + + SCP_vector number_values; + SCP_vector string_values; +}; + + +struct variable_or_container_info { + SCP_string name = ""; + bool container = false; + bool map = false; + bool string = true; + + SCP_vector keys; + SCP_vector number_values; + SCP_vector number_values; +}; + class VariableDialogModel : public AbstractDialogModel { - public: +public: VariableDialogModel(QObject* parent, EditorViewport* viewport); + void changeSelection(SCP_string name, bool container){} + void changeName(SCP_string oldName, SCP_string newName, bool container) + bool apply() override; void reject() override; + +private: + SCP_vector _items; + }; } // namespace dialogs From 5d0ee564ac2a801497a3cc46ae1678220f9e2ab4 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 29 Dec 2023 17:50:39 -0500 Subject: [PATCH 003/153] fix support structs --- qtfred/src/mission/dialogs/VariableDialogModel.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 15a7923f60c..d98797ecc63 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -10,24 +10,21 @@ namespace dialogs { struct variable_info { SCP_string name = ""; - bool container = false; - bool map = false; bool string = true; - SCP_vector number_values; - SCP_vector string_values; + int number_values; + SCP_string string_values; }; -struct variable_or_container_info { +struct container_info { SCP_string name = ""; - bool container = false; bool map = false; bool string = true; SCP_vector keys; SCP_vector number_values; - SCP_vector number_values; + SCP_vector number_values; }; class VariableDialogModel : public AbstractDialogModel { @@ -41,8 +38,8 @@ class VariableDialogModel : public AbstractDialogModel { void reject() override; private: - SCP_vector _items; - + SCP_vector _variableItems; + SCP_vector _containerItems; }; } // namespace dialogs From 64b54d1022940631fc90ab099b7ec5032d9d7151 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 1 Apr 2024 17:58:07 -0400 Subject: [PATCH 004/153] Start writing apply and reject methods --- .../mission/dialogs/VariableDialogModel.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index b40a90689f5..d30af735aff 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1,7 +1,26 @@ #include "VariableDialogModel.h" +#include "parse/sexp.h" +#include "parse/sexp_container.h" + VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) : AbstractDialogModel(parent, viewport) { initializeData(); +} + +void VariableDialogModel::reject() +{ + _variableItems.clear(); + _containerItems.clear(); +} + +void VariableDialogModel::apply() +{ + memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); + + for (const auto& variable : _variableItems){ + + } + } \ No newline at end of file From 52cc1f182e41f450cd99129fb4b53c0d1e954706 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 6 Jan 2024 18:13:19 -0500 Subject: [PATCH 005/153] Make sure flags are included --- qtfred/src/mission/dialogs/VariableDialogModel.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index d98797ecc63..94ae5de0f8a 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -11,9 +11,9 @@ namespace dialogs { struct variable_info { SCP_string name = ""; bool string = true; - - int number_values; - SCP_string string_values; + int flags = 0; + int number_value; + SCP_string string_value; }; @@ -21,6 +21,7 @@ struct container_info { SCP_string name = ""; bool map = false; bool string = true; + int flags = 0; SCP_vector keys; SCP_vector number_values; From 7c15adec1ab8014376d6c3590c9f197fe7a3a0df Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 6 Jan 2024 18:38:12 -0500 Subject: [PATCH 006/153] Finish Loop for saving variables --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index d30af735aff..7a1f4a2e9b5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -19,8 +19,17 @@ void VariableDialogModel::apply() { memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); - for (const auto& variable : _variableItems){ + for (int i = 0; i < static_cast(_variableItems.size()); ++i){ + Sexp_variables[i].type = _variableItems[i].flags; + strcpy_s(Sexp_variables[i].variable_name, _variableItems[i].name.c_str()); + if (_variableItems[i].flags & SEXP_VARIABLE_STRING){ + strcpy_s(Sexp_variables[i].text, _variableItems[i].stringValue); + } else { + strcpy_s(Sexp_variables[i].text, std::to_string(_variableItems[i].numberValue).c_str()) + } } + + } \ No newline at end of file From 286a96e2c3cdd6dbee98429a21dcdbdcdd044700 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 6 Apr 2024 22:25:48 -0400 Subject: [PATCH 007/153] save progress --- .../mission/dialogs/VariableDialogModel.cpp | 245 +++++++++++++++++- .../src/mission/dialogs/VariableDialogModel.h | 106 +++++++- qtfred/src/ui/dialogs/VariableDialog.cpp | 74 ++---- qtfred/src/ui/dialogs/VariableDialog.h | 2 + 4 files changed, 372 insertions(+), 55 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7a1f4a2e9b5..a71217e9dd5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -2,6 +2,9 @@ #include "parse/sexp.h" #include "parse/sexp_container.h" +namespace fso { +namespace fred { +namespace dialogs { VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) : AbstractDialogModel(parent, viewport) @@ -15,6 +18,7 @@ void VariableDialogModel::reject() _containerItems.clear(); } + void VariableDialogModel::apply() { memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); @@ -30,6 +34,245 @@ void VariableDialogModel::apply() } } + // TODO! containers + + +} + +// true on string, false on number +bool VariableDialogModel::getVariableType(SCP_string name) +{ + return (auto variable = lookupVariable(name)) ? (variable->string) : false; +} + +bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) +{ + // TODO! figure out the flag combination for network variable. + return (auto variable = lookupVariable(name)) ? (variable->string) : false; +} + + + +// 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) +int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(SCP_string name) +{ + return (auto variable = lookupVariable(name)) ? (variable->flags) : 0; +} + + +bool VariableDialogModel::getVariableEternalFlag(SCP_string name) +{ + // TODO! figure out correct value for retrieving eternal. + return (auto variable = lookupVariable(name)) ? (variable->flags) : false; +} + + +SCP_string VariableDialogModel::getVariableStringValue(SCP_string name) +{ + return ((auto variable = lookupVariable(name)) && variable->string) ? (variable->stringValue) : ""; +} + +int VariableDialogModel::getVariableNumberValue(SCP_string name) +{ + return ((auto variable = lookupVariable(name)) && !variable->string) ? (variable->numberValue) : 0; +} + + + +// TODO! Need a way to clean up references. + +// true on string, false on number +bool VariableDialogModel::setVariableType(SCP_string name, bool string) +{ + auto variable = lookupVariable(name); + + // nothing to change + if (variable->string == string){ + return string; + } + + //TODO! We need a way to detect the number of references, because then we could see if we need to warn + // about references. + + // changing the type here! + // this variable is currently a string + if (variable->string) { + // no risk change, because no string was specified. + if (variable->stringValue == "") { + variable->string = string; + return variable->string; + } else { + SCP_string question; + sprintf(&question, "Changing variable %s to number variable type will make its string value irrelevant. Continue?", variable->name.c_st()); + SCP_string info; + sprintf(&info, "If the string cleanly converts to an integer and a number has not previously been set for this variable, the converted number value will be retained.") + + // if this was a misclick, let the user say so + if (!confirmAction(question)) { + return variable->string; + } + + // if there was no previous number value + if (variable->numberValue == 0){ + try { + variable->numberValue = std::stoi(variable->stringValue); + } + // nothing to do here, because that just means we can't convert. + catch {} + } + + return string; + } + + // this variable is currently a number + } else { + // safe change because there was no number value specified + if (variable->numberValue == 0){ + varaible->string = string; + return variable->string; + } else { + SCP_string question; + sprintf(&question, "Changing variable %s to a string variable type will make the number value irrelevant. Continue?", variable->name.c_st()); + SCP_string info; + sprintf(&info, "If no string value has been previously set for this variable, then the number value specified will be set as the default string value.") + + // if this was a misclick, let the user say so + if (!confirmAction(question)) { + return variable->string; + } + + // if there was no previous string value + if (variable->stringValue == ""){ + sprintf(&variable->stringValue, "%i", variable->numberValue); + } + + return string; + } + } +} + +bool VariableDialogModel::setVariableNetworkStatus(SCP_string name, bool network) +{ + +} + +int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(SCP_string name, int flags) +{ + +} + +bool VariableDialogModel::setVariableEternalFlag(SCP_string name, bool eternal) +{ + +} + +SCP_string VariableDialogModel::setVariableStringValue(SCP_string name, SCP_string value) +{ + +} + +int VariableDialogModel::setVariableNumberValue(SCP_string name, int value) +{ + +} + +SCP_string VariableDialogModel::addNewVariable() +{ + +} + +SCP_string VariableDialogModel::changeVariableName(SCP_string oldName, SCP_string newName) +{ + +} + +SCP_string VariableDialogModel::copyVariable(SCP_string name) +{ + +} + + + +// returns whether it succeeded +bool VariableDialogModel::removeVariable(SCP_string) +{ + +} + + +// Container Section + +// true on string, false on number +bool VariableDialogModel::getContainerValueType(SCP_string name) +{ + +} + +// true on list, false on map +bool VariableDialogModel::getContainerListOrMap(SCP_string name) +{ + +} + +bool VariableDialogModel::getContainerNetworkStatus(SCP_string name) +{ + +} + +// 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) +int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(SCP_string name) +{ + +} + +bool VariableDialogModel::getContainerEternalFlag(SCP_string name) +{ + +} + + +bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) +{ + +} + +bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) +{ + +} + +bool VariableDialogModel::setContainerNetworkStatus(SCP_string name, bool network) +{ +} + +int VariableDialogModel::setContainerOnMissionCloseOrCompleteFlag(SCP_string name, int flags) +{ + +} + +bool VariableDialogModel::setContainerEternalFlag(SCP_string name, bool eternal) +{ + +} + +SCP_string VariableDialogModel::addContainer() +{ + +} + +SCP_string VariableDialogModel::changeContainerName(SCP_string oldName, SCP_string newName) +{ + +} + +bool VariableDialogModel::removeContainer(SCP_string name) +{ + +} + + -} \ No newline at end of file +} // dialogs +} // fred +} // fso diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 94ae5de0f8a..92a1eb7ab1d 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -12,8 +12,8 @@ struct variable_info { SCP_string name = ""; bool string = true; int flags = 0; - int number_value; - SCP_string string_value; + int numberValue = 0; + SCP_string stringValue = ""; }; @@ -22,18 +22,66 @@ struct container_info { bool map = false; bool string = true; int flags = 0; - + SCP_vector keys; - SCP_vector number_values; - SCP_vector number_values; + SCP_vector numberValues; + SCP_vector stringValues; }; class VariableDialogModel : public AbstractDialogModel { public: VariableDialogModel(QObject* parent, EditorViewport* viewport); - void changeSelection(SCP_string name, bool container){} - void changeName(SCP_string oldName, SCP_string newName, bool container) + // true on string, false on number + bool getVariableType(SCP_string name); + bool getVariableNetworkStatus(SCP_string name); + // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) + int getVariableOnMissionCloseOrCompleteFlag(SCP_string name); + bool getVariableEternalFlag(SCP_string name); + + SCP_string getVariableStringValue(SCP_string name); + int getVariableNumberValue(SCP_string name); + + // !! Note an innovation: when getting a request to set a value, + // this model will return the value that sticks and then will overwrite + // the value in the dialog. This means that we don't have to have the UI + // repopulate the whole editor on each change. + + // true on string, false on number + bool setVariableType(SCP_string name, bool string); + bool setVariableNetworkStatus(SCP_string name, bool network); + int setVariableOnMissionCloseOrCompleteFlag(SCP_string name, int flags); + bool setVariableEternalFlag(SCP_string name, bool eternal); + + SCP_string setVariableStringValue(SCP_string name, SCP_string value); + int setVariableNumberValue(SCP_string name, int value); + + SCP_string addNewVariable(); + SCP_string changeVariableName(SCP_string oldName, SCP_string newName); + SCP_string copyVariable(SCP_string name); + // returns whether it succeeded + bool removeVariable(SCP_string); + + // Container Section + + // true on string, false on number + bool getContainerValueType(SCP_string name); + // true on list, false on map + bool getContainerListOrMap(SCP_string name); + bool getContainerNetworkStatus(SCP_string name); + // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) + int getContainerOnMissionCloseOrCompleteFlag(SCP_string name); + bool getContainerEternalFlag(SCP_string name); + + bool setContainerValueType(SCP_string name, bool type); + bool setContainerListOrMap(SCP_string name, bool list); + bool setContainerNetworkStatus(SCP_string name, bool network); + int setContainerOnMissionCloseOrCompleteFlag(SCP_string name, int flags); + bool setContainerEternalFlag(SCP_string name, bool eternal); + + SCP_string addContainer(); + SCP_string changeContainerName(SCP_string oldName, SCP_string newName); + bool removeContainer(SCP_string name); bool apply() override; void reject() override; @@ -41,8 +89,52 @@ class VariableDialogModel : public AbstractDialogModel { private: SCP_vector _variableItems; SCP_vector _containerItems; + + const variable_info* lookupVariable(SCP_string name){ + for (int x = 0; x < static_cast(_varaibleItems.size()); ++x){ + if (_varaibleItems[x].name == name){ + return &_varaibleItems[x]; + } + } + + return nullptr; + } + + const container_info* lookupContainer(SCP_string name){ + for (int x = 0; x < static_cast(_containerItems.size()); ++x){ + if (_containerItems[x].name == name){ + return &_containerItems[x]; + } + } + + return nullptr; + } + + // many of the controls in this editor can lead to drastic actions, so this will be very useful. + const bool confirmAction(SCP_string question, SCP_string informativeText) + { + QMessageBox msgBox; + msgBox.setText(question.c_str()); + msgBox.setInformativeText(informativeText.C_str()); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Cancel); + int ret = msgBox.exec(); + + switch (ret) { + case QMessageBox::Yes: + return true; + break; + case QMessageBox::Cancel: + return false; + break; + default: + UNREACHABLE("Bad return value from confirmation message box in the Loadout dialog editor."); + break; + } + } }; } // namespace dialogs } // namespace fred } // namespace fso + diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index a7b95db8844..6debb7c4403 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -129,53 +129,33 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &VariableDialog::onSetContainerAsEternalCheckboxClicked); } - void VariableDialog::onVariablesTableUpdated() {} - void VariableDialog::onContainersTableUpdated() {} - void VariableDialog::onContainerContentsTableUpdated() {} - void VariableDialog::onAddVariableButtonPressed() {} - void VariableDialog::onDeleteVariableButtonPressed() {} - void VariableDialog::onSetVariableAsStringRadioSelected() {} - void VariableDialog::onSetVariableAsNumberRadioSelected() {} - void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() {} - void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} - void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} - - void VariableDialog::onAddContainerButtonPressed() {} - void VariableDialog::onDeleteContainerButtonPressed() {} - void VariableDialog::onSetContainerAsMapRadioSelected() {} - void VariableDialog::onSetContainerAsListRadioSelected() {} - void VariableDialog::onSetContainerAsStringRadioSelected() {} - void VariableDialog::onSetContainerAsNumberRadio() {} - void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} - void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} - void VariableDialog::onNetworkContainerCheckboxClicked() {} - void VariableDialog::onSetContainerAsEternalCheckboxClicked() {} - void VariableDialog::onAddContainerItemButtonPressed() {} - void VariableDialog::onDeleteContainerItemButtonPressed() {} - -/* -containersTable -containerContentsTable -addVariableButton -deleteVariableButton -setVariableAsStringRadio -setVariableAsNumberRadio -networkVariableCheckbox -saveVariableOnMissionCompletedRaio -saveVariableOnMissionCloseRadio -setVariableAsEternalcheckbox - -addContainerButton -deleteContainerButton -setContainerAsMapRadio -setContainerAsListRadio -setContainerAsStringRadio -setContainerAsNumberRadio -saveContainerOnMissionCloseRadio -saveContainerOnMissionCompletedRadio -networkContainerCheckbox -setContainerAsEternalCheckbox - */ +void VariableDialog::onVariablesTableUpdated() {} // could be new name or new value +void VariableDialog::onContainersTableUpdated() {} // could be new name +void VariableDialog::onContainerContentsTableUpdated() {} // could be new key or new value +void VariableDialog::onAddVariableButtonPressed() +{ + + +} +void VariableDialog::onDeleteVariableButtonPressed() {} +void VariableDialog::onSetVariableAsStringRadioSelected() {} +void VariableDialog::onSetVariableAsNumberRadioSelected() {} +void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() {} +void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} +void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} + +void VariableDialog::onAddContainerButtonPressed() {} +void VariableDialog::onDeleteContainerButtonPressed() {} +void VariableDialog::onSetContainerAsMapRadioSelected() {} +void VariableDialog::onSetContainerAsListRadioSelected() {} +void VariableDialog::onSetContainerAsStringRadioSelected() {} +void VariableDialog::onSetContainerAsNumberRadio() {} +void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} +void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} +void VariableDialog::onNetworkContainerCheckboxClicked() {} +void VariableDialog::onSetContainerAsEternalCheckboxClicked() {} +void VariableDialog::onAddContainerItemButtonPressed() {} +void VariableDialog::onDeleteContainerItemButtonPressed() {} diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index f3eec607aa6..600ad5dc994 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -32,6 +32,7 @@ class VariableDialog : public QDialog { void onContainerContentsTableUpdated(); void onAddVariableButtonPressed(); void onDeleteVariableButtonPressed(); + void onCopyVariableButtonPressed(); void onSetVariableAsStringRadioSelected(); void onSetVariableAsNumberRadioSelected(); void onSaveVariableOnMissionCompleteRadioSelected(); @@ -40,6 +41,7 @@ class VariableDialog : public QDialog { void onAddContainerButtonPressed(); void onDeleteContainerButtonPressed(); + void onCopyContainerButtonPressed(); void onSetContainerAsMapRadioSelected(); void onSetContainerAsListRadioSelected(); void onSetContainerAsStringRadioSelected(); From cad4f6980da26d8b695fb3b66bd5e7dc1990f191 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 7 Apr 2024 09:51:00 -0400 Subject: [PATCH 008/153] Save progress --- .../mission/dialogs/VariableDialogModel.cpp | 131 ++++++++++++++++-- .../src/mission/dialogs/VariableDialogModel.h | 18 ++- 2 files changed, 129 insertions(+), 20 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index a71217e9dd5..ae564fafdc4 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -6,6 +6,7 @@ namespace fso { namespace fred { namespace dialogs { + VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) : AbstractDialogModel(parent, viewport) { @@ -21,6 +22,9 @@ void VariableDialogModel::reject() void VariableDialogModel::apply() { + // TODO VALIDATE! + // TODO! Look for referenced varaibles and containers. + // We actually can't fully trust what the model says.... memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); for (int i = 0; i < static_cast(_variableItems.size()); ++i){ @@ -47,8 +51,7 @@ bool VariableDialogModel::getVariableType(SCP_string name) bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) { - // TODO! figure out the flag combination for network variable. - return (auto variable = lookupVariable(name)) ? (variable->string) : false; + return (auto variable = lookupVariable(name)) ? (variable->flags & SEXP_VARIABLE_NETWORK > 0) : false; } @@ -86,8 +89,8 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) { auto variable = lookupVariable(name); - // nothing to change - if (variable->string == string){ + // nothing to change, or invalid entry + if (!variable || variable->string == string){ return string; } @@ -153,50 +156,153 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) bool VariableDialogModel::setVariableNetworkStatus(SCP_string name, bool network) { - + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable){ + return false; + } + + // TODO! Look up setting + // if (network){ + // variable->flags |= LOLFLAG; + // } else { + // variable->flags + // } + return network; } int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(SCP_string name, int flags) { + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable){ + return 0; + } + + // TODO! Look up setting + + return flags; } bool VariableDialogModel::setVariableEternalFlag(SCP_string name, bool eternal) { - + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable){ + return false; + } + + // TODO! Look up setting + + + return eternal; } SCP_string VariableDialogModel::setVariableStringValue(SCP_string name, SCP_string value) { + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable || !variable->string){ + return ""; + } + variable->stringValue = value; } int VariableDialogModel::setVariableNumberValue(SCP_string name, int value) { + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable || variable->string){ + return 0; + } + variable->numberValue = value; } SCP_string VariableDialogModel::addNewVariable() { - + variableInfo* variable = nullptr; + int count = 0; + SCP_string name; + + do { + name = ""; + sprintf(&name, "", count); + variable = lookupVariable(); + ++count; + } while (variable != nullptr && count < 50); + + + if (variable){ + return ""; + } + + _variableItems.emplace_back(); + _variableItems.back().name = name; + return name; } SCP_string VariableDialogModel::changeVariableName(SCP_string oldName, SCP_string newName) { - + if (newName == "") { + return ""; + } + + auto variable = lookupVariable(oldName); + + // nothing to change, or invalid entry + if (!variable){ + return ""; + } + + // We cannot have two variables with the same name, but we need to check this somewhere else (like on accept attempt). + variable->name = newName; + return newName; } SCP_string VariableDialogModel::copyVariable(SCP_string name) { - -} + auto variable = lookupVariable(name); + // nothing to change, or invalid entry + if (!variable){ + return ""; + } + int count = 0; + variableInfo* variableCopy = nullptr; + + while (variableCopy == nullptr && count < 50){ + SCP_string newName; + sprintf(&newName, "%s%i", name, count); + variableCopy = lookupVariable(newName); + if (!variableCopy){ + _variableItems.emplace_back(); + _variableItems.back().name = newName; + return newName; + } + } +} // returns whether it succeeded -bool VariableDialogModel::removeVariable(SCP_string) +bool VariableDialogModel::removeVariable(SCP_string name) { - + auto variable = lookupVariable(name); + + // nothing to change, or invalid entry + if (!variable){ + return false; + } + + variable->deleted = true; + return true; } @@ -272,7 +378,6 @@ bool VariableDialogModel::removeContainer(SCP_string name) } - } // dialogs } // fred } // fso diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 92a1eb7ab1d..7b666ccbe67 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -8,8 +8,10 @@ namespace fso { namespace fred { namespace dialogs { -struct variable_info { +struct variableInfo { SCP_string name = ""; + SCP_string original_name = ""; + bool deleted = false; bool string = true; int flags = 0; int numberValue = 0; @@ -17,8 +19,10 @@ struct variable_info { }; -struct container_info { +struct containerInfo { SCP_string name = ""; + SCP_string original_name = ""; + bool deleted = false; bool map = false; bool string = true; int flags = 0; @@ -60,7 +64,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string changeVariableName(SCP_string oldName, SCP_string newName); SCP_string copyVariable(SCP_string name); // returns whether it succeeded - bool removeVariable(SCP_string); + bool removeVariable(SCP_string name); // Container Section @@ -87,10 +91,10 @@ class VariableDialogModel : public AbstractDialogModel { void reject() override; private: - SCP_vector _variableItems; - SCP_vector _containerItems; + SCP_vector _variableItems; + SCP_vector _containerItems; - const variable_info* lookupVariable(SCP_string name){ + const variableInfo* lookupVariable(SCP_string name){ for (int x = 0; x < static_cast(_varaibleItems.size()); ++x){ if (_varaibleItems[x].name == name){ return &_varaibleItems[x]; @@ -100,7 +104,7 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } - const container_info* lookupContainer(SCP_string name){ + const containerInfo* lookupContainer(SCP_string name){ for (int x = 0; x < static_cast(_containerItems.size()); ++x){ if (_containerItems[x].name == name){ return &_containerItems[x]; From 2827e93b2d8ff7ea6bdb53aef64e3206aecfb6c5 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 7 Apr 2024 16:36:29 -0400 Subject: [PATCH 009/153] Continue writing editor model functions Also, add a few declarations for List and Map contents editing. --- .../mission/dialogs/VariableDialogModel.cpp | 180 ++++++++++++++---- .../src/mission/dialogs/VariableDialogModel.h | 18 +- 2 files changed, 155 insertions(+), 43 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index ae564fafdc4..3b17203bf0c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -23,9 +23,12 @@ void VariableDialogModel::reject() void VariableDialogModel::apply() { // TODO VALIDATE! - // TODO! Look for referenced varaibles and containers. - // We actually can't fully trust what the model says.... - memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); + // TODO! Look for referenced variables and containers. + // Need a way to clean up references. I'm thinking making some pop ups to confirm replacements created in the editor. + // This means we need a way to count and replace references. + + // So, previously, I was just obliterating and overwriting, but I need to rethink this info. + /*memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); for (int i = 0; i < static_cast(_variableItems.size()); ++i){ Sexp_variables[i].type = _variableItems[i].flags; @@ -37,6 +40,7 @@ void VariableDialogModel::apply() strcpy_s(Sexp_variables[i].text, std::to_string(_variableItems[i].numberValue).c_str()) } } + */ // TODO! containers @@ -46,7 +50,7 @@ void VariableDialogModel::apply() // true on string, false on number bool VariableDialogModel::getVariableType(SCP_string name) { - return (auto variable = lookupVariable(name)) ? (variable->string) : false; + return (auto variable = lookupVariable(name)) ? (variable->string) : true; } bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) @@ -59,14 +63,26 @@ bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(SCP_string name) { - return (auto variable = lookupVariable(name)) ? (variable->flags) : 0; + auto variable = lookupVariable(name); + + if (!variable) { + return 0; + } + + int returnValue = 0; + + if (variable->flags & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE) + returnValue = 2; + else if (variable->flags & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS) + returnValue = 1; + + return returnValue; } bool VariableDialogModel::getVariableEternalFlag(SCP_string name) { - // TODO! figure out correct value for retrieving eternal. - return (auto variable = lookupVariable(name)) ? (variable->flags) : false; + return (auto variable = lookupVariable(name)) ? (variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE > 0) : false; } @@ -82,8 +98,6 @@ int VariableDialogModel::getVariableNumberValue(SCP_string name) -// TODO! Need a way to clean up references. - // true on string, false on number bool VariableDialogModel::setVariableType(SCP_string name, bool string) { @@ -94,10 +108,8 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) return string; } - //TODO! We need a way to detect the number of references, because then we could see if we need to warn - // about references. - // changing the type here! + // Here we change the variable type! // this variable is currently a string if (variable->string) { // no risk change, because no string was specified. @@ -131,7 +143,7 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) } else { // safe change because there was no number value specified if (variable->numberValue == 0){ - varaible->string = string; + variable->string = string; return variable->string; } else { SCP_string question; @@ -163,12 +175,11 @@ bool VariableDialogModel::setVariableNetworkStatus(SCP_string name, bool network return false; } - // TODO! Look up setting - // if (network){ - // variable->flags |= LOLFLAG; - // } else { - // variable->flags - // } + if (!(variable->flags & SEXP_VARIABLE_NETWORK) && network){ + variable->flags |= SEXP_VARIABLE_NETWORK; + } else { + variable->flags &= ~SEXP_VARIABLE_NETWORK; + } return network; } @@ -177,13 +188,19 @@ int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(SCP_string name auto variable = lookupVariable(name); // nothing to change, or invalid entry - if (!variable){ + if (!variable || flags < 0 || flags > 2){ return 0; } - // TODO! Look up setting + if (flags == 0) { + variable->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + } else if (flags == 1) { + variable->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + variable->flags |= SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS; + } else { + variable->flags |= (SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + } - return flags; } @@ -196,8 +213,11 @@ bool VariableDialogModel::setVariableEternalFlag(SCP_string name, bool eternal) return false; } - // TODO! Look up setting - + if (eternal) { + variable->flags |= SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; + } else { + variable->flags &= ~SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; + } return eternal; } @@ -229,15 +249,15 @@ int VariableDialogModel::setVariableNumberValue(SCP_string name, int value) SCP_string VariableDialogModel::addNewVariable() { variableInfo* variable = nullptr; - int count = 0; + int count = 1; SCP_string name; do { name = ""; - sprintf(&name, "", count); + sprintf(&name, "", count); variable = lookupVariable(); ++count; - } while (variable != nullptr && count < 50); + } while (variable != nullptr && count < 51); if (variable){ @@ -276,19 +296,36 @@ SCP_string VariableDialogModel::copyVariable(SCP_string name) return ""; } - int count = 0; - variableInfo* variableCopy = nullptr; + int count = 1; + variableInfo* variableSearch; - while (variableCopy == nullptr && count < 50){ + do { SCP_string newName; - sprintf(&newName, "%s%i", name, count); - variableCopy = lookupVariable(newName); - if (!variableCopy){ + sprintf(&newName, "%s_copy%i", name, count); + variableSearch = lookupVariable(newName); + + // open slot found! + if (!variableSearch){ + // create the new entry in the model _variableItems.emplace_back(); - _variableItems.back().name = newName; + + // and set everything as a copy from the original, except original name and deleted. + auto& newVariable = _variableItems.back(); + newVariable.name = newName; + newVariable.flags = variable.flags; + newVariable.string = variable.string; + + if (newVariable.string) { + newVariable.stringValue = variable.stringValue; + } else { + newVariable.numberValue = variable.numberValue; + } + return newName; } - } + } while (variableSearch != nullptr && count < 51); + + return ""; } // returns whether it succeeded @@ -301,6 +338,12 @@ bool VariableDialogModel::removeVariable(SCP_string name) return false; } + SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be replaced." + SCP_string info = ""; + if (!confirmAction(question, info)){ + return false; + } + variable->deleted = true; return true; } @@ -311,29 +354,40 @@ bool VariableDialogModel::removeVariable(SCP_string name) // true on string, false on number bool VariableDialogModel::getContainerValueType(SCP_string name) { - + return (auto container = lookupContainer(name)) ? container->string : true; } // true on list, false on map bool VariableDialogModel::getContainerListOrMap(SCP_string name) { - + return (auto contaner = lookupContainer(name)) ? container->list : true; } bool VariableDialogModel::getContainerNetworkStatus(SCP_string name) { - + return (auto container = lookupContainer(name)) ? (container->flags & SEXP_VARIABLE_NETWORK > 0) : false; } // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(SCP_string name) { - + auto container = lookupContainer(name); + + if (!container) { + return 0; + } + + if (container->flags & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE) + return 2; + else if (container->flags & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS) + return 1; + else + return 0; } bool VariableDialogModel::getContainerEternalFlag(SCP_string name) { - + return (auto container = lookupContainer(name)) ? (container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE > 0) : false; } @@ -349,17 +403,59 @@ bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) bool VariableDialogModel::setContainerNetworkStatus(SCP_string name, bool network) { - + auto container = lookupContainer(name); + + // nothing to change, or invalid entry + if (!container){ + return false; + } + + if (network) { + container->flags |= SEXP_VARIABLE_NETWORK; + } else { + container->flags &= ~SEXP_VARIABLE_NETWORK; + } + + return network; } int VariableDialogModel::setContainerOnMissionCloseOrCompleteFlag(SCP_string name, int flags) { + auto container = lookupContainer(name); + + // nothing to change, or invalid entry + if (!container || flags < 0 || flags > 2){ + return 0; + } + + if (flags == 0) { + container->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + } else if (flags == 1) { + container->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + container->flags |= SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS; + } else { + container->flags |= (SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + } + return flags; } bool VariableDialogModel::setContainerEternalFlag(SCP_string name, bool eternal) { - + auto container = lookupContainer(name); + + // nothing to change, or invalid entry + if (!container){ + return false; + } + + if (eternal) { + container->flags |= SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; + } else { + container->flags &= ~SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; + } + + return eternal; } SCP_string VariableDialogModel::addContainer() diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 7b666ccbe67..cae2762ef7b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -23,7 +23,7 @@ struct containerInfo { SCP_string name = ""; SCP_string original_name = ""; bool deleted = false; - bool map = false; + bool list = false; bool string = true; int flags = 0; @@ -87,6 +87,22 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string changeContainerName(SCP_string oldName, SCP_string newName); bool removeContainer(SCP_string name); + SCP_string addListItem(SCP_string containerName); + SCP_string addMapItem(SCP_string ContainerName); + + SCP_string copyStringListItem(SCP_string containerName, int index); + bool removeStringListItem(SCP_string containerName, int index); + int copyIntegerListItem(SCP_string containerName, int index); + int removeIntegerListItem(SCP_string containerName, int index); + + SCP_string copyMapItem(SCP_string containerName, SCP_string key); + bool removeMapItem(SCP_string containerName, SCP_string key); + + SCP_string replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey); + SCP_string changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue); + SCP_string changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue); + + bool apply() override; void reject() override; From 5575ab4c950482b7ec2370dbd6fe979ea87f4bd7 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 7 Apr 2024 23:37:25 -0400 Subject: [PATCH 010/153] Finish setContainerValueType And add stubs for other model functions we'll need --- .../mission/dialogs/VariableDialogModel.cpp | 131 +++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 3b17203bf0c..de164f78234 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -393,9 +393,84 @@ bool VariableDialogModel::getContainerEternalFlag(SCP_string name) bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) { - + auto container = lookupContainer(name); + + if (!container){ + return true; + } + + if (container->string == type){ + return container->string; + } + + if ((container->string && container->stringValues.empty()) || (!container->string && container->numberValues.empty())){ + container->string = type; + return container->type; + } + + // if the other list is not empty, then just convert. No need to confirm. + // The values will be there if they decide to switch back. + if (container->string && !container->numberValues.empty()){ + + container->string = type; + return container->string; + + } else if (!container->string && !container->stringValues.empty()){ + + container->string = type; + return container->string; + } + + // so when the other list *is* empty, then we can attempt to copy values. + if (container->string && container->numberValues.empty()){ + + SCP_string question = "Do you want to attempt conversion of these string values to number values?"; + SCP_string info = "Your string values will still be there if you convert this container back to string type."; + + if (confirmAction(question, info)) { + + bool transferable = true; + SCP_vector numbers; + + for (const auto& item : container->stringValues){ + try { + numbers.push_back(stoi(item)); + } + catch { + transferable = false; + break; + } + } + + if (transferable){ + container->numberValues = std::move(numbers); + } + } + + // now that we've handled value conversion, convert the container + container->string = type; + return container->string; + } else if (!container->string && container->stringValues.empty()){ + + SCP_string question = "Do you want to convert these number values to string values?"; + SCP_string info = "Your number values will still be there if you convert this container back to number type."; + + if (confirmAction(question, info)) { + for (const auto& item : container->numberValues){ + container->stringValues.emplace_back(item); + } + } + + // now that we've handled value conversion, convert the container + container->string = type; + return container->string; + } + + // we shouldn't get here, but if we do return the current value because that's what the model thinks, anyway. + return container->string; } +// this is the most complicated function. bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) { @@ -473,6 +548,60 @@ bool VariableDialogModel::removeContainer(SCP_string name) } +SCP_string VariableDialogModel::addListItem(SCP_string containerName) +{ + +} + +SCP_string VariableDialogModel::addMapItem(SCP_string ContainerName) +{ + +} + +SCP_string VariableDialogModel::copyStringListItem(SCP_string containerName, int index) +{ + +} + +bool VariableDialogModel::removeStringListItem(SCP_string containerName, int index) +{ + +} + +int VariableDialogModel::copyIntegerListItem(SCP_string containerName, int index) +{ + +} + +int VariableDialogModel::removeIntegerListItem(SCP_string containerName, int index) +{ + +} + +SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string key) +{ + +} + +bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key) +{ + +} + +SCP_string VariableDialogModel::replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey) +{ + +} + +SCP_string VariableDialogModel::changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue) +{ + +} + +SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue) +{ + +} } // dialogs } // fred From aea39664bab8eab54b5e171031b5be617383e3a6 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 8 Apr 2024 14:18:14 -0400 Subject: [PATCH 011/153] Add logic for addcontainer and a few other functions --- .../mission/dialogs/VariableDialogModel.cpp | 95 +++++++++++++++---- .../src/mission/dialogs/VariableDialogModel.h | 8 +- 2 files changed, 82 insertions(+), 21 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index de164f78234..5e3b3d57ef0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -255,7 +255,7 @@ SCP_string VariableDialogModel::addNewVariable() do { name = ""; sprintf(&name, "", count); - variable = lookupVariable(); + variable = lookupVariable(name); ++count; } while (variable != nullptr && count < 51); @@ -470,7 +470,7 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) return container->string; } -// this is the most complicated function. +// This is the most complicated function, because we need to query the user on what they want to do if the had already entered data. bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) { @@ -535,52 +535,115 @@ bool VariableDialogModel::setContainerEternalFlag(SCP_string name, bool eternal) SCP_string VariableDialogModel::addContainer() { - + containerInfo* container = nullptr; + int count = 1; + SCP_string name; + + do { + name = ""; + sprintf(&name, "", count); + container = lookupContainer(name); + ++count; + } while (container != nullptr && count < 51); + + if (container){ + return ""; + } + + _containerItems.emplace_back(); + _containerItems.back().name = name; + return name; } SCP_string VariableDialogModel::changeContainerName(SCP_string oldName, SCP_string newName) { - + if (newName == "") { + return ""; + } + + auto container = lookupContainer(oldName); + + // nothing to change, or invalid entry + if (!container){ + return ""; + } + + // We cannot have two containers with the same name, but we need to check this somewhere else (like on accept attempt). + container->name = newName; + return newName; } bool VariableDialogModel::removeContainer(SCP_string name) { - + auto container = lookupContainer(oldName); + + if (!container){ + return false; + } + + container->deleted = true; } SCP_string VariableDialogModel::addListItem(SCP_string containerName) { + auto container = lookupContainer(containerName); + if (!container){ + return ""; + } + + if (container->string) { + container->stringValues.emplace_back("New_Item"); + return container->stringValues.back(); + } else { + container->numberValues.push_back(0); + return "0"; + } } -SCP_string VariableDialogModel::addMapItem(SCP_string ContainerName) +std::pair VariableDialogModel::addMapItem(SCP_string ContainerName) { - + } -SCP_string VariableDialogModel::copyStringListItem(SCP_string containerName, int index) +SCP_string VariableDialogModel::copyListItem(SCP_string containerName, int index) { + auto container = lookupContainer(containerName); -} + if (!container || index < 0 || (cotainer->string && index >= static_cast(contaner->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + return ""; + } -bool VariableDialogModel::removeStringListItem(SCP_string containerName, int index) -{ + if (container->string) { + container->stringValues.push_back(container->stringValues[index]); + return container->stringValues.back(); + } else { + container->numberValues.push_back(container->numberValues[index]); + return "0"; + } } -int VariableDialogModel::copyIntegerListItem(SCP_string containerName, int index) +bool VariableDialogModel::removeListItem(SCP_string containerName, int index) { + auto container = lookupContainer(containerName); -} + if (!container || index < 0 || (cotainer->string && index >= static_cast(contaner->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + return false; + } -int VariableDialogModel::removeIntegerListItem(SCP_string containerName, int index) -{ + // Most efficient, given the situation (single deletions) + if (container->string) { + container->stringValues.erase(container->stringValues.begin() + index); + } else { + container->numberValues.erase(container->numberValues.begin() + index); + } } SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string key) { - + for (const auto& ) } bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index cae2762ef7b..4afd81a62d9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -88,13 +88,11 @@ class VariableDialogModel : public AbstractDialogModel { bool removeContainer(SCP_string name); SCP_string addListItem(SCP_string containerName); - SCP_string addMapItem(SCP_string ContainerName); - SCP_string copyStringListItem(SCP_string containerName, int index); - bool removeStringListItem(SCP_string containerName, int index); - int copyIntegerListItem(SCP_string containerName, int index); - int removeIntegerListItem(SCP_string containerName, int index); + SCP_string copyListItem(SCP_string containerName, int index); + bool removeListItem(SCP_string containerName, int index); + SCP_string addMapItem(SCP_string ContainerName); SCP_string copyMapItem(SCP_string containerName, SCP_string key); bool removeMapItem(SCP_string containerName, SCP_string key); From fa27b8d133072f21e78836258b9d56aa8351af6a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 10 Apr 2024 01:38:48 -0400 Subject: [PATCH 012/153] MOAR FUNCTIONS! --- .../mission/dialogs/VariableDialogModel.cpp | 140 +++++++++++++++++- .../src/mission/dialogs/VariableDialogModel.h | 2 +- 2 files changed, 139 insertions(+), 3 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 5e3b3d57ef0..b062b7bbdb6 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -641,29 +641,165 @@ bool VariableDialogModel::removeListItem(SCP_string containerName, int index) } -SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string key) +SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string keyIn) { - for (const auto& ) + auto container = lookupContainer(containerName); + + if (!container) { + return ""; + } + + for (int x = 0; x < static_cast(container->keys.size()); ++x) { + if (container->keys[x] == keyIn){ + if (container->string){ + if (x < static_cast(container->stringValues.size())){ + SCP_string copyValue = container->stringValues[x]; + SCP_string newKey; + int size = static_cast(container->keys.size()); + sprintf(&newKey, "key%i", size); + + bool found = false; + + do { + found = false; + for (y = 0; y < static_cast(container->keys.size()); ++y){ + if (container->keys[y] == newKey) { + found = true; + break; + } + } + + // attempt did not work, try next number + if (found) { + ++size; + newKey = ""; + sprintf(&newKey, "key%i", size); + } + + } while (found && size < static_cast(container->keys.size()) + 100) + + // we could not generate a new key .... somehow. + if (found){ + return ""; + } + + container->keys.push_back(newKey); + container->keys.push_back(copyValue); + + return std::make_pair(newKey, copyValue); + + } else { + return ""; + } + } else { + // TODO! Make the number value version. + } + + + + } + } } +// it's really because of this feature that we need data to only be in one or the other vector for maps. +// If we attempted to maintain data automatically and there was a deletion, deleting the data in +// both of the map's data vectors might be undesired, and not deleting takes the map immediately +// out of sync. Also, just displaying both data sets would be misleading. +// We just need to tell the user that the data cannot be maintained. bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key) { + auto container = lookupContainer(containerName); + if (!container){ + return false; + } + + for (int x = 0; x < static_cast(container->keys.size()); ++x) { + if (container->keys[x] == key) { + if ((container->string && x < static_cast(container->stringValues.size())) { + container->stringValues.erase(container->stringValues.begin() + x); + } else if (!container->string && x < static_cast(container->numberValues.size()))){ + container->numberValues.erase(container->numberValues.begin() + x); + } else { + return false; + } + + // if we get here, we've succeeded and it's time to bug out + container->keys.erase(container->keys.begin() + x); + // "I'm outta here!" + return true; + } + } + + // NO SPRINGS!!! HEHEHEHEHE + return false; } SCP_string VariableDialogModel::replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey) { + auto container = lookupContainer(containerName); + if (!container){ + return ""; + } + + for (auto& key : container->keys){ + if (key == oldKey) { + key = newKey; + return newKey; + } + } + + // Failure + return oldKey; } SCP_string VariableDialogModel::changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue) { + auto container = lookupContainer(containerName); + + if (!container || !container->string){ + return ""; + } + + for (int x = 0; x < static_cast(container->keys); ++x){ + if (container->keys[x] == oldKey) { + if (x < static_cast(container->stringValues.size())){ + container->stringValues[x] = newValue; + return newValue; + } else { + return ""; + } + } + } + // Failure + return ""; } SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue) { + auto container = lookupContainer(containerName); + + if (!container || !container->string){ + return ""; + } + for (int x = 0; x < static_cast(container->keys); ++x){ + if (container->keys[x] == oldKey) { + if (x < static_cast(container->numberValues.size())){ + container->numberValues[x] = newValue; + SCP_string returnValue; + sprintf(&returnValue, "%i", newValue) + return returnValue; + } else { + return ""; + } + } + } + + // Failure + return ""; } } // dialogs diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 4afd81a62d9..3f6514f7398 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -93,7 +93,7 @@ class VariableDialogModel : public AbstractDialogModel { bool removeListItem(SCP_string containerName, int index); SCP_string addMapItem(SCP_string ContainerName); - SCP_string copyMapItem(SCP_string containerName, SCP_string key); + std::pair copyMapItem(SCP_string containerName, SCP_string key); bool removeMapItem(SCP_string containerName, SCP_string key); SCP_string replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey); From d665c618c1feac48e5c13b596115100d01d7454f Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 11 Apr 2024 15:12:16 -0400 Subject: [PATCH 013/153] Starting progress on initializeData And container functions --- .../mission/dialogs/VariableDialogModel.cpp | 179 +++++++++++++++++- .../src/mission/dialogs/VariableDialogModel.h | 12 +- 2 files changed, 185 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index b062b7bbdb6..0f0c858eb0a 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -47,6 +47,50 @@ void VariableDialogModel::apply() } +void initializeData() +{ + _variableItems.clear(); + _containerItems.clear(); + + for (int i = 0; i < static_cast(_variableItems.size()); ++i){ + if (strlen(Sexp_variables[i].text)) { + _variableItems.emplace_back(); + auto& item = _variableItems.back(); + item.name = Sexp_variables[i].variable_name; + item.originalName = item.name; + + if (Sexp_variables[i].type & SEXP_VARIABLE_STRING) { + item.string = true; + item.stringValue = Sexp_variables[i].text; + item.numberValue = 0; + } else { + item.string = false; + + Sexp_variables[i].text; + try { + item.numberValue = std::stoi(Sexp_variables[i].text) + } + catch{ + item.numberValue = 0; + // TODO! Warning popup + } + + item.stringValue = ""; + } + } + } + + const auto& containers = get_all_sexp_containers(); + + for (const auto& container : containers) { + if + + _containerItems + } +} + + + // true on string, false on number bool VariableDialogModel::getVariableType(SCP_string name) { @@ -684,7 +728,7 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string } container->keys.push_back(newKey); - container->keys.push_back(copyValue); + container->stringValues.push_back(copyValue); return std::make_pair(newKey, copyValue); @@ -692,11 +736,46 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string return ""; } } else { - // TODO! Make the number value version. - } + if (x < static_cast(container->numberVales.size())){ + int copyValue = container->numberVales[x]; + SCP_string newKey; + int size = static_cast(container->keys.size()); + sprintf(&newKey, "key%i", size); + + bool found = false; + do { + found = false; + for (y = 0; y < static_cast(container->keys.size()); ++y){ + if (container->keys[y] == newKey) { + found = true; + break; + } + } + + // attempt did not work, try next number + if (found) { + ++size; + newKey = ""; + sprintf(&newKey, "key%i", size); + } + } while (found && size < static_cast(container->keys.size()) + 100) + + // we could not generate a new key .... somehow. + if (found){ + return ""; + } + container->keys.push_back(newKey); + container->numberValues.push_back(copyValue); + + return std::make_pair(newKey, copyValue); + + } else { + return ""; + } + } } } } @@ -802,6 +881,100 @@ SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerNam return ""; } +// These functions should only be called when the container is guaranteed to exist! +const SCP_vector& VariableDialogModel::getMapKeys(SCP_string containerName) +{ + auto container = lookupContainer(containerName); + + if (!container) { + throw std::invalid_argument("getMapKeys() found that container %s does not exist.", containerName.c_str()); + } + + if (container->list) { + throw std::invalid_argument("getMapKeys() found that container %s is not a map.", containerName.c_str()); + } + + return containerName->keys; +} + +// Only call when the container is guaranteed to exist! +const SCP_vector& VariableDialogModel::getStringValues(SCP_string containerName) +{ + auto container = lookupContainer(containerName); + + if (!container) { + throw std::invalid_argument("getStringValues() found that container %s does not exist.", containerName.c_str()); + } + + if (!container->string) { + throw std::invalid_argument("getStringValues() found that container %s does not store strings.", containerName.c_str()); + } + + return containerName->stringValues; +} + +// Only call when the container is guaranteed to exist! +const SCP_vector& VariableDialogModel::getNumberValues(SCP_string containerName) +{ + auto container = lookupContainer(containerName); + + if (!container) { + throw std::invalid_argument("getNumberValues() found that container %s does not exist.", containerName.c_str()); + } + + if (container->string) { + throw std::invalid_argument("getNumberValues() found that container %s does not store numbers.", containerName.c_str()); + } + + return containerName->numberValues; +} + +const SCP_vector VariableDialogModel::getVariableValues() +{ + SCP_vector outStrings; + + for (const auto& item : _variableItems) { + SCP_string notes = ""; + + if (item.deleted) { + notes = "Marked for Deletion"; + } else if (item.originalName == "") { + notes = "New"; + } else if (item.name != item.originalName){ + notes = "Renamed"; + } else if (item.string && item.stringValue = "") { + notes = "Defaulting to empty string"; + } + + outStrings.emplace_back(item.name, (item.string) ? item.stringValue : SCP_string(item.numberValue), notes); + } + + return outStrings; +} + + +const SCP_vector> VarigableDialogModel::getContainerNames() +{ + SCP_vector> outStrings; + + for (const auto& item : _containerItems) { + SCP_string notes = ""; + + if (item.deleted) { + notes = "Marked for Deletion"; + } else if (item.originalName == "") { + notes = "New"; + } else if (item.name != item.originalName){ + notes = "Renamed"; + } + + outStrings.emplace_back(item.name, notes); + } + + return outStrings; +} + + } // dialogs } // fred } // fso diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 3f6514f7398..53c1c451947 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -10,7 +10,7 @@ namespace dialogs { struct variableInfo { SCP_string name = ""; - SCP_string original_name = ""; + SCP_string originalName = ""; bool deleted = false; bool string = true; int flags = 0; @@ -21,9 +21,9 @@ struct variableInfo { struct containerInfo { SCP_string name = ""; - SCP_string original_name = ""; + SCP_string originalName = ""; bool deleted = false; - bool list = false; + bool list = true; bool string = true; int flags = 0; @@ -100,6 +100,12 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue); SCP_string changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue); + const SCP_vector& getMapKeys(SCP_string containerName); + const SCP_vector& getStringValues(SCP_string containerName); + const SCP_vector& getNumberValues(SCP_string containerName); + + const SCP_vector VariableDialogModel::getVariableValues(); + const SCP_vector> VarigableDialogModel::getContainerNames(); bool apply() override; void reject() override; From de54dea61acc5b8fcdf2beb0b9aacf7e59133541 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 11 Apr 2024 22:29:21 -0400 Subject: [PATCH 014/153] save progress --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 0f0c858eb0a..fe312c07c9c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -83,9 +83,16 @@ void initializeData() const auto& containers = get_all_sexp_containers(); for (const auto& container : containers) { - if + _containerItems.emplace_back(); + auto& newContainer = _containerItems.back(); + + newContainer.name = container.container_name; + newContainer.originalName = newContainer.name; + newContainer.deleted = false; + + newContainer.string = container.C + newContainer.list = container.is_list; - _containerItems } } From a125b8b3ceb8c5e2ea636c7bada7c50c3c5f7285 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 12 Apr 2024 00:58:37 -0400 Subject: [PATCH 015/153] Fixup the Variables Dialog Add it to the editor menu (with shortcut), and fix it showing up when started --- qtfred/src/ui/FredView.cpp | 2 +- qtfred/src/ui/FredView.h | 2 +- qtfred/ui/FredView.ui | 12 + qtfred/ui/VariableDialog.ui | 747 +++++++++++++++++++----------------- 4 files changed, 414 insertions(+), 349 deletions(-) diff --git a/qtfred/src/ui/FredView.cpp b/qtfred/src/ui/FredView.cpp index 1ca3e5e7cbf..81001acb97e 100644 --- a/qtfred/src/ui/FredView.cpp +++ b/qtfred/src/ui/FredView.cpp @@ -752,7 +752,7 @@ void FredView::on_actionLoadout_triggered(bool) { auto editorDialog = new dialogs::LoadoutDialog(this, _viewport); editorDialog->show(); } -void FredView::on_actionVariablesAndContainers_triggered(bool) { +void FredView::on_actionVariables_triggered(bool) { auto editorDialog = new dialogs::VariableDialog(this, _viewport); editorDialog->show(); } diff --git a/qtfred/src/ui/FredView.h b/qtfred/src/ui/FredView.h index b11bfbfa0a3..d63095f02dd 100644 --- a/qtfred/src/ui/FredView.h +++ b/qtfred/src/ui/FredView.h @@ -91,7 +91,7 @@ class FredView: public QMainWindow, public IDialogProvider { void on_actionCommand_Briefing_triggered(bool); void on_actionReinforcements_triggered(bool); void on_actionLoadout_triggered(bool); - void on_actionVariablesAndContainers_triggered(bool); + void on_actionVariables_triggered(bool); void on_actionSelectionLock_triggered(bool enabled); diff --git a/qtfred/ui/FredView.ui b/qtfred/ui/FredView.ui index eca5d7c11de..9ffff9762ad 100644 --- a/qtfred/ui/FredView.ui +++ b/qtfred/ui/FredView.ui @@ -166,6 +166,7 @@ + @@ -1474,6 +1475,17 @@ Shift+G + + + &Variables + + + Open Variables and Containers Editor + + + Shift+V + + diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index b3e99e727a6..b85a2fc68a9 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -1,425 +1,478 @@ - fso::fred::dialogs::VariableDialog - + fso::fred::dialogs::VariableEditorDialog + 0 0 - 589 - 608 + 600 + 649 + + + 600 + 640 + + Fiction Viewer Editor - - - - - 0 - 325 - - - - Containers - - - - - 10 - 30 - 231 - 121 - - - - - - - 10 - 160 - 331 - 161 - - - - Contents - - - - - 10 - 30 - 221 - 121 - - - - - - - 240 - 30 - 81 - 121 - + + + + + + QLayout::SetMaximumSize - - - - - Add - - - - - - - - 8 - - - - Delete - - - - - - - - - - 250 - 30 - 81 - 121 - - - - - - Add + + + Qt::Horizontal - + + + 40 + 20 + + + - + - 8 + 12 - Delete + Variables and Containers Editor - - - - - - 360 - 180 - 201 - 141 - - - - Options - - - - - 0 - 20 - 201 - 121 - - - - - - - Save on Mission Close - - - - - - - Save on Mission Completed - - - - - - - Network-Variable - - - - - - - Eternal - - - - - - - - - - 359 - 18 - 201 - 151 - - - - - - Container Type + + + Qt::Horizontal - - - - 0 - 20 - 201 - 52 - - - - - - - Map - - - - - - - List - - - - - - - - - - - Data Type + + + 40 + 20 + - - - - 0 - 20 - 201 - 52 - - - - - - - String - - - - - - - Number - - - - - - + - - - - - - - - 0 - 230 - - - - Variables - - - - - 260 - 30 - 175 - 61 - - - - - - - Add Variable + + + + + + 0 + 380 + + + + Containers + + + + + 10 + 30 + 231 + 131 + + + + + + + 10 + 170 + 341 + 191 + + + + Contents + + + + + 10 + 30 + 221 + 151 + - - - - - Delete Variable and References + + + + 240 + 30 + 91 + 91 + - - - - - - - - 260 - 100 - 301 - 121 - - - - Options - - - - - 0 - 20 - 301 - 101 - - - - - + - + - String + Add Data - + - Number + Copy Data - + + + + 8 + + - Network-Variable + Delete Data - - - + + + + + + 250 + 40 + 97 + 91 + + + + + + + Add Container + + + + + + + Copy Container + + + + + + + + 8 + + + + Delete Container + + + + + + + + + 360 + 20 + 211 + 141 + + + + Persistence Options + + + + + 10 + 20 + 201 + 121 + + + - + Save on Mission Close - + Save on Mission Completed - + Eternal + + + + Network-Variable + + + - - + + + + + + 360 + 170 + 211 + 191 + + + + Type Options + + + + + 10 + 20 + 201 + 152 + + + + + + + Container Type + + + + + + + + + List + + + + + + + Map + + + + + + + + + Key Type + + + + + + + + + Number + + + + + + + String + + + + + + + + + Data Type + + + + + + + + + Number + + + + + + + String + + + + + + + + - - - - - 10 - 30 - 241 - 191 - - - - - - - - - QLayout::SetMaximumSize - - - - - Qt::Horizontal - - + + + + - 40 - 20 + 0 + 230 - - - - - - - 12 - - - - Variables and Containers Editor + + Variables + + + + 260 + 100 + 311 + 121 + + + + Options + + + + + 10 + 20 + 300 + 101 + + + + + + + + + String + + + + + + + Number + + + + + + + Network-Variable + + + + + + + + + + + Save on Mission Close + + + + + + + Save on Mission Completed + + + + + + + Eternal + + + + + + + + + + + + 10 + 30 + 241 + 191 + + + + + + + 270 + 38 + 301 + 51 + + + + + + + Add Variable + + + + + + + Copy Variable + + + + + + + Delete Variable + + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - - From e1ed5fdd78d4cf532f18e7569f216d939533df68 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 12 Apr 2024 00:59:29 -0400 Subject: [PATCH 016/153] Fixes to allow building Edits were previously done on a machine that could not build or use a linter. --- .../mission/dialogs/VariableDialogModel.cpp | 181 ++++++++++-------- .../src/mission/dialogs/VariableDialogModel.h | 20 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 7 +- qtfred/src/ui/dialogs/VariableDialog.h | 4 +- 4 files changed, 123 insertions(+), 89 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index fe312c07c9c..28b4f09bed7 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -20,7 +20,7 @@ void VariableDialogModel::reject() } -void VariableDialogModel::apply() +bool VariableDialogModel::apply() { // TODO VALIDATE! // TODO! Look for referenced variables and containers. @@ -44,10 +44,10 @@ void VariableDialogModel::apply() // TODO! containers - + return false; } -void initializeData() +void VariableDialogModel::initializeData() { _variableItems.clear(); _containerItems.clear(); @@ -68,9 +68,9 @@ void initializeData() Sexp_variables[i].text; try { - item.numberValue = std::stoi(Sexp_variables[i].text) + item.numberValue = std::stoi(Sexp_variables[i].text); } - catch{ + catch (...) { item.numberValue = 0; // TODO! Warning popup } @@ -90,8 +90,9 @@ void initializeData() newContainer.originalName = newContainer.name; newContainer.deleted = false; - newContainer.string = container.C - newContainer.list = container.is_list; + // TODO FIXME! + newContainer.string = false; + newContainer.list = container.is_list(); } } @@ -101,12 +102,14 @@ void initializeData() // true on string, false on number bool VariableDialogModel::getVariableType(SCP_string name) { - return (auto variable = lookupVariable(name)) ? (variable->string) : true; + auto variable = lookupVariable(name); + return (variable) ? (variable->string) : true; } bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) { - return (auto variable = lookupVariable(name)) ? (variable->flags & SEXP_VARIABLE_NETWORK > 0) : false; + auto variable = lookupVariable(name); + return (variable) ? ((variable->flags & SEXP_VARIABLE_NETWORK) > 0) : false; } @@ -133,18 +136,21 @@ int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(SCP_string name bool VariableDialogModel::getVariableEternalFlag(SCP_string name) { - return (auto variable = lookupVariable(name)) ? (variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE > 0) : false; + auto variable = lookupVariable(name); + return (variable) ? ((variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; } SCP_string VariableDialogModel::getVariableStringValue(SCP_string name) { - return ((auto variable = lookupVariable(name)) && variable->string) ? (variable->stringValue) : ""; + auto variable = lookupVariable(name); + return (variable && variable->string) ? (variable->stringValue) : ""; } int VariableDialogModel::getVariableNumberValue(SCP_string name) { - return ((auto variable = lookupVariable(name)) && !variable->string) ? (variable->numberValue) : 0; + auto variable = lookupVariable(name); + return (variable && !variable->string) ? (variable->numberValue) : 0; } @@ -169,12 +175,12 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) return variable->string; } else { SCP_string question; - sprintf(&question, "Changing variable %s to number variable type will make its string value irrelevant. Continue?", variable->name.c_st()); + sprintf(question, "Changing variable %s to number variable type will make its string value irrelevant. Continue?", variable->name.c_str()); SCP_string info; - sprintf(&info, "If the string cleanly converts to an integer and a number has not previously been set for this variable, the converted number value will be retained.") + sprintf(info, "If the string cleanly converts to an integer and a number has not previously been set for this variable, the converted number value will be retained."); // if this was a misclick, let the user say so - if (!confirmAction(question)) { + if (!confirmAction(question, info)) { return variable->string; } @@ -184,7 +190,7 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) variable->numberValue = std::stoi(variable->stringValue); } // nothing to do here, because that just means we can't convert. - catch {} + catch (...) {} } return string; @@ -198,18 +204,18 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) return variable->string; } else { SCP_string question; - sprintf(&question, "Changing variable %s to a string variable type will make the number value irrelevant. Continue?", variable->name.c_st()); + sprintf(question, "Changing variable %s to a string variable type will make the number value irrelevant. Continue?", variable->name.c_str()); SCP_string info; - sprintf(&info, "If no string value has been previously set for this variable, then the number value specified will be set as the default string value.") + sprintf(info, "If no string value has been previously set for this variable, then the number value specified will be set as the default string value."); // if this was a misclick, let the user say so - if (!confirmAction(question)) { + if (!confirmAction(question, info)) { return variable->string; } // if there was no previous string value if (variable->stringValue == ""){ - sprintf(&variable->stringValue, "%i", variable->numberValue); + sprintf(variable->stringValue, "%i", variable->numberValue); } return string; @@ -305,7 +311,7 @@ SCP_string VariableDialogModel::addNewVariable() do { name = ""; - sprintf(&name, "", count); + sprintf(name, "", count); variable = lookupVariable(name); ++count; } while (variable != nullptr && count < 51); @@ -352,7 +358,7 @@ SCP_string VariableDialogModel::copyVariable(SCP_string name) do { SCP_string newName; - sprintf(&newName, "%s_copy%i", name, count); + sprintf(newName, "%s_copy%i", name, count); variableSearch = lookupVariable(newName); // open slot found! @@ -363,13 +369,13 @@ SCP_string VariableDialogModel::copyVariable(SCP_string name) // and set everything as a copy from the original, except original name and deleted. auto& newVariable = _variableItems.back(); newVariable.name = newName; - newVariable.flags = variable.flags; - newVariable.string = variable.string; + newVariable.flags = variableSearch->flags; + newVariable.string = variableSearch->string; if (newVariable.string) { - newVariable.stringValue = variable.stringValue; + newVariable.stringValue = variableSearch->stringValue; } else { - newVariable.numberValue = variable.numberValue; + newVariable.numberValue = variableSearch->numberValue; } return newName; @@ -389,7 +395,7 @@ bool VariableDialogModel::removeVariable(SCP_string name) return false; } - SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be replaced." + SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be replaced."; SCP_string info = ""; if (!confirmAction(question, info)){ return false; @@ -405,18 +411,21 @@ bool VariableDialogModel::removeVariable(SCP_string name) // true on string, false on number bool VariableDialogModel::getContainerValueType(SCP_string name) { - return (auto container = lookupContainer(name)) ? container->string : true; + auto container = lookupContainer(name); + return (container) ? container->string : true; } // true on list, false on map bool VariableDialogModel::getContainerListOrMap(SCP_string name) { - return (auto contaner = lookupContainer(name)) ? container->list : true; + auto container = lookupContainer(name); + return (container) ? container->list : true; } bool VariableDialogModel::getContainerNetworkStatus(SCP_string name) { - return (auto container = lookupContainer(name)) ? (container->flags & SEXP_VARIABLE_NETWORK > 0) : false; + auto container = lookupContainer(name); + return (container) ? ((container->flags & SEXP_VARIABLE_NETWORK) > 0) : false; } // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) @@ -438,7 +447,8 @@ int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(SCP_string nam bool VariableDialogModel::getContainerEternalFlag(SCP_string name) { - return (auto container = lookupContainer(name)) ? (container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE > 0) : false; + auto container = lookupContainer(name); + return (container) ? ((container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; } @@ -456,7 +466,7 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) if ((container->string && container->stringValues.empty()) || (!container->string && container->numberValues.empty())){ container->string = type; - return container->type; + return container->string; } // if the other list is not empty, then just convert. No need to confirm. @@ -487,7 +497,7 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) try { numbers.push_back(stoi(item)); } - catch { + catch(...) { transferable = false; break; } @@ -508,7 +518,7 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) if (confirmAction(question, info)) { for (const auto& item : container->numberValues){ - container->stringValues.emplace_back(item); + container->stringValues.emplace_back(std::to_string(item)); } } @@ -524,7 +534,7 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) // This is the most complicated function, because we need to query the user on what they want to do if the had already entered data. bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) { - + return false; } bool VariableDialogModel::setContainerNetworkStatus(SCP_string name, bool network) @@ -592,7 +602,7 @@ SCP_string VariableDialogModel::addContainer() do { name = ""; - sprintf(&name, "", count); + sprintf(name, "", count); container = lookupContainer(name); ++count; } while (container != nullptr && count < 51); @@ -626,7 +636,7 @@ SCP_string VariableDialogModel::changeContainerName(SCP_string oldName, SCP_stri bool VariableDialogModel::removeContainer(SCP_string name) { - auto container = lookupContainer(oldName); + auto container = lookupContainer(name); if (!container){ return false; @@ -661,7 +671,7 @@ SCP_string VariableDialogModel::copyListItem(SCP_string containerName, int index { auto container = lookupContainer(containerName); - if (!container || index < 0 || (cotainer->string && index >= static_cast(contaner->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ return ""; } @@ -679,7 +689,7 @@ bool VariableDialogModel::removeListItem(SCP_string containerName, int index) { auto container = lookupContainer(containerName); - if (!container || index < 0 || (cotainer->string && index >= static_cast(contaner->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ return false; } @@ -692,12 +702,12 @@ bool VariableDialogModel::removeListItem(SCP_string containerName, int index) } -SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string keyIn) +std::pair VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string keyIn) { auto container = lookupContainer(containerName); if (!container) { - return ""; + return std::make_pair("", ""); } for (int x = 0; x < static_cast(container->keys.size()); ++x) { @@ -707,13 +717,13 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string SCP_string copyValue = container->stringValues[x]; SCP_string newKey; int size = static_cast(container->keys.size()); - sprintf(&newKey, "key%i", size); + sprintf(newKey, "key%i", size); bool found = false; do { found = false; - for (y = 0; y < static_cast(container->keys.size()); ++y){ + for (int y = 0; y < static_cast(container->keys.size()); ++y){ if (container->keys[y] == newKey) { found = true; break; @@ -724,14 +734,14 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string if (found) { ++size; newKey = ""; - sprintf(&newKey, "key%i", size); + sprintf(newKey, "key%i", size); } - } while (found && size < static_cast(container->keys.size()) + 100) + } while (found && size < static_cast(container->keys.size()) + 100); // we could not generate a new key .... somehow. if (found){ - return ""; + return std::make_pair("", ""); } container->keys.push_back(newKey); @@ -740,20 +750,20 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string return std::make_pair(newKey, copyValue); } else { - return ""; + return std::make_pair("", ""); } } else { - if (x < static_cast(container->numberVales.size())){ - int copyValue = container->numberVales[x]; + if (x < static_cast(container->numberValues.size())){ + int copyValue = container->numberValues[x]; SCP_string newKey; int size = static_cast(container->keys.size()); - sprintf(&newKey, "key%i", size); + sprintf(newKey, "key%i", size); bool found = false; do { found = false; - for (y = 0; y < static_cast(container->keys.size()); ++y){ + for (int y = 0; y < static_cast(container->keys.size()); ++y){ if (container->keys[y] == newKey) { found = true; break; @@ -764,23 +774,26 @@ SCP_string VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string if (found) { ++size; newKey = ""; - sprintf(&newKey, "key%i", size); + sprintf(newKey, "key%i", size); } - } while (found && size < static_cast(container->keys.size()) + 100) + } while (found && size < static_cast(container->keys.size()) + 100); // we could not generate a new key .... somehow. if (found){ - return ""; + return std::make_pair("", ""); } container->keys.push_back(newKey); container->numberValues.push_back(copyValue); - return std::make_pair(newKey, copyValue); + SCP_string temp; + sprintf(temp, "%i", copyValue); + + return std::make_pair(newKey, temp); } else { - return ""; + return std::make_pair("", ""); } } } @@ -802,9 +815,9 @@ bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key for (int x = 0; x < static_cast(container->keys.size()); ++x) { if (container->keys[x] == key) { - if ((container->string && x < static_cast(container->stringValues.size())) { + if (container->string && x < static_cast(container->stringValues.size())) { container->stringValues.erase(container->stringValues.begin() + x); - } else if (!container->string && x < static_cast(container->numberValues.size()))){ + } else if (!container->string && x < static_cast(container->numberValues.size())){ container->numberValues.erase(container->numberValues.begin() + x); } else { return false; @@ -848,8 +861,8 @@ SCP_string VariableDialogModel::changeMapItemStringValue(SCP_string containerNam return ""; } - for (int x = 0; x < static_cast(container->keys); ++x){ - if (container->keys[x] == oldKey) { + for (int x = 0; x < static_cast(container->keys.size()); ++x){ + if (container->keys[x] == key) { if (x < static_cast(container->stringValues.size())){ container->stringValues[x] = newValue; return newValue; @@ -871,12 +884,12 @@ SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerNam return ""; } - for (int x = 0; x < static_cast(container->keys); ++x){ - if (container->keys[x] == oldKey) { + for (int x = 0; x < static_cast(container->keys.size()); ++x){ + if (container->keys[x] == key) { if (x < static_cast(container->numberValues.size())){ container->numberValues[x] = newValue; SCP_string returnValue; - sprintf(&returnValue, "%i", newValue) + sprintf(returnValue, "%i", newValue); return returnValue; } else { return ""; @@ -894,14 +907,18 @@ const SCP_vector& VariableDialogModel::getMapKeys(SCP_string contain auto container = lookupContainer(containerName); if (!container) { - throw std::invalid_argument("getMapKeys() found that container %s does not exist.", containerName.c_str()); + SCP_string temp; + sprintf("getMapKeys() found that container %s does not exist.", containerName.c_str()); + throw std::invalid_argument(temp.c_str()); } if (container->list) { - throw std::invalid_argument("getMapKeys() found that container %s is not a map.", containerName.c_str()); + SCP_string temp; + sprintf("getMapKeys() found that container %s is not a map.", containerName.c_str()); + throw std::invalid_argument(temp); } - return containerName->keys; + return container->keys; } // Only call when the container is guaranteed to exist! @@ -910,14 +927,18 @@ const SCP_vector& VariableDialogModel::getStringValues(SCP_string co auto container = lookupContainer(containerName); if (!container) { - throw std::invalid_argument("getStringValues() found that container %s does not exist.", containerName.c_str()); + SCP_string temp; + sprintf("getStringValues() found that container %s does not exist.", containerName.c_str()); + throw std::invalid_argument(temp); } if (!container->string) { - throw std::invalid_argument("getStringValues() found that container %s does not store strings.", containerName.c_str()); + SCP_string temp; + sprintf("getStringValues() found that container %s does not store strings.", containerName.c_str()); + throw std::invalid_argument(temp); } - return containerName->stringValues; + return container->stringValues; } // Only call when the container is guaranteed to exist! @@ -926,19 +947,23 @@ const SCP_vector& VariableDialogModel::getNumberValues(SCP_string container auto container = lookupContainer(containerName); if (!container) { - throw std::invalid_argument("getNumberValues() found that container %s does not exist.", containerName.c_str()); + SCP_string temp; + sprintf("getNumberValues() found that container %s does not exist.", containerName.c_str()); + throw std::invalid_argument(temp); } if (container->string) { - throw std::invalid_argument("getNumberValues() found that container %s does not store numbers.", containerName.c_str()); + SCP_string temp; + sprintf("getNumberValues() found that container %s does not store numbers.", containerName.c_str()); + throw std::invalid_argument(temp); } - return containerName->numberValues; + return container->numberValues; } -const SCP_vector VariableDialogModel::getVariableValues() +const SCP_vector> VariableDialogModel::getVariableValues() { - SCP_vector outStrings; + SCP_vector> outStrings; for (const auto& item : _variableItems) { SCP_string notes = ""; @@ -949,18 +974,20 @@ const SCP_vector VariableDialogMo notes = "New"; } else if (item.name != item.originalName){ notes = "Renamed"; - } else if (item.string && item.stringValue = "") { + } else if (item.string && item.stringValue == "") { notes = "Defaulting to empty string"; } - outStrings.emplace_back(item.name, (item.string) ? item.stringValue : SCP_string(item.numberValue), notes); + SCP_string temp; + sprintf(temp, "%i", item.numberValue); + outStrings.emplace_back(item.name, (item.string) ? item.stringValue : temp, notes); } return outStrings; } -const SCP_vector> VarigableDialogModel::getContainerNames() +const SCP_vector> VariableDialogModel::getContainerNames() { SCP_vector> outStrings; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 53c1c451947..adff7308548 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -3,6 +3,7 @@ #include "globalincs/pstypes.h" #include "AbstractDialogModel.h" +#include namespace fso { namespace fred { @@ -92,7 +93,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string copyListItem(SCP_string containerName, int index); bool removeListItem(SCP_string containerName, int index); - SCP_string addMapItem(SCP_string ContainerName); + std::pair addMapItem(SCP_string ContainerName); std::pair copyMapItem(SCP_string containerName, SCP_string key); bool removeMapItem(SCP_string containerName, SCP_string key); @@ -104,27 +105,28 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector& getStringValues(SCP_string containerName); const SCP_vector& getNumberValues(SCP_string containerName); - const SCP_vector VariableDialogModel::getVariableValues(); - const SCP_vector> VarigableDialogModel::getContainerNames(); + const SCP_vector> getVariableValues(); + const SCP_vector> getContainerNames(); bool apply() override; void reject() override; + void initializeData(); private: SCP_vector _variableItems; SCP_vector _containerItems; - const variableInfo* lookupVariable(SCP_string name){ - for (int x = 0; x < static_cast(_varaibleItems.size()); ++x){ - if (_varaibleItems[x].name == name){ - return &_varaibleItems[x]; + variableInfo* lookupVariable(SCP_string name){ + for (int x = 0; x < static_cast(_variableItems.size()); ++x){ + if (_variableItems[x].name == name){ + return &_variableItems[x]; } } return nullptr; } - const containerInfo* lookupContainer(SCP_string name){ + containerInfo* lookupContainer(SCP_string name){ for (int x = 0; x < static_cast(_containerItems.size()); ++x){ if (_containerItems[x].name == name){ return &_containerItems[x]; @@ -139,7 +141,7 @@ class VariableDialogModel : public AbstractDialogModel { { QMessageBox msgBox; msgBox.setText(question.c_str()); - msgBox.setInformativeText(informativeText.C_str()); + msgBox.setInformativeText(informativeText.c_str()); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); int ret = msgBox.exec(); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 6debb7c4403..d6fe9fec898 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -13,9 +13,10 @@ namespace fred { namespace dialogs { VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) - : QDialog(parent), ui(new Ui::VariableDialog()), _model(new VariableDialogModel(this, viewport)), _viewport(viewport) + : QDialog(parent), ui(new Ui::VariableEditorDialog()), _model(new VariableDialogModel(this, viewport)), _viewport(viewport) { this->setFocus(); + ui->setupUi(this); // Major Changes, like Applying the model, rejecting changes and updating the UI. connect(_model.get(), &AbstractDialogModel::modelChanged, this, &VariableDialog::updateUI); @@ -127,6 +128,10 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &QCheckBox::clicked, this, &VariableDialog::onSetContainerAsEternalCheckboxClicked); + + updateUI(); + + resize(QDialog::sizeHint()); } void VariableDialog::onVariablesTableUpdated() {} // could be new name or new value diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 600ad5dc994..e84e3fd7056 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -10,7 +10,7 @@ namespace fred { namespace dialogs { namespace Ui { -class VariableDialog; +class VariableEditorDialog; } class VariableDialog : public QDialog { @@ -21,7 +21,7 @@ class VariableDialog : public QDialog { ~VariableDialog() override; private: - std::unique_ptr ui; + std::unique_ptr ui; std::unique_ptr _model; EditorViewport* _viewport; From 9ef56797fe7c3ab15ea3d0626ac6a49b22c9f04d Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 15:26:58 -0400 Subject: [PATCH 017/153] Create the Validate Function And correct the Apply function some. --- .../mission/dialogs/VariableDialogModel.cpp | 182 ++++++++++++++++-- .../src/mission/dialogs/VariableDialogModel.h | 4 +- 2 files changed, 167 insertions(+), 19 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 28b4f09bed7..e31a9f22e46 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1,6 +1,7 @@ #include "VariableDialogModel.h" #include "parse/sexp.h" #include "parse/sexp_container.h" +#include namespace fso { namespace fred { @@ -19,30 +20,155 @@ void VariableDialogModel::reject() _containerItems.clear(); } +bool VariableDialogModel::checkValidModel() +{ + std::unordered_set namesTaken; + std::unordered_set duplicates; + + for (const auto& variable : _variableItems){ + if (!namesTaken.insert(variable.name).second) { + duplicates.insert(variable.name); + } + } + + SCP_string messageOut1; + SCP_string messageOut2; + + if (!duplicates.empty()){ + for (const auto& item : duplicates){ + if (messageOut2.empty()){ + messageOut2 = "\"" + item + "\""; + } else { + messageOut2 += ", "\"" + item + "\""; + } + } + + sprintf(messageOut1, "There are %zu duplicate variables:\n", duplicates.size()); + messageOut1 += messageOut2 + "\n\n"; + } + + duplicates.clear(); + unordered_set namesTakenContainer; + SCP_vector duplicateKeys; + + for (const auto& container : _containerItems){ + if (!namesTakenContainer.insert(container.name).second) { + duplicates.insert(container.name); + } + + if (!container.list){ + unordered_set keysTakenContainer; + + for (const auto& key : container.keys){ + if (!keysTakenContainer.insert(key)) { + SCP_string temp = key + "in map" + container.name + ", "; + duplicateKeys.push_back(temp); + } + } + } + } + + messageOut2.clear(); + + if (!duplicates.empty()){ + for (const auto& item : duplicates){ + if (messageOut2.empty()){ + messageOut2 = "\"" + item + "\""; + } else { + messageOut2 += ", "\"" + item + "\""; + } + } + + SCP_string temp; + + sprintf(temp, "There are %zu duplicate containers:\n\n", duplicates.size()); + messageOut1 += messageOut2 + "\n"; + } + + messageOut2.clear(); + + if (!duplicateKeys.empty()){ + for (const auto& key : duplicateKeys){ + messageOut2 += key; + } + + SCP_string temp; + + sprintf(temp, "There are %zu duplicate map keys:\n\n", duplicateKeys.size()); + messageOut1 += messageOut2 + "\n"; + } + + if (messageOut1.empty()){ + return true; + } else { + messageOut1 = "Please correct these variable, container and key names. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; + + QMessageBox msgBox; + msgBox.setText(messageOut1.c_str()); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + } + +} bool VariableDialogModel::apply() { - // TODO VALIDATE! - // TODO! Look for referenced variables and containers. - // Need a way to clean up references. I'm thinking making some pop ups to confirm replacements created in the editor. - // This means we need a way to count and replace references. + // TODO Change the connect statement to validate before coming here to apply. + + // what did we delete from the original list? We need to check these references and clean them. + std::unordered_set deletedVariables; + SCP_vector> nameChangedVariables; + bool found; + + // first we have to edit known variables. + for (const auto& variable : _variableItems){ + found = false; + + // set of instructions for updating variables + if (!variable.originalName.empty()) { + for (int i = 0; i < MAX_SEXP_VARIABLES; ++i) { + if (!stricmp(Sexp_variables[i].variable_name, variable.originalName)){ + if (variable.deleted) { + memset(Sexp_variables[i].variable_name, 0, NAME_LENGTH); + memset(Sexp_variables[i].text, 0, NAME_LENGTH); + Sexp_variables[i].type = 0; + + deletedVariables.insert(variable.originalName); + } else { + if (variable.name != variable.originalName) { + nameChangedVariables.emplace_back(i, variable.originalName); + } - // So, previously, I was just obliterating and overwriting, but I need to rethink this info. - /*memset(Sexp_variables, 0, MAX_SEXP_VARIABLES * size_of(sexp_variable)); + strcpy_s(Sexp_variables[i].variable_name, variable.name.c_str()); + Sexp_variables[i].flags = variable.flags; - for (int i = 0; i < static_cast(_variableItems.size()); ++i){ - Sexp_variables[i].type = _variableItems[i].flags; - strcpy_s(Sexp_variables[i].variable_name, _variableItems[i].name.c_str()); - - if (_variableItems[i].flags & SEXP_VARIABLE_STRING){ - strcpy_s(Sexp_variables[i].text, _variableItems[i].stringValue); - } else { - strcpy_s(Sexp_variables[i].text, std::to_string(_variableItems[i].numberValue).c_str()) + if (variable.flags & SEXP_VARIABLE_STRING){ + strcpy_s(Sexp_variables[i].text, variable.stringValue); + Sexp_variables[i].flags |= SEXP_VARIABLE_STRING; + } else { + strcpy_s(Sexp_variables[i].text, std::to_string(variable.numberValue).c_str()) + Sexp_variables[i].flags |= SEXP_VARIABLE_NUMBER; + } + } + + found = true; + break; + } + } + } + + if (!found) { + // TODO! Lookup how the old editor does this. (look for an empty slot maybe?) } } - */ + // TODO! containers + std::unordered_set deletedContainers; + + // TODO! Look for referenced variables and containers. + // Need a way to clean up references. I'm thinking making some pop ups to confirm replacements created in the editor. + // This means we need a way to count and replace references. return false; } @@ -90,10 +216,30 @@ void VariableDialogModel::initializeData() newContainer.originalName = newContainer.name; newContainer.deleted = false; - // TODO FIXME! - newContainer.string = false; - newContainer.list = container.is_list(); + if (container.type & ContainerType::STRING_DATA) { + newContainer.string = true; + } else if (container.type & ContainerType::NUMBER_DATA) { + newContainer.string = false; + } + // using the SEXP variable version of these values here makes things easier + if (container.type & ContainerType::SAVE_TO_PLAYER_FILE) { + newContainer.flags |= SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; + } + + if (container.type & ContainerType::SAVE_ON_MISSION_CLOSE) { + newContainer.flags |= SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE; + } + + if (container.type & ContainerType::SAVE_ON_MISSION_PROGRESS) { + newContainer.flags |= SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS; + } + + if (container.type & ContainerType::NETWORK) { + newContainer.flags =| SEXP_VARIABLE_NETWORK; + } + + newContainer.list = container.is_list(); } } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index adff7308548..187633e68bd 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -22,12 +22,14 @@ struct variableInfo { struct containerInfo { SCP_string name = ""; - SCP_string originalName = ""; bool deleted = false; bool list = true; bool string = true; int flags = 0; + // this will allow us to look up the original values used in the mission previously. + SCP_string originalName = ""; + SCP_vector keys; SCP_vector numberValues; SCP_vector stringValues; From 11fac90617620b725af84e7079ffcc5fcb9fcbbd Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 15:27:24 -0400 Subject: [PATCH 018/153] Add missing functions --- qtfred/src/ui/dialogs/VariableDialog.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index d6fe9fec898..f50cd3a9f56 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -43,6 +43,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onAddVariableButtonPressed); + connect(ui->copyVariableButton, + &QPushButton::clicked, + this, + &VariableDialog::onCopyVariableButtonPressed); + connect(ui->deleteVariableButton, &QPushButton::clicked, this, @@ -78,6 +83,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onAddContainerButtonPressed); + connect(ui->copyContainerButton, + &QPushButton::clicked, + this, + &VariableDialog::onCopyContainerButtonPressed); + connect(ui->deleteContainerButton, &QPushButton::clicked, this, @@ -142,6 +152,7 @@ void VariableDialog::onAddVariableButtonPressed() } +void VariableDialog::onCopyVariableButtonPressed(){} void VariableDialog::onDeleteVariableButtonPressed() {} void VariableDialog::onSetVariableAsStringRadioSelected() {} void VariableDialog::onSetVariableAsNumberRadioSelected() {} @@ -150,6 +161,7 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} void VariableDialog::onAddContainerButtonPressed() {} +void VariableDialog::onCopyContainerButtonPressed() {} void VariableDialog::onDeleteContainerButtonPressed() {} void VariableDialog::onSetContainerAsMapRadioSelected() {} void VariableDialog::onSetContainerAsListRadioSelected() {} From 2934e99ddcd1792ce4beb403cf7629a62e79858e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 17:26:14 -0400 Subject: [PATCH 019/153] Progress on applyModel --- qtfred/src/ui/dialogs/VariableDialog.cpp | 124 +++++++++++++++++++++-- qtfred/src/ui/dialogs/VariableDialog.h | 10 +- 2 files changed, 122 insertions(+), 12 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index f50cd3a9f56..ee3a1db029d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -28,16 +28,31 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onVariablesTableUpdated); - connect(ui->variablesTable, + connect(ui->variablesTable, + &QTableWidget::itemSelectionChanged, + this, + &VariableDialog::onVariablesSelectionChanged); + + connect(ui->containersTable, QOverload::of(&QTableWidget::cellChanged), this, &VariableDialog::onContainersTableUpdated); - connect(ui->variablesTable, + connect(ui->containersTable, + &QTableWidget::itemSelectionChanged, + this, + &VariableDialog::onContainersSelectionChanged); + + connect(ui->containerContentsTable, QOverload::of(&QTableWidget::cellChanged), this, &VariableDialog::onContainerContentsTableUpdated); + connect(ui->containerContentsTable, + &QTableWidget::itemSelectionChanged, + this, + &VariableDialog::onContainerContentsSelectionChanged); + connect(ui->addVariableButton, &QPushButton::clicked, this, @@ -123,7 +138,6 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSaveContainerOnMissionCompletedRadioSelected); - connect(ui->addContainerItemButton, &QPushButton::clicked, this, @@ -139,19 +153,42 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSetContainerAsEternalCheckboxClicked); - updateUI(); - resize(QDialog::sizeHint()); + + ui->variablesTable->setColumnCount(3); + ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); + ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); + ui->variablesTable->setColumnWidth(0, 200); + ui->variablesTable->setColumnWidth(1, 200); + ui->variablesTable->setColumnWidth(2, 200); + + ui->containersTable->setColumnCount(3); + ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); + ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); + ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); + ui->containersTable->setColumnWidth(0, 200); + ui->containersTable->setColumnWidth(1, 200); + ui->containersTable->setColumnWidth(2, 200); + + ui->containerContentsTable->setColumnCount(2); + + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + ui->containerContentsTable->setColumnWidth(0, 200); + ui->containerContentsTable->setColumnWidth(1, 200); + + applyModel(); } void VariableDialog::onVariablesTableUpdated() {} // could be new name or new value +void VariableDialog::onVariablesSelectionChanged() {} void VariableDialog::onContainersTableUpdated() {} // could be new name +void VariableDialog::onContainersSelectionChanged() {} void VariableDialog::onContainerContentsTableUpdated() {} // could be new key or new value -void VariableDialog::onAddVariableButtonPressed() -{ - +void VariableDialog::onContainerContentsSelectionChanged() {} -} +void VariableDialog::onAddVariableButtonPressed() {} void VariableDialog::onCopyVariableButtonPressed(){} void VariableDialog::onDeleteVariableButtonPressed() {} void VariableDialog::onSetVariableAsStringRadioSelected() {} @@ -175,10 +212,75 @@ void VariableDialog::onAddContainerItemButtonPressed() {} void VariableDialog::onDeleteContainerItemButtonPressed() {} - VariableDialog::~VariableDialog(){}; // NOLINT -void VariableDialog::updateUI(){}; +void VariableDialog::applyModel() +{ + auto variables = _model->getVariableValues(); + + for (int x = 0; x < static_cast(variables.size()); ++x){ + if (ui->variablesTable->item(x, 0)){ + ui->variablesTable->item(x, 0)->setText(variables[x]<0>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(variables[x]<0>.c_str()); + ui->variablesTable->setItem(x, 0, item); + } + + if (ui->variablesTable->item(x, 1)){ + ui->variablesTable->item(x, 1)->setText(variables[x]<1>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(variables[x]<1>.c_str()); + ui->variablesTable->setItem(x, 1, nameItem); + } + + if (ui->variablesTable->item(x, 2)){ + ui->variablesTable->item(x, 2)->setText(variables[x]<2>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(variables[x]<2>.c_str()); + ui->variablesTable->setItem(x, 2, item); + } + + } + + if (_currentVariable.empty()){ + if( ui->VariablesTable->item(0,0) && strlen(ui->VariablesTable->item(0,0)->text())){ + _currentVariable = ui->VariablesTable->item(0,0)->text(); + } + // TODO! Make new ui function with the following stuff. + // get type with getVariableType + // get network status with getVariableNetworkStatus + // get getVariablesOnMissionCloseOrCompleteFlag + // getVariableEternalFlag + // string or number value with getVariableStringValue or getVariableNumberValue + } + + auto containers = _model->getContainerNames(); + + // TODO! Change getContainerNames to a tuple with notes/maybe data key types? + for (x = 0; x < static_cast(containers.size()); ++x){ + if (ui->containersTable->item(x, 0)){ + ui->containersTable->item(x, 0)->setText(containers[x]<0>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(containers[x]<0>.c_str()); + ui->containersTable->setItem(x, 0, item); + } + + if (ui->containersTable->item(x, 1)){ + ui->containersTable->item(x, 1)->setText(containers[x]<1>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(containers[x]<1>.c_str()); + ui->containersTable->setItem(x, 1, nameItem); + } + + if (ui->containersTable->item(x, 2)){ + ui->containersTable->item(x, 2)->setText(containers[x]<2>.c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(containers[x]<2>.c_str()); + ui->containersTable->setItem(x, 2, item); + } + } + +}; } // namespace dialogs diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index e84e3fd7056..f40ac75f70b 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -25,11 +25,15 @@ class VariableDialog : public QDialog { std::unique_ptr _model; EditorViewport* _viewport; - void updateUI(); + // basically UpdateUI, but called when there is an inconsistency between model and UI + void applyModel(); void onVariablesTableUpdated(); + void onVariablesSelectionChanged(); void onContainersTableUpdated(); + void onContainersSelectionChanged(); void onContainerContentsTableUpdated(); + void onContainerContentsSelectionChanged(); void onAddVariableButtonPressed(); void onDeleteVariableButtonPressed(); void onCopyVariableButtonPressed(); @@ -52,6 +56,10 @@ class VariableDialog : public QDialog { void onSetContainerAsEternalCheckboxClicked(); void onAddContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); + + SCP_string _currentVariable = ""; + SCP_string _currentContainer = ""; + SCP_string _currentContainerItem = ""; }; From e60cf650369306add8e8821148261fa71131e7f4 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 21:04:20 -0400 Subject: [PATCH 020/153] Write part of onVariablesTableUpdated --- qtfred/src/ui/dialogs/VariableDialog.cpp | 170 +++++++++++++++++++++-- 1 file changed, 156 insertions(+), 14 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index ee3a1db029d..01780f8a6aa 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -24,7 +24,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); connect(ui->variablesTable, - QOverload::of(&QTableWidget::cellChanged), + &QTableWidget::itemChanged, this, &VariableDialog::onVariablesTableUpdated); @@ -34,7 +34,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &VariableDialog::onVariablesSelectionChanged); connect(ui->containersTable, - QOverload::of(&QTableWidget::cellChanged), + &QTableWidget::itemChanged, this, &VariableDialog::onContainersTableUpdated); @@ -44,7 +44,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &VariableDialog::onContainersSelectionChanged); connect(ui->containerContentsTable, - QOverload::of(&QTableWidget::cellChanged), + &QTableWidget::itemChanged, this, &VariableDialog::onContainerContentsTableUpdated); @@ -181,7 +181,88 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) applyModel(); } -void VariableDialog::onVariablesTableUpdated() {} // could be new name or new value +// TODO! have applyModel set a variable that has us return early on these table updated functions. +// TODO! make sure that when a variable is added that the whole model is reloaded. +void VariableDialog::onVariablesTableUpdated() +{ + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + if (item->column() == 0){ + + // so if the user just removed the name, mark it as deleted *before changing the name* + if (_currentVariable != "" && !strlen(item->text.c_str())){ + if (!_model->removeVariable(item->row())) { + // marking a variable as deleted failed, resync UI + applyModel(); + return; + } + } + + auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); + + // we put something in the cell, but the model couldn't process it. + if (strlen(item->text()) && ret == ""){ + // update of variable name failed, resync UI + applyModel(); + + // we had a successful rename. So update the variable we reference. + } else if (ret != "") { + item->setText(ret.c_str()); + _currentVariable = ret; + } + + // empty return and cell was handled earlier. + + // data was altered + } else if (item->column() == 0) { + if (_model->getVariableType(int->row())){ + SCP_string ret = _model->setVariableStringValue(int->row(), item->text().toStdString()); + if (ret == ""){ + applyModel(); + } + } else { + SCP_string temp; + SCP_string source = item->text().toStdString(); + + std::copy_if(s1.begin(), s1.end(), std::back_inserter(temp), + [](char c){ + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + return true; + break; + default: + return false; + break; + } + } + ); + + if (temp != ) + + int ret = _model->setVariableNumberValue(int->row(), ) + } + + + // if the user somehow edited the info that comes from the model and should not be editable, reload everything. + } else { + applyModel(); + } + } +} + + void VariableDialog::onVariablesSelectionChanged() {} void VariableDialog::onContainersTableUpdated() {} // could be new name void VariableDialog::onContainersSelectionChanged() {} @@ -217,8 +298,9 @@ VariableDialog::~VariableDialog(){}; // NOLINT void VariableDialog::applyModel() { auto variables = _model->getVariableValues(); + int x, selectedRow = -1; - for (int x = 0; x < static_cast(variables.size()); ++x){ + for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ ui->variablesTable->item(x, 0)->setText(variables[x]<0>.c_str()); } else { @@ -226,6 +308,11 @@ void VariableDialog::applyModel() ui->variablesTable->setItem(x, 0, item); } + // check if this is the current variable. + if (!_currentVariable.empty() && variables[x]<0> == _currentVariable){ + selectedRow = x + } + if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x]<1>.c_str()); } else { @@ -239,22 +326,44 @@ void VariableDialog::applyModel() QTableWidgetItem* item = new QTableWidgetItem(variables[x]<2>.c_str()); ui->variablesTable->setItem(x, 2, item); } + } + // TODO, try setting row count? + // This empties rows that might have previously had variables + if (x < ui->variablesTable->rowCount()) { + ++x; + for (; x < ui->variablesTable->rowCount(); ++x){ + if (ui->variablesTable->item(x, 0)){ + ui->variablesTable->item(x, 0)->setText(""); + } + + if (ui->variablesTable->item(x, 1)){ + ui->variablesTable->item(x, 1)->setText(""); + } + + if (ui->variablesTable->item(x, 2)){ + ui->variablesTable->item(x, 2)->setText(""); + } + } } - if (_currentVariable.empty()){ - if( ui->VariablesTable->item(0,0) && strlen(ui->VariablesTable->item(0,0)->text())){ - _currentVariable = ui->VariablesTable->item(0,0)->text(); + if (_currentVariable.empty() || selectedRow < 0){ + if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text())){ + _currentVariable = ui->variablesTable->item(0,0)->text(); } - // TODO! Make new ui function with the following stuff. - // get type with getVariableType - // get network status with getVariableNetworkStatus - // get getVariablesOnMissionCloseOrCompleteFlag - // getVariableEternalFlag - // string or number value with getVariableStringValue or getVariableNumberValue } + // TODO! Make new ui function with the following stuff. + // get type with getVariableType + // get network status with getVariableNetworkStatus + // get getVariablesOnMissionCloseOrCompleteFlag + // getVariableEternalFlag + // string or number value with getVariableStringValue or getVariableNumberValue + updateVariableOptions(); + + auto containers = _model->getContainerNames(); + selectedRow = -1; // TODO! Change getContainerNames to a tuple with notes/maybe data key types? for (x = 0; x < static_cast(containers.size()); ++x){ @@ -265,6 +374,12 @@ void VariableDialog::applyModel() ui->containersTable->setItem(x, 0, item); } + // check if this is the current variable. + if (!_currentVariable.empty() && containers[x]<0> == _currentVariable){ + selectedRow = x; + } + + if (ui->containersTable->item(x, 1)){ ui->containersTable->item(x, 1)->setText(containers[x]<1>.c_str()); } else { @@ -280,6 +395,33 @@ void VariableDialog::applyModel() } } + // This empties rows that might have previously had containers + if (x < ui->containersTable->rowCount()) { + ++x; + for (; x < ui->containersTable->rowCount(); ++x){ + if (ui->containersTable->item(x, 0)){ + ui->containersTable->item(x, 0)->setText(""); + } + + if (ui->containersTable->item(x, 1)){ + ui->containersTable->item(x, 1)->setText(""); + } + + if (ui->containersTable->item(x, 2)){ + ui->containersTable->item(x, 2)->setText(""); + } + } + } + + if (_currentContainer.empty() || selectedRow < 0){ + if (ui->containersTable->item(0,0) && strlen(ui->containersTable->item(0,0)->text())){ + _currentContainer = ui->containersTable->item(0,0)->text(); + } + } + + // this will update the list/map items. + updateContainerOptions(); + }; From bc059bdb865aea1382a386b6dc5cbdcbffb788f1 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 21:47:42 -0400 Subject: [PATCH 021/153] Add Variable Editor Trigger To Loadout Dialog --- qtfred/src/ui/dialogs/LoadoutDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qtfred/src/ui/dialogs/LoadoutDialog.cpp b/qtfred/src/ui/dialogs/LoadoutDialog.cpp index 9e730551c21..b0542191826 100644 --- a/qtfred/src/ui/dialogs/LoadoutDialog.cpp +++ b/qtfred/src/ui/dialogs/LoadoutDialog.cpp @@ -517,6 +517,7 @@ void LoadoutDialog::onClearAllUsedWeaponsPressed() // TODO! Finish writing a trigger to open that dialog, once the variable editor is created void LoadoutDialog::openEditVariablePressed() { + viewport->on_actionVariables_triggered(); } void LoadoutDialog::onSelectionRequiredPressed() From c9f4982d080200acbb0252872dc133a4b12db617 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 21:48:50 -0400 Subject: [PATCH 022/153] Add apply trigger on validated data And clean up dialog model slightly --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index e31a9f22e46..e084cdb0b30 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -20,7 +20,7 @@ void VariableDialogModel::reject() _containerItems.clear(); } -bool VariableDialogModel::checkValidModel() +void VariableDialogModel::checkValidModel() { std::unordered_set namesTaken; std::unordered_set duplicates; @@ -99,7 +99,7 @@ bool VariableDialogModel::checkValidModel() } if (messageOut1.empty()){ - return true; + apply(); } else { messageOut1 = "Please correct these variable, container and key names. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; @@ -109,11 +109,12 @@ bool VariableDialogModel::checkValidModel() msgBox.exec(); } + + } bool VariableDialogModel::apply() { - // TODO Change the connect statement to validate before coming here to apply. // what did we delete from the original list? We need to check these references and clean them. std::unordered_set deletedVariables; @@ -158,7 +159,7 @@ bool VariableDialogModel::apply() } if (!found) { - // TODO! Lookup how the old editor does this. (look for an empty slot maybe?) + // TODO! Lookup how FRED adds new variables. (look for an empty slot maybe?) } } @@ -168,7 +169,6 @@ bool VariableDialogModel::apply() // TODO! Look for referenced variables and containers. // Need a way to clean up references. I'm thinking making some pop ups to confirm replacements created in the editor. - // This means we need a way to count and replace references. return false; } @@ -198,7 +198,6 @@ void VariableDialogModel::initializeData() } catch (...) { item.numberValue = 0; - // TODO! Warning popup } item.stringValue = ""; From 6e10ee64f82d6b966e2496a14533cee48ceacacc Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 21:56:27 -0400 Subject: [PATCH 023/153] Add TrimNumberString function And other things --- qtfred/src/ui/dialogs/LoadoutDialog.cpp | 1 - qtfred/src/ui/dialogs/VariableDialog.cpp | 120 ++++++++++++++++------- qtfred/src/ui/dialogs/VariableDialog.h | 3 + 3 files changed, 88 insertions(+), 36 deletions(-) diff --git a/qtfred/src/ui/dialogs/LoadoutDialog.cpp b/qtfred/src/ui/dialogs/LoadoutDialog.cpp index b0542191826..c115656b247 100644 --- a/qtfred/src/ui/dialogs/LoadoutDialog.cpp +++ b/qtfred/src/ui/dialogs/LoadoutDialog.cpp @@ -514,7 +514,6 @@ void LoadoutDialog::onClearAllUsedWeaponsPressed() _lastSelectionChanged = USED_WEAPONS; } -// TODO! Finish writing a trigger to open that dialog, once the variable editor is created void LoadoutDialog::openEditVariablePressed() { viewport->on_actionVariables_triggered(); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 01780f8a6aa..5868aa6d83e 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -20,7 +20,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Major Changes, like Applying the model, rejecting changes and updating the UI. connect(_model.get(), &AbstractDialogModel::modelChanged, this, &VariableDialog::updateUI); - connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); + connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::checkValidModel); connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); connect(ui->variablesTable, @@ -181,10 +181,13 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) applyModel(); } -// TODO! have applyModel set a variable that has us return early on these table updated functions. // TODO! make sure that when a variable is added that the whole model is reloaded. void VariableDialog::onVariablesTableUpdated() { + if (_applyingModel){ + return; + } + auto items = ui->variablesTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. @@ -215,47 +218,43 @@ void VariableDialog::onVariablesTableUpdated() // empty return and cell was handled earlier. - // data was altered - } else if (item->column() == 0) { + // data cell was altered + } else if (item->column() == 1) { + + // Variable is a string if (_model->getVariableType(int->row())){ - SCP_string ret = _model->setVariableStringValue(int->row(), item->text().toStdString()); + SCP_string temp = item->text()->toStdString().c_str(); + temp = temp.substr(0, NAME_LENGTH - 1); + + SCP_string ret = _model->setVariableStringValue(int->row(), temp); if (ret == ""){ applyModel(); + return; } + + item->setText(ret.c_str()); } else { SCP_string temp; SCP_string source = item->text().toStdString(); - std::copy_if(s1.begin(), s1.end(), std::back_inserter(temp), - [](char c){ - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - return true; - break; - default: - return false; - break; - } - } - ); - - if (temp != ) - - int ret = _model->setVariableNumberValue(int->row(), ) - } + SCP_string temp = trimNumberString(); + if (temp != source){ + item->setText(temp.c_str()); + } - // if the user somehow edited the info that comes from the model and should not be editable, reload everything. + try { + int ret = _model->setVariableNumberValue(item->row(), std::stoi(temp)); + temp = ""; + sprintf(temp, "%i", ret); + item->setText(temp); + } + catch (...) { + applyModel(); + } + } + + // if the user somehow edited the info that should only come from the model and should not be editable, reload everything. } else { applyModel(); } @@ -264,9 +263,22 @@ void VariableDialog::onVariablesTableUpdated() void VariableDialog::onVariablesSelectionChanged() {} -void VariableDialog::onContainersTableUpdated() {} // could be new name +void VariableDialog::onContainersTableUpdated() +{ + if (_applyingModel){ + return; + } + +} // could be new name void VariableDialog::onContainersSelectionChanged() {} -void VariableDialog::onContainerContentsTableUpdated() {} // could be new key or new value +void VariableDialog::onContainerContentsTableUpdated() +{ + if (_applyingModel){ + return; + } + + +} // could be new key or new value void VariableDialog::onContainerContentsSelectionChanged() {} void VariableDialog::onAddVariableButtonPressed() {} @@ -297,6 +309,8 @@ VariableDialog::~VariableDialog(){}; // NOLINT void VariableDialog::applyModel() { + _applyingModel = true; + auto variables = _model->getVariableValues(); int x, selectedRow = -1; @@ -422,8 +436,44 @@ void VariableDialog::applyModel() // this will update the list/map items. updateContainerOptions(); + _applyingModel = false; }; +SCP_string VariableDialog::trimNumberString(SCP_string source) +{ + SCP_string ret; + + // account for a lead negative sign. + if (source[0] == "-") { + ret = "-"; + } + + // filter out non-numeric digits + std::copy_if(s1.begin(), s1.end(), std::back_inserter(ret), + [](char c){ + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + break; + default: + return false; + break; + } + } + ); + + return ret; +} + } // namespace dialogs } // namespace fred diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index f40ac75f70b..22e06337e24 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -57,6 +57,9 @@ class VariableDialog : public QDialog { void onAddContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); + SCP_string trimNumberString(SCP_string source); + + bool _applyingModel = false; SCP_string _currentVariable = ""; SCP_string _currentContainer = ""; SCP_string _currentContainerItem = ""; From 2ad0571b22e41dfae872385586325616b37c12e2 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 23:55:22 -0400 Subject: [PATCH 024/153] Make sure that setVariableType signals failure --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index e084cdb0b30..beccd62ba8f 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -306,8 +306,10 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) auto variable = lookupVariable(name); // nothing to change, or invalid entry + // Best way to say that it failed is to say + // that it is not switching to what the ui asked for. if (!variable || variable->string == string){ - return string; + return !string; } From 4cac920943a22b4fc975803f70f6947a16457c0a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 12 Apr 2024 23:56:00 -0400 Subject: [PATCH 025/153] Add more dialog functions --- qtfred/src/ui/dialogs/VariableDialog.cpp | 105 +++++++++++++++++++++-- 1 file changed, 97 insertions(+), 8 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 5868aa6d83e..2609e7cc2cb 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -178,6 +178,18 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containerContentsTable->setColumnWidth(0, 200); ui->containerContentsTable->setColumnWidth(1, 200); + // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't + ui->setVariableAsStringRadio->setAutoExclusive(false); + ui->setVariableAsNumberRadio->setAutoExclusive(false); + ui->saveContainerOnMissionCompletedRadio->setAutoExclusive(false); + ui->saveVariableOnMissionCloseRadio->setAutoExclusive(false); + ui->setContainerAsMapRadio->setAutoExclusive(false); + ui->setContainerAsListRadio->setAutoExclusive(false); + ui->setContainerAsStringRadio->setAutoExclusive(false); + ui->setContainerAsNumberRadio->setAutoExclusive(false); + ui->saveContainerOnMissionCloseRadio->setAutoExclusive(false); + ui->saveContainerOnMissionCompletedRadio->setAutoExclusive(false); + applyModel(); } @@ -262,7 +274,14 @@ void VariableDialog::onVariablesTableUpdated() } -void VariableDialog::onVariablesSelectionChanged() {} +void VariableDialog::onVariablesSelectionChanged() +{ + if (_applyingModel){ + return; + } +} + + void VariableDialog::onContainersTableUpdated() { if (_applyingModel){ @@ -270,7 +289,14 @@ void VariableDialog::onContainersTableUpdated() } } // could be new name -void VariableDialog::onContainersSelectionChanged() {} + +void VariableDialog::onContainersSelectionChanged() +{ + if (_applyingModel){ + return; + } +} + void VariableDialog::onContainerContentsTableUpdated() { if (_applyingModel){ @@ -279,13 +305,76 @@ void VariableDialog::onContainerContentsTableUpdated() } // could be new key or new value -void VariableDialog::onContainerContentsSelectionChanged() {} -void VariableDialog::onAddVariableButtonPressed() {} -void VariableDialog::onCopyVariableButtonPressed(){} -void VariableDialog::onDeleteVariableButtonPressed() {} -void VariableDialog::onSetVariableAsStringRadioSelected() {} -void VariableDialog::onSetVariableAsNumberRadioSelected() {} +void VariableDialog::onContainerContentsSelectionChanged() { + if (_applyingModel){ + return; + } + +} + +void VariableDialog::onAddVariableButtonPressed() +{ + auto ret = _model->addNewVriable(); + _currentVariable = ret; + applyModel(); +} + +void VariableDialog::onCopyVariableButtonPressed() +{ + if (_currentVarible.empty()){ + return; + } + + auto ret = _model->copyVariable(_currentVariable); + _currentVariable = ret; + applyModel(); +} + +void VariableDialog::onDeleteVariableButtonPressed() +{ + if (_currentVarible.empty()){ + return; + } + + // Because of the text update we'll need, this needs an applyModel, whether it fails or not. + _model->removeVariable(_currentVariable); + applyModel(); +} + +void VariableDialog::onSetVariableAsStringRadioSelected() +{ + if (_currentVarible.empty() || ui->setVariableAsStringRadio->isChecked()){ + return; + } + + // this doesn't return succeed or fail directly, + // but if it doesn't return true then it failed since this is the string radio + if(!_model->setVariableType(_currentVariable, true)){ + applyModel(); + } else { + ui->setVariableAsStringRadio->setChecked(true); + ui->setVariableAsNumberRadio->setChecked(false); + } +} + +void VariableDialog::onSetVariableAsNumberRadioSelected() +{ + if (_currentVarible.empty() || ui->setVariableAsNumberRadio->isChecked()){ + return; + } + + // this doesn't return succeed or fail directly, + // but if it doesn't return false then it failed since this is the number radio + if(!_model->setVariableType(_currentVariable, false)){ + applyModel(); + } else { + ui->setVariableAsStringRadio->setChecked(false); + ui->setVariableAsNumberRadio->setChecked(true); + } +} + + void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() {} void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} From 8d40952bf5ca8e9a2f602af44724163fca0a0a17 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 13 Apr 2024 00:51:20 -0400 Subject: [PATCH 026/153] Finish adding Variable change options --- qtfred/src/ui/dialogs/VariableDialog.cpp | 129 +++++++++++++++++++++-- qtfred/src/ui/dialogs/VariableDialog.h | 1 + 2 files changed, 123 insertions(+), 7 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 2609e7cc2cb..4c25ed7cd67 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -88,6 +88,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSaveVariableOnMissionCloseRadioSelected); + connect(ui->networkVariableCheckbox, + &QCheckBox::clicked, + this, + &VariableDialog::onNetworkVariableCheckboxClicked); + connect(ui->setVariableAsEternalcheckbox, &QCheckBox::clicked, this, @@ -322,7 +327,7 @@ void VariableDialog::onAddVariableButtonPressed() void VariableDialog::onCopyVariableButtonPressed() { - if (_currentVarible.empty()){ + if (_currentVariable.empty()){ return; } @@ -333,7 +338,7 @@ void VariableDialog::onCopyVariableButtonPressed() void VariableDialog::onDeleteVariableButtonPressed() { - if (_currentVarible.empty()){ + if (_currentVariable.empty()){ return; } @@ -344,7 +349,7 @@ void VariableDialog::onDeleteVariableButtonPressed() void VariableDialog::onSetVariableAsStringRadioSelected() { - if (_currentVarible.empty() || ui->setVariableAsStringRadio->isChecked()){ + if (_currentVariable.empty() || ui->setVariableAsStringRadio->isChecked()){ return; } @@ -360,7 +365,7 @@ void VariableDialog::onSetVariableAsStringRadioSelected() void VariableDialog::onSetVariableAsNumberRadioSelected() { - if (_currentVarible.empty() || ui->setVariableAsNumberRadio->isChecked()){ + if (_currentVariable.empty() || ui->setVariableAsNumberRadio->isChecked()){ return; } @@ -375,9 +380,69 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() } -void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() {} -void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() {} -void VariableDialog::onSaveVariableAsEternalCheckboxClicked() {} +void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() +{ + if (_currentVariable.empty() || ui->saveContainerOnMissionCompletedRadio->isChecked()){ + return; + } + + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(_currentVariable, 1); + + if (ret != 1){ + applyModel(); + } else { + // TODO! Need "no persistence" options and functions! + ui->saveContainerOnMissionCompletedRadio->setChecked(true); + ui->saveVariableOnMissionCloseRadio->setChecked(false); + //ui->saveContainerOnMissionCompletedRadio->setChecked(true); + } +} + +void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() +{ + if (_currentVariable.empty() || ui->saveContainerOnMissionCompletedRadio->isChecked()){ + return; + } + + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(_currentVariable, 2); + + if (ret != 2){ + applyModel(); + } else { + // TODO! Need "no persistence" options. + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(true); + //ui->saveContainerOnMissionCompletedRadio->setChecked(false); + } +} + +void VariableDialog::onSaveVariableAsEternalCheckboxClicked() +{ + if (_currentVariable.empty()){ + return; + } + + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(_currentVariable, !ui->setVariableAsEternalcheckbox->isChecked())){ + applyModel(); + } else { + _ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); + } +} + +void VariableDialog::onNetworkVariableCheckboxClicked() +{ + if (_currentVariable.empty()){ + return; + } + + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->setVariableNetworkStatus->isChecked() == _model->setVariableNetworkStatus(_currentVariable, !ui->setVariableNetworkStatus->isChecked())){ + applyModel(); + } else { + _ui->setVariableNetworkStatus->setChecked(!ui->setVariableNetworkStatus->isChecked()); + } +} void VariableDialog::onAddContainerButtonPressed() {} void VariableDialog::onCopyContainerButtonPressed() {} @@ -528,6 +593,56 @@ void VariableDialog::applyModel() _applyingModel = false; }; +void VariableDialog::updateVariableOptions() +{ + if (_currentVariable.empty()){ + ui->copyVariableButton.setEnabled(false); + ui->deleteVariableButton.setEnabled(false); + ui->setVariableAsStringRadio.setEnabled(false); + ui->setVariableAsNumberRadio.setEnabled(false); + ui->saveContainerOnMissionCompletedRadio.setEnabled(false); + ui->saveVariableOnMissionCloseRadio.setEnabled(false); + ui->setVariableAsEternalcheckbox.setEnabled(false); + + return; + } + + ui->copyVariableButton.setEnabled(true); + ui->deleteVariableButton.setEnabled(true); + ui->setVariableAsStringRadio.setEnabled(true); + ui->setVariableAsNumberRadio.setEnabled(true); + ui->saveContainerOnMissionCompletedRadio.setEnabled(true); + ui->saveVariableOnMissionCloseRadio.setEnabled(true); + ui->setVariableAsEternalcheckbox.setEnabled(true); + + // start populating values + bool string = _model->getVariableType(_currentVariable); + ui->setVariableAsStringRadio.setChecked(string); + ui->setVariableAsNumberRadio.setChecked(!string); + ui->setVariableAsEternalcheckbox.setChecked(); + + int ret = _model->getVariableOnMissionCloseOrCompleteFlag(_currentVariable); + + if (ret == 0){ + // TODO ADD NO PERSISTENCE + } else if (ret == 1) { + ui->saveContainerOnMissionCompletedRadio.setChecked(true); + ui->saveVariableOnMissionCloseRadio.setChecked(false); + } else { + ui->saveContainerOnMissionCompletedRadio.setChecked(false); + ui->saveVariableOnMissionCloseRadio.setChecked(true); + } + + ui->networkVariableCheckbox.setChecked(_model->getVariableNetworkStatus(_currentVariable)); + ui->setVariableAsEternalcheckbox.setChecked(_model->getVariableEternalFlag(_currentVariable)); + +} + +void VariableDialog::updateContainerOptions() +{ + +} + SCP_string VariableDialog::trimNumberString(SCP_string source) { SCP_string ret; diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 22e06337e24..f4a4e70fa0a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -42,6 +42,7 @@ class VariableDialog : public QDialog { void onSaveVariableOnMissionCompleteRadioSelected(); void onSaveVariableOnMissionCloseRadioSelected(); void onSaveVariableAsEternalCheckboxClicked(); + void onNetworkVariableCheckboxClicked(); void onAddContainerButtonPressed(); void onDeleteContainerButtonPressed(); From d4f8706208a1f253f2e14b3732e8f58c9a5663d4 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 14 Apr 2024 12:00:32 -0400 Subject: [PATCH 027/153] Add contents to UpdateContainerOptions --- qtfred/src/ui/dialogs/VariableDialog.cpp | 160 ++++++++++++++++++++--- qtfred/src/ui/dialogs/VariableDialog.h | 9 +- 2 files changed, 153 insertions(+), 16 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 4c25ed7cd67..900cc29c7c1 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -17,6 +17,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) { this->setFocus(); ui->setupUi(this); + resize(QDialog::sizeHint()); // The best I can tell without some research, when a dialog doesn't use an underling grid or layout, it needs to be resized this way before anything will show up // Major Changes, like Applying the model, rejecting changes and updating the UI. connect(_model.get(), &AbstractDialogModel::modelChanged, this, &VariableDialog::updateUI); @@ -131,7 +132,17 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(ui->setContainerAsNumberRadio, &QRadioButton::toggled, this, - &VariableDialog::onSetContainerAsNumberRadio); + &VariableDialog::onSetContainerAsNumberRadioSelected); + + connect(ui->setContainerKeyAsStringRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerKeyAsStringRadioSelected); + + connect(ui->setContainerKeyAsNumberRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onSetContainerKeyAsNumberRadioSelected); connect(ui->saveContainerOnMissionCloseRadio, &QRadioButton::toggled, @@ -143,22 +154,31 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSaveContainerOnMissionCompletedRadioSelected); + connect(ui->setContainerAsEternalCheckbox, + &QCheckBox::clicked, + this, + &VariableDialog::onSetContainerAsEternalCheckboxClicked); + + connect(ui->networkContainerCheckbox, + &QCheckBox::clicked, + this, + &VariableDialog::onNetworkContainerCheckboxClicked); + connect(ui->addContainerItemButton, &QPushButton::clicked, this, &VariableDialog::onAddContainerItemButtonPressed); + connect(ui->copyContainerItemButton, + &QPushButton::clicked, + this, + &VariableDialog::onCopyContainerItemButtonPressed); + connect(ui->deleteContainerItemButton, &QPushButton::clicked, this, &VariableDialog::onDeleteContainerItemButtonPressed); - connect(ui->setContainerAsEternalCheckbox, - &QCheckBox::clicked, - this, - &VariableDialog::onSetContainerAsEternalCheckboxClicked); - - resize(QDialog::sizeHint()); ui->variablesTable->setColumnCount(3); ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -178,8 +198,9 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containerContentsTable->setColumnCount(2); - ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); - ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + // Default to list + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->containerContentsTable->setColumnWidth(0, 200); ui->containerContentsTable->setColumnWidth(1, 200); @@ -284,6 +305,23 @@ void VariableDialog::onVariablesSelectionChanged() if (_applyingModel){ return; } + + auto items = ui->variablesTable->selectedItems(); + + SCP_string newVariableName = ""; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + if (item->column() == 0){ + newVariableName = item->text().toStdString(); + break; + } + } + + if (newVariableName != _currentVariable){ + _currentVariable = newVariableName; + applyModel(); + } } @@ -297,9 +335,23 @@ void VariableDialog::onContainersTableUpdated() void VariableDialog::onContainersSelectionChanged() { - if (_applyingModel){ + if (_applyingModel){ return; } + + auto items = ui->containersTable->selectedItems(); + + SCP_string newVariableName = ""; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + newVariableName = item->text().toStdString(); + } + + if (newVariableName != _currentVariable){ + _currentVariable = newVariableName; + applyModel(); + } } void VariableDialog::onContainerContentsTableUpdated() @@ -450,12 +502,15 @@ void VariableDialog::onDeleteContainerButtonPressed() {} void VariableDialog::onSetContainerAsMapRadioSelected() {} void VariableDialog::onSetContainerAsListRadioSelected() {} void VariableDialog::onSetContainerAsStringRadioSelected() {} -void VariableDialog::onSetContainerAsNumberRadio() {} +void VariableDialog::onSetContainerAsNumberRadioSelected() {} +void VariableDialog::onSetContainerKeyAsStringRadioSelected() {} +void VariableDialog::onSetContainerKeyAsNumberRadioSelected() {} void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} void VariableDialog::onNetworkContainerCheckboxClicked() {} void VariableDialog::onSetContainerAsEternalCheckboxClicked() {} void VariableDialog::onAddContainerItemButtonPressed() {} +void VariableDialog::onCopyContainerItemButtonPressed() {} void VariableDialog::onDeleteContainerItemButtonPressed() {} @@ -600,7 +655,7 @@ void VariableDialog::updateVariableOptions() ui->deleteVariableButton.setEnabled(false); ui->setVariableAsStringRadio.setEnabled(false); ui->setVariableAsNumberRadio.setEnabled(false); - ui->saveContainerOnMissionCompletedRadio.setEnabled(false); + ui->saveVariableOnMissionCompletedRadio.setEnabled(false); ui->saveVariableOnMissionCloseRadio.setEnabled(false); ui->setVariableAsEternalcheckbox.setEnabled(false); @@ -611,7 +666,7 @@ void VariableDialog::updateVariableOptions() ui->deleteVariableButton.setEnabled(true); ui->setVariableAsStringRadio.setEnabled(true); ui->setVariableAsNumberRadio.setEnabled(true); - ui->saveContainerOnMissionCompletedRadio.setEnabled(true); + ui->saveVariableOnMissionCompletedRadio.setEnabled(true); ui->saveVariableOnMissionCloseRadio.setEnabled(true); ui->setVariableAsEternalcheckbox.setEnabled(true); @@ -626,10 +681,10 @@ void VariableDialog::updateVariableOptions() if (ret == 0){ // TODO ADD NO PERSISTENCE } else if (ret == 1) { - ui->saveContainerOnMissionCompletedRadio.setChecked(true); + ui->saveVariableOnMissionCompletedRadio.setChecked(true); ui->saveVariableOnMissionCloseRadio.setChecked(false); } else { - ui->saveContainerOnMissionCompletedRadio.setChecked(false); + ui->saveVariableOnMissionCompletedRadio.setChecked(false); ui->saveVariableOnMissionCloseRadio.setChecked(true); } @@ -639,6 +694,81 @@ void VariableDialog::updateVariableOptions() } void VariableDialog::updateContainerOptions() +{ + if (_currentContainer.empty()){ + ui->copyContainerButton.setEnabled(false); + ui->deleteContainerButton.setEnabled(false); + ui->setContainerAsStringRadio.setEnabled(false); + ui->setContainerAsNumberRadio.setEnabled(false); + ui->saveContainerOnMissionCompletedRadio.setEnabled(false); + ui->saveContainerOnMissionCloseRadio.setEnabled(false); + ui->setContainerAsEternalcheckbox.setEnabled(false); + ui->setContainerAsMapRadio.setEnabled(false); + ui->setContainerAsListRadio.setEnabled(false); + + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + + + } else { + ui->copyContainerButton.setEnabled(false); + ui->deleteContainerButton.setEnabled(false); + ui->setContainerAsStringRadio.setEnabled(false); + ui->setContainerAsNumberRadio.setEnabled(false); + ui->saveContainerOnMissionCompletedRadio.setEnabled(false); + ui->saveContainerOnMissionCloseRadio.setEnabled(false); + ui->setContainerAsEternalcheckbox.setEnabled(false); + ui->setContainerAsMapRadio.setEnabled(false); + ui->setContainerAsListRadio.setEnabled(false); + + if (_model->getContainerType(_currentContainer)){ + ui->setContainerAsStringRadio.setChecked(true); + ui->setContainerAsNumberRadio.setChecked(false); + } else { + ui->setContainerAsStringRadio.setChecked(false); + ui->setContainerAsNumberRadio.setChecked(true); + } + + if (_model->getConainerListOrMap(_currentContainer)){ + ui->setContainerAsListRadio.setChecked(true); + ui->setContainerAsMapRadio.setChecked(false); + + // Don't forget to change headings + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + updateContainerDataOptions(true); + + } else { + ui->setContainerAsListRadio.setChecked(false); + ui->setContainerAsMapRadio.setChecked(true); + + // Don't forget to change headings + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + updateContainerDataOptions(false); + } + + ui->setContainerAsEternalcheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); + ui->networkContainerCheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); + + // TODO! Add key data type controls + + int ret = getContainerOnMissionCloseOrCompleteFlag(_currentContainer); + + if (ret == 0){ + // TODO ADD NO PERSISTENCE + } else if (ret == 1) { + ui->saveContainerOnMissionCompletedRadio.setChecked(true); + ui->saveContainerOnMissionCloseRadio.setChecked(false); + } else { + ui->saveContainerOnMissionCompletedRadio.setChecked(false); + ui->saveContainerOnMissionCloseRadio.setChecked(true); + } + + } +} + +void VariableDialog::updateContainerDataOptions(bool list) { } diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index f4a4e70fa0a..6349adbd293 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -27,6 +27,10 @@ class VariableDialog : public QDialog { // basically UpdateUI, but called when there is an inconsistency between model and UI void applyModel(); + // Helper functions for this + void updateVariableOptions(); + void updateContainerOptions(); + void updateContainerDataOptions(bool list); void onVariablesTableUpdated(); void onVariablesSelectionChanged(); @@ -50,12 +54,15 @@ class VariableDialog : public QDialog { void onSetContainerAsMapRadioSelected(); void onSetContainerAsListRadioSelected(); void onSetContainerAsStringRadioSelected(); - void onSetContainerAsNumberRadio(); + void onSetContainerAsNumberRadioSelected(); + void onSetContainerKeyAsStringRadioSelected(); + void onSetContainerKeyAsNumberRadioSelected() void onSaveContainerOnMissionClosedRadioSelected(); void onSaveContainerOnMissionCompletedRadioSelected(); void onNetworkContainerCheckboxClicked(); void onSetContainerAsEternalCheckboxClicked(); void onAddContainerItemButtonPressed(); + void onCopyContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); SCP_string trimNumberString(SCP_string source); From 1581d9dc1f5fa7c6bf6b6b6ad8ba58dbbd258300 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 14 Apr 2024 12:34:20 -0400 Subject: [PATCH 028/153] Save progress --- qtfred/src/ui/dialogs/VariableDialog.cpp | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 900cc29c7c1..b5b29131bbd 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -228,7 +228,7 @@ void VariableDialog::onVariablesTableUpdated() auto items = ui->variablesTable->selectedItems(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + // yes, selected items returns a list, but we really should only have one row of items because multiselect will be off. for(const auto& item : items) { if (item->column() == 0){ @@ -238,7 +238,11 @@ void VariableDialog::onVariablesTableUpdated() // marking a variable as deleted failed, resync UI applyModel(); return; + } else { + updateVariableOptions(); } + } else { + } auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); @@ -576,15 +580,8 @@ void VariableDialog::applyModel() } } - // TODO! Make new ui function with the following stuff. - // get type with getVariableType - // get network status with getVariableNetworkStatus - // get getVariablesOnMissionCloseOrCompleteFlag - // getVariableEternalFlag - // string or number value with getVariableStringValue or getVariableNumberValue updateVariableOptions(); - auto containers = _model->getContainerNames(); selectedRow = -1; @@ -732,7 +729,11 @@ void VariableDialog::updateContainerOptions() if (_model->getConainerListOrMap(_currentContainer)){ ui->setContainerAsListRadio.setChecked(true); ui->setContainerAsMapRadio.setChecked(false); - + + // Disable Key Controls + ui->setContainerKeyAsStringRadio.setEnabled(false); + ui->setContainerKeyAsNumberRadio.setEnabled(false); + // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); @@ -742,6 +743,10 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsListRadio.setChecked(false); ui->setContainerAsMapRadio.setChecked(true); + // Enabled Key Controls + ui->setContainerKeyAsStringRadio.setEnabled(true); + ui->setContainerKeyAsNumberRadio.setEnabled(true); + // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); @@ -751,8 +756,6 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsEternalcheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); ui->networkContainerCheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); - // TODO! Add key data type controls - int ret = getContainerOnMissionCloseOrCompleteFlag(_currentContainer); if (ret == 0){ From 3d5c43e45dfcddc6baf78f0cc24f996d7c3d2f1e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 15 Apr 2024 22:43:45 -0400 Subject: [PATCH 029/153] Fix model functions by using index Instead of name. --- .../mission/dialogs/VariableDialogModel.cpp | 164 +++++++++--------- .../src/mission/dialogs/VariableDialogModel.h | 18 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 50 ++++-- 3 files changed, 123 insertions(+), 109 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index beccd62ba8f..9aaa440583b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -245,24 +245,24 @@ void VariableDialogModel::initializeData() // true on string, false on number -bool VariableDialogModel::getVariableType(SCP_string name) +bool VariableDialogModel::getVariableType(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); return (variable) ? (variable->string) : true; } -bool VariableDialogModel::getVariableNetworkStatus(SCP_string name) +bool VariableDialogModel::getVariableNetworkStatus(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); return (variable) ? ((variable->flags & SEXP_VARIABLE_NETWORK) > 0) : false; } // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) -int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(SCP_string name) +int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); if (!variable) { return 0; @@ -279,31 +279,31 @@ int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(SCP_string name } -bool VariableDialogModel::getVariableEternalFlag(SCP_string name) +bool VariableDialogModel::getVariableEternalFlag(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); return (variable) ? ((variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; } -SCP_string VariableDialogModel::getVariableStringValue(SCP_string name) +SCP_string VariableDialogModel::getVariableStringValue(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); return (variable && variable->string) ? (variable->stringValue) : ""; } -int VariableDialogModel::getVariableNumberValue(SCP_string name) +int VariableDialogModel::getVariableNumberValue(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); return (variable && !variable->string) ? (variable->numberValue) : 0; } // true on string, false on number -bool VariableDialogModel::setVariableType(SCP_string name, bool string) +bool VariableDialogModel::setVariableType(int index, bool string) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry // Best way to say that it failed is to say @@ -370,9 +370,9 @@ bool VariableDialogModel::setVariableType(SCP_string name, bool string) } } -bool VariableDialogModel::setVariableNetworkStatus(SCP_string name, bool network) +bool VariableDialogModel::setVariableNetworkStatus(int index, bool network) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable){ @@ -387,9 +387,9 @@ bool VariableDialogModel::setVariableNetworkStatus(SCP_string name, bool network return network; } -int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(SCP_string name, int flags) +int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(int index, int flags) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable || flags < 0 || flags > 2){ @@ -408,9 +408,9 @@ int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(SCP_string name return flags; } -bool VariableDialogModel::setVariableEternalFlag(SCP_string name, bool eternal) +bool VariableDialogModel::setVariableEternalFlag(int index, bool eternal) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable){ @@ -426,9 +426,9 @@ bool VariableDialogModel::setVariableEternalFlag(SCP_string name, bool eternal) return eternal; } -SCP_string VariableDialogModel::setVariableStringValue(SCP_string name, SCP_string value) +SCP_string VariableDialogModel::setVariableStringValue(int index, SCP_string value) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable || !variable->string){ @@ -438,9 +438,9 @@ SCP_string VariableDialogModel::setVariableStringValue(SCP_string name, SCP_stri variable->stringValue = value; } -int VariableDialogModel::setVariableNumberValue(SCP_string name, int value) +int VariableDialogModel::setVariableNumberValue(int index, int value) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable || variable->string){ @@ -459,7 +459,7 @@ SCP_string VariableDialogModel::addNewVariable() do { name = ""; sprintf(name, "", count); - variable = lookupVariable(name); + variable = lookupVariableByName(name); ++count; } while (variable != nullptr && count < 51); @@ -473,13 +473,13 @@ SCP_string VariableDialogModel::addNewVariable() return name; } -SCP_string VariableDialogModel::changeVariableName(SCP_string oldName, SCP_string newName) +SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName) { if (newName == "") { return ""; } - auto variable = lookupVariable(oldName); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable){ @@ -491,9 +491,9 @@ SCP_string VariableDialogModel::changeVariableName(SCP_string oldName, SCP_strin return newName; } -SCP_string VariableDialogModel::copyVariable(SCP_string name) +SCP_string VariableDialogModel::copyVariable(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable){ @@ -506,7 +506,7 @@ SCP_string VariableDialogModel::copyVariable(SCP_string name) do { SCP_string newName; sprintf(newName, "%s_copy%i", name, count); - variableSearch = lookupVariable(newName); + variableSearch = lookupVariableByName(newName); // open slot found! if (!variableSearch){ @@ -533,9 +533,9 @@ SCP_string VariableDialogModel::copyVariable(SCP_string name) } // returns whether it succeeded -bool VariableDialogModel::removeVariable(SCP_string name) +bool VariableDialogModel::removeVariable(int index) { - auto variable = lookupVariable(name); + auto variable = lookupVariable(index); // nothing to change, or invalid entry if (!variable){ @@ -556,29 +556,29 @@ bool VariableDialogModel::removeVariable(SCP_string name) // Container Section // true on string, false on number -bool VariableDialogModel::getContainerValueType(SCP_string name) +bool VariableDialogModel::getContainerValueType(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); return (container) ? container->string : true; } // true on list, false on map -bool VariableDialogModel::getContainerListOrMap(SCP_string name) +bool VariableDialogModel::getContainerListOrMap(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); return (container) ? container->list : true; } -bool VariableDialogModel::getContainerNetworkStatus(SCP_string name) +bool VariableDialogModel::getContainerNetworkStatus(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); return (container) ? ((container->flags & SEXP_VARIABLE_NETWORK) > 0) : false; } // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) -int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(SCP_string name) +int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); if (!container) { return 0; @@ -592,16 +592,16 @@ int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(SCP_string nam return 0; } -bool VariableDialogModel::getContainerEternalFlag(SCP_string name) +bool VariableDialogModel::getContainerEternalFlag(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); return (container) ? ((container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; } -bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) +bool VariableDialogModel::setContainerValueType(int index, bool type) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); if (!container){ return true; @@ -679,14 +679,14 @@ bool VariableDialogModel::setContainerValueType(SCP_string name, bool type) } // This is the most complicated function, because we need to query the user on what they want to do if the had already entered data. -bool VariableDialogModel::setContainerListOrMap(SCP_string name, bool list) +bool VariableDialogModel::setContainerListOrMap(int index, bool list) { return false; } -bool VariableDialogModel::setContainerNetworkStatus(SCP_string name, bool network) +bool VariableDialogModel::setContainerNetworkStatus(int index, bool network) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); // nothing to change, or invalid entry if (!container){ @@ -702,9 +702,9 @@ bool VariableDialogModel::setContainerNetworkStatus(SCP_string name, bool networ return network; } -int VariableDialogModel::setContainerOnMissionCloseOrCompleteFlag(SCP_string name, int flags) +int VariableDialogModel::setContainerOnMissionCloseOrCompleteFlag(int index, int flags) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); // nothing to change, or invalid entry if (!container || flags < 0 || flags > 2){ @@ -723,9 +723,9 @@ int VariableDialogModel::setContainerOnMissionCloseOrCompleteFlag(SCP_string nam return flags; } -bool VariableDialogModel::setContainerEternalFlag(SCP_string name, bool eternal) +bool VariableDialogModel::setContainerEternalFlag(int index, bool eternal) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); // nothing to change, or invalid entry if (!container){ @@ -763,13 +763,13 @@ SCP_string VariableDialogModel::addContainer() return name; } -SCP_string VariableDialogModel::changeContainerName(SCP_string oldName, SCP_string newName) +SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) { if (newName == "") { return ""; } - auto container = lookupContainer(oldName); + auto container = lookupContainer(index); // nothing to change, or invalid entry if (!container){ @@ -781,9 +781,9 @@ SCP_string VariableDialogModel::changeContainerName(SCP_string oldName, SCP_stri return newName; } -bool VariableDialogModel::removeContainer(SCP_string name) +bool VariableDialogModel::removeContainer(int index) { - auto container = lookupContainer(name); + auto container = lookupContainer(index); if (!container){ return false; @@ -792,9 +792,9 @@ bool VariableDialogModel::removeContainer(SCP_string name) container->deleted = true; } -SCP_string VariableDialogModel::addListItem(SCP_string containerName) +SCP_string VariableDialogModel::addListItem(int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container){ return ""; @@ -809,14 +809,14 @@ SCP_string VariableDialogModel::addListItem(SCP_string containerName) } } -std::pair VariableDialogModel::addMapItem(SCP_string ContainerName) +std::pair VariableDialogModel::addMapItem(int index) { } -SCP_string VariableDialogModel::copyListItem(SCP_string containerName, int index) +SCP_string VariableDialogModel::copyListItem(int index, int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ return ""; @@ -832,9 +832,9 @@ SCP_string VariableDialogModel::copyListItem(SCP_string containerName, int index } -bool VariableDialogModel::removeListItem(SCP_string containerName, int index) +bool VariableDialogModel::removeListItem(int containerIndex, int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(containerIndex); if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ return false; @@ -849,9 +849,9 @@ bool VariableDialogModel::removeListItem(SCP_string containerName, int index) } -std::pair VariableDialogModel::copyMapItem(SCP_string containerName, SCP_string keyIn) +std::pair VariableDialogModel::copyMapItem(int index, SCP_string keyIn) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container) { return std::make_pair("", ""); @@ -952,9 +952,9 @@ std::pair VariableDialogModel::copyMapItem(SCP_string co // both of the map's data vectors might be undesired, and not deleting takes the map immediately // out of sync. Also, just displaying both data sets would be misleading. // We just need to tell the user that the data cannot be maintained. -bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key) +bool VariableDialogModel::removeMapItem(int index, SCP_string key) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container){ return false; @@ -981,9 +981,9 @@ bool VariableDialogModel::removeMapItem(SCP_string containerName, SCP_string key return false; } -SCP_string VariableDialogModel::replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey) +SCP_string VariableDialogModel::replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container){ return ""; @@ -1000,9 +1000,9 @@ SCP_string VariableDialogModel::replaceMapItemKey(SCP_string containerName, SCP_ return oldKey; } -SCP_string VariableDialogModel::changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue) +SCP_string VariableDialogModel::changeMapItemStringValue(int index, SCP_string key, SCP_string newValue) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container || !container->string){ return ""; @@ -1023,9 +1023,9 @@ SCP_string VariableDialogModel::changeMapItemStringValue(SCP_string containerNam return ""; } -SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue) +SCP_string VariableDialogModel::changeMapItemNumberValue(int index, SCP_string key, int newValue) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container || !container->string){ return ""; @@ -1049,9 +1049,9 @@ SCP_string VariableDialogModel::changeMapItemNumberValue(SCP_string containerNam } // These functions should only be called when the container is guaranteed to exist! -const SCP_vector& VariableDialogModel::getMapKeys(SCP_string containerName) +const SCP_vector& VariableDialogModel::getMapKeys(int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container) { SCP_string temp; @@ -1069,19 +1069,19 @@ const SCP_vector& VariableDialogModel::getMapKeys(SCP_string contain } // Only call when the container is guaranteed to exist! -const SCP_vector& VariableDialogModel::getStringValues(SCP_string containerName) +const SCP_vector& VariableDialogModel::getStringValues(int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container) { SCP_string temp; - sprintf("getStringValues() found that container %s does not exist.", containerName.c_str()); + sprintf("getStringValues() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp); } if (!container->string) { SCP_string temp; - sprintf("getStringValues() found that container %s does not store strings.", containerName.c_str()); + sprintf("getStringValues() found that container %s does not store strings.", container->name.c_str()); throw std::invalid_argument(temp); } @@ -1089,19 +1089,19 @@ const SCP_vector& VariableDialogModel::getStringValues(SCP_string co } // Only call when the container is guaranteed to exist! -const SCP_vector& VariableDialogModel::getNumberValues(SCP_string containerName) +const SCP_vector& VariableDialogModel::getNumberValues(int index) { - auto container = lookupContainer(containerName); + auto container = lookupContainer(index); if (!container) { SCP_string temp; - sprintf("getNumberValues() found that container %s does not exist.", containerName.c_str()); + sprintf("getNumberValues() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp); } if (container->string) { SCP_string temp; - sprintf("getNumberValues() found that container %s does not store numbers.", containerName.c_str()); + sprintf("getNumberValues() found that container %s does not store numbers.", container->name.c_str()); throw std::invalid_argument(temp); } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 187633e68bd..ff8b77054f0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -118,23 +118,19 @@ class VariableDialogModel : public AbstractDialogModel { SCP_vector _variableItems; SCP_vector _containerItems; - variableInfo* lookupVariable(SCP_string name){ - for (int x = 0; x < static_cast(_variableItems.size()); ++x){ - if (_variableItems[x].name == name){ - return &_variableItems[x]; - } + variableInfo* lookupVariable(int index){ + if(index > -1 && index < static_cast(_variableItems.size()) ){ + return &_variableItems[index]; } return nullptr; } - containerInfo* lookupContainer(SCP_string name){ - for (int x = 0; x < static_cast(_containerItems.size()); ++x){ - if (_containerItems[x].name == name){ - return &_containerItems[x]; - } + containerInfo* lookupContainer(int index){ + if(index > -1 && index < static_cast(_containerItems.size()) ){ + return &_containerItems[index]; } - + return nullptr; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b5b29131bbd..70567b3d840 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -243,21 +243,19 @@ void VariableDialog::onVariablesTableUpdated() } } else { - } - - auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); + auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); - // we put something in the cell, but the model couldn't process it. - if (strlen(item->text()) && ret == ""){ - // update of variable name failed, resync UI - applyModel(); + // we put something in the cell, but the model couldn't process it. + if (strlen(item->text()) && ret == ""){ + // update of variable name failed, resync UI + applyModel(); - // we had a successful rename. So update the variable we reference. - } else if (ret != "") { - item->setText(ret.c_str()); - _currentVariable = ret; + // we had a successful rename. So update the variable we reference. + } else if (ret != "") { + item->setText(ret.c_str()); + _currentVariable = ret; + } } - // empty return and cell was handled earlier. // data cell was altered @@ -335,6 +333,7 @@ void VariableDialog::onContainersTableUpdated() return; } + } // could be new name void VariableDialog::onContainersSelectionChanged() @@ -345,15 +344,18 @@ void VariableDialog::onContainersSelectionChanged() auto items = ui->containersTable->selectedItems(); - SCP_string newVariableName = ""; + SCP_string newContainerName = ""; // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for(const auto& item : items) { - newVariableName = item->text().toStdString(); + if (item->column() == 0){ + newContainerName = item->text().toStdString(); + break; + } } - if (newVariableName != _currentVariable){ - _currentVariable = newVariableName; + if (newContainerName != _currentContainer){ + _currentContainer = newContainerName; applyModel(); } } @@ -372,6 +374,22 @@ void VariableDialog::onContainerContentsSelectionChanged() { return; } + auto items = ui->containersContentsTable->selectedItems(); + + SCP_string newContainerItemName = ""; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + if (item->column() == 0){ + newContainerItemName = item->text().toStdString(); + break; + } + } + + if (newContainerItemName != _currentContainerItem){ + _currentContainerItem = newContainerItemName; + applyModel(); + } } void VariableDialog::onAddVariableButtonPressed() From 7938169730935f774630dcb72b6403e96f4a92ec Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 15 Apr 2024 22:50:05 -0400 Subject: [PATCH 030/153] Don't forget lookup by name functions This helps prevent name collisions --- .../src/mission/dialogs/VariableDialogModel.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index ff8b77054f0..a26646ee300 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -126,6 +126,16 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } + variableInfo* lookupVariableByName(SCP_string name){ + for (int x = 0; x < static_cast(_variableItems.size())){ + if (_variableItems.name == name){ + return &_variableItems[x]; + } + } + + return nullptr; + } + containerInfo* lookupContainer(int index){ if(index > -1 && index < static_cast(_containerItems.size()) ){ return &_containerItems[index]; @@ -134,6 +144,16 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } + containerInfo* lookupContainerByName(SCP_string name){ + for (int x = 0; x < static_cast(_containerItems.size())){ + if (_containerItems.name == name){ + return &_containerItems[x]; + } + } + + return nullptr; + } + // many of the controls in this editor can lead to drastic actions, so this will be very useful. const bool confirmAction(SCP_string question, SCP_string informativeText) { From e1662d8501803b81c16c2c1b670089961cab4903 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Tue, 16 Apr 2024 00:22:40 -0400 Subject: [PATCH 031/153] Fix many typos from lack of linter --- .../mission/dialogs/VariableDialogModel.cpp | 48 +-- .../src/mission/dialogs/VariableDialogModel.h | 91 ++--- qtfred/src/ui/dialogs/VariableDialog.cpp | 368 +++++++++++------- qtfred/src/ui/dialogs/VariableDialog.h | 2 +- qtfred/ui/VariableDialog.ui | 142 +++++-- 5 files changed, 392 insertions(+), 259 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 9aaa440583b..59b8b99a681 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -39,7 +39,7 @@ void VariableDialogModel::checkValidModel() if (messageOut2.empty()){ messageOut2 = "\"" + item + "\""; } else { - messageOut2 += ", "\"" + item + "\""; + messageOut2 += ", ""\"" + item + "\""; } } @@ -48,7 +48,7 @@ void VariableDialogModel::checkValidModel() } duplicates.clear(); - unordered_set namesTakenContainer; + std::unordered_set namesTakenContainer; SCP_vector duplicateKeys; for (const auto& container : _containerItems){ @@ -57,10 +57,10 @@ void VariableDialogModel::checkValidModel() } if (!container.list){ - unordered_set keysTakenContainer; + std::unordered_set keysTakenContainer; for (const auto& key : container.keys){ - if (!keysTakenContainer.insert(key)) { + if (!keysTakenContainer.insert(key).second) { SCP_string temp = key + "in map" + container.name + ", "; duplicateKeys.push_back(temp); } @@ -75,7 +75,7 @@ void VariableDialogModel::checkValidModel() if (messageOut2.empty()){ messageOut2 = "\"" + item + "\""; } else { - messageOut2 += ", "\"" + item + "\""; + messageOut2 += ", ""\"" + item + "\""; } } @@ -128,7 +128,7 @@ bool VariableDialogModel::apply() // set of instructions for updating variables if (!variable.originalName.empty()) { for (int i = 0; i < MAX_SEXP_VARIABLES; ++i) { - if (!stricmp(Sexp_variables[i].variable_name, variable.originalName)){ + if (!stricmp(Sexp_variables[i].variable_name, variable.originalName.c_str())){ if (variable.deleted) { memset(Sexp_variables[i].variable_name, 0, NAME_LENGTH); memset(Sexp_variables[i].text, 0, NAME_LENGTH); @@ -141,14 +141,14 @@ bool VariableDialogModel::apply() } strcpy_s(Sexp_variables[i].variable_name, variable.name.c_str()); - Sexp_variables[i].flags = variable.flags; + Sexp_variables[i].type = variable.flags; if (variable.flags & SEXP_VARIABLE_STRING){ - strcpy_s(Sexp_variables[i].text, variable.stringValue); - Sexp_variables[i].flags |= SEXP_VARIABLE_STRING; + strcpy_s(Sexp_variables[i].text, variable.stringValue.c_str()); + Sexp_variables[i].type |= SEXP_VARIABLE_STRING; } else { - strcpy_s(Sexp_variables[i].text, std::to_string(variable.numberValue).c_str()) - Sexp_variables[i].flags |= SEXP_VARIABLE_NUMBER; + strcpy_s(Sexp_variables[i].text, std::to_string(variable.numberValue).c_str()); + Sexp_variables[i].type |= SEXP_VARIABLE_NUMBER; } } @@ -215,27 +215,27 @@ void VariableDialogModel::initializeData() newContainer.originalName = newContainer.name; newContainer.deleted = false; - if (container.type & ContainerType::STRING_DATA) { + if (any(container.type & ContainerType::STRING_DATA)) { newContainer.string = true; - } else if (container.type & ContainerType::NUMBER_DATA) { + } else if (any(container.type & ContainerType::NUMBER_DATA)) { newContainer.string = false; } // using the SEXP variable version of these values here makes things easier - if (container.type & ContainerType::SAVE_TO_PLAYER_FILE) { + if (any(container.type & ContainerType::SAVE_TO_PLAYER_FILE)) { newContainer.flags |= SEXP_VARIABLE_SAVE_TO_PLAYER_FILE; } - if (container.type & ContainerType::SAVE_ON_MISSION_CLOSE) { + if (any(container.type & ContainerType::SAVE_ON_MISSION_CLOSE)) { newContainer.flags |= SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE; } - if (container.type & ContainerType::SAVE_ON_MISSION_PROGRESS) { + if (any(container.type & ContainerType::SAVE_ON_MISSION_PROGRESS)) { newContainer.flags |= SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS; } - if (container.type & ContainerType::NETWORK) { - newContainer.flags =| SEXP_VARIABLE_NETWORK; + if (any(container.type & ContainerType::NETWORK)) { + newContainer.flags |= SEXP_VARIABLE_NETWORK; } newContainer.list = container.is_list(); @@ -505,7 +505,7 @@ SCP_string VariableDialogModel::copyVariable(int index) do { SCP_string newName; - sprintf(newName, "%s_copy%i", name, count); + sprintf(newName, "%s_copy%i", variable->name.c_str(), count); variableSearch = lookupVariableByName(newName); // open slot found! @@ -750,7 +750,7 @@ SCP_string VariableDialogModel::addContainer() do { name = ""; sprintf(name, "", count); - container = lookupContainer(name); + container = lookupContainerByName(name); ++count; } while (container != nullptr && count < 51); @@ -814,9 +814,9 @@ std::pair VariableDialogModel::addMapItem(int index) } -SCP_string VariableDialogModel::copyListItem(int index, int index) +SCP_string VariableDialogModel::copyListItem(int containerIndex, int index) { - auto container = lookupContainer(index); + auto container = lookupContainer(containerIndex); if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ return ""; @@ -1055,13 +1055,13 @@ const SCP_vector& VariableDialogModel::getMapKeys(int index) if (!container) { SCP_string temp; - sprintf("getMapKeys() found that container %s does not exist.", containerName.c_str()); + sprintf("getMapKeys() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp.c_str()); } if (container->list) { SCP_string temp; - sprintf("getMapKeys() found that container %s is not a map.", containerName.c_str()); + sprintf("getMapKeys() found that container %s is not a map.", container->name.c_str()); throw std::invalid_argument(temp); } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index a26646ee300..0933694a832 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -40,14 +40,14 @@ class VariableDialogModel : public AbstractDialogModel { VariableDialogModel(QObject* parent, EditorViewport* viewport); // true on string, false on number - bool getVariableType(SCP_string name); - bool getVariableNetworkStatus(SCP_string name); + bool getVariableType(int index); + bool getVariableNetworkStatus(int index); // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) - int getVariableOnMissionCloseOrCompleteFlag(SCP_string name); - bool getVariableEternalFlag(SCP_string name); + int getVariableOnMissionCloseOrCompleteFlag(int index); + bool getVariableEternalFlag(int index); - SCP_string getVariableStringValue(SCP_string name); - int getVariableNumberValue(SCP_string name); + SCP_string getVariableStringValue(int index); + int getVariableNumberValue(int index); // !! Note an innovation: when getting a request to set a value, // this model will return the value that sticks and then will overwrite @@ -55,60 +55,61 @@ class VariableDialogModel : public AbstractDialogModel { // repopulate the whole editor on each change. // true on string, false on number - bool setVariableType(SCP_string name, bool string); - bool setVariableNetworkStatus(SCP_string name, bool network); - int setVariableOnMissionCloseOrCompleteFlag(SCP_string name, int flags); - bool setVariableEternalFlag(SCP_string name, bool eternal); + bool setVariableType(int index, bool string); + bool setVariableNetworkStatus(int index, bool network); + int setVariableOnMissionCloseOrCompleteFlag(int index, int flags); + bool setVariableEternalFlag(int index, bool eternal); - SCP_string setVariableStringValue(SCP_string name, SCP_string value); - int setVariableNumberValue(SCP_string name, int value); + SCP_string setVariableStringValue(int index, SCP_string value); + int setVariableNumberValue(int index, int value); SCP_string addNewVariable(); - SCP_string changeVariableName(SCP_string oldName, SCP_string newName); - SCP_string copyVariable(SCP_string name); + SCP_string changeVariableName(int index, SCP_string newName); + SCP_string copyVariable(int index); // returns whether it succeeded - bool removeVariable(SCP_string name); + bool removeVariable(int index); // Container Section // true on string, false on number - bool getContainerValueType(SCP_string name); + bool getContainerValueType(int index); // true on list, false on map - bool getContainerListOrMap(SCP_string name); - bool getContainerNetworkStatus(SCP_string name); + bool getContainerListOrMap(int index); + bool getContainerNetworkStatus(int index); // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) - int getContainerOnMissionCloseOrCompleteFlag(SCP_string name); - bool getContainerEternalFlag(SCP_string name); + int getContainerOnMissionCloseOrCompleteFlag(int index); + bool getContainerEternalFlag(int index); - bool setContainerValueType(SCP_string name, bool type); - bool setContainerListOrMap(SCP_string name, bool list); - bool setContainerNetworkStatus(SCP_string name, bool network); - int setContainerOnMissionCloseOrCompleteFlag(SCP_string name, int flags); - bool setContainerEternalFlag(SCP_string name, bool eternal); + bool setContainerValueType(int index, bool type); + bool setContainerListOrMap(int index, bool list); + bool setContainerNetworkStatus(int index, bool network); + int setContainerOnMissionCloseOrCompleteFlag(int index, int flags); + bool setContainerEternalFlag(int index, bool eternal); SCP_string addContainer(); - SCP_string changeContainerName(SCP_string oldName, SCP_string newName); - bool removeContainer(SCP_string name); + SCP_string changeContainerName(int index, SCP_string newName); + bool removeContainer(int index); - SCP_string addListItem(SCP_string containerName); + SCP_string addListItem(int index); - SCP_string copyListItem(SCP_string containerName, int index); - bool removeListItem(SCP_string containerName, int index); + SCP_string copyListItem(int containerIndex, int index); + bool removeListItem(int containerindex, int index); - std::pair addMapItem(SCP_string ContainerName); - std::pair copyMapItem(SCP_string containerName, SCP_string key); - bool removeMapItem(SCP_string containerName, SCP_string key); + std::pair addMapItem(int index); + std::pair copyMapItem(int index, SCP_string key); + bool removeMapItem(int index, SCP_string key); - SCP_string replaceMapItemKey(SCP_string containerName, SCP_string oldKey, SCP_string newKey); - SCP_string changeMapItemStringValue(SCP_string containerName, SCP_string key, SCP_string newValue); - SCP_string changeMapItemNumberValue(SCP_string containerName, SCP_string key, int newValue); + SCP_string replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey); + SCP_string changeMapItemStringValue(int index, SCP_string key, SCP_string newValue); + SCP_string changeMapItemNumberValue(int index, SCP_string key, int newValue); - const SCP_vector& getMapKeys(SCP_string containerName); - const SCP_vector& getStringValues(SCP_string containerName); - const SCP_vector& getNumberValues(SCP_string containerName); + const SCP_vector& getMapKeys(int index); + const SCP_vector& getStringValues(int index); + const SCP_vector& getNumberValues(int index); - const SCP_vector> getVariableValues(); - const SCP_vector> getContainerNames(); + const SCP_vector> getVariableValues(); + const SCP_vector> getContainerNames(); + void VariableDialogModel::checkValidModel(); bool apply() override; void reject() override; @@ -127,8 +128,8 @@ class VariableDialogModel : public AbstractDialogModel { } variableInfo* lookupVariableByName(SCP_string name){ - for (int x = 0; x < static_cast(_variableItems.size())){ - if (_variableItems.name == name){ + for (int x = 0; x < static_cast(_variableItems.size()); ++x) { + if (_variableItems[x].name == name) { return &_variableItems[x]; } } @@ -145,8 +146,8 @@ class VariableDialogModel : public AbstractDialogModel { } containerInfo* lookupContainerByName(SCP_string name){ - for (int x = 0; x < static_cast(_containerItems.size())){ - if (_containerItems.name == name){ + for (int x = 0; x < static_cast(_containerItems.size()); ++x) { + if (_containerItems[x].name == name) { return &_containerItems[x]; } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 70567b3d840..489527eec92 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1,6 +1,7 @@ #include "VariableDialog.h" #include "ui_VariableDialog.h" +#include #include #include @@ -20,7 +21,6 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) resize(QDialog::sizeHint()); // The best I can tell without some research, when a dialog doesn't use an underling grid or layout, it needs to be resized this way before anything will show up // Major Changes, like Applying the model, rejecting changes and updating the UI. - connect(_model.get(), &AbstractDialogModel::modelChanged, this, &VariableDialog::updateUI); connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::checkValidModel); connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); @@ -233,7 +233,7 @@ void VariableDialog::onVariablesTableUpdated() if (item->column() == 0){ // so if the user just removed the name, mark it as deleted *before changing the name* - if (_currentVariable != "" && !strlen(item->text.c_str())){ + if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { if (!_model->removeVariable(item->row())) { // marking a variable as deleted failed, resync UI applyModel(); @@ -246,7 +246,7 @@ void VariableDialog::onVariablesTableUpdated() auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); // we put something in the cell, but the model couldn't process it. - if (strlen(item->text()) && ret == ""){ + if (strlen(item->text().toStdString().c_str()) && ret == ""){ // update of variable name failed, resync UI applyModel(); @@ -262,11 +262,11 @@ void VariableDialog::onVariablesTableUpdated() } else if (item->column() == 1) { // Variable is a string - if (_model->getVariableType(int->row())){ - SCP_string temp = item->text()->toStdString().c_str(); + if (_model->getVariableType(item->row())){ + SCP_string temp = item->text().toStdString().c_str(); temp = temp.substr(0, NAME_LENGTH - 1); - SCP_string ret = _model->setVariableStringValue(int->row(), temp); + SCP_string ret = _model->setVariableStringValue(item->row(), temp); if (ret == ""){ applyModel(); return; @@ -274,10 +274,8 @@ void VariableDialog::onVariablesTableUpdated() item->setText(ret.c_str()); } else { - SCP_string temp; SCP_string source = item->text().toStdString(); - - SCP_string temp = trimNumberString(); + SCP_string temp = trimNumberString(source); if (temp != source){ item->setText(temp.c_str()); @@ -287,7 +285,7 @@ void VariableDialog::onVariablesTableUpdated() int ret = _model->setVariableNumberValue(item->row(), std::stoi(temp)); temp = ""; sprintf(temp, "%i", ret); - item->setText(temp); + item->setText(temp.c_str()); } catch (...) { applyModel(); @@ -374,7 +372,7 @@ void VariableDialog::onContainerContentsSelectionChanged() { return; } - auto items = ui->containersContentsTable->selectedItems(); + auto items = ui->containerContentsTable->selectedItems(); SCP_string newContainerItemName = ""; @@ -394,7 +392,7 @@ void VariableDialog::onContainerContentsSelectionChanged() { void VariableDialog::onAddVariableButtonPressed() { - auto ret = _model->addNewVriable(); + auto ret = _model->addNewVariable(); _currentVariable = ret; applyModel(); } @@ -405,9 +403,15 @@ void VariableDialog::onCopyVariableButtonPressed() return; } - auto ret = _model->copyVariable(_currentVariable); - _currentVariable = ret; - applyModel(); + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + auto ret = _model->copyVariable(item->row()); + _currentVariable = ret; + applyModel(); + break; + } } void VariableDialog::onDeleteVariableButtonPressed() @@ -416,9 +420,15 @@ void VariableDialog::onDeleteVariableButtonPressed() return; } - // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - _model->removeVariable(_currentVariable); - applyModel(); + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + // Because of the text update we'll need, this needs an applyModel, whether it fails or not. + auto ret = _model->removeVariable(item->row()); + applyModel(); + break; + } } void VariableDialog::onSetVariableAsStringRadioSelected() @@ -427,14 +437,23 @@ void VariableDialog::onSetVariableAsStringRadioSelected() return; } - // this doesn't return succeed or fail directly, - // but if it doesn't return true then it failed since this is the string radio - if(!_model->setVariableType(_currentVariable, true)){ - applyModel(); - } else { - ui->setVariableAsStringRadio->setChecked(true); - ui->setVariableAsNumberRadio->setChecked(false); + + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for(const auto& item : items) { + // this doesn't return succeed or fail directly, + // but if it doesn't return true then it failed since this is the string radio + if(!_model->setVariableType(item->row(), true)){ + applyModel(); + } else { + ui->setVariableAsStringRadio->setChecked(true); + ui->setVariableAsNumberRadio->setChecked(false); + } + + break; } + } void VariableDialog::onSetVariableAsNumberRadioSelected() @@ -443,13 +462,20 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() return; } - // this doesn't return succeed or fail directly, - // but if it doesn't return false then it failed since this is the number radio - if(!_model->setVariableType(_currentVariable, false)){ - applyModel(); - } else { - ui->setVariableAsStringRadio->setChecked(false); - ui->setVariableAsNumberRadio->setChecked(true); + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + + // this doesn't return succeed or fail directly, + // but if it doesn't return false then it failed since this is the number radio + if (!_model->setVariableType(item->row(), false)) { + applyModel(); + } + else { + ui->setVariableAsStringRadio->setChecked(false); + ui->setVariableAsNumberRadio->setChecked(true); + } } } @@ -460,15 +486,20 @@ void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() return; } - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(_currentVariable, 1); + auto items = ui->variablesTable->selectedItems(); - if (ret != 1){ - applyModel(); - } else { - // TODO! Need "no persistence" options and functions! - ui->saveContainerOnMissionCompletedRadio->setChecked(true); - ui->saveVariableOnMissionCloseRadio->setChecked(false); - //ui->saveContainerOnMissionCompletedRadio->setChecked(true); + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 1); + + if (ret != 1){ + applyModel(); + } else { + // TODO! Need "no persistence" options and functions! + ui->saveContainerOnMissionCompletedRadio->setChecked(true); + ui->saveVariableOnMissionCloseRadio->setChecked(false); + //ui->saveContainerOnMissionCompletedRadio->setChecked(true); + } } } @@ -478,15 +509,22 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() return; } - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(_currentVariable, 2); - if (ret != 2){ - applyModel(); - } else { - // TODO! Need "no persistence" options. - ui->saveContainerOnMissionCompletedRadio->setChecked(false); - ui->saveVariableOnMissionCloseRadio->setChecked(true); - //ui->saveContainerOnMissionCompletedRadio->setChecked(false); + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 2); + + if (ret != 2){ + applyModel(); + } else { + // TODO! Need "no persistence" options. + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(true); + //ui->saveContainerOnMissionCompletedRadio->setChecked(false); + } } } @@ -496,11 +534,17 @@ void VariableDialog::onSaveVariableAsEternalCheckboxClicked() return; } - // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(_currentVariable, !ui->setVariableAsEternalcheckbox->isChecked())){ - applyModel(); - } else { - _ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); + + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(item->row(), !ui->setVariableAsEternalcheckbox->isChecked())) { + applyModel(); + } else { + ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); + } } } @@ -510,11 +554,17 @@ void VariableDialog::onNetworkVariableCheckboxClicked() return; } - // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableNetworkStatus->isChecked() == _model->setVariableNetworkStatus(_currentVariable, !ui->setVariableNetworkStatus->isChecked())){ - applyModel(); - } else { - _ui->setVariableNetworkStatus->setChecked(!ui->setVariableNetworkStatus->isChecked()); + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(item->row(), !ui->networkVariableCheckbox->isChecked())) { + applyModel(); + } else { + ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); + } } } @@ -547,28 +597,28 @@ void VariableDialog::applyModel() for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ - ui->variablesTable->item(x, 0)->setText(variables[x]<0>.c_str()); + ui->variablesTable->item(x, 0)->setText(variables[x][0].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(variables[x]<0>.c_str()); + QTableWidgetItem* item = new QTableWidgetItem(variables[x][0].c_str()); ui->variablesTable->setItem(x, 0, item); } // check if this is the current variable. - if (!_currentVariable.empty() && variables[x]<0> == _currentVariable){ - selectedRow = x + if (!_currentVariable.empty() && variables[x][0].c_str() == _currentVariable){ + selectedRow = x; } if (ui->variablesTable->item(x, 1)){ - ui->variablesTable->item(x, 1)->setText(variables[x]<1>.c_str()); + ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(variables[x]<1>.c_str()); - ui->variablesTable->setItem(x, 1, nameItem); + QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); + ui->variablesTable->setItem(x, 1, item); } if (ui->variablesTable->item(x, 2)){ - ui->variablesTable->item(x, 2)->setText(variables[x]<2>.c_str()); + ui->variablesTable->item(x, 2)->setText(variables[x][2].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(variables[x]<2>.c_str()); + QTableWidgetItem* item = new QTableWidgetItem(variables[x][2].c_str()); ui->variablesTable->setItem(x, 2, item); } } @@ -593,8 +643,8 @@ void VariableDialog::applyModel() } if (_currentVariable.empty() || selectedRow < 0){ - if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text())){ - _currentVariable = ui->variablesTable->item(0,0)->text(); + if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text().toStdString().c_str())){ + _currentVariable = ui->variablesTable->item(0,0)->text().toStdString(); } } @@ -606,29 +656,29 @@ void VariableDialog::applyModel() // TODO! Change getContainerNames to a tuple with notes/maybe data key types? for (x = 0; x < static_cast(containers.size()); ++x){ if (ui->containersTable->item(x, 0)){ - ui->containersTable->item(x, 0)->setText(containers[x]<0>.c_str()); + ui->containersTable->item(x, 0)->setText(containers[x][0].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(containers[x]<0>.c_str()); + QTableWidgetItem* item = new QTableWidgetItem(containers[x][0].c_str()); ui->containersTable->setItem(x, 0, item); } // check if this is the current variable. - if (!_currentVariable.empty() && containers[x]<0> == _currentVariable){ + if (!_currentVariable.empty() && containers[x][0] == _currentVariable){ selectedRow = x; } if (ui->containersTable->item(x, 1)){ - ui->containersTable->item(x, 1)->setText(containers[x]<1>.c_str()); + ui->containersTable->item(x, 1)->setText(containers[x][1].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(containers[x]<1>.c_str()); - ui->containersTable->setItem(x, 1, nameItem); + QTableWidgetItem* item = new QTableWidgetItem(containers[x][1].c_str()); + ui->containersTable->setItem(x, 1, item); } if (ui->containersTable->item(x, 2)){ - ui->containersTable->item(x, 2)->setText(containers[x]<2>.c_str()); + ui->containersTable->item(x, 2)->setText(containers[x][2].c_str()); } else { - QTableWidgetItem* item = new QTableWidgetItem(containers[x]<2>.c_str()); + QTableWidgetItem* item = new QTableWidgetItem(containers[x][2].c_str()); ui->containersTable->setItem(x, 2, item); } } @@ -652,8 +702,8 @@ void VariableDialog::applyModel() } if (_currentContainer.empty() || selectedRow < 0){ - if (ui->containersTable->item(0,0) && strlen(ui->containersTable->item(0,0)->text())){ - _currentContainer = ui->containersTable->item(0,0)->text(); + if (ui->containersTable->item(0,0) && strlen(ui->containersTable->item(0,0)->text().toStdString().c_str())){ + _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); } } @@ -666,91 +716,108 @@ void VariableDialog::applyModel() void VariableDialog::updateVariableOptions() { if (_currentVariable.empty()){ - ui->copyVariableButton.setEnabled(false); - ui->deleteVariableButton.setEnabled(false); - ui->setVariableAsStringRadio.setEnabled(false); - ui->setVariableAsNumberRadio.setEnabled(false); - ui->saveVariableOnMissionCompletedRadio.setEnabled(false); - ui->saveVariableOnMissionCloseRadio.setEnabled(false); - ui->setVariableAsEternalcheckbox.setEnabled(false); + ui->copyVariableButton->setEnabled(false); + ui->deleteVariableButton->setEnabled(false); + ui->setVariableAsStringRadio->setEnabled(false); + ui->setVariableAsNumberRadio->setEnabled(false); + ui->saveVariableOnMissionCompletedRadio->setEnabled(false); + ui->saveVariableOnMissionCloseRadio->setEnabled(false); + ui->setVariableAsEternalcheckbox->setEnabled(false); return; } - ui->copyVariableButton.setEnabled(true); - ui->deleteVariableButton.setEnabled(true); - ui->setVariableAsStringRadio.setEnabled(true); - ui->setVariableAsNumberRadio.setEnabled(true); - ui->saveVariableOnMissionCompletedRadio.setEnabled(true); - ui->saveVariableOnMissionCloseRadio.setEnabled(true); - ui->setVariableAsEternalcheckbox.setEnabled(true); + ui->copyVariableButton->setEnabled(true); + ui->deleteVariableButton->setEnabled(true); + ui->setVariableAsStringRadio->setEnabled(true); + ui->setVariableAsNumberRadio->setEnabled(true); + ui->saveVariableOnMissionCompletedRadio->setEnabled(true); + ui->saveVariableOnMissionCloseRadio->setEnabled(true); + ui->setVariableAsEternalcheckbox->setEnabled(true); + + auto items = ui->variablesTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } // start populating values - bool string = _model->getVariableType(_currentVariable); - ui->setVariableAsStringRadio.setChecked(string); - ui->setVariableAsNumberRadio.setChecked(!string); - ui->setVariableAsEternalcheckbox.setChecked(); + bool string = _model->getVariableType(row); + ui->setVariableAsStringRadio->setChecked(string); + ui->setVariableAsNumberRadio->setChecked(!string); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); - int ret = _model->getVariableOnMissionCloseOrCompleteFlag(_currentVariable); + int ret = _model->getVariableOnMissionCloseOrCompleteFlag(row); if (ret == 0){ // TODO ADD NO PERSISTENCE } else if (ret == 1) { - ui->saveVariableOnMissionCompletedRadio.setChecked(true); - ui->saveVariableOnMissionCloseRadio.setChecked(false); + ui->saveVariableOnMissionCompletedRadio->setChecked(true); + ui->saveVariableOnMissionCloseRadio->setChecked(false); } else { - ui->saveVariableOnMissionCompletedRadio.setChecked(false); - ui->saveVariableOnMissionCloseRadio.setChecked(true); + ui->saveVariableOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(true); } - ui->networkVariableCheckbox.setChecked(_model->getVariableNetworkStatus(_currentVariable)); - ui->setVariableAsEternalcheckbox.setChecked(_model->getVariableEternalFlag(_currentVariable)); + ui->networkVariableCheckbox->setChecked(_model->getVariableNetworkStatus(row)); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); } void VariableDialog::updateContainerOptions() { if (_currentContainer.empty()){ - ui->copyContainerButton.setEnabled(false); - ui->deleteContainerButton.setEnabled(false); - ui->setContainerAsStringRadio.setEnabled(false); - ui->setContainerAsNumberRadio.setEnabled(false); - ui->saveContainerOnMissionCompletedRadio.setEnabled(false); - ui->saveContainerOnMissionCloseRadio.setEnabled(false); - ui->setContainerAsEternalcheckbox.setEnabled(false); - ui->setContainerAsMapRadio.setEnabled(false); - ui->setContainerAsListRadio.setEnabled(false); + ui->copyContainerButton->setEnabled(false); + ui->deleteContainerButton->setEnabled(false); + ui->setContainerAsStringRadio->setEnabled(false); + ui->setContainerAsNumberRadio->setEnabled(false); + ui->saveContainerOnMissionCompletedRadio->setEnabled(false); + ui->saveContainerOnMissionCloseRadio->setEnabled(false); + ui->setContainerAsEternalCheckbox->setEnabled(false); + ui->setContainerAsMapRadio->setEnabled(false); + ui->setContainerAsListRadio->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); } else { - ui->copyContainerButton.setEnabled(false); - ui->deleteContainerButton.setEnabled(false); - ui->setContainerAsStringRadio.setEnabled(false); - ui->setContainerAsNumberRadio.setEnabled(false); - ui->saveContainerOnMissionCompletedRadio.setEnabled(false); - ui->saveContainerOnMissionCloseRadio.setEnabled(false); - ui->setContainerAsEternalcheckbox.setEnabled(false); - ui->setContainerAsMapRadio.setEnabled(false); - ui->setContainerAsListRadio.setEnabled(false); - - if (_model->getContainerType(_currentContainer)){ - ui->setContainerAsStringRadio.setChecked(true); - ui->setContainerAsNumberRadio.setChecked(false); + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + + ui->copyContainerButton->setEnabled(false); + ui->deleteContainerButton->setEnabled(false); + ui->setContainerAsStringRadio->setEnabled(false); + ui->setContainerAsNumberRadio->setEnabled(false); + ui->saveContainerOnMissionCompletedRadio->setEnabled(false); + ui->saveContainerOnMissionCloseRadio->setEnabled(false); + ui->setContainerAsEternalCheckbox->setEnabled(false); + ui->setContainerAsMapRadio->setEnabled(false); + ui->setContainerAsListRadio->setEnabled(false); + + if (_model->getContainerValueType(row)){ + ui->setContainerAsStringRadio->setChecked(true); + ui->setContainerAsNumberRadio->setChecked(false); } else { - ui->setContainerAsStringRadio.setChecked(false); - ui->setContainerAsNumberRadio.setChecked(true); + ui->setContainerAsStringRadio->setChecked(false); + ui->setContainerAsNumberRadio->setChecked(true); } - if (_model->getConainerListOrMap(_currentContainer)){ - ui->setContainerAsListRadio.setChecked(true); - ui->setContainerAsMapRadio.setChecked(false); + if (_model->getContainerListOrMap(row)){ + ui->setContainerAsListRadio->setChecked(true); + ui->setContainerAsMapRadio->setChecked(false); // Disable Key Controls - ui->setContainerKeyAsStringRadio.setEnabled(false); - ui->setContainerKeyAsNumberRadio.setEnabled(false); + ui->setContainerKeyAsStringRadio->setEnabled(false); + ui->setContainerKeyAsNumberRadio->setEnabled(false); // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); @@ -758,12 +825,12 @@ void VariableDialog::updateContainerOptions() updateContainerDataOptions(true); } else { - ui->setContainerAsListRadio.setChecked(false); - ui->setContainerAsMapRadio.setChecked(true); + ui->setContainerAsListRadio->setChecked(false); + ui->setContainerAsMapRadio->setChecked(true); // Enabled Key Controls - ui->setContainerKeyAsStringRadio.setEnabled(true); - ui->setContainerKeyAsNumberRadio.setEnabled(true); + ui->setContainerKeyAsStringRadio->setEnabled(true); + ui->setContainerKeyAsNumberRadio->setEnabled(true); // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); @@ -771,19 +838,19 @@ void VariableDialog::updateContainerOptions() updateContainerDataOptions(false); } - ui->setContainerAsEternalcheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); - ui->networkContainerCheckbox.setChecked(_model->getContainerNetworkStatus(_currentContainer)); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerNetworkStatus(row)); + ui->networkContainerCheckbox->setChecked(_model->getContainerNetworkStatus(row)); - int ret = getContainerOnMissionCloseOrCompleteFlag(_currentContainer); + int ret = _model->getContainerOnMissionCloseOrCompleteFlag(row); if (ret == 0){ // TODO ADD NO PERSISTENCE } else if (ret == 1) { - ui->saveContainerOnMissionCompletedRadio.setChecked(true); - ui->saveContainerOnMissionCloseRadio.setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(true); + ui->saveContainerOnMissionCloseRadio->setChecked(false); } else { - ui->saveContainerOnMissionCompletedRadio.setChecked(false); - ui->saveContainerOnMissionCloseRadio.setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(true); } } @@ -799,13 +866,15 @@ SCP_string VariableDialog::trimNumberString(SCP_string source) SCP_string ret; // account for a lead negative sign. - if (source[0] == "-") { + if (source[0] == '-') { ret = "-"; } // filter out non-numeric digits - std::copy_if(s1.begin(), s1.end(), std::back_inserter(ret), - [](char c){ + std::copy_if(source.begin(), source.end(), std::back_inserter(ret), + [](char c) -> bool { + bool result = false; + switch (c) { case '0': case '1': @@ -817,12 +886,13 @@ SCP_string VariableDialog::trimNumberString(SCP_string source) case '7': case '8': case '9': - return true; + result = true; break; default: - return false; break; } + + return result; } ); diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 6349adbd293..f803dbdf295 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -56,7 +56,7 @@ class VariableDialog : public QDialog { void onSetContainerAsStringRadioSelected(); void onSetContainerAsNumberRadioSelected(); void onSetContainerKeyAsStringRadioSelected(); - void onSetContainerKeyAsNumberRadioSelected() + void onSetContainerKeyAsNumberRadioSelected(); void onSaveContainerOnMissionClosedRadioSelected(); void onSaveContainerOnMissionCompletedRadioSelected(); void onNetworkContainerCheckboxClicked(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index b85a2fc68a9..69299605fb9 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -6,8 +6,8 @@ 0 0 - 600 - 649 + 601 + 701 @@ -84,21 +84,30 @@ 10 30 231 - 131 + 151 + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + 10 - 170 + 190 341 191 - Contents + Container Contents @@ -109,6 +118,15 @@ 151 + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + @@ -193,7 +211,7 @@ 360 20 211 - 141 + 161 @@ -205,10 +223,17 @@ 10 20 201 - 121 + 136 + + + + No Persistence + + + @@ -244,7 +269,7 @@ 360 - 170 + 190 211 191 @@ -357,13 +382,13 @@ 260 - 100 - 311 - 121 + 90 + 131 + 131 - Options + Type @@ -400,31 +425,6 @@ - - - - - - Save on Mission Close - - - - - - - Save on Mission Completed - - - - - - - Eternal - - - - - @@ -437,14 +437,23 @@ 191 + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + 270 - 38 - 301 - 51 + 50 + 291 + 31 @@ -471,6 +480,59 @@ + + + + 400 + 90 + 171 + 131 + + + + Persistence + + + + + 13 + 18 + 174 + 108 + + + + + + + No Persistence + + + + + + + Save on Mission Close + + + + + + + Save on Mission Completed + + + + + + + Eternal + + + + + + From 364e39cedfecadde3853787b7e0f5a0e08709129 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Tue, 16 Apr 2024 23:24:26 -0400 Subject: [PATCH 032/153] more fixes --- .../src/mission/dialogs/VariableDialogModel.cpp | 16 ++++++++++------ qtfred/src/ui/dialogs/LoadoutDialog.cpp | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 59b8b99a681..2d3b3b74001 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -436,6 +436,7 @@ SCP_string VariableDialogModel::setVariableStringValue(int index, SCP_string val } variable->stringValue = value; + return value; } int VariableDialogModel::setVariableNumberValue(int index, int value) @@ -448,6 +449,8 @@ int VariableDialogModel::setVariableNumberValue(int index, int value) } variable->numberValue = value; + + return value; } SCP_string VariableDialogModel::addNewVariable() @@ -1108,9 +1111,9 @@ const SCP_vector& VariableDialogModel::getNumberValues(int index) return container->numberValues; } -const SCP_vector> VariableDialogModel::getVariableValues() +const SCP_vector> VariableDialogModel::getVariableValues() { - SCP_vector> outStrings; + SCP_vector> outStrings; for (const auto& item : _variableItems) { SCP_string notes = ""; @@ -1127,16 +1130,16 @@ const SCP_vector> VariableDialogM SCP_string temp; sprintf(temp, "%i", item.numberValue); - outStrings.emplace_back(item.name, (item.string) ? item.stringValue : temp, notes); + outStrings.push_back(std::array{item.name, (item.string) ? item.stringValue : temp, notes}); } return outStrings; } -const SCP_vector> VariableDialogModel::getContainerNames() +const SCP_vector> VariableDialogModel::getContainerNames() { - SCP_vector> outStrings; + SCP_vector> outStrings; for (const auto& item : _containerItems) { SCP_string notes = ""; @@ -1149,7 +1152,8 @@ const SCP_vector> VariableDialogModel::getCont notes = "Renamed"; } - outStrings.emplace_back(item.name, notes); + //TODO! FIX ME + outStrings.push_back(std::array{item.name, item.name, notes}); } return outStrings; diff --git a/qtfred/src/ui/dialogs/LoadoutDialog.cpp b/qtfred/src/ui/dialogs/LoadoutDialog.cpp index c115656b247..83678409d45 100644 --- a/qtfred/src/ui/dialogs/LoadoutDialog.cpp +++ b/qtfred/src/ui/dialogs/LoadoutDialog.cpp @@ -516,7 +516,8 @@ void LoadoutDialog::onClearAllUsedWeaponsPressed() void LoadoutDialog::openEditVariablePressed() { - viewport->on_actionVariables_triggered(); + //TODO! FIX ME! + //viewport->on_actionVariables_triggered(); } void LoadoutDialog::onSelectionRequiredPressed() From bd75eff4e447e3b3246e0d9cda5d8b982f928d14 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Wed, 17 Apr 2024 00:05:36 -0400 Subject: [PATCH 033/153] Make sure that tables have contents And fixes and progress --- qtfred/src/ui/dialogs/VariableDialog.cpp | 30 ++-- qtfred/ui/VariableDialog.ui | 192 +++++++++++------------ 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 489527eec92..01561500e87 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -184,25 +184,25 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 200); - ui->variablesTable->setColumnWidth(1, 200); - ui->variablesTable->setColumnWidth(2, 200); + ui->variablesTable->setColumnWidth(0, 70); + ui->variablesTable->setColumnWidth(1, 70); + ui->variablesTable->setColumnWidth(2, 70); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 200); - ui->containersTable->setColumnWidth(1, 200); - ui->containersTable->setColumnWidth(2, 200); + ui->containersTable->setColumnWidth(0, 70); + ui->containersTable->setColumnWidth(1, 70); + ui->containersTable->setColumnWidth(2, 70); ui->containerContentsTable->setColumnCount(2); // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 200); - ui->containerContentsTable->setColumnWidth(1, 200); + ui->containerContentsTable->setColumnWidth(0, 105); + ui->containerContentsTable->setColumnWidth(1, 105); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't ui->setVariableAsStringRadio->setAutoExclusive(false); @@ -595,6 +595,8 @@ void VariableDialog::applyModel() auto variables = _model->getVariableValues(); int x, selectedRow = -1; + ui->variablesTable->setRowCount(static_cast(variables.size())); + for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ ui->variablesTable->item(x, 0)->setText(variables[x][0].c_str()); @@ -604,7 +606,7 @@ void VariableDialog::applyModel() } // check if this is the current variable. - if (!_currentVariable.empty() && variables[x][0].c_str() == _currentVariable){ + if (!_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; } @@ -623,7 +625,7 @@ void VariableDialog::applyModel() } } - // TODO, try setting row count? + /* // This empties rows that might have previously had variables if (x < ui->variablesTable->rowCount()) { ++x; @@ -641,6 +643,7 @@ void VariableDialog::applyModel() } } } + */ if (_currentVariable.empty() || selectedRow < 0){ if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text().toStdString().c_str())){ @@ -651,6 +654,7 @@ void VariableDialog::applyModel() updateVariableOptions(); auto containers = _model->getContainerNames(); + ui->containersTable->setRowCount(static_cast(containers.size())); selectedRow = -1; // TODO! Change getContainerNames to a tuple with notes/maybe data key types? @@ -743,6 +747,12 @@ void VariableDialog::updateVariableOptions() row = item->row(); } + if (row == -1 && ui->variablesTable->rowCount() > 0) { + row = 0; + _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); + } + + // start populating values bool string = _model->getVariableType(row); ui->setVariableAsStringRadio->setChecked(string); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 69299605fb9..28c134d1aa1 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -6,14 +6,14 @@ 0 0 - 601 + 608 701 - 600 - 640 + 608 + 701 @@ -83,7 +83,7 @@ 10 30 - 231 + 251 151 @@ -114,7 +114,7 @@ 10 30 - 221 + 241 151 @@ -131,9 +131,9 @@ - 240 + 260 30 - 91 + 71 91 @@ -141,14 +141,14 @@ - Add Data + Add - Copy Data + Copy @@ -160,7 +160,7 @@ - Delete Data + Delete @@ -170,9 +170,9 @@ - 250 - 40 - 97 + 270 + 30 + 71 91 @@ -180,14 +180,14 @@ - Add Container + Add - Copy Container + Copy @@ -199,7 +199,7 @@ - Delete Container + Delete @@ -235,16 +235,16 @@ - + - Save on Mission Close + Save on Mission Completed - + - Save on Mission Completed + Save on Mission Close @@ -258,7 +258,7 @@ - Network-Variable + Network Variable @@ -382,48 +382,37 @@ 260 - 90 - 131 - 131 + 120 + 81 + 101 Type - + 10 20 - 300 - 101 + 71 + 80 - + - - - - - String - - - - - - - Number - - - - - - - Network-Variable - - - - + + + String + + + + + + + Number + + @@ -447,58 +436,25 @@ QAbstractItemView::SelectRows - - - - 270 - 50 - 291 - 31 - - - - - - - Add Variable - - - - - - - Copy Variable - - - - - - - Delete Variable - - - - - - 400 - 90 - 171 - 131 + 350 + 20 + 231 + 201 - Persistence + Persistence Options - + - 13 - 18 - 174 - 108 + 10 + 20 + 221 + 181 @@ -510,16 +466,16 @@ - + - Save on Mission Close + Save on Mission Completed - + - Save on Mission Completed + Save on Mission Close @@ -530,9 +486,49 @@ + + + + Network Variable + + + + + + + 270 + 30 + 71 + 86 + + + + + + + Add + + + + + + + Copy + + + + + + + Delete + + + + + From 24310690f6dd4b212c5420a868dd98b611c9c6b7 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Wed, 17 Apr 2024 00:26:42 -0400 Subject: [PATCH 034/153] more progress --- qtfred/ui/VariableDialog.ui | 390 +++++++++++++++++------------------- 1 file changed, 183 insertions(+), 207 deletions(-) diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 28c134d1aa1..6cd2503ec8a 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -7,67 +7,195 @@ 0 0 608 - 701 + 636 608 - 701 + 560 - Fiction Viewer Editor + Variables Editor - - - QLayout::SetMaximumSize + + + + 0 + 0 + - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 12 - - - - Variables and Containers Editor + + Variables + + + + + 270 + 120 + 71 + 101 + + + + Type Options + + + + + 0 + 20 + 116 + 80 + + + + + + String + + + + + + + Number + + + + - - - - - Qt::Horizontal - - - - 40 - 20 - + + + + + 10 + 30 + 251 + 191 + + + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::DotLine + + + false + + + false + + + + + + 360 + 20 + 221 + 201 + + + + Persistence Options + + + + + 10 + 20 + 221 + 181 + - - - + + + + + No Persistence + + + + + + + Save on Mission Completed + + + + + + + Save on Mission Close + + + + + + + Eternal + + + + + + + Network Variable + + + + + + + + + + 270 + 30 + 71 + 86 + + + + + + + Add + + + + + + + Copy + + + + + + + Delete + + + + + + - + @@ -96,6 +224,12 @@ QAbstractItemView::SelectRows + + Qt::DotLine + + + false + @@ -127,6 +261,12 @@ QAbstractItemView::SelectRows + + Qt::DotLine + + + false + @@ -367,170 +507,6 @@ - - - - - 0 - 230 - - - - Variables - - - - - 260 - 120 - 81 - 101 - - - - Type - - - - - 10 - 20 - 71 - 80 - - - - - - - String - - - - - - - Number - - - - - - - - - - 10 - 30 - 241 - 191 - - - - QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - - - 350 - 20 - 231 - 201 - - - - Persistence Options - - - - - 10 - 20 - 221 - 181 - - - - - - - No Persistence - - - - - - - Save on Mission Completed - - - - - - - Save on Mission Close - - - - - - - Eternal - - - - - - - Network Variable - - - - - - - - - - 270 - 30 - 71 - 86 - - - - - - - Add - - - - - - - Copy - - - - - - - Delete - - - - - - - From a57949c74788cd9209081322ff13ac8ce1f71f41 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Wed, 17 Apr 2024 00:27:22 -0400 Subject: [PATCH 035/153] getting closer to correct width --- qtfred/src/ui/dialogs/VariableDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 01561500e87..8a8f1f21808 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -192,9 +192,9 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 70); - ui->containersTable->setColumnWidth(1, 70); - ui->containersTable->setColumnWidth(2, 70); + ui->containersTable->setColumnWidth(0, 80); + ui->containersTable->setColumnWidth(1, 80); + ui->containersTable->setColumnWidth(2, 75); ui->containerContentsTable->setColumnCount(2); From 6fe5ab7dc7505ab1422a9e988913da9082e25b92 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 17 Apr 2024 16:29:11 -0400 Subject: [PATCH 036/153] Fix No Persistence not updating And other fixes --- qtfred/src/ui/dialogs/VariableDialog.cpp | 71 +++++++++++++++++------- qtfred/src/ui/dialogs/VariableDialog.h | 2 + qtfred/ui/VariableDialog.ui | 2 +- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 01561500e87..c34df97f64c 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -18,7 +18,8 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) { this->setFocus(); ui->setupUi(this); - resize(QDialog::sizeHint()); // The best I can tell without some research, when a dialog doesn't use an underling grid or layout, it needs to be resized this way before anything will show up + resize(QDialog::sizeHint()); // The best I can tell without some research, when a dialog doesn't use an underlying grid or layout, it needs to be resized this way before anything will show up + // Major Changes, like Applying the model, rejecting changes and updating the UI. connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::checkValidModel); @@ -79,6 +80,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSetVariableAsNumberRadioSelected); + connect(ui->doNotSaveVariableRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onDoNotSaveVariableRadioSelected) + connect(ui->saveContainerOnMissionCompletedRadio, &QRadioButton::toggled, this, @@ -144,6 +150,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSetContainerKeyAsNumberRadioSelected); + connect(ui->doNotSaveContainerRadio, + &QRadioButton::toggled, + this, + &VariableDialog::onDoNotSaveContainerRadioSelected) + connect(ui->saveContainerOnMissionCloseRadio, &QRadioButton::toggled, this, @@ -184,25 +195,27 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 70); - ui->variablesTable->setColumnWidth(1, 70); + ui->variablesTable->setColumnWidth(0, 90); + ui->variablesTable->setColumnWidth(1, 90); ui->variablesTable->setColumnWidth(2, 70); + // TODO! Make sure row 3 is not editable. ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 70); - ui->containersTable->setColumnWidth(1, 70); + ui->containersTable->setColumnWidth(0, 90); + ui->containersTable->setColumnWidth(1, 90); ui->containersTable->setColumnWidth(2, 70); - + // TODO! Make sure row 3 is not editable. + ui->containerContentsTable->setColumnCount(2); // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 105); - ui->containerContentsTable->setColumnWidth(1, 105); + ui->containerContentsTable->setColumnWidth(0, 125); + ui->containerContentsTable->setColumnWidth(1, 125); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't ui->setVariableAsStringRadio->setAutoExclusive(false); @@ -437,7 +450,6 @@ void VariableDialog::onSetVariableAsStringRadioSelected() return; } - auto items = ui->variablesTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. @@ -453,7 +465,6 @@ void VariableDialog::onSetVariableAsStringRadioSelected() break; } - } void VariableDialog::onSetVariableAsNumberRadioSelected() @@ -479,6 +490,11 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() } } +void VariableDialog::onDoNotSaveVariableRadioSelected() +{ + +} + void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() { @@ -577,6 +593,7 @@ void VariableDialog::onSetContainerAsStringRadioSelected() {} void VariableDialog::onSetContainerAsNumberRadioSelected() {} void VariableDialog::onSetContainerKeyAsStringRadioSelected() {} void VariableDialog::onSetContainerKeyAsNumberRadioSelected() {} +void VariableDialog::onDoNotSaveContainerRadioSelected(){} void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} void VariableDialog::onNetworkContainerCheckboxClicked() {} @@ -724,6 +741,7 @@ void VariableDialog::updateVariableOptions() ui->deleteVariableButton->setEnabled(false); ui->setVariableAsStringRadio->setEnabled(false); ui->setVariableAsNumberRadio->setEnabled(false); + ui->doNotSaveVariableRadio->setEnabled(false); ui->saveVariableOnMissionCompletedRadio->setEnabled(false); ui->saveVariableOnMissionCloseRadio->setEnabled(false); ui->setVariableAsEternalcheckbox->setEnabled(false); @@ -735,6 +753,7 @@ void VariableDialog::updateVariableOptions() ui->deleteVariableButton->setEnabled(true); ui->setVariableAsStringRadio->setEnabled(true); ui->setVariableAsNumberRadio->setEnabled(true); + ui->doNotSaveVariableRadio->setEnabled(true); ui->saveVariableOnMissionCompletedRadio->setEnabled(true); ui->saveVariableOnMissionCloseRadio->setEnabled(true); ui->setVariableAsEternalcheckbox->setEnabled(true); @@ -762,11 +781,15 @@ void VariableDialog::updateVariableOptions() int ret = _model->getVariableOnMissionCloseOrCompleteFlag(row); if (ret == 0){ - // TODO ADD NO PERSISTENCE + ui->doNotSaveVariableRadio->setChecked(true); + ui->saveVariableOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(false); } else if (ret == 1) { + ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCompletedRadio->setChecked(true); ui->saveVariableOnMissionCloseRadio->setChecked(false); } else { + ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(true); } @@ -783,6 +806,7 @@ void VariableDialog::updateContainerOptions() ui->deleteContainerButton->setEnabled(false); ui->setContainerAsStringRadio->setEnabled(false); ui->setContainerAsNumberRadio->setEnabled(false); + ui->doNotSaveContainerRadio->setEnabled(false); ui->saveContainerOnMissionCompletedRadio->setEnabled(false); ui->saveContainerOnMissionCloseRadio->setEnabled(false); ui->setContainerAsEternalCheckbox->setEnabled(false); @@ -803,15 +827,16 @@ void VariableDialog::updateContainerOptions() } - ui->copyContainerButton->setEnabled(false); - ui->deleteContainerButton->setEnabled(false); - ui->setContainerAsStringRadio->setEnabled(false); - ui->setContainerAsNumberRadio->setEnabled(false); - ui->saveContainerOnMissionCompletedRadio->setEnabled(false); - ui->saveContainerOnMissionCloseRadio->setEnabled(false); - ui->setContainerAsEternalCheckbox->setEnabled(false); - ui->setContainerAsMapRadio->setEnabled(false); - ui->setContainerAsListRadio->setEnabled(false); + ui->copyContainerButton->setEnabled(true); + ui->deleteContainerButton->setEnabled(true); + ui->setContainerAsStringRadio->setEnabled(true); + ui->setContainerAsNumberRadio->setEnabled(true); + ui->doNotSaveContainerRadio->setEnabled(true); + ui->saveContainerOnMissionCompletedRadio->setEnabled(true); + ui->saveContainerOnMissionCloseRadio->setEnabled(true); + ui->setContainerAsEternalCheckbox->setEnabled(true); + ui->setContainerAsMapRadio->setEnabled(true); + ui->setContainerAsListRadio->setEnabled(true); if (_model->getContainerValueType(row)){ ui->setContainerAsStringRadio->setChecked(true); @@ -854,11 +879,15 @@ void VariableDialog::updateContainerOptions() int ret = _model->getContainerOnMissionCloseOrCompleteFlag(row); if (ret == 0){ - // TODO ADD NO PERSISTENCE + ui->doNotSaveContainerRadio->setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(false); } else if (ret == 1) { + ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(true); ui->saveContainerOnMissionCloseRadio->setChecked(false); } else { + ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(false); ui->saveContainerOnMissionCloseRadio->setChecked(true); } diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index f803dbdf295..d85c4aa0de7 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -43,6 +43,7 @@ class VariableDialog : public QDialog { void onCopyVariableButtonPressed(); void onSetVariableAsStringRadioSelected(); void onSetVariableAsNumberRadioSelected(); + void onDoNotSaveVariableRadioSelected(); void onSaveVariableOnMissionCompleteRadioSelected(); void onSaveVariableOnMissionCloseRadioSelected(); void onSaveVariableAsEternalCheckboxClicked(); @@ -57,6 +58,7 @@ class VariableDialog : public QDialog { void onSetContainerAsNumberRadioSelected(); void onSetContainerKeyAsStringRadioSelected(); void onSetContainerKeyAsNumberRadioSelected(); + void onDoNotSaveContainerRadioSelected(); void onSaveContainerOnMissionClosedRadioSelected(); void onSaveContainerOnMissionCompletedRadioSelected(); void onNetworkContainerCheckboxClicked(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 6cd2503ec8a..a63a7c24a9d 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -123,7 +123,7 @@ - + No Persistence From 94057c5ef29835ab74c0df3c160376579fbbb667 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 14:24:01 -0400 Subject: [PATCH 037/153] Clean up container data updates And move the trimString method. --- .../mission/dialogs/VariableDialogModel.cpp | 37 ++++++ .../src/mission/dialogs/VariableDialogModel.h | 4 + qtfred/src/ui/dialogs/VariableDialog.cpp | 122 +++++++----------- qtfred/src/ui/dialogs/VariableDialog.h | 1 - 4 files changed, 86 insertions(+), 78 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 2d3b3b74001..d289aa99ebd 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1159,6 +1159,43 @@ const SCP_vector> VariableDialogModel::getContainerNam return outStrings; } +SCP_string VariableDialogModel::trimNumberString(SCP_string source) +{ + SCP_string ret; + + // account for a lead negative sign. + if (source[0] == '-') { + ret = "-"; + } + + // filter out non-numeric digits + std::copy_if(source.begin(), source.end(), std::back_inserter(ret), + [](char c) -> bool { + bool result = false; + + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + result = true; + break; + default: + break; + } + + return result; + } + ); + + return ret; +} } // dialogs } // fred diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 0933694a832..19b4b3cc4a6 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -30,6 +30,8 @@ struct containerInfo { // this will allow us to look up the original values used in the mission previously. SCP_string originalName = ""; + // I found out that keys could be strictly typed as numbers *after* finishing the majority of the model.... + // So I am just going to store numerical keys as strings and use a bool to differentiate. SCP_vector keys; SCP_vector numberValues; SCP_vector stringValues; @@ -177,6 +179,8 @@ class VariableDialogModel : public AbstractDialogModel { break; } } + + static SCP_string trimNumberString(SCP_string source); }; } // namespace dialogs diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c34df97f64c..94c90b7bff0 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -288,7 +288,7 @@ void VariableDialog::onVariablesTableUpdated() item->setText(ret.c_str()); } else { SCP_string source = item->text().toStdString(); - SCP_string temp = trimNumberString(source); + SCP_string temp = _model->trimNumberString(source); if (temp != source){ item->setText(temp.c_str()); @@ -492,10 +492,28 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() void VariableDialog::onDoNotSaveVariableRadioSelected() { + if (_currentVariable.empty() || ui->doNotSaveVariableRadio->isChecked()){ + return; + } + + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 1); + if (ret != 1){ + applyModel(); + } else { + ui->doNotSaveVariableRadio->setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(false); + } + } } + void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() { if (_currentVariable.empty() || ui->saveContainerOnMissionCompletedRadio->isChecked()){ @@ -511,10 +529,9 @@ void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() if (ret != 1){ applyModel(); } else { - // TODO! Need "no persistence" options and functions! + ui->doNotSaveVariableRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(true); ui->saveVariableOnMissionCloseRadio->setChecked(false); - //ui->saveContainerOnMissionCompletedRadio->setChecked(true); } } } @@ -536,10 +553,9 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() if (ret != 2){ applyModel(); } else { - // TODO! Need "no persistence" options. + ui->doNotSaveVariableRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(true); - //ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } } @@ -612,7 +628,7 @@ void VariableDialog::applyModel() auto variables = _model->getVariableValues(); int x, selectedRow = -1; - ui->variablesTable->setRowCount(static_cast(variables.size())); + ui->variablesTable->setRowCount(static_cast(variables.size() + 1)); for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ @@ -622,7 +638,8 @@ void VariableDialog::applyModel() ui->variablesTable->setItem(x, 0, item); } - // check if this is the current variable. + // check if this is the current variable. This keeps us selecting the correct variable even when + // there's a deletion. if (!_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; } @@ -642,25 +659,14 @@ void VariableDialog::applyModel() } } - /* - // This empties rows that might have previously had variables - if (x < ui->variablesTable->rowCount()) { - ++x; - for (; x < ui->variablesTable->rowCount(); ++x){ - if (ui->variablesTable->item(x, 0)){ - ui->variablesTable->item(x, 0)->setText(""); - } - - if (ui->variablesTable->item(x, 1)){ - ui->variablesTable->item(x, 1)->setText(""); - } - - if (ui->variablesTable->item(x, 2)){ - ui->variablesTable->item(x, 2)->setText(""); - } - } + // set the Add varaible row + ++x; + if (ui->variablesTable->item(x, 0)){ + ui->variablesTable->item(x, 0)->setText("Add Variable ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add Variable ..."); + ui->variablesTable->setItem(x, 0, item); } - */ if (_currentVariable.empty() || selectedRow < 0){ if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text().toStdString().c_str())){ @@ -674,7 +680,6 @@ void VariableDialog::applyModel() ui->containersTable->setRowCount(static_cast(containers.size())); selectedRow = -1; - // TODO! Change getContainerNames to a tuple with notes/maybe data key types? for (x = 0; x < static_cast(containers.size()); ++x){ if (ui->containersTable->item(x, 0)){ ui->containersTable->item(x, 0)->setText(containers[x][0].c_str()); @@ -704,22 +709,13 @@ void VariableDialog::applyModel() } } - // This empties rows that might have previously had containers - if (x < ui->containersTable->rowCount()) { - ++x; - for (; x < ui->containersTable->rowCount(); ++x){ - if (ui->containersTable->item(x, 0)){ - ui->containersTable->item(x, 0)->setText(""); - } - - if (ui->containersTable->item(x, 1)){ - ui->containersTable->item(x, 1)->setText(""); - } - - if (ui->containersTable->item(x, 2)){ - ui->containersTable->item(x, 2)->setText(""); - } - } + // set the Add container row + ++x; + if (ui->variablesTable->item(x, 0)){ + ui->variablesTable->item(x, 0)->setText("Add Container ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add Container ..."); + ui->variablesTable->setItem(x, 0, item); } if (_currentContainer.empty() || selectedRow < 0){ @@ -897,45 +893,17 @@ void VariableDialog::updateContainerOptions() void VariableDialog::updateContainerDataOptions(bool list) { + if (_currentContainer.empty()){ + ui->copyContainerItemButton->setEnabled(false); + ui->deleteContainerItemButton->setEnabled(false); + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + } else if (list) { -} + } -SCP_string VariableDialog::trimNumberString(SCP_string source) -{ - SCP_string ret; - - // account for a lead negative sign. - if (source[0] == '-') { - ret = "-"; - } - - // filter out non-numeric digits - std::copy_if(source.begin(), source.end(), std::back_inserter(ret), - [](char c) -> bool { - bool result = false; - - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - result = true; - break; - default: - break; - } - return result; - } - ); - return ret; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index d85c4aa0de7..acdc69d425d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -67,7 +67,6 @@ class VariableDialog : public QDialog { void onCopyContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); - SCP_string trimNumberString(SCP_string source); bool _applyingModel = false; SCP_string _currentVariable = ""; From 7d7b6eeeb83a7047e124f3312e936525c31192bd Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 14:25:18 -0400 Subject: [PATCH 038/153] Prevent crash from empty source string --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index d289aa99ebd..f16cb193ec2 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1161,6 +1161,10 @@ const SCP_vector> VariableDialogModel::getContainerNam SCP_string VariableDialogModel::trimNumberString(SCP_string source) { + if (source.empty()){ + return ""; + } + SCP_string ret; // account for a lead negative sign. From 83fde5acfc902f61df7ce8ff02baf9f96633d64a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 14:45:20 -0400 Subject: [PATCH 039/153] Actually, upgrade the lambda This handles the leading negative no matter where it is. --- .../mission/dialogs/VariableDialogModel.cpp | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index f16cb193ec2..8712127878d 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1161,24 +1161,19 @@ const SCP_vector> VariableDialogModel::getContainerNam SCP_string VariableDialogModel::trimNumberString(SCP_string source) { - if (source.empty()){ - return ""; - } - SCP_string ret; - - // account for a lead negative sign. - if (source[0] == '-') { - ret = "-"; - } + bool foundNonZero = false; // filter out non-numeric digits std::copy_if(source.begin(), source.end(), std::back_inserter(ret), - [](char c) -> bool { - bool result = false; - + [&foundNonZero, &ret](char c) -> bool { switch (c) { + // ignore leading zeros case '0': + if (foundNonZero) + return true; + else + return false; case '1': case '2': case '3': @@ -1188,16 +1183,28 @@ SCP_string VariableDialogModel::trimNumberString(SCP_string source) case '7': case '8': case '9': - result = true; + foundNonZero = true; + return true; break; + // only copy the '-' char if it is the first thing to be copied. + case '-': + if (ret.empty()){ + return true; + } else { + return false; + } default: + return false; break; } - - return result; } ); + // if all that made it out was a dash, then return nothing. + if (ret == "-"){ + return ""; + } + return ret; } From f61649e911ac26a777a85ecf4a276892303a9f18 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 15:14:25 -0400 Subject: [PATCH 040/153] Add type text to container Table --- .../mission/dialogs/VariableDialogModel.cpp | 28 +++++++++++++++++-- .../src/mission/dialogs/VariableDialogModel.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 8712127878d..db620668ea9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1142,10 +1142,34 @@ const SCP_vector> VariableDialogModel::getContainerNam SCP_vector> outStrings; for (const auto& item : _containerItems) { + SCP_string type = ""; SCP_string notes = ""; + if (item.list){ + type = "List of "; + + if (item.string) { + type += "Strings"; + } else { + type += "Numbers"; + } + } else { + if (item.integerKeys){ + type = "Number-Keyed Map of " + } else { + type = "String-Keyed Map of " + } + + if (item.string){ + type += "Strings" + } else { + type += "Numbers" + } + } + + if (item.deleted) { - notes = "Marked for Deletion"; + notes = "Flaged for Deletion"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ @@ -1153,7 +1177,7 @@ const SCP_vector> VariableDialogModel::getContainerNam } //TODO! FIX ME - outStrings.push_back(std::array{item.name, item.name, notes}); + outStrings.push_back(std::array{item.name, type, notes}); } return outStrings; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 19b4b3cc4a6..2d0bbbaad3e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -25,6 +25,7 @@ struct containerInfo { bool deleted = false; bool list = true; bool string = true; + bool integerKeys = false; int flags = 0; // this will allow us to look up the original values used in the mission previously. From e4254636dd70290db515f8b4e61def97ef12d57e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 16:52:45 -0400 Subject: [PATCH 041/153] Finish addMapItem and upgrade getcontainernames This has an upgrade for displaying List and Map info in a configurable manner. --- .../mission/dialogs/VariableDialogModel.cpp | 171 ++++++++++++++++-- .../src/mission/dialogs/VariableDialogModel.h | 5 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 +- 3 files changed, 165 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index db620668ea9..5ac1ecf6300 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -814,7 +814,50 @@ SCP_string VariableDialogModel::addListItem(int index) std::pair VariableDialogModel::addMapItem(int index) { - + auto container = lookupContainer(index); + + std::pair ret = {"", ""}; + + // no container available + if (!container){ + return ret; + } + + bool conflict; + int count = 0; + SCP_string newKey; + + do { + conflict = false; + + if (container->integerKeys){ + sprintf(newKey, "%i", count); + } else { + sprintf(newKey, "key%i", count); + } + + for (int x = 0; x < static_cast(container->keys.size()); ++x) { + if (container->keys[x] == newKey){ + conflict = true; + break; + } + } + + ++count; + } while (conflict && count < 101); + + if (conflict) { + return ret; + } + + ret.first = newKey; + + if (container.string) + ret.second = ""; + else + ret.second = "0"; + + return ret; } SCP_string VariableDialogModel::copyListItem(int containerIndex, int index) @@ -1136,35 +1179,138 @@ const SCP_vector> VariableDialogModel::getVariableValu return outStrings; } - const SCP_vector> VariableDialogModel::getContainerNames() { + // This logic makes the mode which we use to display, easily configureable. + SCP_string listPrefix; + SCP_string listPostscript; + + SCP_string mapPrefix; + SCP_string mapMidScript; + SCP_string mapPostscript + + switch (_listTextMode) { + case 1: + listPrefix = ""; + listPostscript = " List"; + break; + + case 2: + listPrefix = "List ("; + listPostscript = ")"; + break; + + case 3: + listPrefix = "List <"; + listPostscript = ">"; + break; + + case 4: + listPrefix = "("; + listPostscript = ")"; + break; + + case 5: + listPrefix = "<" + listPostscript = ">" + break; + + case 6: + listPrefix = "" + listPostscript = "" + break; + + + default: + // this takes care of weird cases. The logic should be simple enough to not have bugs, but just in case, switch back to default. + _listTextMode = 0; + listPrefix = "List of"; + listPostscript = "s"; + break; + } + + switch (_mapTextMode) { + case 1: + mapPrefix = ""; + mapMidScript = "-keyed Map of "; + mapPostscript = " Values"; + + break; + case 2: + mapPrefix = "Map ("; + mapMidScript = ", "; + mapPostscript = ")"; + + break; + case 3: + mapPrefix = "Map <"; + mapMidScript = ", "; + mapPostscript = ">"; + + break; + case 4: + mapPrefix = "("; + mapMidScript = ", "; + mapPostscript = ")"; + + break; + case 5: + mapPrefix = "<"; + mapMidScript = ", "; + mapPostscript = ">"; + + break; + case 6: + mapPrefix = ""; + mapMidScript = ", "; + mapPostscript = ""; + + break; + + case default: + _mapTextMode = 0; + mapPrefix = "Map with "; + mapMidScript = " Keys and "; + mapPostscript = " Values"; + + break; + } + + SCP_vector> outStrings; for (const auto& item : _containerItems) { SCP_string type = ""; SCP_string notes = ""; + if (item.string) { + type = "String"; + } else { + type += "Number"; + } + if (item.list){ - type = "List of "; + type = listPrefix + type + listPostscript; - if (item.string) { - type += "Strings"; - } else { - type += "Numbers"; - } } else { + + type = mapPrefix; + if (item.integerKeys){ - type = "Number-Keyed Map of " + type += "Number"; } else { - type = "String-Keyed Map of " + type += "String"; } + type += mapMidScript; + if (item.string){ - type += "Strings" + type += "String" } else { - type += "Numbers" + type += "Number" } + + type += mapPostscript; } @@ -1176,7 +1322,6 @@ const SCP_vector> VariableDialogModel::getContainerNam notes = "Renamed"; } - //TODO! FIX ME outStrings.push_back(std::array{item.name, type, notes}); } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 2d0bbbaad3e..e5cead090fd 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -121,6 +121,8 @@ class VariableDialogModel : public AbstractDialogModel { private: SCP_vector _variableItems; SCP_vector _containerItems; + int _listTextMode = 0; + int _mapTextMode = 0; variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ @@ -158,6 +160,8 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } + static SCP_string trimNumberString(SCP_string source); + // many of the controls in this editor can lead to drastic actions, so this will be very useful. const bool confirmAction(SCP_string question, SCP_string informativeText) { @@ -181,7 +185,6 @@ class VariableDialogModel : public AbstractDialogModel { } } - static SCP_string trimNumberString(SCP_string source); }; } // namespace dialogs diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 94c90b7bff0..c307a1826f9 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -380,7 +380,8 @@ void VariableDialog::onContainerContentsTableUpdated() } // could be new key or new value -void VariableDialog::onContainerContentsSelectionChanged() { +void VariableDialog::onContainerContentsSelectionChanged() +{ if (_applyingModel){ return; } @@ -600,6 +601,7 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } } +// TODO! 17 more functions to write void VariableDialog::onAddContainerButtonPressed() {} void VariableDialog::onCopyContainerButtonPressed() {} void VariableDialog::onDeleteContainerButtonPressed() {} From a06cb0c68842f4634fcbe83e6bb1c4b36ece7325 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 18 Apr 2024 18:03:37 -0400 Subject: [PATCH 042/153] More progress on updateContainerDataOptions --- qtfred/src/ui/dialogs/VariableDialog.cpp | 41 +++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c307a1826f9..dfd6fb875e6 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -895,15 +895,54 @@ void VariableDialog::updateContainerOptions() void VariableDialog::updateContainerDataOptions(bool list) { + if (_currentContainer.empty()){ ui->copyContainerItemButton->setEnabled(false); ui->deleteContainerItemButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + + return; } else if (list) { + ui->copyContainerItemButton->setEnabled(true); + ui->deleteContainerItemButton->setEnabled(true); + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - } + = _model->getMapKeys(); + + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + const SCP_vector& getMapKeys(int index); + const SCP_vector& getStringValues(int index); + const SCP_vector& getNumberValues(int index); + + + if (row < 0){ + return; + } + + + + ui->containerContentstable->setRowCount( ); + + + } else { + ui->copyContainerItemButton->setEnabled(true); + ui->deleteContainerItemButton->setEnabled(true); + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + + + ui->continerContentsTable->setRowCount(); + + } } From 2a337133cb5cd3dbd72614202acb63c750a91e83 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 18:36:30 -0400 Subject: [PATCH 043/153] Fixes and add a couple more UI functions --- .../mission/dialogs/VariableDialogModel.cpp | 18 ++-- .../src/mission/dialogs/VariableDialogModel.h | 1 + qtfred/src/ui/dialogs/VariableDialog.cpp | 91 +++++++++++++------ 3 files changed, 74 insertions(+), 36 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 5ac1ecf6300..a08fbc9df01 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -477,11 +477,7 @@ SCP_string VariableDialogModel::addNewVariable() } SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName) -{ - if (newName == "") { - return ""; - } - +{ auto variable = lookupVariable(index); // nothing to change, or invalid entry @@ -489,6 +485,16 @@ SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName return ""; } + // no name means no variable + if (newName == "") { + variable->deleted = true; + } + + // Truncate name if needed + if (newName.len() >= TOKEN_LENGTH){ + newName = newName.substr(0, TAKEN_LENGTH - 1); + } + // We cannot have two variables with the same name, but we need to check this somewhere else (like on accept attempt). variable->name = newName; return newName; @@ -508,7 +514,7 @@ SCP_string VariableDialogModel::copyVariable(int index) do { SCP_string newName; - sprintf(newName, "%s_copy%i", variable->name.c_str(), count); + sprintf(newName, "%s_copy%i", variable->name.substr(0, TOKEN_LENGTH - 6).c_str(), count); variableSearch = lookupVariableByName(newName); // open slot found! diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index e5cead090fd..6fb18c1f0d4 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -90,6 +90,7 @@ class VariableDialogModel : public AbstractDialogModel { bool setContainerEternalFlag(int index, bool eternal); SCP_string addContainer(); + SCP_string copyContainer(int index); SCP_string changeContainerName(int index, SCP_string newName); bool removeContainer(int index); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index dfd6fb875e6..b854b917ca9 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -198,7 +198,6 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setColumnWidth(0, 90); ui->variablesTable->setColumnWidth(1, 90); ui->variablesTable->setColumnWidth(2, 70); - // TODO! Make sure row 3 is not editable. ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -207,7 +206,6 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->setColumnWidth(0, 90); ui->containersTable->setColumnWidth(1, 90); ui->containersTable->setColumnWidth(2, 70); - // TODO! Make sure row 3 is not editable. ui->containerContentsTable->setColumnCount(2); @@ -601,10 +599,45 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } } -// TODO! 17 more functions to write -void VariableDialog::onAddContainerButtonPressed() {} +void VariableDialog::onAddContainerButtonPressed() +{ + auto result = (_model->addContainer()); + + if (result.empty()) { + QMessageBox msgBox; + msgBox.setText("Adding a container failed because the code is out of automatic names. Try adding a container directly in the table."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.exec(); + } + + applyModel(); + +} + +// TODO! 16 more functions to write void VariableDialog::onCopyContainerButtonPressed() {} -void VariableDialog::onDeleteContainerButtonPressed() {} + +void VariableDialog::onDeleteContainerButtonPressed() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + // UI is somehow out of sync with the model, so update UI. + if (!_model->removeContainer(row)) { + applyModel(); + } + +} void VariableDialog::onSetContainerAsMapRadioSelected() {} void VariableDialog::onSetContainerAsListRadioSelected() {} void VariableDialog::onSetContainerAsStringRadioSelected() {} @@ -623,8 +656,10 @@ void VariableDialog::onDeleteContainerItemButtonPressed() {} VariableDialog::~VariableDialog(){}; // NOLINT + void VariableDialog::applyModel() { + // TODO! We need an undelete action. Best way is to change the text on the button if the notes say "Deleted" _applyingModel = true; auto variables = _model->getVariableValues(); @@ -648,9 +683,11 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); + ui->varaiblesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); ui->variablesTable->setItem(x, 1, item); + ui->variablesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); } if (ui->variablesTable->item(x, 2)){ @@ -658,6 +695,7 @@ void VariableDialog::applyModel() } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][2].c_str()); ui->variablesTable->setItem(x, 2, item); + ui->variablesTable->item(x, 2)->setFlags(item->flags() & ~Qt::ItemIsEditable); } } @@ -670,6 +708,24 @@ void VariableDialog::applyModel() ui->variablesTable->setItem(x, 0, item); } + if (ui->variablesTable->item(x, 1)){ + ui->varaiblesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 1)->setText(""); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->setItem(x, 1, item); + } + + if (ui->variablesTable->item(x, 2)){ + ui->varaiblesTable->item(x, 2)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 2)->setText(""); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->setItem(x, 2, item); + } + if (_currentVariable.empty() || selectedRow < 0){ if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text().toStdString().c_str())){ _currentVariable = ui->variablesTable->item(0,0)->text().toStdString(); @@ -695,7 +751,6 @@ void VariableDialog::applyModel() selectedRow = x; } - if (ui->containersTable->item(x, 1)){ ui->containersTable->item(x, 1)->setText(containers[x][1].c_str()); } else { @@ -909,30 +964,6 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - = _model->getMapKeys(); - - auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } - - const SCP_vector& getMapKeys(int index); - const SCP_vector& getStringValues(int index); - const SCP_vector& getNumberValues(int index); - - - if (row < 0){ - return; - } - - - - ui->containerContentstable->setRowCount( ); - - } else { ui->copyContainerItemButton->setEnabled(true); ui->deleteContainerItemButton->setEnabled(true); From 7c37628e1ae82d3b345a54da1ded3a91da33ab58 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 18:52:36 -0400 Subject: [PATCH 044/153] Add get item rows to reduce duplicate code --- .../src/mission/dialogs/VariableDialogModel.h | 1 + qtfred/src/ui/dialogs/VariableDialog.cpp | 140 +++++++++++++++++- qtfred/src/ui/dialogs/VariableDialog.h | 3 + 3 files changed, 138 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 6fb18c1f0d4..62819e6df4f 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -84,6 +84,7 @@ class VariableDialogModel : public AbstractDialogModel { bool getContainerEternalFlag(int index); bool setContainerValueType(int index, bool type); + bool setContainerKeyType(int index, bool string); bool setContainerListOrMap(int index, bool list); bool setContainerNetworkStatus(int index, bool network); int setContainerOnMissionCloseOrCompleteFlag(int index, int flags); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b854b917ca9..d9e65af207e 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -615,7 +615,7 @@ void VariableDialog::onAddContainerButtonPressed() } -// TODO! 16 more functions to write +// TODO! 15 more functions to write void VariableDialog::onCopyContainerButtonPressed() {} void VariableDialog::onDeleteContainerButtonPressed() @@ -638,11 +638,101 @@ void VariableDialog::onDeleteContainerButtonPressed() } } -void VariableDialog::onSetContainerAsMapRadioSelected() {} -void VariableDialog::onSetContainerAsListRadioSelected() {} -void VariableDialog::onSetContainerAsStringRadioSelected() {} -void VariableDialog::onSetContainerAsNumberRadioSelected() {} -void VariableDialog::onSetContainerKeyAsStringRadioSelected() {} + +void VariableDialog::onSetContainerAsMapRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + setContainerListOrMap(row, false); + applyModel(); +} + +void VariableDialog::onSetContainerAsListRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + setContainerListOrMap(row, true); + applyModel(); +} + + +void VariableDialog::onSetContainerAsStringRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + setContainerValueType(row, true); + applyModel(); +} + +void VariableDialog::onSetContainerAsNumberRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + setContainerValueType(row, false); + applyModel(); +} + +void VariableDialog::onSetContainerKeyAsStringRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = -1; + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + row = item->row(); + } + + if (row == -1){ + return; + } + + setContainerKeyType(row, true); + applyModel(); + +} + + + void VariableDialog::onSetContainerKeyAsNumberRadioSelected() {} void VariableDialog::onDoNotSaveContainerRadioSelected(){} void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} @@ -979,6 +1069,44 @@ void VariableDialog::updateContainerDataOptions(bool list) } +int VariableDialog::getCurrentVariableRow() +{ + auto items = ui->variablesTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + if (item){ + return item->row(); + } + } + + return -1; +} + +int VariableDialog::getCurrentContainerRow(){ + auto items = ui->containersTable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + if (item) { + return item->row(); + } + } + + return -1; +} + +int variableDialog::getCurrentContainerItemRow(){ + auto items = ui->containerItemsTeable->selectedItems(); + + // yes, selected items returns a list, but we really should only have one item because multiselect will be off. + for (const auto& item : items) { + return item->row(); + } + + return -1; +} + } // namespace dialogs } // namespace fred } // namespace fso \ No newline at end of file diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index acdc69d425d..7c6552ffa8b 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -67,6 +67,9 @@ class VariableDialog : public QDialog { void onCopyContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); + int getCurrentVariableRow(); + int getCurrentContainerRow(); + int getCurrentContainerItemRow(); bool _applyingModel = false; SCP_string _currentVariable = ""; From e7b0f61870ba1f6d5afaa29a8bf7a58b2c58e8cb Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 19:04:14 -0400 Subject: [PATCH 045/153] Start applying currentVariableRow --- qtfred/src/ui/dialogs/VariableDialog.cpp | 113 ++++++++++++----------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index d9e65af207e..73df4b5580c 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -317,8 +317,6 @@ void VariableDialog::onVariablesSelectionChanged() return; } - auto items = ui->variablesTable->selectedItems(); - SCP_string newVariableName = ""; // yes, selected items returns a list, but we really should only have one item because multiselect will be off. @@ -415,15 +413,15 @@ void VariableDialog::onCopyVariableButtonPressed() return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - auto ret = _model->copyVariable(item->row()); - _currentVariable = ret; - applyModel(); - break; - } + if (currentRow < 0){ + return; + } + + auto ret = _model->copyVariable(currentRow); + _currentVariable = ret; + applyModel(); } void VariableDialog::onDeleteVariableButtonPressed() @@ -432,82 +430,85 @@ void VariableDialog::onDeleteVariableButtonPressed() return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - auto ret = _model->removeVariable(item->row()); - applyModel(); - break; - } + if (currentRow < 0){ + return; + } + + // Because of the text update we'll need, this needs an applyModel, whether it fails or not. + _model->removeVariable(currentRow); + applyModel(); } void VariableDialog::onSetVariableAsStringRadioSelected() { - if (_currentVariable.empty() || ui->setVariableAsStringRadio->isChecked()){ + if (ui->setVariableAsStringRadio->isChecked()){ return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - // this doesn't return succeed or fail directly, - // but if it doesn't return true then it failed since this is the string radio - if(!_model->setVariableType(item->row(), true)){ - applyModel(); - } else { - ui->setVariableAsStringRadio->setChecked(true); - ui->setVariableAsNumberRadio->setChecked(false); - } + if (currentRow < 0){ + return; + } - break; + // this doesn't return succeed or fail directly, + // but if it doesn't return true then it failed since this is the string radio + if(!_model->setVariableType(currentRow, true)){ + applyModel(); + } else { + ui->setVariableAsStringRadio->setChecked(true); + ui->setVariableAsNumberRadio->setChecked(false); } + + break; } void VariableDialog::onSetVariableAsNumberRadioSelected() { - if (_currentVariable.empty() || ui->setVariableAsNumberRadio->isChecked()){ + if (ui->setVariableAsNumberRadio->isChecked()){ return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { + if (currentRow < 0){ + return; + } - // this doesn't return succeed or fail directly, - // but if it doesn't return false then it failed since this is the number radio - if (!_model->setVariableType(item->row(), false)) { - applyModel(); - } - else { - ui->setVariableAsStringRadio->setChecked(false); - ui->setVariableAsNumberRadio->setChecked(true); - } + // this doesn't return succeed or fail directly, + // but if it doesn't return false then it failed since this is the number radio + if (!_model->setVariableType(currentRow, false)) { + applyModel(); } + else { + ui->setVariableAsStringRadio->setChecked(false); + ui->setVariableAsNumberRadio->setChecked(true); + } + break; } void VariableDialog::onDoNotSaveVariableRadioSelected() { - if (_currentVariable.empty() || ui->doNotSaveVariableRadio->isChecked()){ + if (ui->doNotSaveVariableRadio->isChecked()){ return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 1); + if (currentRow < 0){ + return; + } - if (ret != 1){ - applyModel(); - } else { - ui->doNotSaveVariableRadio->setChecked(true); - ui->saveContainerOnMissionCompletedRadio->setChecked(false); - ui->saveVariableOnMissionCloseRadio->setChecked(false); - } + int ret = _model->setVariableOnMissionCloseOrCompleteFlag(currentRow, 1); + + if (ret != 1){ + applyModel(); + } else { + ui->doNotSaveVariableRadio->setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(false); } } From ad74c21b8273c6ee89734c6b1ed43c3ca0ca80b5 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 23:31:17 -0400 Subject: [PATCH 046/153] Edit onVariablesTableUpdated And Apply GetCurrentContainerRow --- .../src/mission/dialogs/VariableDialogModel.h | 1 + qtfred/src/ui/dialogs/VariableDialog.cpp | 204 ++++++++++-------- 2 files changed, 110 insertions(+), 95 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 62819e6df4f..d15bcb8509b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -91,6 +91,7 @@ class VariableDialogModel : public AbstractDialogModel { bool setContainerEternalFlag(int index, bool eternal); SCP_string addContainer(); + SCP_string addContainer(SCP_string nameIn); SCP_string copyContainer(int index); SCP_string changeContainerName(int index, SCP_string newName); bool removeContainer(int index); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 73df4b5580c..55f7912cce0 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -237,76 +237,77 @@ void VariableDialog::onVariablesTableUpdated() return; } - auto items = ui->variablesTable->selectedItems(); + int currentRow = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one row of items because multiselect will be off. - for(const auto& item : items) { - if (item->column() == 0){ + if (currentRow < 0){ + return; + } + + auto item = - // so if the user just removed the name, mark it as deleted *before changing the name* - if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { - if (!_model->removeVariable(item->row())) { - // marking a variable as deleted failed, resync UI - applyModel(); - return; - } else { - updateVariableOptions(); - } - } else { - - auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); - - // we put something in the cell, but the model couldn't process it. - if (strlen(item->text().toStdString().c_str()) && ret == ""){ - // update of variable name failed, resync UI - applyModel(); - - // we had a successful rename. So update the variable we reference. - } else if (ret != "") { - item->setText(ret.c_str()); - _currentVariable = ret; - } - } - // empty return and cell was handled earlier. + // so if the user just removed the name, mark it as deleted *before changing the name* + if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { + if (!_model->removeVariable(item->row())) { + // marking a variable as deleted failed, resync UI + applyModel(); + return; + } else { + updateVariableOptions(); + } + } else { - // data cell was altered - } else if (item->column() == 1) { - - // Variable is a string - if (_model->getVariableType(item->row())){ - SCP_string temp = item->text().toStdString().c_str(); - temp = temp.substr(0, NAME_LENGTH - 1); - - SCP_string ret = _model->setVariableStringValue(item->row(), temp); - if (ret == ""){ - applyModel(); - return; - } - - item->setText(ret.c_str()); - } else { - SCP_string source = item->text().toStdString(); - SCP_string temp = _model->trimNumberString(source); - - if (temp != source){ - item->setText(temp.c_str()); - } - - try { - int ret = _model->setVariableNumberValue(item->row(), std::stoi(temp)); - temp = ""; - sprintf(temp, "%i", ret); - item->setText(temp.c_str()); - } - catch (...) { - applyModel(); - } - } + auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); - // if the user somehow edited the info that should only come from the model and should not be editable, reload everything. - } else { + // we put something in the cell, but the model couldn't process it. + if (strlen(item->text().toStdString().c_str()) && ret == ""){ + // update of variable name failed, resync UI applyModel(); + + // we had a successful rename. So update the variable we reference. + } else if (ret != "") { + item->setText(ret.c_str()); + _currentVariable = ret; + } + } + // empty return and cell was handled earlier. + + // data cell was altered + } else if (item->column() == 1) { + + // Variable is a string + if (_model->getVariableType(item->row())){ + SCP_string temp = item->text().toStdString().c_str(); + temp = temp.substr(0, NAME_LENGTH - 1); + + SCP_string ret = _model->setVariableStringValue(item->row(), temp); + if (ret == ""){ + applyModel(); + return; + } + + item->setText(ret.c_str()); + } else { + SCP_string source = item->text().toStdString(); + SCP_string temp = _model->trimNumberString(source); + + if (temp != source){ + item->setText(temp.c_str()); + } + + try { + int ret = _model->setVariableNumberValue(item->row(), std::stoi(temp)); + temp = ""; + sprintf(temp, "%i", ret); + item->setText(temp.c_str()); + } + catch (...) { + applyModel(); + } } + + // if the user somehow edited the info that should only come from the model and should not be editable, reload everything. + } else { + applyModel(); } } @@ -340,8 +341,33 @@ void VariableDialog::onContainersTableUpdated() return; } + int row = getCurrentContainerRow(); + + // just in case something is goofy, return + if (row < 0){ + return; + } + + // Are they adding a new container? + if (row == ui->containersTable->rowCount - 1){ + if (ui->containersTable->item(row, 0)) { + SCP_string newString = ui->containersTable->item(row, 0).text().toStdString(); + if (!newString.empty() && newString != "Add Container ..."){ + _model->addContainer(newSTring); + _currentContainer = newString(); + applyModel(); + } + } -} // could be new name + // are they editing an existing container name? + } else if (ui->containersTable->item(row, 0)){ + _currentContainer = ui->containersTable->item(row,0).toStdString(); + + if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0).toStdString())){ + applyModel(); + } + } +} void VariableDialog::onContainersSelectionChanged() { @@ -645,10 +671,7 @@ void VariableDialog::onSetContainerAsMapRadioSelected() auto items = ui->containersTable->selectedItems(); int row = -1; - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); if (row == -1){ return; @@ -661,12 +684,7 @@ void VariableDialog::onSetContainerAsMapRadioSelected() void VariableDialog::onSetContainerAsListRadioSelected() { auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); if (row == -1){ return; @@ -680,12 +698,7 @@ void VariableDialog::onSetContainerAsListRadioSelected() void VariableDialog::onSetContainerAsStringRadioSelected() { auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); if (row == -1){ return; @@ -698,12 +711,7 @@ void VariableDialog::onSetContainerAsStringRadioSelected() void VariableDialog::onSetContainerAsNumberRadioSelected() { auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); if (row == -1){ return; @@ -716,17 +724,11 @@ void VariableDialog::onSetContainerAsNumberRadioSelected() void VariableDialog::onSetContainerKeyAsStringRadioSelected() { auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); if (row == -1){ return; } - setContainerKeyType(row, true); applyModel(); @@ -734,7 +736,19 @@ void VariableDialog::onSetContainerKeyAsStringRadioSelected() -void VariableDialog::onSetContainerKeyAsNumberRadioSelected() {} +void VariableDialog::onSetContainerKeyAsNumberRadioSelected() +{ + auto items = ui->containersTable->selectedItems(); + int row = getCurrentContainerRow(); + + if (row == -1){ + return; + } + + setContainerKeyType(row, false); + applyModel(); +} + void VariableDialog::onDoNotSaveContainerRadioSelected(){} void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} From bb838ea4ddc62e8949453f3b738649cc497a0e73 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 23:38:32 -0400 Subject: [PATCH 047/153] Place getCurrentContainerRow in more places --- qtfred/src/ui/dialogs/VariableDialog.cpp | 122 ++++++++++------------- 1 file changed, 51 insertions(+), 71 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 55f7912cce0..7ee65550a8a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -542,88 +542,82 @@ void VariableDialog::onDoNotSaveVariableRadioSelected() void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() { - if (_currentVariable.empty() || ui->saveContainerOnMissionCompletedRadio->isChecked()){ + if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ return; } - auto items = ui->variablesTable->selectedItems(); + int row = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 1); + if (row < 0){ + return; + } + + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(row(), 1); - if (ret != 1){ - applyModel(); - } else { - ui->doNotSaveVariableRadio->setChecked(false); - ui->saveContainerOnMissionCompletedRadio->setChecked(true); - ui->saveVariableOnMissionCloseRadio->setChecked(false); - } + if (ret != 1){ + applyModel(); + } else { + ui->doNotSaveVariableRadio->setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(true); + ui->saveVariableOnMissionCloseRadio->setChecked(false); } } void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() { - if (_currentVariable.empty() || ui->saveContainerOnMissionCompletedRadio->isChecked()){ + if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ return; } + int row = getCurrentVariableRow(); - auto items = ui->variablesTable->selectedItems(); - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { + if (row < 0){ + return; + } - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(item->row(), 2); + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(row, 2); - if (ret != 2){ - applyModel(); - } else { - ui->doNotSaveVariableRadio->setChecked(false); - ui->saveContainerOnMissionCompletedRadio->setChecked(false); - ui->saveVariableOnMissionCloseRadio->setChecked(true); - } + // out of sync because we did not get the expected return value. + if (ret != 2){ + applyModel(); + } else { + ui->doNotSaveVariableRadio->setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(true); } } void VariableDialog::onSaveVariableAsEternalCheckboxClicked() { - if (_currentVariable.empty()){ + int row = getCurrentVariableRow(); + + if (row < 0){ return; } - - auto items = ui->variablesTable->selectedItems(); - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(item->row(), !ui->setVariableAsEternalcheckbox->isChecked())) { - applyModel(); - } else { - ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); - } + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(row, !ui->setVariableAsEternalcheckbox->isChecked())) { + applyModel(); + } else { + ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); } } void VariableDialog::onNetworkVariableCheckboxClicked() { - if (_currentVariable.empty()){ + int row = getCurrentVariableRow(); + + if (row < 0){ return; } - auto items = ui->variablesTable->selectedItems(); - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - - // If the model returns the old status, then the change failed and we're out of sync. - if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(item->row(), !ui->networkVariableCheckbox->isChecked())) { - applyModel(); - } else { - ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); - } + // If the model returns the old status, then the change failed and we're out of sync. + if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(row, !ui->networkVariableCheckbox->isChecked())) { + applyModel(); + } else { + ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); } + } void VariableDialog::onAddContainerButtonPressed() @@ -647,15 +641,9 @@ void VariableDialog::onCopyContainerButtonPressed() {} void VariableDialog::onDeleteContainerButtonPressed() { - auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } + int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } @@ -668,12 +656,9 @@ void VariableDialog::onDeleteContainerButtonPressed() void VariableDialog::onSetContainerAsMapRadioSelected() { - auto items = ui->containersTable->selectedItems(); - int row = -1; - int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } @@ -683,10 +668,9 @@ void VariableDialog::onSetContainerAsMapRadioSelected() void VariableDialog::onSetContainerAsListRadioSelected() { - auto items = ui->containersTable->selectedItems(); int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } @@ -697,10 +681,9 @@ void VariableDialog::onSetContainerAsListRadioSelected() void VariableDialog::onSetContainerAsStringRadioSelected() { - auto items = ui->containersTable->selectedItems(); int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } @@ -710,10 +693,9 @@ void VariableDialog::onSetContainerAsStringRadioSelected() void VariableDialog::onSetContainerAsNumberRadioSelected() { - auto items = ui->containersTable->selectedItems(); int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } @@ -723,10 +705,9 @@ void VariableDialog::onSetContainerAsNumberRadioSelected() void VariableDialog::onSetContainerKeyAsStringRadioSelected() { - auto items = ui->containersTable->selectedItems(); int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } setContainerKeyType(row, true); @@ -738,10 +719,9 @@ void VariableDialog::onSetContainerKeyAsStringRadioSelected() void VariableDialog::onSetContainerKeyAsNumberRadioSelected() { - auto items = ui->containersTable->selectedItems(); int row = getCurrentContainerRow(); - if (row == -1){ + if (row < 0){ return; } From 72271be1f9b4888d8a205aeef090bfb7402ace6f Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 20 Apr 2024 23:50:54 -0400 Subject: [PATCH 048/153] Getting closer to completion of basics --- qtfred/src/ui/dialogs/VariableDialog.cpp | 135 ++++++++++++++++++++--- 1 file changed, 121 insertions(+), 14 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 7ee65550a8a..36fd06035ea 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -636,7 +636,7 @@ void VariableDialog::onAddContainerButtonPressed() } -// TODO! 15 more functions to write +// TODO! 4 more functions to write void VariableDialog::onCopyContainerButtonPressed() {} void VariableDialog::onDeleteContainerButtonPressed() @@ -656,84 +656,191 @@ void VariableDialog::onDeleteContainerButtonPressed() void VariableDialog::onSetContainerAsMapRadioSelected() { + if (ui->setContainerAsMapRadio->isChecked()){ + return; + } + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerListOrMap(row, false); + model->setContainerListOrMap(row, false); applyModel(); } void VariableDialog::onSetContainerAsListRadioSelected() { + if (ui->setContainerAsListRadio->isChecked()){ + return; + } + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerListOrMap(row, true); + model->setContainerListOrMap(row, true); applyModel(); } void VariableDialog::onSetContainerAsStringRadioSelected() { + if (ui->setContainerAsStringRadio->isChecked()){ + return; + } + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerValueType(row, true); + model->setContainerValueType(row, true); applyModel(); } void VariableDialog::onSetContainerAsNumberRadioSelected() { + if (ui->setContainerAsNumberRadio->isChecked()){ + return; + } + + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerValueType(row, false); + model->setContainerValueType(row, false); applyModel(); } void VariableDialog::onSetContainerKeyAsStringRadioSelected() { + if (ui->setContainerKeyAsStringRadio->isChecked()){ + return; + } + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerKeyType(row, true); - applyModel(); + model->setContainerKeyType(row, true); + applyModel(); } - void VariableDialog::onSetContainerKeyAsNumberRadioSelected() { + if (ui->setContainerKeyAsNumberRadio->isChecked()){ + return; + } + int row = getCurrentContainerRow(); if (row < 0){ return; } - setContainerKeyType(row, false); + model->setContainerKeyType(row, false); applyModel(); } -void VariableDialog::onDoNotSaveContainerRadioSelected(){} -void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() {} -void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() {} -void VariableDialog::onNetworkContainerCheckboxClicked() {} -void VariableDialog::onSetContainerAsEternalCheckboxClicked() {} +void VariableDialog::onDoNotSaveContainerRadioSelected() +{ + if (ui->doNotSaveContainerRadio->isChecked()){ + return; + } + + int row = getCurrentContainerRow(); + + if (row < 0){ + return; + } + + if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 0) != 0){ + applyModel(); + } else { + ui->doNotSaveContainerRadio.setChecked(true); + ui->saveContainerOnMissionClosedRadio.setChecked(false); + ui->saveContainerOnMissionCompletedRadio.setChecked(false); + } +} +void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() +{ + if (ui->saveContainerOnMissionClosedRadio->isChecked()){ + return; + } + + int row = getCurrentContainerRow(); + + if (row < 0){ + return; + } + + if (model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) + applyModel(); + else { + ui->doNotSaveContainerRadio.setChecked(false); + ui->saveContainerOnMissionClosedRadio.setChecked(true); + ui->saveContainerOnMissionCompletedRadio.setChecked(false); + } +} + +void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() +{ + if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ + return; + } + + int row = getCurrentContainerRow(); + + if (row < 0){ + return; + } + + if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 1) != 1) + applyModel(); + else { + ui->doNotSaveContainerRadio.setChecked(false); + ui->saveContainerOnMissionClosedRadio.setChecked(false); + ui->saveContainerOnMissionCompletedRadio.setChecked(true); + } +} + +void VariableDialog::onNetworkContainerCheckboxClicked() +{ + int row = getCurrentContainerRow(); + + if (row < 0){ + return; + } + + if (ui->networkContainerCheckbox->ischecked() != _model->setContainerNetworkStatus(row, ui->networkContainerCheckbox->ischecked())){ + applyModel(); + } +} + +void VariableDialog::onSetContainerAsEternalCheckboxClicked() +{ + int row = getCurrentContainerRow(); + + if (row < 0){ + return; + } + + if (ui->setContainerAsEternalCheckbox->ischecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->ischecked())){ + applyModel(); + } +} + void VariableDialog::onAddContainerItemButtonPressed() {} void VariableDialog::onCopyContainerItemButtonPressed() {} void VariableDialog::onDeleteContainerItemButtonPressed() {} From 3bec6d8cfc93866e1329193cce14912c5c1ea89d Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 00:14:19 -0400 Subject: [PATCH 049/153] No const here --- qtfred/src/mission/dialogs/VariableDialogModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index d15bcb8509b..245f79821a0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -166,7 +166,7 @@ class VariableDialogModel : public AbstractDialogModel { static SCP_string trimNumberString(SCP_string source); // many of the controls in this editor can lead to drastic actions, so this will be very useful. - const bool confirmAction(SCP_string question, SCP_string informativeText) + bool confirmAction(SCP_string question, SCP_string informativeText) { QMessageBox msgBox; msgBox.setText(question.c_str()); From 6bd3b43cd893d3493523bbc4fddcb697dadb0a12 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 00:17:01 -0400 Subject: [PATCH 050/153] Don't forget extra line left by accident --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index a08fbc9df01..a0038453d02 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -192,7 +192,6 @@ void VariableDialogModel::initializeData() } else { item.string = false; - Sexp_variables[i].text; try { item.numberValue = std::stoi(Sexp_variables[i].text); } From 6264656097ea2fe08add5512ab823d25534cd198 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 00:37:46 -0400 Subject: [PATCH 051/153] As far as I can tell populating items is done --- qtfred/src/ui/dialogs/VariableDialog.cpp | 167 ++++++++++++++++++++++- 1 file changed, 164 insertions(+), 3 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 36fd06035ea..109746082c5 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1142,32 +1142,193 @@ void VariableDialog::updateContainerOptions() void VariableDialog::updateContainerDataOptions(bool list) { + int row = getCurrentContainerRow(); - if (_currentContainer.empty()){ + // No overarching container, no container contents + if (row < 0){ + ui->addContainerItemButton->setEnabled(false); ui->copyContainerItemButton->setEnabled(false); ui->deleteContainerItemButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + ui->containerContentsTable->setRowCount(0); return; + + // list type container } else if (list) { + ui->addContainerItemButton->setEnabled(true); ui->copyContainerItemButton->setEnabled(true); ui->deleteContainerItemButton->setEnabled(true); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + // with string contents + if (_model->getContainerValueType(row)){ + auto strings = _model->getStringValues(); + ui->continerContentsTable->setRowCount(static_cast(strings.size()) + 1); + + int x; + for (x = 0; x < static_cast(strings.size()); ++x){ + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText(strings[x].c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); + ui->containerContentsTable->setItem(x, 0, item); + } + + // empty out the second column as it's not needed in list mode + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } + } + + ++x; + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText("Add item ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + ui->containerContentsTable->setItem(x, 0, item); + } + + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } + + // list with number contents + } else { + auto numbers = _model->getNumberValues(); + ui->continerContentsTable->setRowCount(static_cast(numbers.size()) + 1); + + int x; + for (x = 0; x < static_cast(numbers.size()); ++x){ + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText(std::to_string(numbers[x]).c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); + ui->containerContentsTable->setItem(x, 0, item); + } + + // empty out the second column as it's not needed in list mode + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } + } + + ++x; + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText("Add item ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + ui->containerContentsTable->setItem(x, 0, item); + } + + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + } + + } + + // or it could be a map container } else { + ui->addContainerItemButton->setEnabled(true); ui->copyContainerItemButton->setEnabled(true); ui->deleteContainerItemButton->setEnabled(true); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + // keys I didn't bother to make separate. Should have done the same with values. + auto keys = _model->getMapKeys(row); - ui->continerContentsTable->setRowCount(); + // string valued map. + if (_model->getContainerValueType(row)){ + auto strings = _model->getStringValues(); + + // use the map as the size because map containers are only as good as their keys anyway. + ui->continerContentsTable->setRowCount(static_cast(keys.size()) + 1); + + int x; + for (x = 0; x < static_cast(keys.size()); ++x){ + if (ui->contiainerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(keys[x].c_str()); + ui->containerContentsTable->setItem(x, 0, item); + } + + + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(strings[x].c_str()); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } + } - } + // number valued map + } else { + auto numbers = _model->getNumberValues(); + ui->continerContentsTable->setRowCount(static_cast(keys.size()) + 1); + + int x; + for (x = 0; x < static_cast(keys.size()); ++x){ + if (ui->contiainerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); + } else { + QTableWidgetItem* item = new QTableWidgetItem(keys[x].c_str()); + ui->containerContentsTable->setItem(x, 0, item); + } + + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(std::to_string(numbers[x]).c_str()); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } + } + ++x; + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText("Add key ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add key ..."); + ui->containerContentsTable->setItem(x, 0, item); + } + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText("Add Value ..."); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add Value ..."); + ui->containerContentsTable->setItem(x, 1, item); + ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + } + } + } } From 314ba92782c19fe17b2c3eafa29c48d0947dc713 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 00:41:38 -0400 Subject: [PATCH 052/153] Fix Compiler Errors --- .../mission/dialogs/VariableDialogModel.cpp | 18 +++++++++--------- .../src/mission/dialogs/VariableDialogModel.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index a0038453d02..68c7046307a 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -490,8 +490,8 @@ SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName } // Truncate name if needed - if (newName.len() >= TOKEN_LENGTH){ - newName = newName.substr(0, TAKEN_LENGTH - 1); + if (newName.length() >= TOKEN_LENGTH){ + newName = newName.substr(0, TOKEN_LENGTH - 1); } // We cannot have two variables with the same name, but we need to check this somewhere else (like on accept attempt). @@ -857,7 +857,7 @@ std::pair VariableDialogModel::addMapItem(int index) ret.first = newKey; - if (container.string) + if (container->string) ret.second = ""; else ret.second = "0"; @@ -1106,13 +1106,13 @@ const SCP_vector& VariableDialogModel::getMapKeys(int index) if (!container) { SCP_string temp; - sprintf("getMapKeys() found that container %s does not exist.", container->name.c_str()); + sprintf(temp, "getMapKeys() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp.c_str()); } if (container->list) { SCP_string temp; - sprintf("getMapKeys() found that container %s is not a map.", container->name.c_str()); + sprintf(temp, "getMapKeys() found that container %s is not a map.", container->name.c_str()); throw std::invalid_argument(temp); } @@ -1126,13 +1126,13 @@ const SCP_vector& VariableDialogModel::getStringValues(int index) if (!container) { SCP_string temp; - sprintf("getStringValues() found that container %s does not exist.", container->name.c_str()); + sprintf(temp, "getStringValues() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp); } if (!container->string) { SCP_string temp; - sprintf("getStringValues() found that container %s does not store strings.", container->name.c_str()); + sprintf(temp, "getStringValues() found that container %s does not store strings.", container->name.c_str()); throw std::invalid_argument(temp); } @@ -1146,13 +1146,13 @@ const SCP_vector& VariableDialogModel::getNumberValues(int index) if (!container) { SCP_string temp; - sprintf("getNumberValues() found that container %s does not exist.", container->name.c_str()); + sprintf(temp, "getNumberValues() found that container %s does not exist.", container->name.c_str()); throw std::invalid_argument(temp); } if (container->string) { SCP_string temp; - sprintf("getNumberValues() found that container %s does not store numbers.", container->name.c_str()); + sprintf(temp, "getNumberValues() found that container %s does not store numbers.", container->name.c_str()); throw std::invalid_argument(temp); } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 245f79821a0..ea201446b48 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -115,7 +115,7 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); - void VariableDialogModel::checkValidModel(); + void checkValidModel(); bool apply() override; void reject() override; From 792cf0a0ed8d9221d664504b9701018b2f5fc054 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 01:11:57 -0400 Subject: [PATCH 053/153] More fixes --- .../mission/dialogs/VariableDialogModel.cpp | 16 +++++++------- qtfred/src/ui/dialogs/VariableDialog.cpp | 22 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 68c7046307a..c122133afd9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1192,7 +1192,7 @@ const SCP_vector> VariableDialogModel::getContainerNam SCP_string mapPrefix; SCP_string mapMidScript; - SCP_string mapPostscript + SCP_string mapPostscript; switch (_listTextMode) { case 1: @@ -1216,13 +1216,13 @@ const SCP_vector> VariableDialogModel::getContainerNam break; case 5: - listPrefix = "<" - listPostscript = ">" + listPrefix = "<"; + listPostscript = ">"; break; case 6: - listPrefix = "" - listPostscript = "" + listPrefix = ""; + listPostscript = ""; break; @@ -1272,7 +1272,7 @@ const SCP_vector> VariableDialogModel::getContainerNam break; - case default: + default: _mapTextMode = 0; mapPrefix = "Map with "; mapMidScript = " Keys and "; @@ -1310,9 +1310,9 @@ const SCP_vector> VariableDialogModel::getContainerNam type += mapMidScript; if (item.string){ - type += "String" + type += "String"; } else { - type += "Number" + type += "Number"; } type += mapPostscript; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 109746082c5..b4bb238a38a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -83,7 +83,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(ui->doNotSaveVariableRadio, &QRadioButton::toggled, this, - &VariableDialog::onDoNotSaveVariableRadioSelected) + &VariableDialog::onDoNotSaveVariableRadioSelected); connect(ui->saveContainerOnMissionCompletedRadio, &QRadioButton::toggled, @@ -243,7 +243,7 @@ void VariableDialog::onVariablesTableUpdated() return; } - auto item = + auto item = ui->variablesTable->item(currentRow); // so if the user just removed the name, mark it as deleted *before changing the name* if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { @@ -272,7 +272,7 @@ void VariableDialog::onVariablesTableUpdated() // empty return and cell was handled earlier. // data cell was altered - } else if (item->column() == 1) { + if (item->column() == 1) { // Variable is a string if (_model->getVariableType(item->row())){ @@ -318,16 +318,18 @@ void VariableDialog::onVariablesSelectionChanged() return; } - SCP_string newVariableName = ""; + int row = getCurrentVariableRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - if (item->column() == 0){ - newVariableName = item->text().toStdString(); - break; - } + if (row < 0){ + return; } + + SCP_string newVariableName = ""; + if (item == 0){ + newVariableName = item->text().toStdString(); + } + if (newVariableName != _currentVariable){ _currentVariable = newVariableName; applyModel(); From ce32ef30226fef25ce6555069f739b6facd3d675 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 13:41:23 -0400 Subject: [PATCH 054/153] Linter Fixes --- .../mission/dialogs/VariableDialogModel.cpp | 5 +- .../src/mission/dialogs/VariableDialogModel.h | 4 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 85 ++++++++++--------- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c122133afd9..d56b6611552 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -798,6 +798,7 @@ bool VariableDialogModel::removeContainer(int index) } container->deleted = true; + return container->deleted; } SCP_string VariableDialogModel::addListItem(int index) @@ -996,6 +997,8 @@ std::pair VariableDialogModel::copyMapItem(int index, SC } } } + + return std::make_pair("", ""); } // it's really because of this feature that we need data to only be in one or the other vector for maps. @@ -1184,7 +1187,7 @@ const SCP_vector> VariableDialogModel::getVariableValu return outStrings; } -const SCP_vector> VariableDialogModel::getContainerNames() +SCP_vector> VariableDialogModel::getContainerNames() { // This logic makes the mode which we use to display, easily configureable. SCP_string listPrefix; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index ea201446b48..2f8c7b48aff 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -121,6 +121,9 @@ class VariableDialogModel : public AbstractDialogModel { void reject() override; void initializeData(); + + static SCP_string trimNumberString(SCP_string source); + private: SCP_vector _variableItems; SCP_vector _containerItems; @@ -163,7 +166,6 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } - static SCP_string trimNumberString(SCP_string source); // many of the controls in this editor can lead to drastic actions, so this will be very useful. bool confirmAction(SCP_string question, SCP_string informativeText) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b4bb238a38a..cff5802a88d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -153,7 +153,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(ui->doNotSaveContainerRadio, &QRadioButton::toggled, this, - &VariableDialog::onDoNotSaveContainerRadioSelected) + &VariableDialog::onDoNotSaveContainerRadioSelected); connect(ui->saveContainerOnMissionCloseRadio, &QRadioButton::toggled, @@ -231,6 +231,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) } // TODO! make sure that when a variable is added that the whole model is reloaded. +// TODO! Fix me. This function does not work as intended because it must process both, not just one. void VariableDialog::onVariablesTableUpdated() { if (_applyingModel){ @@ -243,14 +244,14 @@ void VariableDialog::onVariablesTableUpdated() return; } - auto item = ui->variablesTable->item(currentRow); + auto item = ui->variablesTable->item(currentRow, 0); + bool apply = false; // so if the user just removed the name, mark it as deleted *before changing the name* if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { if (!_model->removeVariable(item->row())) { // marking a variable as deleted failed, resync UI - applyModel(); - return; + apply = true; } else { updateVariableOptions(); } @@ -261,7 +262,7 @@ void VariableDialog::onVariablesTableUpdated() // we put something in the cell, but the model couldn't process it. if (strlen(item->text().toStdString().c_str()) && ret == ""){ // update of variable name failed, resync UI - applyModel(); + apply = true; // we had a successful rename. So update the variable we reference. } else if (ret != "") { @@ -271,7 +272,11 @@ void VariableDialog::onVariablesTableUpdated() } // empty return and cell was handled earlier. - // data cell was altered + + item = ui->variablesTable->item(currentRow, 1); + + // check if data column was altered + // TODO! Set up comparison between last and current value if (item->column() == 1) { // Variable is a string @@ -281,11 +286,10 @@ void VariableDialog::onVariablesTableUpdated() SCP_string ret = _model->setVariableStringValue(item->row(), temp); if (ret == ""){ - applyModel(); - return; - } - - item->setText(ret.c_str()); + apply = true; + } else { + item->setText(ret.c_str()); + } } else { SCP_string source = item->text().toStdString(); SCP_string temp = _model->trimNumberString(source); @@ -323,10 +327,12 @@ void VariableDialog::onVariablesSelectionChanged() if (row < 0){ return; } - + SCP_string newVariableName = ""; - if (item == 0){ + auto item = ui->variablesTable->item(x, 0); + + if (item){ newVariableName = item->text().toStdString(); } @@ -351,19 +357,19 @@ void VariableDialog::onContainersTableUpdated() } // Are they adding a new container? - if (row == ui->containersTable->rowCount - 1){ + if (row == ui->containersTable->rowCount() - 1){ if (ui->containersTable->item(row, 0)) { - SCP_string newString = ui->containersTable->item(row, 0).text().toStdString(); + SCP_string newString = ui->containersTable->item(row, 0)->text().toStdString(); if (!newString.empty() && newString != "Add Container ..."){ - _model->addContainer(newSTring); - _currentContainer = newString(); + _model->addContainer(newString); + _currentContainer = newString; applyModel(); } } // are they editing an existing container name? } else if (ui->containersTable->item(row, 0)){ - _currentContainer = ui->containersTable->item(row,0).toStdString(); + _currentContainer = ui->containersTable->item(row,0)->text().toStdString(); if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0).toStdString())){ applyModel(); @@ -489,8 +495,6 @@ void VariableDialog::onSetVariableAsStringRadioSelected() ui->setVariableAsStringRadio->setChecked(true); ui->setVariableAsNumberRadio->setChecked(false); } - - break; } void VariableDialog::onSetVariableAsNumberRadioSelected() @@ -514,7 +518,6 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() ui->setVariableAsStringRadio->setChecked(false); ui->setVariableAsNumberRadio->setChecked(true); } - break; } void VariableDialog::onDoNotSaveVariableRadioSelected() @@ -554,7 +557,7 @@ void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() return; } - auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(row(), 1); + auto ret = _model->setVariableOnMissionCloseOrCompleteFlag(row, 1); if (ret != 1){ applyModel(); @@ -668,7 +671,7 @@ void VariableDialog::onSetContainerAsMapRadioSelected() return; } - model->setContainerListOrMap(row, false); + _model->setContainerListOrMap(row, false); applyModel(); } @@ -684,7 +687,7 @@ void VariableDialog::onSetContainerAsListRadioSelected() return; } - model->setContainerListOrMap(row, true); + _model->setContainerListOrMap(row, true); applyModel(); } @@ -701,7 +704,7 @@ void VariableDialog::onSetContainerAsStringRadioSelected() return; } - model->setContainerValueType(row, true); + _model->setContainerValueType(row, true); applyModel(); } @@ -718,7 +721,7 @@ void VariableDialog::onSetContainerAsNumberRadioSelected() return; } - model->setContainerValueType(row, false); + _model->setContainerValueType(row, false); applyModel(); } @@ -734,7 +737,7 @@ void VariableDialog::onSetContainerKeyAsStringRadioSelected() return; } - model->setContainerKeyType(row, true); + _model->setContainerKeyType(row, true); applyModel(); } @@ -751,7 +754,7 @@ void VariableDialog::onSetContainerKeyAsNumberRadioSelected() return; } - model->setContainerKeyType(row, false); + _model->setContainerKeyType(row, false); applyModel(); } @@ -770,9 +773,9 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 0) != 0){ applyModel(); } else { - ui->doNotSaveContainerRadio.setChecked(true); - ui->saveContainerOnMissionClosedRadio.setChecked(false); - ui->saveContainerOnMissionCompletedRadio.setChecked(false); + ui->doNotSaveContainerRadio->setChecked(true); + ui->saveContainerOnMissionCloseRadio->setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() @@ -790,9 +793,9 @@ void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() if (model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) applyModel(); else { - ui->doNotSaveContainerRadio.setChecked(false); - ui->saveContainerOnMissionClosedRadio.setChecked(true); - ui->saveContainerOnMissionCompletedRadio.setChecked(false); + ui->doNotSaveContainerRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } @@ -811,9 +814,9 @@ void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 1) != 1) applyModel(); else { - ui->doNotSaveContainerRadio.setChecked(false); - ui->saveContainerOnMissionClosedRadio.setChecked(false); - ui->saveContainerOnMissionCompletedRadio.setChecked(true); + ui->doNotSaveContainerRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(true); } } @@ -825,7 +828,7 @@ void VariableDialog::onNetworkContainerCheckboxClicked() return; } - if (ui->networkContainerCheckbox->ischecked() != _model->setContainerNetworkStatus(row, ui->networkContainerCheckbox->ischecked())){ + if (ui->networkContainerCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->networkContainerCheckbox->ischecked())){ applyModel(); } } @@ -843,7 +846,11 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() } } -void VariableDialog::onAddContainerItemButtonPressed() {} +void VariableDialog::onAddContainerItemButtonPressed() +{ + +} + void VariableDialog::onCopyContainerItemButtonPressed() {} void VariableDialog::onDeleteContainerItemButtonPressed() {} From 474527ef8381ec85d27b8d2a66c725ef7db1dd86 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 14:15:35 -0400 Subject: [PATCH 055/153] More Linter Fixes --- .../mission/dialogs/VariableDialogModel.cpp | 3 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 41 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index d56b6611552..b3c71bc16aa 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -899,6 +899,7 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) container->numberValues.erase(container->numberValues.begin() + index); } + return true; } std::pair VariableDialogModel::copyMapItem(int index, SCP_string keyIn) @@ -1187,7 +1188,7 @@ const SCP_vector> VariableDialogModel::getVariableValu return outStrings; } -SCP_vector> VariableDialogModel::getContainerNames() +const SCP_vector> VariableDialogModel::getContainerNames() { // This logic makes the mode which we use to display, easily configureable. SCP_string listPrefix; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index cff5802a88d..c0a5ee4370a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1174,8 +1174,8 @@ void VariableDialog::updateContainerDataOptions(bool list) // with string contents if (_model->getContainerValueType(row)){ - auto strings = _model->getStringValues(); - ui->continerContentsTable->setRowCount(static_cast(strings.size()) + 1); + auto strings = _model->getStringValues(row); + ui->containerContentsTable->setRowCount(static_cast(strings.size()) + 1); int x; for (x = 0; x < static_cast(strings.size()); ++x){ @@ -1189,11 +1189,11 @@ void VariableDialog::updateContainerDataOptions(bool list) // empty out the second column as it's not needed in list mode if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } @@ -1207,17 +1207,17 @@ void VariableDialog::updateContainerDataOptions(bool list) if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } // list with number contents } else { auto numbers = _model->getNumberValues(); - ui->continerContentsTable->setRowCount(static_cast(numbers.size()) + 1); + ui->containerContentsTable->setRowCount(static_cast(numbers.size()) + 1); int x; for (x = 0; x < static_cast(numbers.size()); ++x){ @@ -1231,7 +1231,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // empty out the second column as it's not needed in list mode if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); ui->containerContentsTable->setItem(x, 1, item); @@ -1249,11 +1249,11 @@ void VariableDialog::updateContainerDataOptions(bool list) if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } @@ -1274,7 +1274,7 @@ void VariableDialog::updateContainerDataOptions(bool list) auto strings = _model->getStringValues(); // use the map as the size because map containers are only as good as their keys anyway. - ui->continerContentsTable->setRowCount(static_cast(keys.size()) + 1); + ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); int x; for (x = 0; x < static_cast(keys.size()); ++x){ @@ -1285,21 +1285,20 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 0, item); } - if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(strings[x].c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } // number valued map } else { - auto numbers = _model->getNumberValues(); - ui->continerContentsTable->setRowCount(static_cast(keys.size()) + 1); + auto numbers = _model->getNumberValues(row); + ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); int x; for (x = 0; x < static_cast(keys.size()); ++x){ @@ -1312,11 +1311,11 @@ void VariableDialog::updateContainerDataOptions(bool list) if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(std::to_string(numbers[x]).c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } @@ -1330,11 +1329,11 @@ void VariableDialog::updateContainerDataOptions(bool list) if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText("Add Value ..."); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem("Add Value ..."); - ui->containerContentsTable->setItem(x, 1, item); ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } } @@ -1368,7 +1367,7 @@ int VariableDialog::getCurrentContainerRow(){ return -1; } -int variableDialog::getCurrentContainerItemRow(){ +int VariableDialog::getCurrentContainerItemRow(){ auto items = ui->containerItemsTeable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. From 29754cafc285f5201bf3cd8eda92f4926f499906 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 14:39:45 -0400 Subject: [PATCH 056/153] More Linter Fixes --- qtfred/src/ui/dialogs/VariableDialog.cpp | 20 ++++++++++---------- qtfred/src/ui/dialogs/VariableDialog.h | 2 ++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c0a5ee4370a..bf97488fa9a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -330,7 +330,7 @@ void VariableDialog::onVariablesSelectionChanged() SCP_string newVariableName = ""; - auto item = ui->variablesTable->item(x, 0); + auto item = ui->variablesTable->item(row, 0); if (item){ newVariableName = item->text().toStdString(); @@ -790,7 +790,7 @@ void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() return; } - if (model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) + if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) applyModel(); else { ui->doNotSaveContainerRadio->setChecked(false); @@ -841,7 +841,7 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() return; } - if (ui->setContainerAsEternalCheckbox->ischecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->ischecked())){ + if (ui->setContainerAsEternalCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->ischecked())){ applyModel(); } } @@ -884,7 +884,7 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); - ui->varaiblesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); ui->variablesTable->setItem(x, 1, item); @@ -910,7 +910,7 @@ void VariableDialog::applyModel() } if (ui->variablesTable->item(x, 1)){ - ui->varaiblesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 1)->setFlags(ui->variablesTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); ui->variablesTable->item(x, 1)->setText(""); } else { QTableWidgetItem* item = new QTableWidgetItem(""); @@ -919,7 +919,7 @@ void VariableDialog::applyModel() } if (ui->variablesTable->item(x, 2)){ - ui->varaiblesTable->item(x, 2)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 2)->setFlags(ui->variablesTable->item(x, 2)->flags() & ~Qt::ItemIsEditable); ui->variablesTable->item(x, 2)->setText(""); } else { QTableWidgetItem* item = new QTableWidgetItem(""); @@ -1216,7 +1216,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // list with number contents } else { - auto numbers = _model->getNumberValues(); + auto numbers = _model->getNumberValues(row); ui->containerContentsTable->setRowCount(static_cast(numbers.size()) + 1); int x; @@ -1278,7 +1278,7 @@ void VariableDialog::updateContainerDataOptions(bool list) int x; for (x = 0; x < static_cast(keys.size()); ++x){ - if (ui->contiainerContentsTable->item(x, 0)){ + if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); } else { QTableWidgetItem* item = new QTableWidgetItem(keys[x].c_str()); @@ -1302,7 +1302,7 @@ void VariableDialog::updateContainerDataOptions(bool list) int x; for (x = 0; x < static_cast(keys.size()); ++x){ - if (ui->contiainerContentsTable->item(x, 0)){ + if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); } else { QTableWidgetItem* item = new QTableWidgetItem(keys[x].c_str()); @@ -1368,7 +1368,7 @@ int VariableDialog::getCurrentContainerRow(){ } int VariableDialog::getCurrentContainerItemRow(){ - auto items = ui->containerItemsTeable->selectedItems(); + auto items = ui->containerItemsTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 7c6552ffa8b..b41817fb2e7 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -73,8 +73,10 @@ class VariableDialog : public QDialog { bool _applyingModel = false; SCP_string _currentVariable = ""; + SCP_string _currentVariableData = ""; SCP_string _currentContainer = ""; SCP_string _currentContainerItem = ""; + SCP_string _currentContainerItemData = ""; }; From 3698cbe09ff856abb914fdc1ace8df58d87c935d Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 15:00:44 -0400 Subject: [PATCH 057/153] Hopefully Final Linter mistakes --- qtfred/src/ui/dialogs/VariableDialog.cpp | 26 ++++++++++++++---------- qtfred/src/ui/dialogs/VariableDialog.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index bf97488fa9a..c5778d90694 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -158,7 +158,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(ui->saveContainerOnMissionCloseRadio, &QRadioButton::toggled, this, - &VariableDialog::onSaveContainerOnMissionClosedRadioSelected); + &VariableDialog::onSaveContainerOnMissionCloseRadioSelected); connect(ui->saveContainerOnMissionCompletedRadio, &QRadioButton::toggled, @@ -371,7 +371,7 @@ void VariableDialog::onContainersTableUpdated() } else if (ui->containersTable->item(row, 0)){ _currentContainer = ui->containersTable->item(row,0)->text().toStdString(); - if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0).toStdString())){ + if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0)->text().toStdString())){ applyModel(); } } @@ -641,8 +641,11 @@ void VariableDialog::onAddContainerButtonPressed() } -// TODO! 4 more functions to write -void VariableDialog::onCopyContainerButtonPressed() {} +// TODO! 3 more functions to write +void VariableDialog::onCopyContainerButtonPressed() +{ + +} void VariableDialog::onDeleteContainerButtonPressed() { @@ -778,9 +781,9 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } -void VariableDialog::onSaveContainerOnMissionClosedRadioSelected() +void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() { - if (ui->saveContainerOnMissionClosedRadio->isChecked()){ + if (ui->saveContainerOnMissionCloseRadio->isChecked()){ return; } @@ -828,7 +831,7 @@ void VariableDialog::onNetworkContainerCheckboxClicked() return; } - if (ui->networkContainerCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->networkContainerCheckbox->ischecked())){ + if (ui->networkContainerCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->networkContainerCheckbox->isChecked())){ applyModel(); } } @@ -841,7 +844,7 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() return; } - if (ui->setContainerAsEternalCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->ischecked())){ + if (ui->setContainerAsEternalCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->isChecked())){ applyModel(); } } @@ -884,7 +887,7 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); - ui->variablesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->variablesTable->item(x, 1)->setFlags(ui->variablesTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); ui->variablesTable->setItem(x, 1, item); @@ -893,6 +896,7 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 2)){ ui->variablesTable->item(x, 2)->setText(variables[x][2].c_str()); + ui->variablesTable->item(x, 2)->setFlags(ui->variablesTable->item(x, 2)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][2].c_str()); ui->variablesTable->setItem(x, 2, item); @@ -1271,7 +1275,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // string valued map. if (_model->getContainerValueType(row)){ - auto strings = _model->getStringValues(); + auto strings = _model->getStringValues(row); // use the map as the size because map containers are only as good as their keys anyway. ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); @@ -1368,7 +1372,7 @@ int VariableDialog::getCurrentContainerRow(){ } int VariableDialog::getCurrentContainerItemRow(){ - auto items = ui->containerItemsTable->selectedItems(); + auto items = ui->containerContentsTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index b41817fb2e7..2d4bf1425fa 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -59,7 +59,7 @@ class VariableDialog : public QDialog { void onSetContainerKeyAsStringRadioSelected(); void onSetContainerKeyAsNumberRadioSelected(); void onDoNotSaveContainerRadioSelected(); - void onSaveContainerOnMissionClosedRadioSelected(); + void onSaveContainerOnMissionCloseRadioSelected(); void onSaveContainerOnMissionCompletedRadioSelected(); void onNetworkContainerCheckboxClicked(); void onSetContainerAsEternalCheckboxClicked(); From 22663cb2972e5779ae85ab4f6dc652f18aa2ecbf Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 15:54:11 -0400 Subject: [PATCH 058/153] Finish Dialog Code Need to make more changes to the model --- .../mission/dialogs/VariableDialogModel.cpp | 4 +- .../src/mission/dialogs/VariableDialogModel.h | 3 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 103 ++++++++++++++++-- 3 files changed, 95 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index b3c71bc16aa..c4c6267bc6d 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1007,7 +1007,7 @@ std::pair VariableDialogModel::copyMapItem(int index, SC // both of the map's data vectors might be undesired, and not deleting takes the map immediately // out of sync. Also, just displaying both data sets would be misleading. // We just need to tell the user that the data cannot be maintained. -bool VariableDialogModel::removeMapItem(int index, SCP_string key) +bool VariableDialogModel::removeMapItem(int index, int itemIndex) { auto container = lookupContainer(index); @@ -1015,6 +1015,8 @@ bool VariableDialogModel::removeMapItem(int index, SCP_string key) return false; } + auto item = lookupContainerItem(itemIndex); + for (int x = 0; x < static_cast(container->keys.size()); ++x) { if (container->keys[x] == key) { if (container->string && x < static_cast(container->stringValues.size())) { diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 2f8c7b48aff..d84c74eefed 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -97,13 +97,12 @@ class VariableDialogModel : public AbstractDialogModel { bool removeContainer(int index); SCP_string addListItem(int index); - SCP_string copyListItem(int containerIndex, int index); bool removeListItem(int containerindex, int index); std::pair addMapItem(int index); std::pair copyMapItem(int index, SCP_string key); - bool removeMapItem(int index, SCP_string key); + bool removeMapItem(int index, int rowIndex); SCP_string replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey); SCP_string changeMapItemStringValue(int index, SCP_string key, SCP_string newValue); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c5778d90694..f70ffacf953 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -335,7 +335,13 @@ void VariableDialog::onVariablesSelectionChanged() if (item){ newVariableName = item->text().toStdString(); } - + + item = ui->variablesTable->item(row, 1); + + if (item){ + _currentVariableData = item->text().toStdString(); + } + if (newVariableName != _currentVariable){ _currentVariable = newVariableName; applyModel(); @@ -401,6 +407,7 @@ void VariableDialog::onContainersSelectionChanged() } } +// TODO, finish this function void VariableDialog::onContainerContentsTableUpdated() { if (_applyingModel){ @@ -416,16 +423,26 @@ void VariableDialog::onContainerContentsSelectionChanged() return; } - auto items = ui->containerContentsTable->selectedItems(); + int row = getCurrentContainerItemRow(); - SCP_string newContainerItemName = ""; + if (row < 0){ + return; + } - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - if (item->column() == 0){ - newContainerItemName = item->text().toStdString(); - break; - } + auto item = ui->containerContentsTable->item(row, 0); + + if (item){ + SCP_string newContainerItemName = item->text().toStdString(); + } else { + return; + } + + item = ui->containerContentsTable->item(row, 1); + + if (item){ + _currentContainerItemData = item->text().toStdString(); + } else { + _currentContainerItemData = ""; } if (newContainerItemName != _currentContainerItem){ @@ -641,10 +658,17 @@ void VariableDialog::onAddContainerButtonPressed() } -// TODO! 3 more functions to write void VariableDialog::onCopyContainerButtonPressed() { + int row = getCurrentContainerRow(); + + if (row < 0 ){ + return; + } + // This will always need an apply model update, whether it succeeds or fails. + copyContainer(row); + applyModel(); } void VariableDialog::onDeleteContainerButtonPressed() @@ -851,11 +875,66 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() void VariableDialog::onAddContainerItemButtonPressed() { + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + if (_model->getContainerListOrMap(containerRow)) { + _model->addListItem(containerRow); + } else { + _model->addMapItem(containerRow); + } + + applyModel(); +} + +void VariableDialog::onCopyContainerItemButtonPressed() +{ + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + int itemRow = getCurrentContainerItemRow(); + + if (itemRow < 0){ + return; + } + + if (_model->getContainerListOrMap(containerRow)) { + _model->copyListItem(containerRow, itemRow); + } else { + _model->copyMapItem(containerRow, itemRow); + } + applyModel(); } -void VariableDialog::onCopyContainerItemButtonPressed() {} -void VariableDialog::onDeleteContainerItemButtonPressed() {} +void VariableDialog::onDeleteContainerItemButtonPressed() +{ + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + int itemRow = getCurrentContainerItemRow(); + + if (itemRow < 0){ + return; + } + + if (_model->getContainerListOrMap(containerRow)) { + _model->removeListItem(containerRow, itemRow); + } else { + _model->removeMapItem(containerRow, itemRow); + } + + applyModel(); +} VariableDialog::~VariableDialog(){}; // NOLINT From a82db02b41ecb935fbed9956fa352ec3a955185e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 15:56:47 -0400 Subject: [PATCH 059/153] Fix missing function --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c4c6267bc6d..1556d94905f 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -768,7 +768,14 @@ SCP_string VariableDialogModel::addContainer() _containerItems.emplace_back(); _containerItems.back().name = name; - return name; + return _containerItems.back().name; +} + +SCP_string VariableDialogModel::addContainer(SCP_string nameIn) +{ + _containerItems.emplace_back(); + _containerItems.back().name = nameIn; + return _containerItems.back().name; } SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) From 209e905a0565433c7f6f0f6847c10e83a2811302 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 16:00:43 -0400 Subject: [PATCH 060/153] Add copy Container Function --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 1556d94905f..94a3ef348f0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -778,6 +778,19 @@ SCP_string VariableDialogModel::addContainer(SCP_string nameIn) return _containerItems.back().name; } +SCP_string VariableDialogModel::copyContainer(int index) +{ + auto container = lookupContainer(index); + + // nothing to copy, invalid entry + if (!container){ + return ""; + } + + // K.I.S.S. + _containerItems.push_back(*container); +} + SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) { if (newName == "") { From 4e669f9ce4bad3f8a0d547a9bdd3640af27cee0a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 16:02:00 -0400 Subject: [PATCH 061/153] don't forget to change name. --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 94a3ef348f0..c9d146c0a54 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -789,6 +789,9 @@ SCP_string VariableDialogModel::copyContainer(int index) // K.I.S.S. _containerItems.push_back(*container); + _containerItems.back().name += "_copy"; + _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH); + return } SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) From 91723be9c50c8f72365066f3202a76e583738b84 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 16:05:12 -0400 Subject: [PATCH 062/153] And stub another function for now There are at least two stubbed functions left on the model --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c9d146c0a54..8073992e676 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -686,6 +686,11 @@ bool VariableDialogModel::setContainerValueType(int index, bool type) return container->string; } +// TODO finish these two functions. +bool VariableDialogModel::setContainerKeyType(int index, bool string) { + return false; +} + // This is the most complicated function, because we need to query the user on what they want to do if the had already entered data. bool VariableDialogModel::setContainerListOrMap(int index, bool list) { From 7f0666cc334de2427dbe75060e0672a194d6d1e1 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 16:46:57 -0400 Subject: [PATCH 063/153] More Fixes, but Requires Linter For more progress --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 2 +- qtfred/src/mission/dialogs/VariableDialogModel.h | 2 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 8073992e676..68dbdd2e138 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -930,7 +930,7 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) return true; } -std::pair VariableDialogModel::copyMapItem(int index, SCP_string keyIn) +std::pair VariableDialogModel::copyMapItem(int index, int mapIndex) { auto container = lookupContainer(index); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index d84c74eefed..e3e64421cdb 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -101,7 +101,7 @@ class VariableDialogModel : public AbstractDialogModel { bool removeListItem(int containerindex, int index); std::pair addMapItem(int index); - std::pair copyMapItem(int index, SCP_string key); + std::pair copyMapItem(int index, int itemIndex); bool removeMapItem(int index, int rowIndex); SCP_string replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index f70ffacf953..70195806797 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -430,13 +430,14 @@ void VariableDialog::onContainerContentsSelectionChanged() } auto item = ui->containerContentsTable->item(row, 0); - - if (item){ - SCP_string newContainerItemName = item->text().toStdString(); - } else { + SCP_string newContainerItemName; + + if (!item){ return; } + newContainerItemName = item->text().toStdString(); + item = ui->containerContentsTable->item(row, 1); if (item){ @@ -667,7 +668,7 @@ void VariableDialog::onCopyContainerButtonPressed() } // This will always need an apply model update, whether it succeeds or fails. - copyContainer(row); + _model->copyContainer(row); applyModel(); } From f38dbae310f714c1cc89a967731400706944a7a4 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sun, 21 Apr 2024 22:50:51 -0400 Subject: [PATCH 064/153] Save changes to transfer over --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 68dbdd2e138..7d8df7e6a92 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -796,7 +796,7 @@ SCP_string VariableDialogModel::copyContainer(int index) _containerItems.push_back(*container); _containerItems.back().name += "_copy"; _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH); - return + return _containerItems.back().name; } SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) @@ -934,7 +934,10 @@ std::pair VariableDialogModel::copyMapItem(int index, in { auto container = lookupContainer(index); - if (!container) { + // any invalid case, early return + if (!container || mapIndex < 0 || mapIndex >= static_cast(container->keys.size()) + || (mapIndex >= static_cast(container->stringValues.size()) && container->string) + || (mapIndex >= static_cast(container->numberValues.size()) && !container->string)){ return std::make_pair("", ""); } From d147330739246294ff590a81d27000ce718a38cd Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 21 Apr 2024 23:38:14 -0400 Subject: [PATCH 065/153] Fix null item crash --- .../src/mission/dialogs/VariableDialogModel.cpp | 8 ++++---- qtfred/src/ui/dialogs/VariableDialog.cpp | 17 ++++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7d8df7e6a92..33d54a3a2ee 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -932,7 +932,7 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) std::pair VariableDialogModel::copyMapItem(int index, int mapIndex) { - auto container = lookupContainer(index); + /*auto container = lookupContainer(index); // any invalid case, early return if (!container || mapIndex < 0 || mapIndex >= static_cast(container->keys.size()) @@ -1029,7 +1029,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in } } } - + */ return std::make_pair("", ""); } @@ -1040,7 +1040,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in // We just need to tell the user that the data cannot be maintained. bool VariableDialogModel::removeMapItem(int index, int itemIndex) { - auto container = lookupContainer(index); +/* auto container = lookupContainer(index); if (!container){ return false; @@ -1065,7 +1065,7 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) } } - // NO SPRINGS!!! HEHEHEHEHE + // NO SPRINGS!!! HEHEHEHEHE*/ return false; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 70195806797..73c39436b09 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -277,6 +277,9 @@ void VariableDialog::onVariablesTableUpdated() // check if data column was altered // TODO! Set up comparison between last and current value + // TODO! Also this crashes because item->(x, 1) is null + // TODO! Variable is not editable + // TODO! Network container does not turn off if (item->column() == 1) { // Variable is a string @@ -1276,7 +1279,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + item->->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } } @@ -1294,7 +1297,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } @@ -1318,8 +1321,8 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); } } @@ -1336,7 +1339,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } @@ -1374,7 +1377,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } } @@ -1398,7 +1401,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } } @@ -1416,7 +1419,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem("Add Value ..."); - ui->containerContentsTable->item(x, 1)->setFlags(item->flags() | Qt::ItemIsEditable); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } } From 7f1e72ecca7e3be6651aef2b57f1b4b49f04c152 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Mon, 22 Apr 2024 00:32:51 -0400 Subject: [PATCH 066/153] Some final ui adjustments --- qtfred/src/ui/dialogs/VariableDialog.cpp | 8 ++--- qtfred/ui/VariableDialog.ui | 44 +++++++++++++++--------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 73c39436b09..aeab2a3a494 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -197,7 +197,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); ui->variablesTable->setColumnWidth(0, 90); ui->variablesTable->setColumnWidth(1, 90); - ui->variablesTable->setColumnWidth(2, 70); + ui->variablesTable->setColumnWidth(2, 65); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -205,7 +205,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); ui->containersTable->setColumnWidth(0, 90); ui->containersTable->setColumnWidth(1, 90); - ui->containersTable->setColumnWidth(2, 70); + ui->containersTable->setColumnWidth(2, 65); ui->containerContentsTable->setColumnCount(2); @@ -213,7 +213,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->containerContentsTable->setColumnWidth(0, 125); - ui->containerContentsTable->setColumnWidth(1, 125); + ui->containerContentsTable->setColumnWidth(1, 120); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't ui->setVariableAsStringRadio->setAutoExclusive(false); @@ -1279,7 +1279,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(""); - item->->setFlags(item->flags() & ~Qt::ItemIsEditable); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } } diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index a63a7c24a9d..7417a5a0661 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -7,13 +7,13 @@ 0 0 608 - 636 + 665 608 - 560 + 665 @@ -38,19 +38,19 @@ 270 120 - 71 + 81 101 Type Options - + - 0 + 10 20 - 116 + 71 80 @@ -103,9 +103,9 @@ - 360 + 370 20 - 221 + 211 201 @@ -165,7 +165,7 @@ 270 30 - 71 + 82 86 @@ -236,7 +236,7 @@ 10 190 - 341 + 351 191 @@ -273,7 +273,7 @@ 260 30 - 71 + 82 91 @@ -312,7 +312,7 @@ 270 30 - 71 + 82 91 @@ -348,9 +348,9 @@ - 360 + 370 20 - 211 + 201 161 @@ -408,9 +408,9 @@ - 360 + 370 190 - 211 + 191 191 @@ -422,7 +422,7 @@ 10 20 - 201 + 181 152 @@ -509,6 +509,16 @@ + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + From 3c7639a9e313015f074b938decd0d120f1f24c8f Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Mon, 22 Apr 2024 00:33:16 -0400 Subject: [PATCH 067/153] And one more apparently --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index aeab2a3a494..69fa2f7a385 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -212,7 +212,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 125); + ui->containerContentsTable->setColumnWidth(0, 120); ui->containerContentsTable->setColumnWidth(1, 120); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't From 9dfc6d7c686914fbd8f4e5af3af1f4e4193759b7 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 01:02:17 -0400 Subject: [PATCH 068/153] Fixes for UI bugs --- qtfred/src/ui/dialogs/VariableDialog.cpp | 49 +++++++++++++----------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 69fa2f7a385..28107a2fa95 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -71,27 +71,27 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &VariableDialog::onDeleteVariableButtonPressed); connect(ui->setVariableAsStringRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetVariableAsStringRadioSelected); connect(ui->setVariableAsNumberRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetVariableAsNumberRadioSelected); connect(ui->doNotSaveVariableRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onDoNotSaveVariableRadioSelected); connect(ui->saveContainerOnMissionCompletedRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSaveVariableOnMissionCompleteRadioSelected); connect(ui->saveVariableOnMissionCloseRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSaveVariableOnMissionCloseRadioSelected); @@ -121,47 +121,47 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) &VariableDialog::onDeleteContainerButtonPressed); connect(ui->setContainerAsMapRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerAsMapRadioSelected); connect(ui->setContainerAsListRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerAsListRadioSelected); connect(ui->setContainerAsStringRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerAsStringRadioSelected); connect(ui->setContainerAsNumberRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerAsNumberRadioSelected); connect(ui->setContainerKeyAsStringRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerKeyAsStringRadioSelected); connect(ui->setContainerKeyAsNumberRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSetContainerKeyAsNumberRadioSelected); connect(ui->doNotSaveContainerRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onDoNotSaveContainerRadioSelected); connect(ui->saveContainerOnMissionCloseRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSaveContainerOnMissionCloseRadioSelected); connect(ui->saveContainerOnMissionCompletedRadio, - &QRadioButton::toggled, + &QRadioButton::clicked, this, &VariableDialog::onSaveContainerOnMissionCompletedRadioSelected); @@ -950,9 +950,9 @@ void VariableDialog::applyModel() _applyingModel = true; auto variables = _model->getVariableValues(); - int x, selectedRow = -1; + int x = 0, selectedRow = -1; - ui->variablesTable->setRowCount(static_cast(variables.size() + 1)); + ui->variablesTable->setRowCount(static_cast(variables.size()) + 1); for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ @@ -970,11 +970,9 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); - ui->variablesTable->item(x, 1)->setFlags(ui->variablesTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); ui->variablesTable->setItem(x, 1, item); - ui->variablesTable->item(x, 1)->setFlags(item->flags() & ~Qt::ItemIsEditable); } if (ui->variablesTable->item(x, 2)){ @@ -987,8 +985,8 @@ void VariableDialog::applyModel() } } - // set the Add varaible row - ++x; + // set the Add variable row + // TODO, fix this not appearing if (ui->variablesTable->item(x, 0)){ ui->variablesTable->item(x, 0)->setText("Add Variable ..."); } else { @@ -1086,6 +1084,7 @@ void VariableDialog::updateVariableOptions() ui->saveVariableOnMissionCompletedRadio->setEnabled(false); ui->saveVariableOnMissionCloseRadio->setEnabled(false); ui->setVariableAsEternalcheckbox->setEnabled(false); + ui->networkVariableCheckbox->setEnabled(false); return; } @@ -1098,6 +1097,7 @@ void VariableDialog::updateVariableOptions() ui->saveVariableOnMissionCompletedRadio->setEnabled(true); ui->saveVariableOnMissionCloseRadio->setEnabled(true); ui->setVariableAsEternalcheckbox->setEnabled(true); + ui->networkVariableCheckbox->setEnabled(true); auto items = ui->variablesTable->selectedItems(); int row = -1; @@ -1107,8 +1107,10 @@ void VariableDialog::updateVariableOptions() row = item->row(); } + // if nothing is selected, but something could be selected, make it so. if (row == -1 && ui->variablesTable->rowCount() > 0) { row = 0; + ui->variablesTable->item(row, 0).setSelected(true); _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); } @@ -1117,8 +1119,7 @@ void VariableDialog::updateVariableOptions() bool string = _model->getVariableType(row); ui->setVariableAsStringRadio->setChecked(string); ui->setVariableAsNumberRadio->setChecked(!string); - ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); - + int ret = _model->getVariableOnMissionCloseOrCompleteFlag(row); if (ret == 0){ @@ -1153,6 +1154,7 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsEternalCheckbox->setEnabled(false); ui->setContainerAsMapRadio->setEnabled(false); ui->setContainerAsListRadio->setEnabled(false); + ui->networkContainerCheckbox->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); @@ -1178,6 +1180,7 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsEternalCheckbox->setEnabled(true); ui->setContainerAsMapRadio->setEnabled(true); ui->setContainerAsListRadio->setEnabled(true); + ui->networkContainerCheckbox->setEnabled(true); if (_model->getContainerValueType(row)){ ui->setContainerAsStringRadio->setChecked(true); @@ -1214,7 +1217,7 @@ void VariableDialog::updateContainerOptions() updateContainerDataOptions(false); } - ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerNetworkStatus(row)); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); ui->networkContainerCheckbox->setChecked(_model->getContainerNetworkStatus(row)); int ret = _model->getContainerOnMissionCloseOrCompleteFlag(row); From 84cad8c18841ed846c75fc71e3450fa5403e34f8 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 01:09:44 -0400 Subject: [PATCH 069/153] More Fixes and polish --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 8 ++++---- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 33d54a3a2ee..73483db4189 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -460,7 +460,7 @@ SCP_string VariableDialogModel::addNewVariable() do { name = ""; - sprintf(name, "", count); + sprintf(name, "newVar%i", count); variable = lookupVariableByName(name); ++count; } while (variable != nullptr && count < 51); @@ -762,7 +762,7 @@ SCP_string VariableDialogModel::addContainer() do { name = ""; - sprintf(name, "", count); + sprintf(name, "newCont%i", count); container = lookupContainerByName(name); ++count; } while (container != nullptr && count < 51); @@ -794,8 +794,8 @@ SCP_string VariableDialogModel::copyContainer(int index) // K.I.S.S. _containerItems.push_back(*container); - _containerItems.back().name += "_copy"; - _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH); + _containerItems.back().name = "copy_" + _containerItems.back().name; + _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH - 1); return _containerItems.back().name; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 28107a2fa95..7a8e7d72c26 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1119,7 +1119,7 @@ void VariableDialog::updateVariableOptions() bool string = _model->getVariableType(row); ui->setVariableAsStringRadio->setChecked(string); ui->setVariableAsNumberRadio->setChecked(!string); - + int ret = _model->getVariableOnMissionCloseOrCompleteFlag(row); if (ret == 0){ @@ -1158,7 +1158,7 @@ void VariableDialog::updateContainerOptions() ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - + ui->containerContentsTable->setRowCount(0); } else { auto items = ui->containersTable->selectedItems(); From dd44d7d13a13b2be8574bcc0538caaa48afaaa9c Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 01:40:46 -0400 Subject: [PATCH 070/153] Fixing more issues --- .../mission/dialogs/VariableDialogModel.cpp | 190 +++++++++--------- .../src/mission/dialogs/VariableDialogModel.h | 31 +++ qtfred/src/ui/dialogs/VariableDialog.cpp | 3 +- 3 files changed, 128 insertions(+), 96 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 73483db4189..285dc8f1e4b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -932,104 +932,104 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) std::pair VariableDialogModel::copyMapItem(int index, int mapIndex) { - /*auto container = lookupContainer(index); + auto container = lookupContainer(index); // any invalid case, early return - if (!container || mapIndex < 0 || mapIndex >= static_cast(container->keys.size()) - || (mapIndex >= static_cast(container->stringValues.size()) && container->string) - || (mapIndex >= static_cast(container->numberValues.size()) && !container->string)){ + if (!container) { return std::make_pair("", ""); } - for (int x = 0; x < static_cast(container->keys.size()); ++x) { - if (container->keys[x] == keyIn){ - if (container->string){ - if (x < static_cast(container->stringValues.size())){ - SCP_string copyValue = container->stringValues[x]; - SCP_string newKey; - int size = static_cast(container->keys.size()); - sprintf(newKey, "key%i", size); - - bool found = false; - - do { - found = false; - for (int y = 0; y < static_cast(container->keys.size()); ++y){ - if (container->keys[y] == newKey) { - found = true; - break; - } - } + auto key = lookupContainerKey(index, mapIndex); - // attempt did not work, try next number - if (found) { - ++size; - newKey = ""; - sprintf(newKey, "key%i", size); - } + if (!key) { + return std::make_pair("", ""); + } + + - } while (found && size < static_cast(container->keys.size()) + 100); - - // we could not generate a new key .... somehow. - if (found){ - return std::make_pair("", ""); - } + if (container->string){ + auto value = lookupContainerStringItem(index, mapIndex); - container->keys.push_back(newKey); - container->stringValues.push_back(copyValue); + // no valid value. + if (!value){ + return std::make_pair("", ""); + } + + SCP_string copyValue = *value; + SCP_string newKey = *key + "0"; + int count = 0; - return std::make_pair(newKey, copyValue); + bool found; - } else { - return std::make_pair("", ""); + do { + found = false; + for (int y = 0; y < static_cast(container->keys.size()); ++y){ + if (container->keys[y] == newKey) { + found = true; + break; } - } else { - if (x < static_cast(container->numberValues.size())){ - int copyValue = container->numberValues[x]; - SCP_string newKey; - int size = static_cast(container->keys.size()); - sprintf(newKey, "key%i", size); - - bool found = false; - - do { - found = false; - for (int y = 0; y < static_cast(container->keys.size()); ++y){ - if (container->keys[y] == newKey) { - found = true; - break; - } - } + } - // attempt did not work, try next number - if (found) { - ++size; - newKey = ""; - sprintf(newKey, "key%i", size); - } + // attempt did not work, try next number + if (found) { + sprintf(newKey, "%s%i", *key.c_str(), ++count); + } - } while (found && size < static_cast(container->keys.size()) + 100); - - // we could not generate a new key .... somehow. - if (found){ - return std::make_pair("", ""); - } + } while (found && count < 100); + + // we could not generate a new key .... somehow. + if (found){ + return std::make_pair("", ""); + } - container->keys.push_back(newKey); - container->numberValues.push_back(copyValue); + container->keys.push_back(newKey); + container->stringValues.push_back(copyValue); + + return std::make_pair(newKey, copyValue); + + } else { + auto value = lookupContainerNumberItem(index, mapIndex); - SCP_string temp; - sprintf(temp, "%i", copyValue); + // no valid value. + if (!value){ + return std::make_pair("", ""); + } - return std::make_pair(newKey, temp); + bool found; + SCP_string newKey = *key + "0"; + int count = 0; - } else { - return std::make_pair("", ""); + do { + found = false; + for (int y = 0; y < static_cast(container->keys.size()); ++y){ + if (container->keys[y] == newKey) { + found = true; + break; } } + + // attempt did not work, try next number + if (found) { + sprintf(newKey, "%s%i", *key.c_str(), ++count); + } + + } while (found && count < 100); + + + // we could not generate a new key .... somehow. + if (found){ + return std::make_pair("", ""); } + + container->keys.push_back(newKey); + container->numberValues.push_back(copyValue); + + SCP_string temp; + sprintf(temp, "%i", copyValue); + + return std::make_pair(newKey, temp); } - */ + return std::make_pair("", ""); } @@ -1040,33 +1040,33 @@ std::pair VariableDialogModel::copyMapItem(int index, in // We just need to tell the user that the data cannot be maintained. bool VariableDialogModel::removeMapItem(int index, int itemIndex) { -/* auto container = lookupContainer(index); + auto container = lookupContainer(index); if (!container){ return false; } + // container is valid. - auto item = lookupContainerItem(itemIndex); + auto item = lookupContainerKey(itemIndex); - for (int x = 0; x < static_cast(container->keys.size()); ++x) { - if (container->keys[x] == key) { - if (container->string && x < static_cast(container->stringValues.size())) { - container->stringValues.erase(container->stringValues.begin() + x); - } else if (!container->string && x < static_cast(container->numberValues.size())){ - container->numberValues.erase(container->numberValues.begin() + x); - } else { - return false; - } + if (!item){ + return false; + } + // key is valid - // if we get here, we've succeeded and it's time to bug out - container->keys.erase(container->keys.begin() + x); - // "I'm outta here!" - return true; - } + // Now double check that we have a data value. + if (container->string && lookupContainerStringItem(itemIndex)){ + container->stringValues.erase(container->stringValues.begin() + itemIndex); + } else if (!container->string && lookupContainerNumberItem(itemIndex)){ + container->numberValues.erase(container->numberValues.begin() + itemIndex); + } else { + return false; } - // NO SPRINGS!!! HEHEHEHEHE*/ - return false; + // if we get here, we've succeeded and it's time to erase the key and bug out + container->keys.erase(container->keys.begin() + itemIndex); + // "I'm outta here!" + return true; } SCP_string VariableDialogModel::replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index e3e64421cdb..cf18b991a1b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -165,6 +165,36 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } + SCP_string* lookupContainerKey(int containerIndex, int itemIndex){ + if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ + if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].keys.size())){ + return &_containerItems[index].keys[itemIndex]; + } + } + + return nullptr; + } + + SCP_string* lookupContainerStringItem(int containerIndex, int itemIndex){ + if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ + if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].stringValues.size())){ + return &_containerItems[index].stringValues[itemIndex]; + } + } + + return nullptr; + } + + int* lookupContainerNumberItem(int containerIndex, int itemIndex){ + if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ + if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].numberValues.size())){ + return &_containerItems[index].numberValues[itemIndex]; + } + } + + return nullptr; + } + // many of the controls in this editor can lead to drastic actions, so this will be very useful. bool confirmAction(SCP_string question, SCP_string informativeText) @@ -185,6 +215,7 @@ class VariableDialogModel : public AbstractDialogModel { break; default: UNREACHABLE("Bad return value from confirmation message box in the Loadout dialog editor."); + return false; break; } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 7a8e7d72c26..54af3a62868 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1062,8 +1062,9 @@ void VariableDialog::applyModel() } if (_currentContainer.empty() || selectedRow < 0){ - if (ui->containersTable->item(0,0) && strlen(ui->containersTable->item(0,0)->text().toStdString().c_str())){ + if (ui->containersTable->item(0,0)){ _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); + ui->containersTable->item(row, 0).setSelected(true); } } From a18ac34c038adda00a1c439ff7b56d0c158756e6 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 12:43:26 -0400 Subject: [PATCH 071/153] Fix Linter errors --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 4 ++-- qtfred/src/mission/dialogs/VariableDialogModel.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 285dc8f1e4b..a5ce5bf4284 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -972,7 +972,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in // attempt did not work, try next number if (found) { - sprintf(newKey, "%s%i", *key.c_str(), ++count); + sprintf(newKey, "%s%i", key->c_str(), ++count); } } while (found && count < 100); @@ -1010,7 +1010,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in // attempt did not work, try next number if (found) { - sprintf(newKey, "%s%i", *key.c_str(), ++count); + sprintf(newKey, "%s%i", key->c_str(), ++count); } } while (found && count < 100); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index cf18b991a1b..5411c47e5cc 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -168,7 +168,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string* lookupContainerKey(int containerIndex, int itemIndex){ if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].keys.size())){ - return &_containerItems[index].keys[itemIndex]; + return &_containerItems[containerIndex].keys[itemIndex]; } } @@ -178,7 +178,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string* lookupContainerStringItem(int containerIndex, int itemIndex){ if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].stringValues.size())){ - return &_containerItems[index].stringValues[itemIndex]; + return &_containerItems[containerIndex].stringValues[itemIndex]; } } @@ -188,7 +188,7 @@ class VariableDialogModel : public AbstractDialogModel { int* lookupContainerNumberItem(int containerIndex, int itemIndex){ if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].numberValues.size())){ - return &_containerItems[index].numberValues[itemIndex]; + return &_containerItems[containerIndex].numberValues[itemIndex]; } } From 880167230109480a80fc2f69905e552042a77947 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 13:03:22 -0400 Subject: [PATCH 072/153] Fix more linter errors --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 10 ++++++---- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index a5ce5bf4284..901668942cd 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -995,10 +995,12 @@ std::pair VariableDialogModel::copyMapItem(int index, in return std::make_pair("", ""); } - bool found; + int copyValue = *value; SCP_string newKey = *key + "0"; int count = 0; + bool found; + do { found = false; for (int y = 0; y < static_cast(container->keys.size()); ++y){ @@ -1047,7 +1049,7 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) } // container is valid. - auto item = lookupContainerKey(itemIndex); + auto item = lookupContainerKey(index, itemIndex); if (!item){ return false; @@ -1055,9 +1057,9 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) // key is valid // Now double check that we have a data value. - if (container->string && lookupContainerStringItem(itemIndex)){ + if (container->string && lookupContainerStringItem(index, itemIndex)){ container->stringValues.erase(container->stringValues.begin() + itemIndex); - } else if (!container->string && lookupContainerNumberItem(itemIndex)){ + } else if (!container->string && lookupContainerNumberItem(index, itemIndex)){ container->numberValues.erase(container->numberValues.begin() + itemIndex); } else { return false; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 54af3a62868..f95c98a0a79 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1064,7 +1064,7 @@ void VariableDialog::applyModel() if (_currentContainer.empty() || selectedRow < 0){ if (ui->containersTable->item(0,0)){ _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); - ui->containersTable->item(row, 0).setSelected(true); + ui->containersTable->item(0, 0).setSelected(true); } } @@ -1111,7 +1111,7 @@ void VariableDialog::updateVariableOptions() // if nothing is selected, but something could be selected, make it so. if (row == -1 && ui->variablesTable->rowCount() > 0) { row = 0; - ui->variablesTable->item(row, 0).setSelected(true); + ui->variablesTable->item(row, 0)->setSelected(true); _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); } From 4f0f57e711ea0897a88953617d21fc19b8b97f88 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 22 Apr 2024 16:46:04 -0400 Subject: [PATCH 073/153] Clean up the model in a few places --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 901668942cd..fd35f21e568 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -253,7 +253,7 @@ bool VariableDialogModel::getVariableType(int index) bool VariableDialogModel::getVariableNetworkStatus(int index) { auto variable = lookupVariable(index); - return (variable) ? ((variable->flags & SEXP_VARIABLE_NETWORK) > 0) : false; + return (variable) ? ((variable->flags & SEXP_VARIABLE_NETWORK) != 0) : false; } @@ -281,7 +281,7 @@ int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(int index) bool VariableDialogModel::getVariableEternalFlag(int index) { auto variable = lookupVariable(index); - return (variable) ? ((variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; + return (variable) ? ((variable->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) != 0) : false; } @@ -398,7 +398,7 @@ int VariableDialogModel::setVariableOnMissionCloseOrCompleteFlag(int index, int if (flags == 0) { variable->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); } else if (flags == 1) { - variable->flags &= ~(SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); + variable->flags &= ~SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE; variable->flags |= SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS; } else { variable->flags |= (SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS | SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE); @@ -580,7 +580,7 @@ bool VariableDialogModel::getContainerListOrMap(int index) bool VariableDialogModel::getContainerNetworkStatus(int index) { auto container = lookupContainer(index); - return (container) ? ((container->flags & SEXP_VARIABLE_NETWORK) > 0) : false; + return (container) ? ((container->flags & SEXP_VARIABLE_NETWORK) != 0) : false; } // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) @@ -603,7 +603,7 @@ int VariableDialogModel::getContainerOnMissionCloseOrCompleteFlag(int index) bool VariableDialogModel::getContainerEternalFlag(int index) { auto container = lookupContainer(index); - return (container) ? ((container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) > 0) : false; + return (container) ? ((container->flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) != 0) : false; } From 3a5a2ab43c5ee2090eaa702dd00e56ccb7bbeb1a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 23 Apr 2024 12:01:17 -0400 Subject: [PATCH 074/153] Linter errors from recent changes --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- qtfred/ui/VariableDialog.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index f95c98a0a79..282fe4413bd 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1064,7 +1064,7 @@ void VariableDialog::applyModel() if (_currentContainer.empty() || selectedRow < 0){ if (ui->containersTable->item(0,0)){ _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); - ui->containersTable->item(0, 0).setSelected(true); + ui->containersTable->item(0, 0)->setSelected(true); } } diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 7417a5a0661..f43e67f7ec2 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -112,7 +112,7 @@ Persistence Options - + 10 From 55380f7e8f579dd93bb51474b86698fa3a07eedf Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 23 Apr 2024 13:02:48 -0400 Subject: [PATCH 075/153] Start on SetContainerListOrMap --- .../mission/dialogs/VariableDialogModel.cpp | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index fd35f21e568..eeb7d3b47a5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -687,14 +687,105 @@ bool VariableDialogModel::setContainerValueType(int index, bool type) } // TODO finish these two functions. -bool VariableDialogModel::setContainerKeyType(int index, bool string) { +bool VariableDialogModel::setContainerKeyType(int index, bool string) +{ + auto container = lookupContainer(index); + + // nothing to change, or invalid entry + if (!container){ + return false; + } + + + return false; } // This is the most complicated function, because we need to query the user on what they want to do if the had already entered data. bool VariableDialogModel::setContainerListOrMap(int index, bool list) { - return false; + auto container = lookupContainer(index); + + // nothing to change, or invalid entry + if (!container){ + return !list; + } + + if (container->list && list) { + // no change needed + if (list){ + return list; + } + + // no data to either transfer to map/purge/ignore + if (container->string && container->stringValues.empty()){ + container->list = list; + + // still need to deal with extant keys by resizing data values. + if (!keys.empty()){ + stringValues.resize(keys.size()); + } + + return list; + } else if (!container->string && container->numberValues.empty()){ + container->list = list; + + // still need to deal with extant keys by resizing data values. + if (!keys.empty()){ + numberValues.resize(keys.size()); + } + + return list; + } + + QMessageBox msgBoxListToMapConfirm; + msgBoxListToMapConfirm.setText("This list already has data. Continue conversion to map?"); + msgBoxListToMapConfirm.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBoxListToMapConfirm.setDefaultButton(QMessageBox::Cancel); + int ret = msgBoxListToMapConfirm.exec(); + + switch (ret) { + case QMessageBox::Yes: + break; + case QMessageBox::Cancel: + return container->list; + break; + default: + UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); + return false; + break; + } + } + + // now ask about data + QMessageBox msgBoxListToMapRetainData; + msgBoxListToMapRetainData.setText("Would you to keep the list data as keys or values, or would you like to purge the container contents?"); + msgBoxListToMapRetainData.addButton("Keep as Keys", QMessageBox::Discard); + msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::Discard); + msgBoxListToMapRetainData.addButton("Purge", QMessageBox::Discard); + msgBoxListToMapRetainData.setStandardButtons(QMessageBox::Cancel); + msgBoxListToMapRetainData.setDefaultButton(QMessageBox::Cancel); + ret = msgBoxListToMapRetainData.exec(); + + switch (ret) { + case QMessageBox::Discard: + if () + container->list = list; + break; + case QMessageBox::Cancel: + return container->list; + break; + default: + UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); + return false; + break; + } + } + + } + + + return !list; } bool VariableDialogModel::setContainerNetworkStatus(int index, bool network) From 2a4894d6963b14ffafca7da975365b2c873ac015 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 24 Apr 2024 16:02:28 -0400 Subject: [PATCH 076/153] start implementing unified values in containers And write map key changing function. Revert "start implementing unified values in containers" This reverts commit 25eeae42413373bc7f12831285f8f639c8a93904. From 6134a42ef0b4e459eae28455f950f816484a1bbe Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 00:00:48 -0400 Subject: [PATCH 077/153] Ton of fixes from testing --- .../mission/dialogs/VariableDialogModel.cpp | 27 ++++++++-------- qtfred/src/ui/dialogs/VariableDialog.cpp | 28 ++++++++--------- qtfred/ui/VariableDialog.ui | 31 ++++++++++++------- 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index eeb7d3b47a5..a77ee6b27b0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -722,8 +722,8 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) container->list = list; // still need to deal with extant keys by resizing data values. - if (!keys.empty()){ - stringValues.resize(keys.size()); + if (!container->keys.empty()){ + container->stringValues.resize(container->keys.size()); } return list; @@ -731,8 +731,8 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) container->list = list; // still need to deal with extant keys by resizing data values. - if (!keys.empty()){ - numberValues.resize(keys.size()); + if (!container->keys.empty()){ + container->numberValues.resize(container->keys.size()); } return list; @@ -754,22 +754,21 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); return false; break; - } - } + + } // now ask about data QMessageBox msgBoxListToMapRetainData; msgBoxListToMapRetainData.setText("Would you to keep the list data as keys or values, or would you like to purge the container contents?"); - msgBoxListToMapRetainData.addButton("Keep as Keys", QMessageBox::Discard); - msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::Discard); - msgBoxListToMapRetainData.addButton("Purge", QMessageBox::Discard); + msgBoxListToMapRetainData.addButton("Keep as Keys", QMessageBox::ActionRole); + msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::ApplyRole); + msgBoxListToMapRetainData.addButton("Purge", QMessageBox::RejectRole); msgBoxListToMapRetainData.setStandardButtons(QMessageBox::Cancel); msgBoxListToMapRetainData.setDefaultButton(QMessageBox::Cancel); ret = msgBoxListToMapRetainData.exec(); switch (ret) { case QMessageBox::Discard: - if () container->list = list; break; case QMessageBox::Cancel: @@ -779,13 +778,13 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); return false; break; - } - } + + } } - return !list; + return !container->list; } bool VariableDialogModel::setContainerNetworkStatus(int index, bool network) @@ -1359,7 +1358,7 @@ const SCP_vector> VariableDialogModel::getContainerNam default: // this takes care of weird cases. The logic should be simple enough to not have bugs, but just in case, switch back to default. _listTextMode = 0; - listPrefix = "List of"; + listPrefix = "List of "; listPostscript = "s"; break; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 282fe4413bd..6c55c2ed05e 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -22,7 +22,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Major Changes, like Applying the model, rejecting changes and updating the UI. - connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::checkValidModel); + connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); connect(ui->variablesTable, @@ -195,7 +195,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 90); + ui->variablesTable->setColumnWidth(0, 91); ui->variablesTable->setColumnWidth(1, 90); ui->variablesTable->setColumnWidth(2, 65); @@ -203,7 +203,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 90); + ui->containersTable->setColumnWidth(0, 91); ui->containersTable->setColumnWidth(1, 90); ui->containersTable->setColumnWidth(2, 65); @@ -213,7 +213,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->containerContentsTable->setColumnWidth(0, 120); - ui->containerContentsTable->setColumnWidth(1, 120); + ui->containerContentsTable->setColumnWidth(1, 115); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't ui->setVariableAsStringRadio->setAutoExclusive(false); @@ -622,7 +622,7 @@ void VariableDialog::onSaveVariableAsEternalCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(row, !ui->setVariableAsEternalcheckbox->isChecked())) { + if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(row, ui->setVariableAsEternalcheckbox->isChecked())) { applyModel(); } else { ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); @@ -638,7 +638,7 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(row, !ui->networkVariableCheckbox->isChecked())) { + if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(row, ui->networkVariableCheckbox->isChecked())) { applyModel(); } else { ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); @@ -1054,11 +1054,11 @@ void VariableDialog::applyModel() // set the Add container row ++x; - if (ui->variablesTable->item(x, 0)){ - ui->variablesTable->item(x, 0)->setText("Add Container ..."); + if (ui->containersTable->item(x, 0)){ + ui->containersTable->item(x, 0)->setText("Add Container ..."); } else { QTableWidgetItem* item = new QTableWidgetItem("Add Container ..."); - ui->variablesTable->setItem(x, 0, item); + ui->containersTable->setItem(x, 0, item); } if (_currentContainer.empty() || selectedRow < 0){ @@ -1109,7 +1109,7 @@ void VariableDialog::updateVariableOptions() } // if nothing is selected, but something could be selected, make it so. - if (row == -1 && ui->variablesTable->rowCount() > 0) { + if (row == -1 && ui->variablesTable->rowCount() > 1) { row = 0; ui->variablesTable->item(row, 0)->setSelected(true); _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); @@ -1196,8 +1196,8 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsMapRadio->setChecked(false); // Disable Key Controls - ui->setContainerKeyAsStringRadio->setEnabled(false); - ui->setContainerKeyAsNumberRadio->setEnabled(false); + ui->setContainerKeyAsStringRadio->setEnabled(true); + ui->setContainerKeyAsNumberRadio->setEnabled(true); // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); @@ -1209,8 +1209,8 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsMapRadio->setChecked(true); // Enabled Key Controls - ui->setContainerKeyAsStringRadio->setEnabled(true); - ui->setContainerKeyAsNumberRadio->setEnabled(true); + ui->setContainerKeyAsStringRadio->setEnabled(false); + ui->setContainerKeyAsNumberRadio->setEnabled(false); // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index f43e67f7ec2..3033a1c19d5 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -82,7 +82,10 @@ - QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true QAbstractItemView::SingleSelection @@ -216,7 +219,10 @@ - QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true QAbstractItemView::SingleSelection @@ -253,7 +259,10 @@ - QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true QAbstractItemView::SingleSelection @@ -349,9 +358,9 @@ 370 - 20 - 201 - 161 + 190 + 211 + 181 @@ -409,9 +418,9 @@ 370 - 190 - 191 - 191 + 20 + 211 + 161 @@ -422,8 +431,8 @@ 10 20 - 181 - 152 + 161 + 141 From 4324b4110980d7b9a25668d3054d57a6779e8b40 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 01:02:22 -0400 Subject: [PATCH 078/153] More Fixes and Tweaks based on testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 31 +- qtfred/ui/VariableDialog.ui | 541 ++++++++++++----------- 2 files changed, 297 insertions(+), 275 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 6c55c2ed05e..14d93a4d6ae 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -498,10 +498,6 @@ void VariableDialog::onDeleteVariableButtonPressed() void VariableDialog::onSetVariableAsStringRadioSelected() { - if (ui->setVariableAsStringRadio->isChecked()){ - return; - } - int currentRow = getCurrentVariableRow(); if (currentRow < 0){ @@ -520,10 +516,6 @@ void VariableDialog::onSetVariableAsStringRadioSelected() void VariableDialog::onSetVariableAsNumberRadioSelected() { - if (ui->setVariableAsNumberRadio->isChecked()){ - return; - } - int currentRow = getCurrentVariableRow(); if (currentRow < 0){ @@ -543,22 +535,17 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() void VariableDialog::onDoNotSaveVariableRadioSelected() { - if (ui->doNotSaveVariableRadio->isChecked()){ - return; - } - int currentRow = getCurrentVariableRow(); if (currentRow < 0){ return; } - int ret = _model->setVariableOnMissionCloseOrCompleteFlag(currentRow, 1); + int ret = _model->setVariableOnMissionCloseOrCompleteFlag(currentRow, 0); - if (ret != 1){ + if (ret != 0){ applyModel(); } else { - ui->doNotSaveVariableRadio->setChecked(true); ui->saveContainerOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(false); } @@ -568,10 +555,6 @@ void VariableDialog::onDoNotSaveVariableRadioSelected() void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() { - if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ - return; - } - int row = getCurrentVariableRow(); if (row < 0){ @@ -584,17 +567,12 @@ void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() applyModel(); } else { ui->doNotSaveVariableRadio->setChecked(false); - ui->saveContainerOnMissionCompletedRadio->setChecked(true); ui->saveVariableOnMissionCloseRadio->setChecked(false); } } void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() { - if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ - return; - } - int row = getCurrentVariableRow(); if (row < 0){ @@ -609,7 +587,6 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() } else { ui->doNotSaveVariableRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(false); - ui->saveVariableOnMissionCloseRadio->setChecked(true); } } @@ -957,8 +934,10 @@ void VariableDialog::applyModel() for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ ui->variablesTable->item(x, 0)->setText(variables[x][0].c_str()); + ui->variablesTable->item(x, 0)->setFlags(ui->variablesTable->item(x, 0)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][0].c_str()); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->variablesTable->setItem(x, 0, item); } @@ -970,8 +949,10 @@ void VariableDialog::applyModel() if (ui->variablesTable->item(x, 1)){ ui->variablesTable->item(x, 1)->setText(variables[x][1].c_str()); + ui->variablesTable->item(x, 1)->setFlags(ui->variablesTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(variables[x][1].c_str()); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->variablesTable->setItem(x, 1, item); } diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 3033a1c19d5..58f13ae9f3f 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -6,8 +6,8 @@ 0 0 - 608 - 665 + 641 + 678 @@ -36,7 +36,7 @@ - 270 + 330 120 81 101 @@ -77,10 +77,13 @@ 10 30 - 251 + 311 191 + + Qt::ScrollBarAlwaysOff + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed @@ -99,6 +102,9 @@ false + + false + false @@ -106,9 +112,9 @@ - 370 + 420 20 - 211 + 191 201 @@ -166,7 +172,7 @@ - 270 + 330 30 82 86 @@ -196,68 +202,36 @@ - - - - - - - 0 - 380 - - - - Containers - - + - 10 - 30 - 251 - 151 + 0 + 230 + 611 + 401 - - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::DotLine - - - false - - - - - - 10 - 190 - 351 - 191 - + + + 0 + 380 + - Container Contents + Containers - + 10 30 - 241 - 151 + 311 + 161 + + Qt::ScrollBarAlwaysOff + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed @@ -273,36 +247,141 @@ Qt::DotLine + + false + false - + - 260 + 10 + 200 + 401 + 191 + + + + Container Contents + + + + + 10 + 30 + 291 + 151 + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::DotLine + + + false + + + false + + + + + + 310 + 30 + 82 + 101 + + + + + + + Add + + + + + + + Copy + + + + + + + Item Up + + + + + + + Item Down + + + + + + + + + 310 + 160 + 80 + 23 + + + + + 8 + + + + Delete + + + + + + + 330 30 82 - 91 + 85 - + - + Add - + Copy - + 8 @@ -315,203 +394,165 @@ - - - - - 270 - 30 - 82 - 91 - - - - - - - Add - - - - - - - Copy - - - - - - - - 8 - - - - Delete - - - - - - - - - 370 - 190 - 211 - 181 - - - - Persistence Options - - + - 10 - 20 - 201 - 136 + 420 + 200 + 181 + 181 - - - - - No Persistence - - - - - - - Save on Mission Completed - - - - - - - Save on Mission Close - - - - - - - Eternal - - - - - - - Network Variable - - - - + + Persistence Options + + + + + 10 + 20 + 171 + 161 + + + + + + + No Persistence + + + + + + + Save on Mission Completed + + + + + + + Save on Mission Close + + + + + + + Eternal + + + + + + + Network Variable + + + + + - - - - - 370 - 20 - 211 - 161 - - - - Type Options - - + - 10 + 420 20 - 161 - 141 + 181 + 171 - - - - - Container Type - - - - - - - - - List - - - - - - - Map - - - - - - - - - Key Type - - - - - - - - - Number - - - - - - - String - - - - - - - - - Data Type - - - - - - - - - Number - - - - - - - String - - - - - - + + Type Options + + + + + 10 + 20 + 161 + 141 + + + + + + + Container Type + + + + + + + + + List + + + + + + + Map + + + + + + + + + Key Type + + + + + + + + + Number + + + + + + + String + + + + + + + + + Data Type + + + + + + + + + Number + + + + + + + String + + + + + + + From 5503aec7b4dca3ed27e45870b782e937f72be599 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 15:57:33 -0400 Subject: [PATCH 079/153] Fix filtering out zero by accident --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index a77ee6b27b0..89341e2f317 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1475,7 +1475,7 @@ SCP_string VariableDialogModel::trimNumberString(SCP_string source) case '0': if (foundNonZero) return true; - else + else return false; case '1': case '2': @@ -1503,6 +1503,14 @@ SCP_string VariableDialogModel::trimNumberString(SCP_string source) } ); + // -0 is not a possible edge case because if we haven't found a digit, we don't copy zero. + // but "-" is and an empty string that should be zero is possible as well. + + // if we had a zero, but it was the only type of digit included and got filtered out. + if (ret.empty() && source.find('0') != std::string::npos){ + return "0"; + } + // if all that made it out was a dash, then return nothing. if (ret == "-"){ return ""; From 4bb8456f69f4b4bb12f2db15cf5914164d6619ff Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 16:06:58 -0400 Subject: [PATCH 080/153] Further Fix and Rename function for clarity It turns out that an empty string is not the only possible desired value if the filtered string is "-". "-0" should return "0", but would return "" before this. --- .../mission/dialogs/VariableDialogModel.cpp | 18 +++++++++++++----- .../src/mission/dialogs/VariableDialogModel.h | 2 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 89341e2f317..88784aa3881 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1462,7 +1462,8 @@ const SCP_vector> VariableDialogModel::getContainerNam return outStrings; } -SCP_string VariableDialogModel::trimNumberString(SCP_string source) +// This function should not normally return an error. +SCP_string VariableDialogModel::trimIntegerString(SCP_string source) { SCP_string ret; bool foundNonZero = false; @@ -1471,7 +1472,7 @@ SCP_string VariableDialogModel::trimNumberString(SCP_string source) std::copy_if(source.begin(), source.end(), std::back_inserter(ret), [&foundNonZero, &ret](char c) -> bool { switch (c) { - // ignore leading zeros + // ignore leading zeros. If all digits are zero, this will be handled elsewhere case '0': if (foundNonZero) return true; @@ -1503,16 +1504,23 @@ SCP_string VariableDialogModel::trimNumberString(SCP_string source) } ); - // -0 is not a possible edge case because if we haven't found a digit, we don't copy zero. - // but "-" is and an empty string that should be zero is possible as well. + // -0 as a string value is not a possible edge case because if we haven't found a digit, we don't copy zero. + // "-" is possible and could be zero, however, and an empty string that should be zero is possible as well. + + // if we had a zero, but it was the only type of digit included and got filtered out. if (ret.empty() && source.find('0') != std::string::npos){ return "0"; } - // if all that made it out was a dash, then return nothing. + // if all that made it out was a dash, then return either zero or nothing. if (ret == "-"){ + // Checked for a filtered out 0 + if (source.find('0') != std::string::npos){ + return "0"; + } + return ""; } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 5411c47e5cc..5bc452e10d2 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -121,7 +121,7 @@ class VariableDialogModel : public AbstractDialogModel { void initializeData(); - static SCP_string trimNumberString(SCP_string source); + static SCP_string trimIntegerString(SCP_string source); private: SCP_vector _variableItems; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 14d93a4d6ae..c3d93ac383c 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -295,7 +295,7 @@ void VariableDialog::onVariablesTableUpdated() } } else { SCP_string source = item->text().toStdString(); - SCP_string temp = _model->trimNumberString(source); + SCP_string temp = _model->trimIntegerString(source); if (temp != source){ item->setText(temp.c_str()); From c24457ff6d942a13b2d88a159f3ea3856f86791e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 16:41:13 -0400 Subject: [PATCH 081/153] Add Clamping Function And more cleanup for trimIntegerString --- .../mission/dialogs/VariableDialogModel.cpp | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 88784aa3881..686f3326057 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -2,6 +2,7 @@ #include "parse/sexp.h" #include "parse/sexp_container.h" #include +#include namespace fso { namespace fred { @@ -1462,11 +1463,16 @@ const SCP_vector> VariableDialogModel::getContainerNam return outStrings; } -// This function should not normally return an error. +// This function is for cleaning up input strings that should be numbers. We could use std::stoi, +// but this helps to not erase the entire string if user ends up mistyping just one digit. +// If we ever allowed float types in sexp variables ... *shudder* ... we would definitely need a float +// version of this cleanup. SCP_string VariableDialogModel::trimIntegerString(SCP_string source) { SCP_string ret; - bool foundNonZero = false; + bool foundNonZero = false; + // I was tempted to prevent exceeding the max length of the destination c-string here, but no integer + // can exceed the 31 digit limit. And we *will* have an integer at the end of this. // filter out non-numeric digits std::copy_if(source.begin(), source.end(), std::back_inserter(ret), @@ -1506,25 +1512,32 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) // -0 as a string value is not a possible edge case because if we haven't found a digit, we don't copy zero. // "-" is possible and could be zero, however, and an empty string that should be zero is possible as well. + if (ret.empty() || ret == "-"){ + ret = "0"; + } + return std::move(clampIntegerString(ret)); +} +// Helper function for trimIntegerString that makes sure we don't try to save a value that overflows or underflows +// I don't recommend using outside of there, as there can be data loss if the input string is not cleaned first. +SCP_string VariableDialogModel::clampIntegerString(SCP_string source) +{ + try { + long test = std::stol(source); - // if we had a zero, but it was the only type of digit included and got filtered out. - if (ret.empty() && source.find('0') != std::string::npos){ - return "0"; - } - - // if all that made it out was a dash, then return either zero or nothing. - if (ret == "-"){ - // Checked for a filtered out 0 - if (source.find('0') != std::string::npos){ - return "0"; + if (test > INT_MAX) { + return "2147483647"; + } else if (test < INT_MIN) { + return "-2147483648"; } - return ""; + return std::move(source); + } + // most truly ludicrous cases should be caught before here in the calling function, so this should not cause much if any data loss + catch (...){ + return "0"; } - - return ret; } } // dialogs From ed3fcc8acaa9c0b1e5be2784378faad1fb46a3ac Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 17:16:34 -0400 Subject: [PATCH 082/153] Switch Key Options and Data Options The data type options are going to be used much more regularly and always enabled, and so should be higher on the layout. --- qtfred/ui/VariableDialog.ui | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 58f13ae9f3f..20405741511 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -502,23 +502,23 @@ - + - Key Type + Data Type - + - + Number - + String @@ -527,23 +527,23 @@ - + - Data Type + Key Type - + - + Number - + String From d143add82d62c989fe08b8b1282fae892489e06d Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 17:17:10 -0400 Subject: [PATCH 083/153] Fixes to container options updates And other fixes and adjustments --- .../mission/dialogs/VariableDialogModel.cpp | 22 +++++++------ .../src/mission/dialogs/VariableDialogModel.h | 4 ++- qtfred/src/ui/dialogs/VariableDialog.cpp | 31 ++++++++++++++----- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 686f3326057..7cc6be14be9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -258,7 +258,6 @@ bool VariableDialogModel::getVariableNetworkStatus(int index) } - // 0 neither, 1 on mission complete, 2 on mission close (higher number saves more often) int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(int index) { @@ -278,7 +277,6 @@ int VariableDialogModel::getVariableOnMissionCloseOrCompleteFlag(int index) return returnValue; } - bool VariableDialogModel::getVariableEternalFlag(int index) { auto variable = lookupVariable(index); @@ -571,6 +569,12 @@ bool VariableDialogModel::getContainerValueType(int index) return (container) ? container->string : true; } +bool VariableDialogModel::getContainerKeyType(int index) +{ + auto container = lookupContainer(index); + return (container) ? container-> +} + // true on list, false on map bool VariableDialogModel::getContainerListOrMap(int index) { @@ -955,10 +959,10 @@ std::pair VariableDialogModel::addMapItem(int index) do { conflict = false; - if (container->integerKeys){ - sprintf(newKey, "%i", count); - } else { + if (container->stringKeys){ sprintf(newKey, "key%i", count); + } else { + sprintf(newKey, "%i", count); } for (int x = 0; x < static_cast(container->keys.size()); ++x) { @@ -1316,7 +1320,7 @@ const SCP_vector> VariableDialogModel::getVariableValu const SCP_vector> VariableDialogModel::getContainerNames() { - // This logic makes the mode which we use to display, easily configureable. + // This logic makes the string which we use to display the type of the container, based on the specific mode we're using. SCP_string listPrefix; SCP_string listPostscript; @@ -1431,10 +1435,10 @@ const SCP_vector> VariableDialogModel::getContainerNam type = mapPrefix; - if (item.integerKeys){ - type += "Number"; - } else { + if (item.stringKeys){ type += "String"; + } else { + type += "Number"; } type += mapMidScript; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 5bc452e10d2..f9566a8ab9a 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -25,7 +25,7 @@ struct containerInfo { bool deleted = false; bool list = true; bool string = true; - bool integerKeys = false; + bool stringKeys = false; int flags = 0; // this will allow us to look up the original values used in the mission previously. @@ -76,6 +76,8 @@ class VariableDialogModel : public AbstractDialogModel { // true on string, false on number bool getContainerValueType(int index); + // true on string, false on number -- this returns nonsense if it's not a map, please use responsibly! + bool getContainerKeyType(int index); // true on list, false on map bool getContainerListOrMap(int index); bool getContainerNetworkStatus(int index); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c3d93ac383c..8dbc36861cd 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -212,14 +212,17 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 120); - ui->containerContentsTable->setColumnWidth(1, 115); + ui->containerContentsTable->setColumnWidth(0, 118); + ui->containerContentsTable->setColumnWidth(1, 117); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't + // and I don't mind just manually toggling them. ui->setVariableAsStringRadio->setAutoExclusive(false); ui->setVariableAsNumberRadio->setAutoExclusive(false); - ui->saveContainerOnMissionCompletedRadio->setAutoExclusive(false); + ui->doNotSaveVariableRadio->setAutoExclusive(false); + ui->saveVariableOnMissionCompletedRadio->setAutoExclusive(false); ui->saveVariableOnMissionCloseRadio->setAutoExclusive(false); + ui->setContainerAsMapRadio->setAutoExclusive(false); ui->setContainerAsListRadio->setAutoExclusive(false); ui->setContainerAsStringRadio->setAutoExclusive(false); @@ -1149,6 +1152,7 @@ void VariableDialog::updateContainerOptions() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { row = item->row(); + break; } @@ -1177,8 +1181,8 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsMapRadio->setChecked(false); // Disable Key Controls - ui->setContainerKeyAsStringRadio->setEnabled(true); - ui->setContainerKeyAsNumberRadio->setEnabled(true); + ui->setContainerKeyAsStringRadio->setEnabled(false); + ui->setContainerKeyAsNumberRadio->setEnabled(false); // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); @@ -1189,9 +1193,20 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsListRadio->setChecked(false); ui->setContainerAsMapRadio->setChecked(true); - // Enabled Key Controls - ui->setContainerKeyAsStringRadio->setEnabled(false); - ui->setContainerKeyAsNumberRadio->setEnabled(false); + // Enable Key Controls + ui->setContainerKeyAsStringRadio->setEnabled(true); + ui->setContainerKeyAsNumberRadio->setEnabled(true); + + // string keys + if (_model->getContainerKeyType(row)){ + ui->setContainerKeyAsStringRadio->setChecked(true); + ui->setContainerKeyAsNumberRadio->setChecked(false); + + // number keys + } else { + ui->setContainerKeyAsStringRadio->setChecked(false); + ui->setContainerKeyAsNumberRadio->setChecked(true); + } // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); From ec4e50481bf5e13bcbe6f634eeb52770097c53ac Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 26 Apr 2024 17:21:18 -0400 Subject: [PATCH 084/153] Hopefully fix Variable Persistence Not saving --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 8dbc36861cd..8405cc0934d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -85,7 +85,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onDoNotSaveVariableRadioSelected); - connect(ui->saveContainerOnMissionCompletedRadio, + connect(ui->saveVariableOnMissionCompletedRadio, &QRadioButton::clicked, this, &VariableDialog::onSaveVariableOnMissionCompleteRadioSelected); From fc11ddcd450ab9f82be65d30ccf1e3c1f173f0d2 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 18:15:59 -0400 Subject: [PATCH 085/153] Fixes Based On Linter and Testing --- .../mission/dialogs/VariableDialogModel.cpp | 8 +- .../src/mission/dialogs/VariableDialogModel.h | 2 + qtfred/src/ui/dialogs/VariableDialog.cpp | 32 +++++-- qtfred/ui/VariableDialog.ui | 92 +++++++++++-------- 4 files changed, 87 insertions(+), 47 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7cc6be14be9..d937e7aa86c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -572,7 +572,7 @@ bool VariableDialogModel::getContainerValueType(int index) bool VariableDialogModel::getContainerKeyType(int index) { auto container = lookupContainer(index); - return (container) ? container-> + return (container) ? container->stringKeys : true; } // true on list, false on map @@ -1301,7 +1301,7 @@ const SCP_vector> VariableDialogModel::getVariableValu SCP_string notes = ""; if (item.deleted) { - notes = "Marked for Deletion"; + notes = "Flagged for Deletion"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ @@ -1454,7 +1454,7 @@ const SCP_vector> VariableDialogModel::getContainerNam if (item.deleted) { - notes = "Flaged for Deletion"; + notes = "Flagged for Deletion"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ @@ -1520,7 +1520,7 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) ret = "0"; } - return std::move(clampIntegerString(ret)); + return std::move(clampIntegerString(ret)); } // Helper function for trimIntegerString that makes sure we don't try to save a value that overflows or underflows diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index f9566a8ab9a..201b0e817e9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -131,6 +131,8 @@ class VariableDialogModel : public AbstractDialogModel { int _listTextMode = 0; int _mapTextMode = 0; + static SCP_string clampIntegerString(SCP_string source); + variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ return &_variableItems[index]; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 8405cc0934d..b80d54492be 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -195,17 +195,17 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 91); - ui->variablesTable->setColumnWidth(1, 90); - ui->variablesTable->setColumnWidth(2, 65); + ui->variablesTable->setColumnWidth(0, 95); + ui->variablesTable->setColumnWidth(1, 95); + ui->variablesTable->setColumnWidth(2, 120); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 91); - ui->containersTable->setColumnWidth(1, 90); - ui->containersTable->setColumnWidth(2, 65); + ui->containersTable->setColumnWidth(0, 95); + ui->containersTable->setColumnWidth(1, 95); + ui->containersTable->setColumnWidth(2, 120); ui->containerContentsTable->setColumnCount(2); @@ -1133,6 +1133,8 @@ void VariableDialog::updateContainerOptions() ui->deleteContainerButton->setEnabled(false); ui->setContainerAsStringRadio->setEnabled(false); ui->setContainerAsNumberRadio->setEnabled(false); + ui->setContainerKeyAsStringRadio->setEnabled(false); + ui->setContainerKeyAsNumberRadio->setEnabled(false); ui->doNotSaveContainerRadio->setEnabled(false); ui->saveContainerOnMissionCompletedRadio->setEnabled(false); ui->saveContainerOnMissionCloseRadio->setEnabled(false); @@ -1145,6 +1147,16 @@ void VariableDialog::updateContainerOptions() ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->containerContentsTable->setRowCount(0); + // if there's no container, there's no container items + ui->addContainerItemButton->setEnabled(false); + ui->copyContainerItemButton->setEnabled(false); + ui->deleteContainerItemButton->setEnabled(false); + ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); + ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + ui->containerContentsTable->setRowCount(0); + ui->shiftItemDownButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); + } else { auto items = ui->containersTable->selectedItems(); int row = -1; @@ -1240,7 +1252,7 @@ void VariableDialog::updateContainerDataOptions(bool list) { int row = getCurrentContainerRow(); - // No overarching container, no container contents + // Just in case, No overarching container, no container contents if (row < 0){ ui->addContainerItemButton->setEnabled(false); ui->copyContainerItemButton->setEnabled(false); @@ -1248,14 +1260,20 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->containerContentsTable->setRowCount(0); + ui->shiftItemDownButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); return; // list type container } else if (list) { + // if there's no container, there's no container items ui->addContainerItemButton->setEnabled(true); ui->copyContainerItemButton->setEnabled(true); ui->deleteContainerItemButton->setEnabled(true); + ui->containerContentsTable->setRowCount(0); + ui->shiftItemDownButton->setEnabled(true); + ui->shiftItemUpButton->setEnabled(true); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 20405741511..e4f4c9043ad 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -7,13 +7,13 @@ 0 0 641 - 678 + 693 - 608 - 665 + 641 + 693 @@ -208,7 +208,7 @@ 0 230 611 - 401 + 411 @@ -226,7 +226,7 @@ 10 30 311 - 161 + 171 @@ -258,7 +258,7 @@ 10 - 200 + 210 401 191 @@ -302,8 +302,8 @@ 310 30 - 82 - 101 + 85 + 157 @@ -322,39 +322,59 @@ - + + + Shift Up + + + + + - Item Up + Shift Down - + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 8 + + - Item Down + Delete - - - - 310 - 160 - 80 - 23 - - - - - 8 - - - - Delete - - @@ -398,9 +418,9 @@ 420 - 200 + 210 181 - 181 + 191 @@ -411,8 +431,8 @@ 10 20 - 171 - 161 + 174 + 171 @@ -460,7 +480,7 @@ 420 20 181 - 171 + 181 @@ -472,7 +492,7 @@ 10 20 161 - 141 + 152 From 6e6b4098f32e3d90452a2b7f6b6d51b6b0d9a2ed Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 19:03:22 -0400 Subject: [PATCH 086/153] Fix add container and add item rows They were not appearing. --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b80d54492be..22ce76e4218 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1037,7 +1037,6 @@ void VariableDialog::applyModel() } // set the Add container row - ++x; if (ui->containersTable->item(x, 0)){ ui->containersTable->item(x, 0)->setText("Add Container ..."); } else { @@ -1302,7 +1301,6 @@ void VariableDialog::updateContainerDataOptions(bool list) } } - ++x; if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText("Add item ..."); } else { From 94dbd95530a19dda928a2b99240032cc31323964 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 19:10:24 -0400 Subject: [PATCH 087/153] Fix nullptr on copy --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index d937e7aa86c..5790db0c964 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -518,18 +518,18 @@ SCP_string VariableDialogModel::copyVariable(int index) // open slot found! if (!variableSearch){ // create the new entry in the model - _variableItems.emplace_back(); + variableSearch = &_variableItems.back(); // and set everything as a copy from the original, except original name and deleted. auto& newVariable = _variableItems.back(); newVariable.name = newName; - newVariable.flags = variableSearch->flags; - newVariable.string = variableSearch->string; + newVariable.flags = variable->flags; + newVariable.string = variable->string; if (newVariable.string) { - newVariable.stringValue = variableSearch->stringValue; + newVariable.stringValue = variable->stringValue; } else { - newVariable.numberValue = variableSearch->numberValue; + newVariable.numberValue = variable->numberValue; } return newName; From dac5fbeb826ab8d1762fa9611cbe29227ee105e8 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 26 Apr 2024 20:11:40 -0400 Subject: [PATCH 088/153] Fix more Container issues based on testing --- .../mission/dialogs/VariableDialogModel.cpp | 6 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 55 ++++--------------- 2 files changed, 13 insertions(+), 48 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 5790db0c964..6979dd51ee2 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -512,13 +512,13 @@ SCP_string VariableDialogModel::copyVariable(int index) do { SCP_string newName; - sprintf(newName, "%s_copy%i", variable->name.substr(0, TOKEN_LENGTH - 6).c_str(), count); + sprintf(newName, "%s_cpy%i", variable->name.substr(0, TOKEN_LENGTH - 6).c_str(), count); variableSearch = lookupVariableByName(newName); // open slot found! if (!variableSearch){ // create the new entry in the model - variableSearch = &_variableItems.back(); + _variableItems.emplace_back(); // and set everything as a copy from the original, except original name and deleted. auto& newVariable = _variableItems.back(); @@ -887,7 +887,7 @@ SCP_string VariableDialogModel::copyContainer(int index) return ""; } - // K.I.S.S. + // K.I.S.S. We could guarantee the names be unique, but so can the user, and there will definitely be a lower number of containers _containerItems.push_back(*container); _containerItems.back().name = "copy_" + _containerItems.back().name; _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH - 1); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 22ce76e4218..1c28b345eb4 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -230,6 +230,13 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->saveContainerOnMissionCloseRadio->setAutoExclusive(false); ui->saveContainerOnMissionCompletedRadio->setAutoExclusive(false); + ui->variablesTable->setRowCount(0); + ui->containersTable->setRowCount(0); + ui->containerContentsTable->setRowCount(0); + ui->variablesTable->clearSelection(); + ui->containersTable->clearSelection(); + ui->containerContentsTable->clearSelection(); + applyModel(); } @@ -663,19 +670,11 @@ void VariableDialog::onDeleteContainerButtonPressed() return; } - // UI is somehow out of sync with the model, so update UI. - if (!_model->removeContainer(row)) { - applyModel(); - } - + applyModel(); } void VariableDialog::onSetContainerAsMapRadioSelected() { - if (ui->setContainerAsMapRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -688,10 +687,6 @@ void VariableDialog::onSetContainerAsMapRadioSelected() void VariableDialog::onSetContainerAsListRadioSelected() { - if (ui->setContainerAsListRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -705,10 +700,6 @@ void VariableDialog::onSetContainerAsListRadioSelected() void VariableDialog::onSetContainerAsStringRadioSelected() { - if (ui->setContainerAsStringRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -721,11 +712,6 @@ void VariableDialog::onSetContainerAsStringRadioSelected() void VariableDialog::onSetContainerAsNumberRadioSelected() { - if (ui->setContainerAsNumberRadio->isChecked()){ - return; - } - - int row = getCurrentContainerRow(); if (row < 0){ @@ -738,10 +724,6 @@ void VariableDialog::onSetContainerAsNumberRadioSelected() void VariableDialog::onSetContainerKeyAsStringRadioSelected() { - if (ui->setContainerKeyAsStringRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -755,10 +737,6 @@ void VariableDialog::onSetContainerKeyAsStringRadioSelected() void VariableDialog::onSetContainerKeyAsNumberRadioSelected() { - if (ui->setContainerKeyAsNumberRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -771,10 +749,6 @@ void VariableDialog::onSetContainerKeyAsNumberRadioSelected() void VariableDialog::onDoNotSaveContainerRadioSelected() { - if (ui->doNotSaveContainerRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -791,10 +765,6 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() } void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() { - if (ui->saveContainerOnMissionCloseRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -812,10 +782,6 @@ void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() { - if (ui->saveContainerOnMissionCompletedRadio->isChecked()){ - return; - } - int row = getCurrentContainerRow(); if (row < 0){ @@ -970,7 +936,6 @@ void VariableDialog::applyModel() } // set the Add variable row - // TODO, fix this not appearing if (ui->variablesTable->item(x, 0)){ ui->variablesTable->item(x, 0)->setText("Add Variable ..."); } else { @@ -1005,7 +970,7 @@ void VariableDialog::applyModel() updateVariableOptions(); auto containers = _model->getContainerNames(); - ui->containersTable->setRowCount(static_cast(containers.size())); + ui->containersTable->setRowCount(static_cast(containers.size() + 1)); selectedRow = -1; for (x = 0; x < static_cast(containers.size()); ++x){ @@ -1045,7 +1010,7 @@ void VariableDialog::applyModel() } if (_currentContainer.empty() || selectedRow < 0){ - if (ui->containersTable->item(0,0)){ + if (ui->containersTable->item(0,0) && ui->containersTable->item(0,0)->text().toStdString() != "Add Container ..."){ _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); ui->containersTable->item(0, 0)->setSelected(true); } From c984faeda1443e3e96c1c2809e38d54fa9147337 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 28 Apr 2024 01:37:29 -0400 Subject: [PATCH 089/153] Add Accept and Reject Signal Reactions --- .../mission/dialogs/VariableDialogModel.cpp | 6 ++-- .../src/mission/dialogs/VariableDialogModel.h | 2 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 30 +++++++++++++++++-- qtfred/src/ui/dialogs/VariableDialog.h | 3 ++ qtfred/ui/VariableDialog.ui | 12 ++++---- 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 6979dd51ee2..f1b8967660e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -21,7 +21,7 @@ void VariableDialogModel::reject() _containerItems.clear(); } -void VariableDialogModel::checkValidModel() +bool VariableDialogModel::checkValidModel() { std::unordered_set namesTaken; std::unordered_set duplicates; @@ -100,7 +100,7 @@ void VariableDialogModel::checkValidModel() } if (messageOut1.empty()){ - apply(); + return true; } else { messageOut1 = "Please correct these variable, container and key names. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; @@ -108,6 +108,8 @@ void VariableDialogModel::checkValidModel() msgBox.setText(messageOut1.c_str()); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); + + return false; } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 201b0e817e9..03c696881d5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -116,7 +116,7 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); - void checkValidModel(); + bool checkValidModel(); bool apply() override; void reject() override; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 1c28b345eb4..5f5e7ff9486 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -20,8 +20,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->setupUi(this); resize(QDialog::sizeHint()); // The best I can tell without some research, when a dialog doesn't use an underlying grid or layout, it needs to be resized this way before anything will show up - // Major Changes, like Applying the model, rejecting changes and updating the UI. + // Here we need to check that there are no issues with variable names or container names, or with maps having duplicate keys. + connect(ui->OkCancelButtons, &QDialogButtonBox::accepted, this, &VariableDialog::checkValidModel); + // Reject if the user wants to. + connect(ui->OkCancelButtons, &QDialogButtonBox::rejected, this, &VariableDialog::preReject); connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); @@ -1422,7 +1425,8 @@ int VariableDialog::getCurrentVariableRow() return -1; } -int VariableDialog::getCurrentContainerRow(){ +int VariableDialog::getCurrentContainerRow() +{ auto items = ui->containersTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. @@ -1435,7 +1439,8 @@ int VariableDialog::getCurrentContainerRow(){ return -1; } -int VariableDialog::getCurrentContainerItemRow(){ +int VariableDialog::getCurrentContainerItemRow() +{ auto items = ui->containerContentsTable->selectedItems(); // yes, selected items returns a list, but we really should only have one item because multiselect will be off. @@ -1446,6 +1451,25 @@ int VariableDialog::getCurrentContainerItemRow(){ return -1; } +void VariableDialog::preReject() +{ + QMessageBox msgBox; + msgBox.setText("Are you sure you want to discard your changes?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int ret = msgBox.exec(); + + if (ret == QMessageBox::Yes) { + this->reject(); + } +} + +void VariableDialog::checkValidModel() +{ + if (_model->checkValidModel()) { + accept(); + } +} + } // namespace dialogs } // namespace fred } // namespace fso \ No newline at end of file diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 2d4bf1425fa..5faa2bb5045 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -27,6 +27,9 @@ class VariableDialog : public QDialog { // basically UpdateUI, but called when there is an inconsistency between model and UI void applyModel(); + void preReject(); + void checkValidModel(); + // Helper functions for this void updateVariableOptions(); void updateContainerOptions(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index e4f4c9043ad..ec9f894a7ba 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -36,7 +36,7 @@ - 330 + 320 120 81 101 @@ -77,7 +77,7 @@ 10 30 - 311 + 301 191 @@ -172,7 +172,7 @@ - 330 + 320 30 82 86 @@ -225,7 +225,7 @@ 10 30 - 311 + 301 171 @@ -379,7 +379,7 @@ - 330 + 320 30 82 85 @@ -580,7 +580,7 @@ - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok From 0c2d1a7a10a25464d770e2f6366ef2e6401e7424 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 28 Apr 2024 01:52:30 -0400 Subject: [PATCH 090/153] Save Changes --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- qtfred/ui/VariableDialog.ui | 71 ++++++++++++------------ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 5f5e7ff9486..4b99b580c3d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1459,7 +1459,7 @@ void VariableDialog::preReject() int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { - this->reject(); + reject(); } } diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index ec9f894a7ba..665e78f7742 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -220,40 +220,6 @@ Containers - - - - 10 - 30 - 301 - 171 - - - - Qt::ScrollBarAlwaysOff - - - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::DotLine - - - false - - - false - - @@ -574,6 +540,43 @@ + + + + 10 + 30 + 301 + 171 + + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::DotLine + + + false + + + false + + + false + + From e902f6d07521bded8353b89f4ac69e1125ed9f7f Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 28 Apr 2024 13:38:40 -0400 Subject: [PATCH 091/153] More change based on testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 61 ++++++++++-------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 4b99b580c3d..6c97ae5dfa4 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -200,7 +200,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); ui->variablesTable->setColumnWidth(0, 95); ui->variablesTable->setColumnWidth(1, 95); - ui->variablesTable->setColumnWidth(2, 120); + ui->variablesTable->setColumnWidth(2, 105); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -208,15 +208,15 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); ui->containersTable->setColumnWidth(0, 95); ui->containersTable->setColumnWidth(1, 95); - ui->containersTable->setColumnWidth(2, 120); + ui->containersTable->setColumnWidth(2, 105); ui->containerContentsTable->setColumnCount(2); // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 118); - ui->containerContentsTable->setColumnWidth(1, 117); + ui->containerContentsTable->setColumnWidth(0, 150); + ui->containerContentsTable->setColumnWidth(1, 150); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. @@ -290,9 +290,6 @@ void VariableDialog::onVariablesTableUpdated() // check if data column was altered // TODO! Set up comparison between last and current value - // TODO! Also this crashes because item->(x, 1) is null - // TODO! Variable is not editable - // TODO! Network container does not turn off if (item->column() == 1) { // Variable is a string @@ -341,10 +338,11 @@ void VariableDialog::onVariablesSelectionChanged() int row = getCurrentVariableRow(); if (row < 0){ + updateVariableOptions(); return; } - SCP_string newVariableName = ""; + SCP_string newVariableName; auto item = ui->variablesTable->item(row, 0); @@ -407,16 +405,16 @@ void VariableDialog::onContainersSelectionChanged() auto items = ui->containersTable->selectedItems(); - SCP_string newContainerName = ""; + int row = getCurrentContainerRow(); - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for(const auto& item : items) { - if (item->column() == 0){ - newContainerName = item->text().toStdString(); - break; - } + if (row < 0) { + updateContainerOptions(); + return; } + // guaranteed not to be null, since getCurrentContainerRow already checked. + SCP_string newContainerName = ui->containersTable->item(row, 0)->text().toStdString(); + if (newContainerName != _currentContainer){ _currentContainer = newContainerName; applyModel(); @@ -1027,7 +1025,9 @@ void VariableDialog::applyModel() void VariableDialog::updateVariableOptions() { - if (_currentVariable.empty()){ + int row = getCurrentVariableRow(); + + if (row < 0){ ui->copyVariableButton->setEnabled(false); ui->deleteVariableButton->setEnabled(false); ui->setVariableAsStringRadio->setEnabled(false); @@ -1051,14 +1051,6 @@ void VariableDialog::updateVariableOptions() ui->setVariableAsEternalcheckbox->setEnabled(true); ui->networkVariableCheckbox->setEnabled(true); - auto items = ui->variablesTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - } - // if nothing is selected, but something could be selected, make it so. if (row == -1 && ui->variablesTable->rowCount() > 1) { row = 0; @@ -1095,7 +1087,9 @@ void VariableDialog::updateVariableOptions() void VariableDialog::updateContainerOptions() { - if (_currentContainer.empty()){ + int row = getCurrentContainerRow(); + + if (row < 0){ ui->copyContainerButton->setEnabled(false); ui->deleteContainerButton->setEnabled(false); ui->setContainerAsStringRadio->setEnabled(false); @@ -1126,14 +1120,6 @@ void VariableDialog::updateContainerOptions() } else { auto items = ui->containersTable->selectedItems(); - int row = -1; - - // yes, selected items returns a list, but we really should only have one item because multiselect will be off. - for (const auto& item : items) { - row = item->row(); - break; - } - ui->copyContainerButton->setEnabled(true); ui->deleteContainerButton->setEnabled(true); @@ -1310,7 +1296,6 @@ void VariableDialog::updateContainerDataOptions(bool list) } } - ++x; if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText("Add item ..."); } else { @@ -1417,7 +1402,7 @@ int VariableDialog::getCurrentVariableRow() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { - if (item){ + if (item && item->column() == 0 && item->text().toStdString() != "Add Variable ...") { return item->row(); } } @@ -1431,7 +1416,7 @@ int VariableDialog::getCurrentContainerRow() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { - if (item) { + if (item && item->column() == 0 && item->text().toStdString() != "Add Container ...") { return item->row(); } } @@ -1445,7 +1430,9 @@ int VariableDialog::getCurrentContainerItemRow() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { - return item->row(); + if (item && item->column() == 0 && item->text().toStdString() != "Add Item ...") { + return item->row(); + } } return -1; From a8cc7d289606229c55c572d1c2270c23ef7da85b Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 28 Apr 2024 14:44:38 -0400 Subject: [PATCH 092/153] Appease the linter --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index f1b8967660e..705c7e0f3e9 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1522,7 +1522,7 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) ret = "0"; } - return std::move(clampIntegerString(ret)); + return clampIntegerString(ret); } // Helper function for trimIntegerString that makes sure we don't try to save a value that overflows or underflows @@ -1538,7 +1538,7 @@ SCP_string VariableDialogModel::clampIntegerString(SCP_string source) return "-2147483648"; } - return std::move(source); + return source; } // most truly ludicrous cases should be caught before here in the calling function, so this should not cause much if any data loss catch (...){ From f1dd86477aab364a93ff5ebb74653063f9dc45ae Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 28 Apr 2024 23:30:23 -0400 Subject: [PATCH 093/153] More Fixes Based on testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 20 +++++++++++++++++++- qtfred/ui/VariableDialog.ui | 16 ++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 6c97ae5dfa4..82c7d9f683a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -819,7 +819,7 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() return; } - if (ui->setContainerAsEternalCheckbox->isChecked() != _model->setContainerNetworkStatus(row, ui->setContainerAsEternalCheckbox->isChecked())){ + if (ui->setContainerAsEternalCheckbox->isChecked() != _model->setContainerEternalFlag(row, ui->setContainerAsEternalCheckbox->isChecked())){ applyModel(); } } @@ -1010,6 +1010,24 @@ void VariableDialog::applyModel() ui->containersTable->setItem(x, 0, item); } + if (ui->containersTable->item(x, 1)){ + ui->containersTable->item(x, 1)->setFlags(ui->containersTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); + ui->containersTable->item(x, 1)->setText(""); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containersTable->setItem(x, 1, item); + } + + if (ui->containersTable->item(x, 2)){ + ui->containersTable->item(x, 2)->setFlags(ui->containersTable->item(x, 2)->flags() & ~Qt::ItemIsEditable); + ui->containersTable->item(x, 2)->setText(""); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containersTable->setItem(x, 2, item); + } + if (_currentContainer.empty() || selectedRow < 0){ if (ui->containersTable->item(0,0) && ui->containersTable->item(0,0)->text().toStdString() != "Add Container ..."){ _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 665e78f7742..8d03cac8d52 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -497,16 +497,16 @@ - + - Number + String - + - String + Number @@ -522,16 +522,16 @@ - + - Number + String - + - String + Number From c5b033235ad68f7ea37d11999c708f3b5eabc271 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Mon, 29 Apr 2024 00:03:02 -0400 Subject: [PATCH 094/153] More Fixes Based On Testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 82c7d9f683a..2cd8bd04712 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -963,8 +963,12 @@ void VariableDialog::applyModel() } if (_currentVariable.empty() || selectedRow < 0){ - if (ui->variablesTable->item(0,0) && strlen(ui->variablesTable->item(0,0)->text().toStdString().c_str())){ - _currentVariable = ui->variablesTable->item(0,0)->text().toStdString(); + if (ui->variablesTable->item(0, 0) && !ui->variablesTable->item(0, 0)->text().toStdString().empty()){ + _currentVariable = ui->variablesTable->item(0, 0)->text().toStdString(); + } + + if (ui->variablesTable->item(0, 1)) { + _currentVariableData = ui->variablesTable->item(0, 1)->text().toStdString(); } } @@ -977,8 +981,10 @@ void VariableDialog::applyModel() for (x = 0; x < static_cast(containers.size()); ++x){ if (ui->containersTable->item(x, 0)){ ui->containersTable->item(x, 0)->setText(containers[x][0].c_str()); + ui->containersTable->item(x, 0)->setFlags(ui->containersTable->item(x, 0)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem(containers[x][0].c_str()); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containersTable->setItem(x, 0, item); } @@ -1028,9 +1034,9 @@ void VariableDialog::applyModel() ui->containersTable->setItem(x, 2, item); } - if (_currentContainer.empty() || selectedRow < 0){ - if (ui->containersTable->item(0,0) && ui->containersTable->item(0,0)->text().toStdString() != "Add Container ..."){ - _currentContainer = ui->containersTable->item(0,0)->text().toStdString(); + if (selectedRow < 0 && ui->containersTable->rowCount() > 1) { + if (ui->containersTable->item(0, 0) && ui->containersTable->item(0, 0)->text().toStdString() != "Add Container ..."){ + _currentContainer = ui->containersTable->item(0, 0)->text().toStdString(); ui->containersTable->item(0, 0)->setSelected(true); } } @@ -1070,7 +1076,7 @@ void VariableDialog::updateVariableOptions() ui->networkVariableCheckbox->setEnabled(true); // if nothing is selected, but something could be selected, make it so. - if (row == -1 && ui->variablesTable->rowCount() > 1) { + if (row < 0 && ui->variablesTable->rowCount() > 1) { row = 0; ui->variablesTable->item(row, 0)->setSelected(true); _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); @@ -1393,7 +1399,6 @@ void VariableDialog::updateContainerDataOptions(bool list) } } - ++x; if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText("Add key ..."); } else { From 898f8a99634aa75c8ffd3f09c6d59ade93baf964 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Mon, 29 Apr 2024 00:54:02 -0400 Subject: [PATCH 095/153] Increase size of dialog to store info better And ... more Fixes Based On Testing --- .../mission/dialogs/VariableDialogModel.cpp | 25 ++++++----- qtfred/src/ui/dialogs/VariableDialog.cpp | 14 +++--- qtfred/ui/VariableDialog.ui | 44 ++++++++++++------- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 705c7e0f3e9..beb68060ba0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -511,32 +511,35 @@ SCP_string VariableDialogModel::copyVariable(int index) int count = 1; variableInfo* variableSearch; + SCP_string newName; do { - SCP_string newName; - sprintf(newName, "%s_cpy%i", variable->name.substr(0, TOKEN_LENGTH - 6).c_str(), count); + sprintf(newName, "%i_%s", count, variable->name.substr(0, TOKEN_LENGTH - 4).c_str()); variableSearch = lookupVariableByName(newName); // open slot found! if (!variableSearch){ // create the new entry in the model - _variableItems.emplace_back(); + variableInfo newInfo; // and set everything as a copy from the original, except original name and deleted. - auto& newVariable = _variableItems.back(); - newVariable.name = newName; - newVariable.flags = variable->flags; - newVariable.string = variable->string; + newInfo.name = newName; + newInfo.flags = variable->flags; + newInfo.string = variable->string; - if (newVariable.string) { - newVariable.stringValue = variable->stringValue; + if (newInfo.string) { + newInfo.stringValue = variable->stringValue; } else { - newVariable.numberValue = variable->numberValue; + newInfo.numberValue = variable->numberValue; } + _variableItems.push_back(std::move(newInfo)); + return newName; } - } while (variableSearch != nullptr && count < 51); + + ++count; + } while (variableSearch != nullptr && count < 100); return ""; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 2cd8bd04712..380c349aa13 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -358,8 +358,9 @@ void VariableDialog::onVariablesSelectionChanged() if (newVariableName != _currentVariable){ _currentVariable = newVariableName; - applyModel(); } + + applyModel(); } @@ -403,8 +404,6 @@ void VariableDialog::onContainersSelectionChanged() return; } - auto items = ui->containersTable->selectedItems(); - int row = getCurrentContainerRow(); if (row < 0) { @@ -417,8 +416,9 @@ void VariableDialog::onContainersSelectionChanged() if (newContainerName != _currentContainer){ _currentContainer = newContainerName; - applyModel(); } + + applyModel(); // Seems to be buggy unless I have this outside the if. } // TODO, finish this function @@ -1347,11 +1347,11 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); // keys I didn't bother to make separate. Should have done the same with values. - auto keys = _model->getMapKeys(row); + auto& keys = _model->getMapKeys(row); // string valued map. if (_model->getContainerValueType(row)){ - auto strings = _model->getStringValues(row); + auto& strings = _model->getStringValues(row); // use the map as the size because map containers are only as good as their keys anyway. ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); @@ -1377,7 +1377,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // number valued map } else { - auto numbers = _model->getNumberValues(row); + auto& numbers = _model->getNumberValues(row); ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); int x; diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 8d03cac8d52..fa71f7e0888 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -6,13 +6,19 @@ 0 0 - 641 + 754 693 - 641 + 754 + 693 + + + + + 754 693 @@ -26,8 +32,14 @@ - 0 - 0 + 734 + 643 + + + + + 734 + 643 @@ -36,7 +48,7 @@ - 320 + 430 120 81 101 @@ -77,7 +89,7 @@ 10 30 - 301 + 411 191 @@ -112,7 +124,7 @@ - 420 + 530 20 191 201 @@ -172,7 +184,7 @@ - 320 + 430 30 82 86 @@ -207,7 +219,7 @@ 0 230 - 611 + 721 411 @@ -225,7 +237,7 @@ 10 210 - 401 + 511 191 @@ -237,7 +249,7 @@ 10 30 - 291 + 401 151 @@ -266,7 +278,7 @@ - 310 + 420 30 85 157 @@ -345,7 +357,7 @@ - 320 + 430 30 82 85 @@ -383,7 +395,7 @@ - 420 + 530 210 181 191 @@ -443,7 +455,7 @@ - 420 + 530 20 181 181 @@ -545,7 +557,7 @@ 10 30 - 301 + 411 171 From 5ee211203a4865c01c09d32e009b5f806fe8179c Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Mon, 29 Apr 2024 01:06:04 -0400 Subject: [PATCH 096/153] Fix Containers not deleting --- qtfred/src/ui/dialogs/VariableDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 380c349aa13..5565cb10755 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -671,6 +671,7 @@ void VariableDialog::onDeleteContainerButtonPressed() return; } + _model->removeContainer(row); applyModel(); } From 4677fb8801ecb8f63da2478ad92adbaf025e9b1e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 29 Apr 2024 14:02:13 -0400 Subject: [PATCH 097/153] Start Applying List values to Keys, etc. --- .../mission/dialogs/VariableDialogModel.cpp | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index beb68060ba0..7a478cc2e59 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -721,12 +721,11 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) return !list; } - if (container->list && list) { - // no change needed - if (list){ - return list; - } + if (container->list == list){ + return list; + } + if (container->list && !list) { // no data to either transfer to map/purge/ignore if (container->string && container->stringValues.empty()){ container->list = list; @@ -770,7 +769,7 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) // now ask about data QMessageBox msgBoxListToMapRetainData; msgBoxListToMapRetainData.setText("Would you to keep the list data as keys or values, or would you like to purge the container contents?"); - msgBoxListToMapRetainData.addButton("Keep as Keys", QMessageBox::ActionRole); + msgBoxListToMapRetainData.addButton("Convert to Keys", QMessageBox::ActionRole); msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::ApplyRole); msgBoxListToMapRetainData.addButton("Purge", QMessageBox::RejectRole); msgBoxListToMapRetainData.setStandardButtons(QMessageBox::Cancel); @@ -778,8 +777,36 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) ret = msgBoxListToMapRetainData.exec(); switch (ret) { - case QMessageBox::Discard: + case QMessageBox::ActionRole: + // TODO! overwite the current keys with the current list values. Empty list values. + + case QMessageBox::ApplyRole: + + if ((container->string && container->stringValues.size() == container->keys.size()) + || (!container->string && container->numberValues.size() == container->keys.size())){ + container->list = list; + return; + } + + auto currentSize = (container->string) ? container->stringValues.size() : container->numberValues.size(); + int index = 0; + + + if (currentSize < containe) + + for (; currentSize < container->keys.size(); ++currentSize){ + if (container->string){ + + } + } + + case QMessageBox::RejectRole: + container->list = list; + container->stringValues.clear(); + container->numberValues.clear(); + container->keys.clear(); + return container->list; break; case QMessageBox::Cancel: return container->list; From cf356ed3dfb582ab57f88675699f0cfd733f898c Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 29 Apr 2024 17:26:57 -0400 Subject: [PATCH 098/153] Finish writing change from list to map --- .../mission/dialogs/VariableDialogModel.cpp | 85 +++++++++++++++---- .../src/mission/dialogs/VariableDialogModel.h | 12 +++ 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7a478cc2e59..39bc5d16d90 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -756,21 +756,23 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) switch (ret) { case QMessageBox::Yes: break; + case QMessageBox::Cancel: return container->list; break; + default: UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); return false; - break; - + break; } // now ask about data QMessageBox msgBoxListToMapRetainData; msgBoxListToMapRetainData.setText("Would you to keep the list data as keys or values, or would you like to purge the container contents?"); - msgBoxListToMapRetainData.addButton("Convert to Keys", QMessageBox::ActionRole); + msgBoxListToMapRetainData.setInformativeText("Converting to keys will erase current keys and cannot be undone. Purging all container data cannot be undone.") msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::ApplyRole); + msgBoxListToMapRetainData.addButton("Convert to Keys", QMessageBox::ActionRole); msgBoxListToMapRetainData.addButton("Purge", QMessageBox::RejectRole); msgBoxListToMapRetainData.setStandardButtons(QMessageBox::Cancel); msgBoxListToMapRetainData.setDefaultButton(QMessageBox::Cancel); @@ -778,27 +780,76 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) switch (ret) { case QMessageBox::ActionRole: - // TODO! overwite the current keys with the current list values. Empty list values. + // The easy version. (I know ... I should have standardized all storage as strings internally.... Now I'm in too deep) + if (container->string){ + container->keys = contianer->stringValues; + container->stringValues.clear(); + container->list = list; + return container->list; + } - case QMessageBox::ApplyRole: + // The hard version ...... I guess it's not that bad, actually + container->keys.clear(); - if ((container->string && container->stringValues.size() == container->keys.size()) - || (!container->string && container->numberValues.size() == container->keys.size())){ - container->list = list; - return; + for (auto& number : container->numberValues){ + SCP_string temp; + sprintf(temp, "%i", number); + contianer->keys.push_back(temp); } + + container->numberValues.clear(); + container->list = list; + return container->list; + + case QMessageBox::ApplyRole: auto currentSize = (container->string) ? container->stringValues.size() : container->numberValues.size(); - int index = 0; + // Keys and data are already set to the correct sizes. Key type should persist from the last time it was a map, so no need + // to adjust keys. + if (currentSize == container->keys.size()){ + container->list = list; + return container->list; + } - if (currentSize < containe) + // not enough data items. + if (currentSize < container->keys.size()){ + // just put the default value in them. Any string I specify for string values will + // be inconvenient to someone. + SCP_string newValue = ""; - for (; currentSize < container->keys.size(); ++currentSize){ if (container->string){ + container->stringValues.resize(container->keys.size(), newValue); + } else { + // But differentiating numbers by having zero be the default is a good idea and does + newvalue = "0"; + container->numberValues.resize(container->keys.size(), newValue); + } + + } else { + // here currentSize must be greater than the key size, because we already dealt with equal size. + // So let's add a few keys to make them level. + while (currentSize > container->keys.size() ){ + int keyIndex = 0; + SCPstring newKey; + if (container->stringKeys){ + sprintf(newKey, "key%i", keyIndex); + } else { + sprintf(newKey, "%i", KeyIndex); + } + + // avoid duplicates + if (!lookupContainerKeyByName(index, newKey)) { + container->keys.push_back(newKey); + } + + ++keyIndex; } - } + } + + container->list = list; + return container->list; case QMessageBox::RejectRole: @@ -808,20 +859,20 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) container->keys.clear(); return container->list; break; + case QMessageBox::Cancel: - return container->list; + return !list; break; + default: UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); return false; break; } - } - - return !container->list; + return !list; } bool VariableDialogModel::setContainerNetworkStatus(int index, bool network) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 03c696881d5..37c778c9c1e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -179,6 +179,18 @@ class VariableDialogModel : public AbstractDialogModel { return nullptr; } + SCP_string* lookupContainerKeyByName(int containerIndex, SCP_string keyIn){ + if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ + for (const auto& key ; _containerItems[containerIndex].keys){ + if (key == keyIn){ + return &key; + } + } + } + + return nullptr; + } + SCP_string* lookupContainerStringItem(int containerIndex, int itemIndex){ if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ if (itemIndex > -1 && itemIndex < static_cast(_containerItems[containerIndex].stringValues.size())){ From d333694a0902d1b8945013132062f2f468422ea5 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Tue, 30 Apr 2024 00:50:26 -0400 Subject: [PATCH 099/153] Adding Button for Key/Value Swap And Add more width for table views --- qtfred/ui/VariableDialog.ui | 83 +++++++++++++------------------------ 1 file changed, 29 insertions(+), 54 deletions(-) diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index fa71f7e0888..ffea1219e2a 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -6,20 +6,20 @@ 0 0 - 754 - 693 + 899 + 729 - 754 - 693 + 899 + 729 - 754 - 693 + 899 + 729 @@ -36,19 +36,13 @@ 643 - - - 734 - 643 - - Variables - 430 + 550 120 81 101 @@ -89,7 +83,7 @@ 10 30 - 411 + 521 191 @@ -124,7 +118,7 @@ - 530 + 650 20 191 201 @@ -138,7 +132,7 @@ 10 20 - 221 + 181 181 @@ -184,7 +178,7 @@ - 430 + 550 30 82 86 @@ -219,8 +213,8 @@ 0 230 - 721 - 411 + 881 + 451 @@ -237,8 +231,8 @@ 10 210 - 511 - 191 + 631 + 221 @@ -249,7 +243,7 @@ 10 30 - 401 + 471 151 @@ -278,10 +272,10 @@ - 420 - 30 - 85 - 157 + 520 + 20 + 106 + 175 @@ -314,30 +308,11 @@ - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - + + + Swap Key/Value - + @@ -357,7 +332,7 @@ - 430 + 550 30 82 85 @@ -395,7 +370,7 @@ - 530 + 650 210 181 191 @@ -409,7 +384,7 @@ 10 20 - 174 + 171 171 @@ -455,7 +430,7 @@ - 530 + 650 20 181 181 @@ -557,7 +532,7 @@ 10 30 - 411 + 521 171 From ba263d68892ecdf6d21c9c16d087420560eecf3b Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Tue, 30 Apr 2024 00:50:55 -0400 Subject: [PATCH 100/153] Trying to fixup The map/list switch function --- .../mission/dialogs/VariableDialogModel.cpp | 129 +++++++++--------- .../src/mission/dialogs/VariableDialogModel.h | 8 +- 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 39bc5d16d90..9513e6f7c0c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -725,7 +725,7 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) return list; } - if (container->list && !list) { + if (container->list) { // no data to either transfer to map/purge/ignore if (container->string && container->stringValues.empty()){ container->list = list; @@ -769,21 +769,23 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) // now ask about data QMessageBox msgBoxListToMapRetainData; + msgBoxListToMapRetainData.setWindowTitle("List to Map Conversion"); msgBoxListToMapRetainData.setText("Would you to keep the list data as keys or values, or would you like to purge the container contents?"); - msgBoxListToMapRetainData.setInformativeText("Converting to keys will erase current keys and cannot be undone. Purging all container data cannot be undone.") - msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::ApplyRole); - msgBoxListToMapRetainData.addButton("Convert to Keys", QMessageBox::ActionRole); - msgBoxListToMapRetainData.addButton("Purge", QMessageBox::RejectRole); - msgBoxListToMapRetainData.setStandardButtons(QMessageBox::Cancel); - msgBoxListToMapRetainData.setDefaultButton(QMessageBox::Cancel); + msgBoxListToMapRetainData.setInformativeText("Converting to keys will erase current keys and cannot be undone. Purging all container data cannot be undone."); + msgBoxListToMapRetainData.addButton("Keep as Values", QMessageBox::ActionRole); // No, these categories don't make sense, but QT makes underlying assumptions about where each button will be + msgBoxListToMapRetainData.addButton("Convert to Keys", QMessageBox::RejectRole); // Instead of putting them in order of input to the + msgBoxListToMapRetainData.addButton("Purge", QMessageBox::ApplyRole); + auto defaultButton = msgBoxListToMapRetainData.addButton("Cancel", QMessageBox::HelpRole); + msgBoxListToMapRetainData.setDefaultButton(defaultButton); ret = msgBoxListToMapRetainData.exec(); switch (ret) { - case QMessageBox::ActionRole: + case QMessageBox::RejectRole: // The easy version. (I know ... I should have standardized all storage as strings internally.... Now I'm in too deep) if (container->string){ - container->keys = contianer->stringValues; + container->keys = container->stringValues; container->stringValues.clear(); + container->stringValues.resize(container->keys.size(), ""); container->list = list; return container->list; } @@ -794,65 +796,66 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) for (auto& number : container->numberValues){ SCP_string temp; sprintf(temp, "%i", number); - contianer->keys.push_back(temp); + container->keys.push_back(temp); } container->numberValues.clear(); container->list = list; return container->list; + case QMessageBox::ActionRole: + { + auto currentSize = (container->string) ? container->stringValues.size() : container->numberValues.size(); + + // Keys and data are already set to the correct sizes. Key type should persist from the last time it was a map, so no need + // to adjust keys. + if (currentSize == container->keys.size()) { + container->list = list; + return container->list; + } + + // not enough data items. + if (currentSize < container->keys.size()) { + // just put the default value in them. Any string I specify for string values will + // be inconvenient to someone. + if (container->string) { + SCP_string newValue = ""; + container->stringValues.resize(container->keys.size(), newValue); + } + else { + // But differentiating numbers by having zero be the default is a good idea and does + container->numberValues.resize(container->keys.size(), 0); + } + + } + else { + // here currentSize must be greater than the key size, because we already dealt with equal size. + // So let's add a few keys to make them level. + while (currentSize > container->keys.size()) { + int keyIndex = 0; + SCP_string newKey; + + if (container->stringKeys) { + sprintf(newKey, "key%i", keyIndex); + } + else { + sprintf(newKey, "%i", keyIndex); + } + + // avoid duplicates + if (!lookupContainerKeyByName(index, newKey)) { + container->keys.push_back(newKey); + } + + ++keyIndex; + } + } + + container->list = list; + return container->list; + } case QMessageBox::ApplyRole: - auto currentSize = (container->string) ? container->stringValues.size() : container->numberValues.size(); - - // Keys and data are already set to the correct sizes. Key type should persist from the last time it was a map, so no need - // to adjust keys. - if (currentSize == container->keys.size()){ - container->list = list; - return container->list; - } - - // not enough data items. - if (currentSize < container->keys.size()){ - // just put the default value in them. Any string I specify for string values will - // be inconvenient to someone. - SCP_string newValue = ""; - - if (container->string){ - container->stringValues.resize(container->keys.size(), newValue); - } else { - // But differentiating numbers by having zero be the default is a good idea and does - newvalue = "0"; - container->numberValues.resize(container->keys.size(), newValue); - } - - } else { - // here currentSize must be greater than the key size, because we already dealt with equal size. - // So let's add a few keys to make them level. - while (currentSize > container->keys.size() ){ - int keyIndex = 0; - SCPstring newKey; - - if (container->stringKeys){ - sprintf(newKey, "key%i", keyIndex); - } else { - sprintf(newKey, "%i", KeyIndex); - } - - // avoid duplicates - if (!lookupContainerKeyByName(index, newKey)) { - container->keys.push_back(newKey); - } - - ++keyIndex; - } - } - - container->list = list; - return container->list; - - case QMessageBox::RejectRole: - container->list = list; container->stringValues.clear(); container->numberValues.clear(); @@ -860,7 +863,7 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) return container->list; break; - case QMessageBox::Cancel: + case QMessageBox::HelpRole: return !list; break; @@ -870,6 +873,10 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) break; } + } else { + // why yes, in this case it really is that simple. It doesn't matter what keys are doing, and there should already be valid values. + container->list = list; + return container->list; } return !list; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 37c778c9c1e..afa76eb5ad0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -25,7 +25,7 @@ struct containerInfo { bool deleted = false; bool list = true; bool string = true; - bool stringKeys = false; + bool stringKeys = true; int flags = 0; // this will allow us to look up the original values used in the mission previously. @@ -181,9 +181,9 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string* lookupContainerKeyByName(int containerIndex, SCP_string keyIn){ if(containerIndex > -1 && containerIndex < static_cast(_containerItems.size()) ){ - for (const auto& key ; _containerItems[containerIndex].keys){ - if (key == keyIn){ - return &key; + for (auto key = _containerItems[containerIndex].keys.begin(); key != _containerItems[containerIndex].keys.end(); ++key) { + if (*key == keyIn){ + return &(*key); } } } From 237bd53b6df8fa88ab34051ad268ef358ee8d931 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 17:47:55 -0400 Subject: [PATCH 101/153] Rename this variable for clarity And add a comment --- .../mission/dialogs/VariableDialogModel.cpp | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 9513e6f7c0c..1055b504d29 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -33,19 +33,19 @@ bool VariableDialogModel::checkValidModel() } SCP_string messageOut1; - SCP_string messageOut2; + SCP_string messageBuffer; if (!duplicates.empty()){ for (const auto& item : duplicates){ - if (messageOut2.empty()){ - messageOut2 = "\"" + item + "\""; + if (messageBuffer.empty()){ + messageBuffer = "\"" + item + "\""; } else { - messageOut2 += ", ""\"" + item + "\""; + messageBuffer += ", ""\"" + item + "\""; } } sprintf(messageOut1, "There are %zu duplicate variables:\n", duplicates.size()); - messageOut1 += messageOut2 + "\n\n"; + messageOut1 += messageBuffer + "\n\n"; } duplicates.clear(); @@ -69,34 +69,34 @@ bool VariableDialogModel::checkValidModel() } } - messageOut2.clear(); + messageBuffer.clear(); if (!duplicates.empty()){ for (const auto& item : duplicates){ - if (messageOut2.empty()){ - messageOut2 = "\"" + item + "\""; + if (messageBuffer.empty()){ + messageBuffer = "\"" + item + "\""; } else { - messageOut2 += ", ""\"" + item + "\""; + messageBuffer += ", ""\"" + item + "\""; } } SCP_string temp; sprintf(temp, "There are %zu duplicate containers:\n\n", duplicates.size()); - messageOut1 += messageOut2 + "\n"; + messageOut1 += temp + messageBuffer + "\n"; } - messageOut2.clear(); + messageBuffer.clear(); if (!duplicateKeys.empty()){ for (const auto& key : duplicateKeys){ - messageOut2 += key; + messageBuffer += key; } SCP_string temp; sprintf(temp, "There are %zu duplicate map keys:\n\n", duplicateKeys.size()); - messageOut1 += messageOut2 + "\n"; + messageOut1 += messageBuffer + "\n"; } if (messageOut1.empty()){ @@ -111,11 +111,9 @@ bool VariableDialogModel::checkValidModel() return false; } - - - } +// TODO! This function in general just needs a lot of work. bool VariableDialogModel::apply() { From 2a8ec9cc450ff4258bfcb4a25df8bfe25b187219 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 18:51:29 -0400 Subject: [PATCH 102/153] Write setContainerKeyType --- .../mission/dialogs/VariableDialogModel.cpp | 82 +++++++++++++++++-- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 1055b504d29..2572025cad8 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -32,7 +32,7 @@ bool VariableDialogModel::checkValidModel() } } - SCP_string messageOut1; + SCP_string messageOut; SCP_string messageBuffer; if (!duplicates.empty()){ @@ -44,8 +44,8 @@ bool VariableDialogModel::checkValidModel() } } - sprintf(messageOut1, "There are %zu duplicate variables:\n", duplicates.size()); - messageOut1 += messageBuffer + "\n\n"; + sprintf(messageOut, "There are %zu duplicate variables:\n", duplicates.size()); + messageOut += messageBuffer + "\n\n"; } duplicates.clear(); @@ -83,7 +83,7 @@ bool VariableDialogModel::checkValidModel() SCP_string temp; sprintf(temp, "There are %zu duplicate containers:\n\n", duplicates.size()); - messageOut1 += temp + messageBuffer + "\n"; + messageOut += temp + messageBuffer + "\n"; } messageBuffer.clear(); @@ -96,13 +96,13 @@ bool VariableDialogModel::checkValidModel() SCP_string temp; sprintf(temp, "There are %zu duplicate map keys:\n\n", duplicateKeys.size()); - messageOut1 += messageBuffer + "\n"; + messageOut += messageBuffer + "\n"; } if (messageOut1.empty()){ return true; } else { - messageOut1 = "Please correct these variable, container and key names. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; + messageOut = "Please correct these issues. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; QMessageBox msgBox; msgBox.setText(messageOut1.c_str()); @@ -694,7 +694,6 @@ bool VariableDialogModel::setContainerValueType(int index, bool type) return container->string; } -// TODO finish these two functions. bool VariableDialogModel::setContainerKeyType(int index, bool string) { auto container = lookupContainer(index); @@ -704,7 +703,72 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) return false; } + if (container->stringKeys == string){ + return container->stringKeys; + } + + if (container->stringKeys) { + // Ok, this is the complicated type. First check if all keys can just quickly be transferred to numbers. + bool quickConvert = true; + + for (auto& key : container->keys) { + try { + std::stoi(key); + } + catch (...) { + quickConvert = false; + } + } + + // Don't even notify the user. Switching back is exceedingly easy. + if (quickConvert) { + container->stringKeys = string; + return container->stringKeys; + } + // If we couldn't convert easily, then we need some input from the user + // now ask about data + QMessageBox msgBoxListToMapRetainData; + msgBoxListToMapRetainData.setWindowTitle("Key Type Conversion"); + msgBoxListToMapRetainData.setText("Fred could not convert all string keys to numbers automatically. Would you like to use default keys, filter out integers from the current keys or cancel the operation?"); + msgBoxListToMapRetainData.setInformativeText("Current keys will be overwritten unless you cancel and cannot be restored. Filtering will keep *any* numerical digits and starting \"-\" in the string. Filtering also does not prevent duplicate keys."); + msgBoxListToMapRetainData.addButton("Use Default Keys", QMessageBox::ActionRole); // No, these categories don't make sense, but QT makes underlying assumptions about where each button will be + msgBoxListToMapRetainData.addButton("Filter Current Keys ", QMessageBox::RejectRole); + auto defaultButton = msgBoxListToMapRetainData.addButton("Cancel", QMessageBox::HelpRole); + msgBoxListToMapRetainData.setDefaultButton(defaultButton); + ret = msgBoxListToMapRetainData.exec(); + + switch(ret){ + // just use default keys + case QMessageBox::ActionRole: + { + int current = 0; + for (auto& key : container->keys){ + sprintf(key, "%i", current); + key = temp; + ++current; + } + + } + + // filter out current keys + case QMessageBox::RejectRole: + for (auto& key: container->keys){ + key = trimIntegerString(key); + } + + // cancel the operation + case QMessageBox::HelpRole: + return !string; + default: + UNREACHABLE("Bad button value from confirmation message box in the Variable editor, please report!"); + } + + } else { + // transferring to keys to string type. This can just change because a valid number is always a valid string. + container->stringKeys = string; + return container->stringKeys; + } return false; } @@ -760,7 +824,7 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) break; default: - UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); + UNREACHABLE("Bad button value from confirmation message box in the Variable editor, please report!"); return false; break; } @@ -866,7 +930,7 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) break; default: - UNREACHABLE("Bad button value from confirmation message box in the Variable dialog editor, please report!"); + UNREACHABLE("Bad button value from confirmation message box in the Variable editor, please report!"); return false; break; From 824b5bbb37659fc0f61a01f220621f60ec0f5d2b Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 18:59:24 -0400 Subject: [PATCH 103/153] Write addNewVariable overload for typed items --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 6 ++++++ qtfred/src/mission/dialogs/VariableDialogModel.h | 1 + 2 files changed, 7 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 2572025cad8..2f967aee2c1 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -474,6 +474,12 @@ SCP_string VariableDialogModel::addNewVariable() return name; } +SCP_string VariableDialogModel::addNewVariable(SCP_string nameIn){ + _variableItems.emplace_back(); + _variableItems.back().name = nameIn; + return _variableItems.back().name; +} + SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName) { auto variable = lookupVariable(index); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index afa76eb5ad0..78e56df0602 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -67,6 +67,7 @@ class VariableDialogModel : public AbstractDialogModel { int setVariableNumberValue(int index, int value); SCP_string addNewVariable(); + SCP_string addNewVariable(SCP_string nameIn); SCP_string changeVariableName(int index, SCP_string newName); SCP_string copyVariable(int index); // returns whether it succeeded From 72b13631c86f384894b105f298b0d9cfa0723192 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 20:56:04 -0400 Subject: [PATCH 104/153] Implement sift up and down buttons --- .../mission/dialogs/VariableDialogModel.cpp | 48 +++++++++++ .../src/mission/dialogs/VariableDialogModel.h | 3 + qtfred/src/ui/dialogs/VariableDialog.cpp | 85 ++++++++++++++++--- qtfred/src/ui/dialogs/VariableDialog.h | 2 + 4 files changed, 128 insertions(+), 10 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 2f967aee2c1..93830b3654f 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1288,6 +1288,54 @@ std::pair VariableDialogModel::copyMapItem(int index, in return std::make_pair("", ""); } +// requires a model reload anyway, so no return value. +void VariableDialogModel::shiftListItemUp(int containerIndex, int itemIndex) +{ + auto container = lookupContainer(containerIndex); + + // handle bogus cases; < 1 is not a typo, since shifting the top item up should do nothing. + if (!container || !container->list || itemIndex < 1) { + return; + } + + // handle itemIndex out of bounds + if ( (container->string && itemIndex <= static_cast(container->stringValues.size())) + || (!container->string && itemIndex <= static_cast(container->numberValues.size())) ){ + return; + } + + // now that we know it's going to work, just swap em. + if (container->string) { + std::swap(container->stringValues[itemIndex], container->stringValues[itemIndex - 1]); + } else { + std::swap(container->numberValues[itemIndex], container->numberValues[itemIndex - 1]); + } +} + +// requires a model reload anyway, so no return value. +void VariableDialogModel::shiftListItemDown(int containerIndex, int itemIndex) +{ + auto container = lookupContainer(containerIndex); + + // handle bogus cases + if (!container || !container->list || itemIndex < 0) { + return; + } + + // handle itemIndex out of bounds. -1 is necessary. since the bottom item is cannot be moved down. + if ( (container->string && itemIndex <= static_cast(container->stringValues.size()) - 1) + || (!container->string && itemIndex <= static_cast(container->numberValues.size()) - 1) ){ + return; + } + + // now that we know it's going to work, just swap em. + if (container->string) { + std::swap(container->stringValues[itemIndex], container->stringValues[itemIndex + 1]); + } else { + std::swap(container->numberValues[itemIndex], container->numberValues[itemIndex + 1]); + } +} + // it's really because of this feature that we need data to only be in one or the other vector for maps. // If we attempted to maintain data automatically and there was a deletion, deleting the data in // both of the map's data vectors might be undesired, and not deleting takes the map immediately diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 78e56df0602..612d73663ee 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -107,6 +107,9 @@ class VariableDialogModel : public AbstractDialogModel { std::pair copyMapItem(int index, int itemIndex); bool removeMapItem(int index, int rowIndex); + void shiftListItemUp(int containerIndex, int itemIndex); + void shiftListItemDown(int containerIndex, int itemIndex); + SCP_string replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey); SCP_string changeMapItemStringValue(int index, SCP_string key, SCP_string newValue); SCP_string changeMapItemNumberValue(int index, SCP_string key, int newValue); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 5565cb10755..9dc629ce165 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -193,6 +193,16 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onDeleteContainerItemButtonPressed); + connect(ui->shiftItemUpButton, + &QPushButton::clicked, + this, + &VarableDialog::onShiftItemUpButtonPressed); + + connect(ui->shiftItemDownButton, + &QPushButton::clicked, + this, + &VarableDialog::onShiftItemDownButtonPressed); + ui->variablesTable->setColumnCount(3); ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -451,17 +461,12 @@ void VariableDialog::onContainerContentsSelectionChanged() } newContainerItemName = item->text().toStdString(); - item = ui->containerContentsTable->item(row, 1); + SCP_string newContainerDataText = (item) ? item->text().toStdString() : ""; - if (item){ - _currentContainerItemData = item->text().toStdString(); - } else { - _currentContainerItemData = ""; - } - - if (newContainerItemName != _currentContainerItem){ + if (newContainerItemName != _currentContainerItem || _currentContainerItemData != newContainerDataText){ _currentContainerItem = newContainerItemName; + _currentContainerItemData = newContainerDataText; applyModel(); } } @@ -888,6 +893,40 @@ void VariableDialog::onDeleteContainerItemButtonPressed() applyModel(); } +VariableDialog::onShiftItemUpButtonPressed() +{ + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + int itemRow = getCurrentContainerItemRow(); + + if (itemRow < 0){ + return; + } + + _model->shiftListItemUp(containerRow, itemRow); +} + +VariableDialog::onShiftItemDownButtonPressed() +{ + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + int itemRow = getCurrentContainerItemRow(); + + if (itemRow < 0){ + return; + } + + _model->shiftListItemUp(containerRow, itemRow); +} + VariableDialog::~VariableDialog(){}; // NOLINT @@ -1036,9 +1075,11 @@ void VariableDialog::applyModel() } if (selectedRow < 0 && ui->containersTable->rowCount() > 1) { - if (ui->containersTable->item(0, 0) && ui->containersTable->item(0, 0)->text().toStdString() != "Add Container ..."){ + if (ui->containersTable->item(0, 0)){ _currentContainer = ui->containersTable->item(0, 0)->text().toStdString(); + ui->containersTable->clearSelection(); ui->containersTable->item(0, 0)->setSelected(true); + } } @@ -1062,7 +1103,8 @@ void VariableDialog::updateVariableOptions() ui->saveVariableOnMissionCloseRadio->setEnabled(false); ui->setVariableAsEternalcheckbox->setEnabled(false); ui->networkVariableCheckbox->setEnabled(false); - + ui->onShiftItemUpButton->setEnabled(false); + ui->onShiftItemDownButton->setEnabled(false); return; } @@ -1128,6 +1170,8 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsMapRadio->setEnabled(false); ui->setContainerAsListRadio->setEnabled(false); ui->networkContainerCheckbox->setEnabled(false); + ui->onShiftItemUpButton->setEnabled(false); + ui->onShiftItemDownButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); @@ -1177,6 +1221,7 @@ void VariableDialog::updateContainerOptions() // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + updateContainerDataOptions(true); } else { @@ -1255,6 +1300,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + // with string contents if (_model->getContainerValueType(row)){ auto strings = _model->getStringValues(row); @@ -1269,6 +1315,21 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 0, item); } + // set selected and enable shifting functions + if (strings[x] == _currentContainerItem){ + ui->containerContentsTable->clearSelection(); + ui->containerContentsTable->item(x,0)->setSelected(true); + + // more than one item and not already at the top of the list. + if (x > 0 && x < static_cast(strings.size())){ + ui->onShiftItemUpButton->setEnabled(false); + } + + if (x > -1 && x < static_Cast(strings.size()) - 1){ + ui->onShiftItemDownButton->setEnabled(false); + } + } + // empty out the second column as it's not needed in list mode if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); @@ -1347,6 +1408,10 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + // Enable shift up and down buttons are off in Map mode. + ui->onShiftItemUpButton->setEnabled(false); + ui->onShiftItemDownButton->setEnabled(false); + // keys I didn't bother to make separate. Should have done the same with values. auto& keys = _model->getMapKeys(row); diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 5faa2bb5045..919c813e6e1 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -69,6 +69,8 @@ class VariableDialog : public QDialog { void onAddContainerItemButtonPressed(); void onCopyContainerItemButtonPressed(); void onDeleteContainerItemButtonPressed(); + void onShiftItemUpButtonPressed(); + void onShiftItemDownButtonPressed(); int getCurrentVariableRow(); int getCurrentContainerRow(); From eda645dcfc53722d09fd99007bcc49f1a947ee6b Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 22:03:50 -0400 Subject: [PATCH 105/153] Make sure delete button changes text The button should now say restore when the item has already been deleted. Also, this expands how well we warn about deletions and will dynamically decide if we need to warn about deletion. --- .../mission/dialogs/VariableDialogModel.cpp | 89 ++++++++++++++++--- .../src/mission/dialogs/VariableDialogModel.h | 10 ++- qtfred/src/ui/dialogs/VariableDialog.cpp | 27 +++++- 3 files changed, 109 insertions(+), 17 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 93830b3654f..47b25fe9d7a 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -549,7 +549,7 @@ SCP_string VariableDialogModel::copyVariable(int index) } // returns whether it succeeded -bool VariableDialogModel::removeVariable(int index) +bool VariableDialogModel::removeVariable(int index, bool toDelete) { auto variable = lookupVariable(index); @@ -558,14 +558,32 @@ bool VariableDialogModel::removeVariable(int index) return false; } - SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be replaced."; - SCP_string info = ""; - if (!confirmAction(question, info)){ - return false; + if (variable->deleted == toDelete){ + return variable->deleted; } - variable->deleted = true; - return true; + if (toDelete){ + if (_deleteWarningCount < 3){ + + SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be changed."; + SCP_string info = ""; + + if (!confirmAction(question, info)){ + --_deleteWarningCount; + return variable->deleted; + } + + // adjust to the user's actions. If they are deleting variable after variable, allow after a while. + ++_deleteWarningCount; + } + + variable->deleted = toDelete; + return variable->deleted; + + } else { + variable->deleted = toDelete; + return variable->deleted; + } } @@ -1070,7 +1088,7 @@ SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newNam return newName; } -bool VariableDialogModel::removeContainer(int index) +bool VariableDialogModel::removeContainer(int index, bool toDelete) { auto container = lookupContainer(index); @@ -1078,8 +1096,31 @@ bool VariableDialogModel::removeContainer(int index) return false; } - container->deleted = true; - return container->deleted; + if (container->deleted == toDelete){ + return container->deleted; + } + + if (toDelete){ + + if (_deleteWarningCount < 3){ + SCP_string question = "Are you sure you want to delete this container? Any references to it will have to be changed."; + SCP_string info = ""; + + if (!confirmAction(question, info)){ + return variable->deleted; + } + + // adjust to the user's actions. If they are deleting container after container, allow after a while. + ++_deleteWarningCount; + } + + variable->deleted = toDelete; + return variable->deleted; + + } else { + variable->deleted = toDelete; + return variable->deleted; + } } SCP_string VariableDialogModel::addListItem(int index) @@ -1173,6 +1214,19 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) return false; } + if (_deleteWarningCount < 3){ + SCP_string question = "Are you sure you want to delete this list item? This can't be undone."; + SCP_string info = ""; + + if (!confirmAction(question, info)){ + --_deleteWarningCount; + return variable->deleted; + } + + // adjust to the user's actions. If they are deleting variable after variable, allow after a while. + ++_deleteWarningCount; + } + // Most efficient, given the situation (single deletions) if (container->string) { container->stringValues.erase(container->stringValues.begin() + index); @@ -1357,6 +1411,21 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) } // key is valid + // double check that we want to delete + if (_deleteWarningCount < 3){ + SCP_string question = "Are you sure you want to delete this map item? This can't be undone."; + SCP_string info = ""; + + if (!confirmAction(question, info)){ + --_deleteWarningCount; + return variable->deleted; + } + + // adjust to the user's actions. If they are deleting variable after variable, allow after a while. + ++_deleteWarningCount; + } + + // Now double check that we have a data value. if (container->string && lookupContainerStringItem(index, itemIndex)){ container->stringValues.erase(container->stringValues.begin() + itemIndex); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 612d73663ee..780729cb0ed 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -71,7 +71,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string changeVariableName(int index, SCP_string newName); SCP_string copyVariable(int index); // returns whether it succeeded - bool removeVariable(int index); + bool removeVariable(int index, bool toDelete); // Container Section @@ -97,15 +97,15 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string addContainer(SCP_string nameIn); SCP_string copyContainer(int index); SCP_string changeContainerName(int index, SCP_string newName); - bool removeContainer(int index); + bool removeContainer(int index, bool toDelete); SCP_string addListItem(int index); SCP_string copyListItem(int containerIndex, int index); - bool removeListItem(int containerindex, int index); + bool removeListItem(int containerindex, int index, bool toDelete); std::pair addMapItem(int index); std::pair copyMapItem(int index, int itemIndex); - bool removeMapItem(int index, int rowIndex); + bool removeMapItem(int index, int rowIndex, bool toDelete); void shiftListItemUp(int containerIndex, int itemIndex); void shiftListItemDown(int containerIndex, int itemIndex); @@ -135,6 +135,8 @@ class VariableDialogModel : public AbstractDialogModel { int _listTextMode = 0; int _mapTextMode = 0; + static int _deleteWarningCount = 0; + static SCP_string clampIntegerString(SCP_string source); variableInfo* lookupVariable(int index){ diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 9dc629ce165..e6f8aba01ca 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -508,8 +508,14 @@ void VariableDialog::onDeleteVariableButtonPressed() } // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - _model->removeVariable(currentRow); - applyModel(); + if (ui->deleteVariableButton->item(currentRow, 2) && ui->deleteVariableButton->item(currentRow, 2)->text().toStdString() == "Flagged For Deletion"){ + _model->removeVariable(currentRow, false); + applyModel(); + } else { + _model->removeVariable(currentRow, true); + applyModel(); + } + } void VariableDialog::onSetVariableAsStringRadioSelected() @@ -1048,6 +1054,13 @@ void VariableDialog::applyModel() } } + // do we need to switch the delete button to a restore button? + if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged for Deletion"){ + ui->deleteContainerButton->setText("Restore"); + } else { + ui->deleteContainerButton->setText("Delete"); + } + // set the Add container row if (ui->containersTable->item(x, 0)){ ui->containersTable->item(x, 0)->setText("Add Container ..."); @@ -1096,6 +1109,7 @@ void VariableDialog::updateVariableOptions() if (row < 0){ ui->copyVariableButton->setEnabled(false); ui->deleteVariableButton->setEnabled(false); + ui->deleteVariableButton->setText("Delete"); ui->setVariableAsStringRadio->setEnabled(false); ui->setVariableAsNumberRadio->setEnabled(false); ui->doNotSaveVariableRadio->setEnabled(false); @@ -1125,12 +1139,18 @@ void VariableDialog::updateVariableOptions() _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); } - // start populating values bool string = _model->getVariableType(row); ui->setVariableAsStringRadio->setChecked(string); ui->setVariableAsNumberRadio->setChecked(!string); + // do we need to switch the delete button to a restore button? + if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Flagged for Deletion"){ + ui->deleteVariableButton->setText("Restore"); + } else { + ui->deleteVariableButton->setText("Delete"); + } + int ret = _model->getVariableOnMissionCloseOrCompleteFlag(row); if (ret == 0){ @@ -1159,6 +1179,7 @@ void VariableDialog::updateContainerOptions() if (row < 0){ ui->copyContainerButton->setEnabled(false); ui->deleteContainerButton->setEnabled(false); + ui->deleteContainerButton->setText("Delete"); ui->setContainerAsStringRadio->setEnabled(false); ui->setContainerAsNumberRadio->setEnabled(false); ui->setContainerKeyAsStringRadio->setEnabled(false); From 83404273889d22ce8b10238eb6b3f9a32d2d2973 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 30 Apr 2024 22:15:31 -0400 Subject: [PATCH 106/153] Make sure shift buttons apply the model --- qtfred/src/ui/dialogs/VariableDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index e6f8aba01ca..ae107c155f4 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -914,6 +914,7 @@ VariableDialog::onShiftItemUpButtonPressed() } _model->shiftListItemUp(containerRow, itemRow); + applyModel(); } VariableDialog::onShiftItemDownButtonPressed() @@ -931,6 +932,7 @@ VariableDialog::onShiftItemDownButtonPressed() } _model->shiftListItemUp(containerRow, itemRow); + applyModel(); } @@ -1505,7 +1507,6 @@ void VariableDialog::updateContainerDataOptions(bool list) } } - int VariableDialog::getCurrentVariableRow() { auto items = ui->variablesTable->selectedItems(); From d04ce617fe2ba47b576de86fad8787ecf623f857 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 1 May 2024 00:53:45 -0400 Subject: [PATCH 107/153] Add swap keys and values button --- .../mission/dialogs/VariableDialogModel.cpp | 101 ++++++++++++++++++ .../src/mission/dialogs/VariableDialogModel.h | 6 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 23 +++- qtfred/src/ui/dialogs/VariableDialog.h | 1 + 4 files changed, 125 insertions(+), 6 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 47b25fe9d7a..bd014348f35 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1483,6 +1483,106 @@ SCP_string VariableDialogModel::changeMapItemStringValue(int index, SCP_string k return ""; } +void VariableDialogModel::swapKeyAndValues(int index) +{ + auto container = lookupContainer(index); + + // bogus cases + if (!container || container->list){ + return; + } + + // data type is the same as the key type + if (container->string == container->stringKeys){ + // string-string is the easiest case + if (container->string){ + std::swap(container->stringValues, container->keys); + + // Complicated + } else { + // All right, make a copy. + SCP_vector keysCopy = container->keys; + + // easy part 1 + for (int x = 0; x < static_cast(container->numberValues.size()); ++x) { + // Honestly, if we did our job correctly, this shouldn't happen, but just in case. + if (x >= static_cast(container->keys.size()) ){ + // emplacing should be sufficient since we start at index 0. + container->keys.emplace_back(); + keysCopy.emplace_back(); + } + + container->keys[x] = ""; + sprintf(container->keys[x], "%i", container->numberValues[x]); + } + + // not as easy part 2 + for (int x = 0; x < static_cast(container->keysCopy)) { + if (container->keysCopy[x] == ""){ + container->numberValues[x] = 0; + } else { + try { + // why *yes* it did occur to me that I made a mistake when I designed this + int temp = std::stoi(container->keysCopy[x]); + container->numberValues[x] = temp; + } + catch(...){ + container->numberValues[x] = 0; + } + } + } + } + // not the same types + } else { + // Ok. Because keys are always strings, it will be easier when keys are numbers, because they are underlied by strings. + if (container->string){ + // Make a copy of the keys.... + SCP_vector keysCopy = container->keys; + // make the easy transfer from stringvalues to keys. Requiring that key values change type. + container->keys = container->stringValues; + container->stringKeys = true; + + for (int x = 0; x < static_cast(container->keysCopy.size()); ++x){ + // This *is* likely to happen as these sizes were not in sync. + if (x >= static_cast(container->numberValues.size())){ + container->numberValues.emplace_back(); + } + + try { + // why *yes* it did occur to me that I made a mistake when I designed this + int temp = std::stoi(container->keysCopy[x]); + container->numberValues[x] = temp; + } + catch(...){ + container->numberValues[x] = 0; + } + } + + container->string = false; + + // so here values are numbers and keys are strings. This might actually be easier than I thought. + } else { + // Directly copy key strings to the string values + container->stringValues = container->keys; + + // Transfer the number values to a temporary string, then place that string in the keys vector + for (int x = 0; x < static_cast(container->numberValues.size()); ++x){ + // Here, this shouldn't happen, but just in case. The direct assignment above is where it could have been mis-aligned. + if (x >= static_cast(container->keys.size())){ + container->keys.emplace_back(); + } + + sprintf(container->keys[x], "%i", container->numberValues[x]); + } + + // change the types of the container keys and values. + container->string = true; + container->stringKeys = false; + } + + } +} + SCP_string VariableDialogModel::changeMapItemNumberValue(int index, SCP_string key, int newValue) { auto container = lookupContainer(index); @@ -1508,6 +1608,7 @@ SCP_string VariableDialogModel::changeMapItemNumberValue(int index, SCP_string k return ""; } + // These functions should only be called when the container is guaranteed to exist! const SCP_vector& VariableDialogModel::getMapKeys(int index) { diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 780729cb0ed..92fceba010b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -101,11 +101,11 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string addListItem(int index); SCP_string copyListItem(int containerIndex, int index); - bool removeListItem(int containerindex, int index, bool toDelete); + bool removeListItem(int containerindex, int index); std::pair addMapItem(int index); std::pair copyMapItem(int index, int itemIndex); - bool removeMapItem(int index, int rowIndex, bool toDelete); + bool removeMapItem(int index, int rowIndex); void shiftListItemUp(int containerIndex, int itemIndex); void shiftListItemDown(int containerIndex, int itemIndex); @@ -118,6 +118,8 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector& getStringValues(int index); const SCP_vector& getNumberValues(int index); + void swapKeyAndValues(int index); + const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); bool checkValidModel(); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index ae107c155f4..384a21288f7 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -196,13 +196,17 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) connect(ui->shiftItemUpButton, &QPushButton::clicked, this, - &VarableDialog::onShiftItemUpButtonPressed); + &VariableDialog::onShiftItemUpButtonPressed); connect(ui->shiftItemDownButton, &QPushButton::clicked, this, - &VarableDialog::onShiftItemDownButtonPressed); + &VariableDialog::onShiftItemDownButtonPressed); + connect(ui->swapKeysAndValuesButton, + &QPushButton::clicked, + this, + &VariableDialog::onSwapKeysAndValuesButtonPressed); ui->variablesTable->setColumnCount(3); ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); @@ -899,7 +903,7 @@ void VariableDialog::onDeleteContainerItemButtonPressed() applyModel(); } -VariableDialog::onShiftItemUpButtonPressed() +void VariableDialog::onShiftItemUpButtonPressed() { int containerRow = getCurrentContainerRow(); @@ -917,7 +921,7 @@ VariableDialog::onShiftItemUpButtonPressed() applyModel(); } -VariableDialog::onShiftItemDownButtonPressed() +void VariableDialog::onShiftItemDownButtonPressed() { int containerRow = getCurrentContainerRow(); @@ -935,6 +939,17 @@ VariableDialog::onShiftItemDownButtonPressed() applyModel(); } +void VariableDialog::onSwapKeysAndValuesButtonPressed() +{ + int containerRow = getCurrentContainerRow(); + + if (containerRow < 0){ + return; + } + + _model->swapKeyAndValues(containerRow); + applyModel(); +} VariableDialog::~VariableDialog(){}; // NOLINT diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 919c813e6e1..10b1704e3a1 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -71,6 +71,7 @@ class VariableDialog : public QDialog { void onDeleteContainerItemButtonPressed(); void onShiftItemUpButtonPressed(); void onShiftItemDownButtonPressed(); + void onSwapKeysAndValuesButtonPressed(); int getCurrentVariableRow(); int getCurrentContainerRow(); From 50762246cbf2e52966519bcf763cbc6fd3da423d Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 3 May 2024 23:22:27 -0400 Subject: [PATCH 108/153] Fixes based on linter And size adjustments --- .../mission/dialogs/VariableDialogModel.cpp | 36 +++++++++---------- .../src/mission/dialogs/VariableDialogModel.h | 2 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 35 ++++++++++-------- qtfred/ui/VariableDialog.ui | 22 ++++++------ 4 files changed, 50 insertions(+), 45 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index bd014348f35..e9465b9f16c 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -12,7 +12,8 @@ namespace dialogs { VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) : AbstractDialogModel(parent, viewport) { - initializeData(); + _deleteWarningCount = 0; + initializeData(); } void VariableDialogModel::reject() @@ -99,13 +100,13 @@ bool VariableDialogModel::checkValidModel() messageOut += messageBuffer + "\n"; } - if (messageOut1.empty()){ + if (messageOut.empty()){ return true; } else { - messageOut = "Please correct these issues. The editor cannot apply your changes until they are fixed:\n\n" + messageOut1; + messageOut = "Please correct these issues. The editor cannot apply your changes until they are fixed:\n\n" + messageOut; QMessageBox msgBox; - msgBox.setText(messageOut1.c_str()); + msgBox.setText(messageOut.c_str()); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); @@ -760,7 +761,7 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) msgBoxListToMapRetainData.addButton("Filter Current Keys ", QMessageBox::RejectRole); auto defaultButton = msgBoxListToMapRetainData.addButton("Cancel", QMessageBox::HelpRole); msgBoxListToMapRetainData.setDefaultButton(defaultButton); - ret = msgBoxListToMapRetainData.exec(); + auto ret = msgBoxListToMapRetainData.exec(); switch(ret){ // just use default keys @@ -769,7 +770,6 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) int current = 0; for (auto& key : container->keys){ sprintf(key, "%i", current); - key = temp; ++current; } @@ -1107,19 +1107,19 @@ bool VariableDialogModel::removeContainer(int index, bool toDelete) SCP_string info = ""; if (!confirmAction(question, info)){ - return variable->deleted; + return container->deleted; } // adjust to the user's actions. If they are deleting container after container, allow after a while. ++_deleteWarningCount; } - variable->deleted = toDelete; - return variable->deleted; + container->deleted = toDelete; + return container->deleted; } else { - variable->deleted = toDelete; - return variable->deleted; + container->deleted = toDelete; + return container->deleted; } } @@ -1220,7 +1220,7 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) if (!confirmAction(question, info)){ --_deleteWarningCount; - return variable->deleted; + return container->deleted; } // adjust to the user's actions. If they are deleting variable after variable, allow after a while. @@ -1418,7 +1418,7 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) if (!confirmAction(question, info)){ --_deleteWarningCount; - return variable->deleted; + return container->deleted; } // adjust to the user's actions. If they are deleting variable after variable, allow after a while. @@ -1517,13 +1517,13 @@ void VariableDialogModel::swapKeyAndValues(int index) } // not as easy part 2 - for (int x = 0; x < static_cast(container->keysCopy)) { - if (container->keysCopy[x] == ""){ + for (int x = 0; x < static_cast(keysCopy.size()); ++x) { + if (keysCopy[x] == ""){ container->numberValues[x] = 0; } else { try { // why *yes* it did occur to me that I made a mistake when I designed this - int temp = std::stoi(container->keysCopy[x]); + int temp = std::stoi(keysCopy[x]); container->numberValues[x] = temp; } catch(...){ @@ -1542,7 +1542,7 @@ void VariableDialogModel::swapKeyAndValues(int index) container->keys = container->stringValues; container->stringKeys = true; - for (int x = 0; x < static_cast(container->keysCopy.size()); ++x){ + for (int x = 0; x < static_cast(keysCopy.size()); ++x){ // This *is* likely to happen as these sizes were not in sync. if (x >= static_cast(container->numberValues.size())){ container->numberValues.emplace_back(); @@ -1550,7 +1550,7 @@ void VariableDialogModel::swapKeyAndValues(int index) try { // why *yes* it did occur to me that I made a mistake when I designed this - int temp = std::stoi(container->keysCopy[x]); + int temp = std::stoi(keysCopy[x]); container->numberValues[x] = temp; } catch(...){ diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 92fceba010b..2bc4709dd01 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -137,7 +137,7 @@ class VariableDialogModel : public AbstractDialogModel { int _listTextMode = 0; int _mapTextMode = 0; - static int _deleteWarningCount = 0; + int _deleteWarningCount; static SCP_string clampIntegerString(SCP_string source); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 384a21288f7..f78b5a34548 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -276,7 +276,7 @@ void VariableDialog::onVariablesTableUpdated() // so if the user just removed the name, mark it as deleted *before changing the name* if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { - if (!_model->removeVariable(item->row())) { + if (!_model->removeVariable(item->row(), true)) { // marking a variable as deleted failed, resync UI apply = true; } else { @@ -512,14 +512,13 @@ void VariableDialog::onDeleteVariableButtonPressed() } // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - if (ui->deleteVariableButton->item(currentRow, 2) && ui->deleteVariableButton->item(currentRow, 2)->text().toStdString() == "Flagged For Deletion"){ + if (ui->variablesTable->item(currentRow, 2) && ui->variablesTable->item(currentRow, 2)->text().toStdString() == "Flagged For Deletion"){ _model->removeVariable(currentRow, false); applyModel(); } else { _model->removeVariable(currentRow, true); applyModel(); } - } void VariableDialog::onSetVariableAsStringRadioSelected() @@ -686,8 +685,14 @@ void VariableDialog::onDeleteContainerButtonPressed() return; } - _model->removeContainer(row); - applyModel(); + // Because of the text update we'll need, this needs an applyModel, whether it fails or not. + if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged For Deletion"){ + _model->removeVariable(row, false); + applyModel(); + } else { + _model->removeVariable(row, true); + applyModel(); + } } void VariableDialog::onSetContainerAsMapRadioSelected() @@ -1072,7 +1077,7 @@ void VariableDialog::applyModel() } // do we need to switch the delete button to a restore button? - if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged for Deletion"){ + if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "Flagged for Deletion") { ui->deleteContainerButton->setText("Restore"); } else { ui->deleteContainerButton->setText("Delete"); @@ -1134,8 +1139,8 @@ void VariableDialog::updateVariableOptions() ui->saveVariableOnMissionCloseRadio->setEnabled(false); ui->setVariableAsEternalcheckbox->setEnabled(false); ui->networkVariableCheckbox->setEnabled(false); - ui->onShiftItemUpButton->setEnabled(false); - ui->onShiftItemDownButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); + ui->shiftItemDownButton->setEnabled(false); return; } @@ -1208,8 +1213,8 @@ void VariableDialog::updateContainerOptions() ui->setContainerAsMapRadio->setEnabled(false); ui->setContainerAsListRadio->setEnabled(false); ui->networkContainerCheckbox->setEnabled(false); - ui->onShiftItemUpButton->setEnabled(false); - ui->onShiftItemDownButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); + ui->shiftItemDownButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); @@ -1360,11 +1365,11 @@ void VariableDialog::updateContainerDataOptions(bool list) // more than one item and not already at the top of the list. if (x > 0 && x < static_cast(strings.size())){ - ui->onShiftItemUpButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); } - if (x > -1 && x < static_Cast(strings.size()) - 1){ - ui->onShiftItemDownButton->setEnabled(false); + if (x > -1 && x < static_cast(strings.size()) - 1){ + ui->shiftItemDownButton->setEnabled(false); } } @@ -1447,8 +1452,8 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); // Enable shift up and down buttons are off in Map mode. - ui->onShiftItemUpButton->setEnabled(false); - ui->onShiftItemDownButton->setEnabled(false); + ui->shiftItemUpButton->setEnabled(false); + ui->shiftItemDownButton->setEnabled(false); // keys I didn't bother to make separate. Should have done the same with values. auto& keys = _model->getMapKeys(row); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index ffea1219e2a..4b2d503fb4b 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -7,19 +7,19 @@ 0 0 899 - 729 + 711 899 - 729 + 711 899 - 729 + 711 @@ -214,7 +214,7 @@ 0 230 881 - 451 + 431 @@ -244,7 +244,7 @@ 10 30 471 - 151 + 171 @@ -371,8 +371,8 @@ 650 - 210 - 181 + 30 + 191 191 @@ -384,7 +384,7 @@ 10 20 - 171 + 181 171 @@ -431,8 +431,8 @@ 650 - 20 - 181 + 230 + 191 181 @@ -444,7 +444,7 @@ 10 20 - 161 + 181 152 From d7c4c544e69f52d9ab1f66d05a0e080440a96cae Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 3 May 2024 23:54:07 -0400 Subject: [PATCH 109/153] Bug fixes according to testing --- .../mission/dialogs/VariableDialogModel.cpp | 35 +++++-------------- qtfred/src/ui/dialogs/VariableDialog.cpp | 25 +++++++------ 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index e9465b9f16c..3a9abc8c9ea 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -311,7 +311,6 @@ bool VariableDialogModel::setVariableType(int index, bool string) return !string; } - // Here we change the variable type! // this variable is currently a string if (variable->string) { @@ -320,26 +319,18 @@ bool VariableDialogModel::setVariableType(int index, bool string) variable->string = string; return variable->string; } else { - SCP_string question; - sprintf(question, "Changing variable %s to number variable type will make its string value irrelevant. Continue?", variable->name.c_str()); - SCP_string info; - sprintf(info, "If the string cleanly converts to an integer and a number has not previously been set for this variable, the converted number value will be retained."); - - // if this was a misclick, let the user say so - if (!confirmAction(question, info)) { - return variable->string; - } - // if there was no previous number value if (variable->numberValue == 0){ try { variable->numberValue = std::stoi(variable->stringValue); } - // nothing to do here, because that just means we can't convert. + // nothing to do here, because that just means we can't convert and we have to use the old value. catch (...) {} + } - return string; + variable->string = string; + return variable->string; } // this variable is currently a number @@ -349,22 +340,13 @@ bool VariableDialogModel::setVariableType(int index, bool string) variable->string = string; return variable->string; } else { - SCP_string question; - sprintf(question, "Changing variable %s to a string variable type will make the number value irrelevant. Continue?", variable->name.c_str()); - SCP_string info; - sprintf(info, "If no string value has been previously set for this variable, then the number value specified will be set as the default string value."); - - // if this was a misclick, let the user say so - if (!confirmAction(question, info)) { - return variable->string; - } - // if there was no previous string value if (variable->stringValue == ""){ sprintf(variable->stringValue, "%i", variable->numberValue); } - return string; + variable->string = string; + return variable->string; } } } @@ -735,13 +717,14 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) if (container->stringKeys) { // Ok, this is the complicated type. First check if all keys can just quickly be transferred to numbers. bool quickConvert = true; - + int test; for (auto& key : container->keys) { try { - std::stoi(key); + test = std::stoi(key); } catch (...) { quickConvert = false; + nprintf(("Cyborg", "This is Cyborg. Long story short, I don't need this variable, but c++ thinks I do. Last good number on conversion was: %i\n", test)); } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index f78b5a34548..55749586792 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -571,7 +571,7 @@ void VariableDialog::onDoNotSaveVariableRadioSelected() if (ret != 0){ applyModel(); } else { - ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(false); } } @@ -611,7 +611,7 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() applyModel(); } else { ui->doNotSaveVariableRadio->setChecked(false); - ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveVariableOnMissionCompletedRadio->setChecked(false); } } @@ -697,6 +697,8 @@ void VariableDialog::onDeleteContainerButtonPressed() void VariableDialog::onSetContainerAsMapRadioSelected() { + // to avoid visual weirdness, make it false. + ui->setContainerAsListRadio->setChecked(false); int row = getCurrentContainerRow(); if (row < 0){ @@ -709,6 +711,8 @@ void VariableDialog::onSetContainerAsMapRadioSelected() void VariableDialog::onSetContainerAsListRadioSelected() { + // to avoid visual weirdness, make it false. + ui->setContainerAsMapRadio->setChecked(false); int row = getCurrentContainerRow(); if (row < 0){ @@ -785,7 +789,8 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } -void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() + +void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() { int row = getCurrentContainerRow(); @@ -793,16 +798,16 @@ void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() return; } - if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) + if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 1) != 1) applyModel(); else { ui->doNotSaveContainerRadio->setChecked(false); - ui->saveContainerOnMissionCloseRadio->setChecked(true); - ui->saveContainerOnMissionCompletedRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(false); + ui->saveContainerOnMissionCompletedRadio->setChecked(true); } } -void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() +void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() { int row = getCurrentContainerRow(); @@ -810,12 +815,12 @@ void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() return; } - if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 1) != 1) + if (_model->setContainerOnMissionCloseOrCompleteFlag(row, 2) != 2) applyModel(); else { ui->doNotSaveContainerRadio->setChecked(false); - ui->saveContainerOnMissionCloseRadio->setChecked(false); - ui->saveContainerOnMissionCompletedRadio->setChecked(true); + ui->saveContainerOnMissionCloseRadio->setChecked(true); + ui->saveContainerOnMissionCompletedRadio->setChecked(false); } } From c9e11d465771157907df818131dfd6661f520e4e Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 00:35:46 -0400 Subject: [PATCH 110/153] Fixes Based On Testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 110 ++++++++++++++--------- qtfred/ui/VariableDialog.ui | 15 +++- 2 files changed, 81 insertions(+), 44 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 55749586792..5861e46d444 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -212,25 +212,25 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 95); - ui->variablesTable->setColumnWidth(1, 95); - ui->variablesTable->setColumnWidth(2, 105); + ui->variablesTable->setColumnWidth(0, 175); + ui->variablesTable->setColumnWidth(1, 175); + ui->variablesTable->setColumnWidth(2, 140); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 95); - ui->containersTable->setColumnWidth(1, 95); - ui->containersTable->setColumnWidth(2, 105); + ui->containersTable->setColumnWidth(0, 175); + ui->containersTable->setColumnWidth(1, 175); + ui->containersTable->setColumnWidth(2, 140); ui->containerContentsTable->setColumnCount(2); // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 150); - ui->containerContentsTable->setColumnWidth(1, 150); + ui->containerContentsTable->setColumnWidth(0, 240); + ui->containerContentsTable->setColumnWidth(1, 240); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. @@ -258,7 +258,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) } // TODO! make sure that when a variable is added that the whole model is reloaded. -// TODO! Fix me. This function does not work as intended because it must process both, not just one. +// TODO! Fix me. This function does not work as intended because it must process both varaible and contents, not just one. void VariableDialog::onVariablesTableUpdated() { if (_applyingModel){ @@ -346,6 +346,7 @@ void VariableDialog::onVariablesTableUpdated() void VariableDialog::onVariablesSelectionChanged() { if (_applyingModel){ + applyModel(); return; } @@ -381,6 +382,7 @@ void VariableDialog::onVariablesSelectionChanged() void VariableDialog::onContainersTableUpdated() { if (_applyingModel){ + applyModel(); return; } @@ -388,6 +390,7 @@ void VariableDialog::onContainersTableUpdated() // just in case something is goofy, return if (row < 0){ + applyModel(); return; } @@ -415,6 +418,7 @@ void VariableDialog::onContainersTableUpdated() void VariableDialog::onContainersSelectionChanged() { if (_applyingModel){ + applyModel(); return; } @@ -426,19 +430,15 @@ void VariableDialog::onContainersSelectionChanged() } // guaranteed not to be null, since getCurrentContainerRow already checked. - SCP_string newContainerName = ui->containersTable->item(row, 0)->text().toStdString(); - - if (newContainerName != _currentContainer){ - _currentContainer = newContainerName; - } - - applyModel(); // Seems to be buggy unless I have this outside the if. + _currentContainer = ui->containersTable->item(row, 0)->text().toStdString(); + applyModel(); } // TODO, finish this function void VariableDialog::onContainerContentsTableUpdated() { if (_applyingModel){ + applyModel(); return; } @@ -448,12 +448,14 @@ void VariableDialog::onContainerContentsTableUpdated() void VariableDialog::onContainerContentsSelectionChanged() { if (_applyingModel){ + applyModel(); return; } int row = getCurrentContainerItemRow(); if (row < 0){ + applyModel(); return; } @@ -461,6 +463,7 @@ void VariableDialog::onContainerContentsSelectionChanged() SCP_string newContainerItemName; if (!item){ + applyModel(); return; } @@ -485,12 +488,14 @@ void VariableDialog::onAddVariableButtonPressed() void VariableDialog::onCopyVariableButtonPressed() { if (_currentVariable.empty()){ + applyModel(); return; } int currentRow = getCurrentVariableRow(); if (currentRow < 0){ + applyModel(); return; } @@ -502,12 +507,14 @@ void VariableDialog::onCopyVariableButtonPressed() void VariableDialog::onDeleteVariableButtonPressed() { if (_currentVariable.empty()){ + applyModel(); return; } int currentRow = getCurrentVariableRow(); if (currentRow < 0){ + applyModel(); return; } @@ -526,17 +533,14 @@ void VariableDialog::onSetVariableAsStringRadioSelected() int currentRow = getCurrentVariableRow(); if (currentRow < 0){ + applyModel(); return; } // this doesn't return succeed or fail directly, // but if it doesn't return true then it failed since this is the string radio - if(!_model->setVariableType(currentRow, true)){ - applyModel(); - } else { - ui->setVariableAsStringRadio->setChecked(true); - ui->setVariableAsNumberRadio->setChecked(false); - } + _model->setVariableType(currentRow, true); + applyModel(); } void VariableDialog::onSetVariableAsNumberRadioSelected() @@ -544,25 +548,22 @@ void VariableDialog::onSetVariableAsNumberRadioSelected() int currentRow = getCurrentVariableRow(); if (currentRow < 0){ + applyModel(); return; } // this doesn't return succeed or fail directly, // but if it doesn't return false then it failed since this is the number radio - if (!_model->setVariableType(currentRow, false)) { - applyModel(); - } - else { - ui->setVariableAsStringRadio->setChecked(false); - ui->setVariableAsNumberRadio->setChecked(true); - } + _model->setVariableType(currentRow, false); + applyModel(); } void VariableDialog::onDoNotSaveVariableRadioSelected() { int currentRow = getCurrentVariableRow(); - if (currentRow < 0){ + if (currentRow < 0 || !ui->doNotSaveVariableRadio->isChecked()){ + applyModel(); return; } @@ -576,13 +577,12 @@ void VariableDialog::onDoNotSaveVariableRadioSelected() } } - - void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() { int row = getCurrentVariableRow(); - if (row < 0){ + if (row < 0 || !ui->saveVariableOnMissionCompletedRadio->isChecked()){ + applyModel(); return; } @@ -600,7 +600,8 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() { int row = getCurrentVariableRow(); - if (row < 0){ + if (row < 0 || !ui->saveVariableOnMissionCloseRadio->isChecked()){ + applyModel(); return; } @@ -645,7 +646,6 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } else { ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); } - } void VariableDialog::onAddContainerButtonPressed() @@ -682,17 +682,18 @@ void VariableDialog::onDeleteContainerButtonPressed() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } // Because of the text update we'll need, this needs an applyModel, whether it fails or not. if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged For Deletion"){ _model->removeVariable(row, false); - applyModel(); } else { _model->removeVariable(row, true); - applyModel(); } + + applyModel(); } void VariableDialog::onSetContainerAsMapRadioSelected() @@ -702,6 +703,7 @@ void VariableDialog::onSetContainerAsMapRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -716,6 +718,7 @@ void VariableDialog::onSetContainerAsListRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -729,6 +732,7 @@ void VariableDialog::onSetContainerAsStringRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -741,6 +745,7 @@ void VariableDialog::onSetContainerAsNumberRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -753,6 +758,7 @@ void VariableDialog::onSetContainerKeyAsStringRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -766,6 +772,7 @@ void VariableDialog::onSetContainerKeyAsNumberRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -778,6 +785,7 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -795,6 +803,7 @@ void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -812,6 +821,7 @@ void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -829,6 +839,7 @@ void VariableDialog::onNetworkContainerCheckboxClicked() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -842,6 +853,7 @@ void VariableDialog::onSetContainerAsEternalCheckboxClicked() int row = getCurrentContainerRow(); if (row < 0){ + applyModel(); return; } @@ -855,6 +867,7 @@ void VariableDialog::onAddContainerItemButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } @@ -872,12 +885,14 @@ void VariableDialog::onCopyContainerItemButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } int itemRow = getCurrentContainerItemRow(); if (itemRow < 0){ + applyModel(); return; } @@ -895,12 +910,14 @@ void VariableDialog::onDeleteContainerItemButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } int itemRow = getCurrentContainerItemRow(); if (itemRow < 0){ + applyModel(); return; } @@ -918,12 +935,14 @@ void VariableDialog::onShiftItemUpButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } int itemRow = getCurrentContainerItemRow(); if (itemRow < 0){ + applyModel(); return; } @@ -936,12 +955,14 @@ void VariableDialog::onShiftItemDownButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } int itemRow = getCurrentContainerItemRow(); if (itemRow < 0){ + applyModel(); return; } @@ -954,6 +975,7 @@ void VariableDialog::onSwapKeysAndValuesButtonPressed() int containerRow = getCurrentContainerRow(); if (containerRow < 0){ + applyModel(); return; } @@ -966,7 +988,10 @@ VariableDialog::~VariableDialog(){}; // NOLINT void VariableDialog::applyModel() { - // TODO! We need an undelete action. Best way is to change the text on the button if the notes say "Deleted" + if (_applyingModel) { + return; + } + _applyingModel = true; auto variables = _model->getVariableValues(); @@ -986,7 +1011,7 @@ void VariableDialog::applyModel() // check if this is the current variable. This keeps us selecting the correct variable even when // there's a deletion. - if (!_currentVariable.empty() && variables[x][0] == _currentVariable){ + if (selectedRow < 0 && !_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; } @@ -1062,7 +1087,7 @@ void VariableDialog::applyModel() } // check if this is the current variable. - if (!_currentVariable.empty() && containers[x][0] == _currentVariable){ + if (selectedRow < 0 && !_currentContainer.empty() && containers[x][0] == _currentContainer){ selectedRow = x; } @@ -1119,7 +1144,6 @@ void VariableDialog::applyModel() _currentContainer = ui->containersTable->item(0, 0)->text().toStdString(); ui->containersTable->clearSelection(); ui->containersTable->item(0, 0)->setSelected(true); - } } @@ -1220,6 +1244,7 @@ void VariableDialog::updateContainerOptions() ui->networkContainerCheckbox->setEnabled(false); ui->shiftItemUpButton->setEnabled(false); ui->shiftItemDownButton->setEnabled(false); + ui->swapKeysAndValuesButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); @@ -1333,6 +1358,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setRowCount(0); ui->shiftItemDownButton->setEnabled(false); ui->shiftItemUpButton->setEnabled(false); + ui->swapKeysAndValuesButton->setEnabled(false); return; @@ -1347,6 +1373,7 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->shiftItemUpButton->setEnabled(true); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); + ui->swapKeysAndValuesButton->setEnabled(false); // with string contents @@ -1459,6 +1486,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // Enable shift up and down buttons are off in Map mode. ui->shiftItemUpButton->setEnabled(false); ui->shiftItemDownButton->setEnabled(false); + ui->swapKeysAndValuesButton->setEnabled(true); // keys I didn't bother to make separate. Should have done the same with values. auto& keys = _model->getMapKeys(row); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 4b2d503fb4b..8a9bf4783b4 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -87,6 +87,9 @@ 191 + + Qt::ScrollBarAlwaysOn + Qt::ScrollBarAlwaysOff @@ -94,7 +97,7 @@ QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - true + false QAbstractItemView::SingleSelection @@ -247,11 +250,14 @@ 171 + + Qt::ScrollBarAlwaysOn + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - true + false QAbstractItemView::SingleSelection @@ -536,6 +542,9 @@ 171 + + Qt::ScrollBarAlwaysOn + Qt::ScrollBarAlwaysOff @@ -543,7 +552,7 @@ QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - true + false QAbstractItemView::SingleSelection From e1b9832faff2cf0e260cdeec042f18ea69908292 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 00:51:39 -0400 Subject: [PATCH 111/153] Fixes Based on Testing --- qtfred/src/ui/dialogs/VariableDialog.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 5861e46d444..135940aaae0 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -212,16 +212,16 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 175); - ui->variablesTable->setColumnWidth(1, 175); + ui->variablesTable->setColumnWidth(0, 180); + ui->variablesTable->setColumnWidth(1, 180); ui->variablesTable->setColumnWidth(2, 140); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 175); - ui->containersTable->setColumnWidth(1, 175); + ui->containersTable->setColumnWidth(0, 180); + ui->containersTable->setColumnWidth(1, 180); ui->containersTable->setColumnWidth(2, 140); ui->containerContentsTable->setColumnCount(2); @@ -229,8 +229,8 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 240); - ui->containerContentsTable->setColumnWidth(1, 240); + ui->containerContentsTable->setColumnWidth(0, 237); + ui->containerContentsTable->setColumnWidth(1, 237); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. @@ -519,7 +519,7 @@ void VariableDialog::onDeleteVariableButtonPressed() } // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - if (ui->variablesTable->item(currentRow, 2) && ui->variablesTable->item(currentRow, 2)->text().toStdString() == "Flagged For Deletion"){ + if (ui->deleteVariableButton->text().toStdString() == "Restore") { _model->removeVariable(currentRow, false); applyModel(); } else { @@ -688,9 +688,9 @@ void VariableDialog::onDeleteContainerButtonPressed() // Because of the text update we'll need, this needs an applyModel, whether it fails or not. if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged For Deletion"){ - _model->removeVariable(row, false); + _model->removeContainer(row, false); } else { - _model->removeVariable(row, true); + _model->removeContainer(row, true); } applyModel(); From 98e78ec086be62b5cbc472c705c07f3f65f18df0 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 01:03:34 -0400 Subject: [PATCH 112/153] Fix Containers Not Restoring Deleted Items And Change Deletion Text for size savings --- qtfred/src/ui/dialogs/VariableDialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 135940aaae0..b5b75b92da1 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -229,8 +229,8 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 237); - ui->containerContentsTable->setColumnWidth(1, 237); + ui->containerContentsTable->setColumnWidth(0, 230); + ui->containerContentsTable->setColumnWidth(1, 230); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. @@ -687,7 +687,7 @@ void VariableDialog::onDeleteContainerButtonPressed() } // Because of the text update we'll need, this needs an applyModel, whether it fails or not. - if (ui->containersTable->item(row, 2) && ui->containersTable->item(row, 2)->text().toStdString() == "Flagged For Deletion"){ + if (ui->deleteContainerButton->text().toStdString() == "Restore"){ _model->removeContainer(row, false); } else { _model->removeContainer(row, true); @@ -1107,7 +1107,7 @@ void VariableDialog::applyModel() } // do we need to switch the delete button to a restore button? - if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "Flagged for Deletion") { + if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "Deleted") { ui->deleteContainerButton->setText("Restore"); } else { ui->deleteContainerButton->setText("Delete"); @@ -1196,7 +1196,7 @@ void VariableDialog::updateVariableOptions() ui->setVariableAsNumberRadio->setChecked(!string); // do we need to switch the delete button to a restore button? - if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Flagged for Deletion"){ + if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Deleted"){ ui->deleteVariableButton->setText("Restore"); } else { ui->deleteVariableButton->setText("Delete"); From 8dde6d47cbdad1392c9e7e8b899a77eef7d913ed Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 01:19:42 -0400 Subject: [PATCH 113/153] More spacing adjustments and text changes --- .../src/mission/dialogs/VariableDialogModel.cpp | 4 ++-- qtfred/src/ui/dialogs/VariableDialog.cpp | 16 ++++++++-------- qtfred/ui/VariableDialog.ui | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 3a9abc8c9ea..6813afbd926 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1660,7 +1660,7 @@ const SCP_vector> VariableDialogModel::getVariableValu SCP_string notes = ""; if (item.deleted) { - notes = "Flagged for Deletion"; + notes = "Deleted"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ @@ -1813,7 +1813,7 @@ const SCP_vector> VariableDialogModel::getContainerNam if (item.deleted) { - notes = "Flagged for Deletion"; + notes = "Deleted"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b5b75b92da1..fccd2b3e9c3 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -212,25 +212,25 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 180); - ui->variablesTable->setColumnWidth(1, 180); - ui->variablesTable->setColumnWidth(2, 140); + ui->variablesTable->setColumnWidth(0, 190); + ui->variablesTable->setColumnWidth(1, 190); + ui->variablesTable->setColumnWidth(2, 120); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->containersTable->setColumnWidth(0, 180); - ui->containersTable->setColumnWidth(1, 180); - ui->containersTable->setColumnWidth(2, 140); + ui->containersTable->setColumnWidth(0, 190); + ui->containersTable->setColumnWidth(1, 190); + ui->containersTable->setColumnWidth(2, 120); ui->containerContentsTable->setColumnCount(2); // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 230); - ui->containerContentsTable->setColumnWidth(1, 230); + ui->containerContentsTable->setColumnWidth(0, 225); + ui->containerContentsTable->setColumnWidth(1, 225); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 8a9bf4783b4..d9e10475e65 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -377,7 +377,7 @@ 650 - 30 + 20 191 191 @@ -437,9 +437,9 @@ 650 - 230 + 220 191 - 181 + 191 From 3120d6dda143235b8478b3a652eac85f645f8455 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 16:57:30 -0400 Subject: [PATCH 114/153] Fix the Addition of variables by typing And start adding container Items by typing. --- .../mission/dialogs/VariableDialogModel.cpp | 28 ++++ .../src/mission/dialogs/VariableDialogModel.h | 2 + qtfred/src/ui/dialogs/VariableDialog.cpp | 130 +++++++++++++++--- qtfred/ui/VariableDialog.ui | 47 ++++++- 4 files changed, 180 insertions(+), 27 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 6813afbd926..9e881ef72d6 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1123,6 +1123,34 @@ SCP_string VariableDialogModel::addListItem(int index) } } +SCP_string VariableDialogModel::addListItem(int index, SCP_string item) +{ + auto container = lookupContainer(index); + + if (!container){ + return ""; + } + + if (container->string) { + container->stringValues.push_back(item); + return container->stringValues.back(); + } else { + auto temp = trimIntegerString(item); + + try { + int tempNumber = std::stoi(temp); + container->numberValues.push_back(tempNumber); + } + catch(...){ + container->numberValues.push_back(0); + return "0"; + } + + sprintf(temp, "%i", container->numberValues.back()); + return temp; + } +} + std::pair VariableDialogModel::addMapItem(int index) { auto container = lookupContainer(index); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 2bc4709dd01..a1b0eddeba3 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -100,10 +100,12 @@ class VariableDialogModel : public AbstractDialogModel { bool removeContainer(int index, bool toDelete); SCP_string addListItem(int index); + SCP_string addListItem(int index, SCP_string item); SCP_string copyListItem(int containerIndex, int index); bool removeListItem(int containerindex, int index); std::pair addMapItem(int index); + std::pair addMapItem(int index, SCP_string key, SCP_string value); std::pair copyMapItem(int index, int itemIndex); bool removeMapItem(int index, int rowIndex); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index fccd2b3e9c3..6a2f7a32b73 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -272,19 +272,56 @@ void VariableDialog::onVariablesTableUpdated() } auto item = ui->variablesTable->item(currentRow, 0); + SCP_string itemText = item->text().toStdString(); bool apply = false; - // so if the user just removed the name, mark it as deleted *before changing the name* - if (_currentVariable != "" && !strlen(item->text().toStdString().c_str())) { - if (!_model->removeVariable(item->row(), true)) { + // This will only be true if the user is trying to add a new variable. + if (currentRow == ui->variablesTable->rowCount() - 1) { + + // make sure the item exists before we dereference + if (ui->variablesTable->item(currentRow, 0)) { + + // Add the new container. + if (!itemText.empty() && itemText != "Add Variable ...") { + _model->addNewVariable(itemText); + _currentVariable = itemText; + _currentVariableData = ""; + applyModel(); + } + + } else { + // reapply the model if the item is null. + applyModel(); + } + + // we're done here because we cannot edit the data column on the add variable row + return; + } + + // so if the user just removed the name, mark it as deleted + if (itemText.empty() && !_currentVariable.empty()) { + if (!_model->removeVariable(item->row(), true) ) { // marking a variable as deleted failed, resync UI apply = true; } else { + // now that we know that the variable was deleted updateVariableOptions(); } - } else { - - auto ret = _model->changeVariableName(item->row(), item->text().toStdString()); + + // if the user is restoring a deleted variable by inserting a name.... + } else if (!itemText.empty() && _currentVariable.empty()){ + + if (!_model->removeVariable(item->row(), true) ) { + // marking a variable as deleted failed, resync UI + apply = true; + } else { + // now that we know that the variable was deleted + updateVariableOptions(); + } + + } else if (itemText != _currentVariable){ + + auto ret = _model->changeVariableName(item->row(), itemText); // we put something in the cell, but the model couldn't process it. if (strlen(item->text().toStdString().c_str()) && ret == ""){ @@ -296,19 +333,18 @@ void VariableDialog::onVariablesTableUpdated() item->setText(ret.c_str()); _currentVariable = ret; } - } - // empty return and cell was handled earlier. + }// No action needed if the first cell was not changed. + // now work on the variable data cell item = ui->variablesTable->item(currentRow, 1); + itemText = item->text().toStdString(); // check if data column was altered - // TODO! Set up comparison between last and current value - if (item->column() == 1) { - + if (itemText != _currentVariableData) { // Variable is a string if (_model->getVariableType(item->row())){ - SCP_string temp = item->text().toStdString().c_str(); + SCP_string temp = itemText; temp = temp.substr(0, NAME_LENGTH - 1); SCP_string ret = _model->setVariableStringValue(item->row(), temp); @@ -316,15 +352,14 @@ void VariableDialog::onVariablesTableUpdated() apply = true; } else { item->setText(ret.c_str()); - } + _currentVariableData = ret; + } + + // Variable is a number } else { SCP_string source = item->text().toStdString(); SCP_string temp = _model->trimIntegerString(source); - if (temp != source){ - item->setText(temp.c_str()); - } - try { int ret = _model->setVariableNumberValue(item->row(), std::stoi(temp)); temp = ""; @@ -332,12 +367,16 @@ void VariableDialog::onVariablesTableUpdated() item->setText(temp.c_str()); } catch (...) { - applyModel(); + // that's not good.... + apply = true; } + + // best we can do is to set this to temp, whether conversion fails or not. + _currentContainerItemData = temp; } + } - // if the user somehow edited the info that should only come from the model and should not be editable, reload everything. - } else { + if (apply) { applyModel(); } } @@ -404,6 +443,11 @@ void VariableDialog::onContainersTableUpdated() applyModel(); } } + else { + applyModel(); + } + + return; // are they editing an existing container name? } else if (ui->containersTable->item(row, 0)){ @@ -442,8 +486,52 @@ void VariableDialog::onContainerContentsTableUpdated() return; } + int containerRow = getCurrentContainerRow(); + int row = getCurrentContainerItemRow(); + + // just in case something is goofy, return + if (row < 0 || containerRow < 0){ + applyModel(); + return; + } + + // Are they adding a new item? + if (row == ui->containerContentsTable->rowCount() - 1){ + if (ui->containerContentsTable->item(row, 0)) { + SCP_string newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); + if (!newString.empty() && newString != "Add Item ..."){ + + if (_model->getContainerListOrMap(containerRow)) { + _model->addListItem(containerRow, newString); + + } else { + + _model->addMapItem(containerRow, newString); + } + + _currentContainer = newString; + applyModel(); + } + } + else { + applyModel(); + } + + return; + + // are they editing an existing container name? + } else if (ui->containerContentsTable->item(row, 0)){ + _currentContainer = ui->containersTable->item(row,0)->text().toStdString(); + + if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0)->text().toStdString())){ + applyModel(); + } + } + + + -} // could be new key or new value +} void VariableDialog::onContainerContentsSelectionChanged() { diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index d9e10475e65..20d19c58e92 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -279,7 +279,7 @@ 520 - 20 + 30 106 175 @@ -379,7 +379,7 @@ 650 20 191 - 191 + 181 @@ -391,7 +391,7 @@ 10 20 181 - 171 + 161 @@ -437,9 +437,9 @@ 650 - 220 + 210 191 - 191 + 221 @@ -451,7 +451,7 @@ 10 20 181 - 152 + 181 @@ -590,6 +590,41 @@ + + variablesTable + addVariableButton + copyVariableButton + deleteVariableButton + setVariableAsStringRadio + setVariableAsNumberRadio + doNotSaveVariableRadio + saveVariableOnMissionCompletedRadio + saveVariableOnMissionCloseRadio + setVariableAsEternalcheckbox + networkVariableCheckbox + containersTable + addContainerButton + copyContainerButton + deleteContainerButton + doNotSaveContainerRadio + saveContainerOnMissionCompletedRadio + saveContainerOnMissionCloseRadio + setContainerAsEternalCheckbox + networkContainerCheckbox + containerContentsTable + addContainerItemButton + copyContainerItemButton + shiftItemUpButton + shiftItemDownButton + swapKeysAndValuesButton + deleteContainerItemButton + setContainerAsListRadio + setContainerAsMapRadio + setContainerAsStringRadio + setContainerAsNumberRadio + setContainerKeyAsStringRadio + setContainerKeyAsNumberRadio + From 03083d1a91bc5f972165261721848615cf65625c Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 4 May 2024 23:25:09 -0400 Subject: [PATCH 115/153] Implement a few missing container item features --- .../mission/dialogs/VariableDialogModel.cpp | 156 +++++++++++++----- .../src/mission/dialogs/VariableDialogModel.h | 7 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 106 ++++++++++-- qtfred/src/ui/dialogs/VariableDialog.h | 4 +- 4 files changed, 213 insertions(+), 60 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 9e881ef72d6..c7ca3506236 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1191,14 +1191,79 @@ std::pair VariableDialogModel::addMapItem(int index) ret.first = newKey; - if (container->string) + + if (container->string){ ret.second = ""; - else + container->stringValues.push_back(""); + } else { ret.second = "0"; + container->numberValues.push_back(0); + } return ret; } +std::pair VariableDialogModel::addMapItem(int index, SCP_string key, SCP_string value) +{ + auto container = lookupContainer(index); + + std::pair ret = { "", "" }; + + // no container available + if (!container) { + return ret; + } + + bool conflict; + int count = 0; + SCP_string newKey; + + if (key.empty()) { + do { + conflict = false; + + if (container->stringKeys){ + sprintf(newKey, "key%i", count); + } else { + sprintf(newKey, "%i", count); + } + + for (int x = 0; x < static_cast(container->keys.size()); ++x) { + if (container->keys[x] == newKey){ + conflict = true; + break; + } + } + + ++count; + } while (conflict && count < 101); + } else { + newKey = key; + } + + if (conflict) { + return ret; + } + + ret.first = newKey; + container->keys.push_back(ret.first); + + if (container->string) { + ret.second = value; + } else { + try { + container->numberValues.push_back(std::stoi(value)); + ret.second = value; + } + catch (...) { + ret.second = "0"; + container->numberValues.push_back(0); + } + } + + return ret; +} + SCP_string VariableDialogModel::copyListItem(int containerIndex, int index) { auto container = lookupContainer(containerIndex); @@ -1217,6 +1282,43 @@ SCP_string VariableDialogModel::copyListItem(int containerIndex, int index) } +SCP_string VariableDialogModel::changeListItem(int containerIndex, int index, SCP_string newString) +{ + auto container = lookupContainer(containerIndex); + + if (!container){ + return ""; + } + + if (container->string){ + auto listItem = lookupContainerStringItem(containerIndex, index); + + if (!listItem){ + return ""; + } + + *listItem = newString; + + } else { + auto listItem = lookupContainerNumberItem(containerIndex, index); + + if (!listItem){ + return ""; + } + + try{ + *listItem = std::stoi(newString); + } + catch(...){ + SCP_string temp; + sprintf(temp, "%i", *listItem); + return temp; + } + } + + return ""; +} + bool VariableDialogModel::removeListItem(int containerIndex, int index) { auto container = lookupContainer(containerIndex); @@ -1452,7 +1554,7 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) return true; } -SCP_string VariableDialogModel::replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey) +SCP_string VariableDialogModel::changeMapItemKey(int index, SCP_string oldKey, SCP_string newKey) { auto container = lookupContainer(index); @@ -1471,27 +1573,17 @@ SCP_string VariableDialogModel::replaceMapItemKey(int index, SCP_string oldKey, return oldKey; } -SCP_string VariableDialogModel::changeMapItemStringValue(int index, SCP_string key, SCP_string newValue) +SCP_string VariableDialogModel::changeMapItemStringValue(int index, int itemIndex, SCP_string newValue) { - auto container = lookupContainer(index); - - if (!container || !container->string){ + auto item = lookupContainerStringItem(index, itemIndex); + + if (!item){ return ""; } - for (int x = 0; x < static_cast(container->keys.size()); ++x){ - if (container->keys[x] == key) { - if (x < static_cast(container->stringValues.size())){ - container->stringValues[x] = newValue; - return newValue; - } else { - return ""; - } - } - } + *item = newValue; - // Failure - return ""; + return *item; } void VariableDialogModel::swapKeyAndValues(int index) @@ -1594,29 +1686,19 @@ void VariableDialogModel::swapKeyAndValues(int index) } } -SCP_string VariableDialogModel::changeMapItemNumberValue(int index, SCP_string key, int newValue) +SCP_string VariableDialogModel::changeMapItemNumberValue(int index, int itemIndex, int newValue) { - auto container = lookupContainer(index); + auto mapItem = lookupContainerNumberItem(index, itemIndex); - if (!container || !container->string){ + if (!mapItem){ return ""; } - for (int x = 0; x < static_cast(container->keys.size()); ++x){ - if (container->keys[x] == key) { - if (x < static_cast(container->numberValues.size())){ - container->numberValues[x] = newValue; - SCP_string returnValue; - sprintf(returnValue, "%i", newValue); - return returnValue; - } else { - return ""; - } - } - } - - // Failure - return ""; + *mapItem = newValue; + + SCP_string ret; + sprintf(ret, "%i", newValue); + return ret; } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index a1b0eddeba3..f10d73cd01b 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -107,14 +107,15 @@ class VariableDialogModel : public AbstractDialogModel { std::pair addMapItem(int index); std::pair addMapItem(int index, SCP_string key, SCP_string value); std::pair copyMapItem(int index, int itemIndex); + SCP_string changeListItem(int containerIndex, int index, SCP_string newString); bool removeMapItem(int index, int rowIndex); void shiftListItemUp(int containerIndex, int itemIndex); void shiftListItemDown(int containerIndex, int itemIndex); - SCP_string replaceMapItemKey(int index, SCP_string oldKey, SCP_string newKey); - SCP_string changeMapItemStringValue(int index, SCP_string key, SCP_string newValue); - SCP_string changeMapItemNumberValue(int index, SCP_string key, int newValue); + SCP_string changeMapItemKey(int index, SCP_string oldKey, SCP_string newKey); + SCP_string changeMapItemStringValue(int index, int itemIndex, SCP_string newValue); + SCP_string changeMapItemNumberValue(int index, int itemIndex, int newValue); const SCP_vector& getMapKeys(int index); const SCP_vector& getStringValues(int index); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 6a2f7a32b73..de7d571f464 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -372,7 +372,7 @@ void VariableDialog::onVariablesTableUpdated() } // best we can do is to set this to temp, whether conversion fails or not. - _currentContainerItemData = temp; + _currentContainerItemCol2 = temp; } } @@ -497,8 +497,13 @@ void VariableDialog::onContainerContentsTableUpdated() // Are they adding a new item? if (row == ui->containerContentsTable->rowCount() - 1){ + + bool newItemCreated = false; + SCP_string newString; + if (ui->containerContentsTable->item(row, 0)) { - SCP_string newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); + newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); + if (!newString.empty() && newString != "Add Item ..."){ if (_model->getContainerListOrMap(containerRow)) { @@ -506,31 +511,94 @@ void VariableDialog::onContainerContentsTableUpdated() } else { - _model->addMapItem(containerRow, newString); + _model->addMapItem(containerRow, newString, ""); } _currentContainer = newString; applyModel(); + return; } - } - else { + + } + + if (!ui->containerContentsTable->item(row, 1)) { + // At this point there's nothing else we can do and something may be off, anyway. applyModel(); + return; } + // if we got here, we know that the second cell is valid. + newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); + + // But we can only create a new map item here. Ignore if this container is a list. + if (!newString.empty() && newString.substr(0, 10) != "Add Item ..."){ + if (!_model->getContainerListOrMap(containerRow)) { + auto ret = _model->addMapItem(containerRow, "", newString); + _currentContainerItemCol1 = ret.first; + _currentContainerItemCol2 = ret.second; + } + } + + // nothing else to determine at this point. + applyModel(); return; - // are they editing an existing container name? + // are they editing an existing container item column 1? } else if (ui->containerContentsTable->item(row, 0)){ - _currentContainer = ui->containersTable->item(row,0)->text().toStdString(); + SCP_string newText = ui->containerContentsTable->item(row, 0)->text().toStdString(); + + if (_model->getContainerListOrMap(containerRow)){ - if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0)->text().toStdString())){ - applyModel(); - } - } + if (newText != _currentContainerItemCol1){ + // Trim the string if necessary + if (!_model->getContainerValueType(containerRow)){ + newText = _model->trimIntegerString(newText); + } + + // Finally change the list item + _currentContainerItemCol1 = _model->changeListItem(containerRow, row, newText); + return; + } + + } else if (newText != _currentContainerItemCol1){ + + if (!_model->getContainerKeyType(containerRow)){ + + if (!_model->getContainerKeyType(containerRow)){ + newText = _model->trimIntegerString(newText); + } + + // TODO! Write a key change function so you can put something here. + } + return; + } + } + + // if we're here, nothing has changed so far. So let's attempt column 2 + if (ui->containerContentsTable->item(row, 1) && !_model->getContainerListOrMap(containerRow)){ + + SCP_string newText = ui->containerContentsTable->item(row, 1)->text().toStdString(); + + if(newText != _currentContainerItemCol2){ + + if (_model->getContainerValueType(containerRow)){ + _currentContainerItemCol2 = _model->changeMapItemStringValue(containerRow, row, newText); + + } else { + try{ + _currentContainerItemCol2 = _model->changeMapItemNumberValue(containerRow, row, std::stoi(_model->trimIntegerString(newText))); + } + catch(...) { + _currentContainerItemCol2 = _model->changeMapItemNumberValue(containerRow, row, 0); + } + } + applyModel(); + } + } } void VariableDialog::onContainerContentsSelectionChanged() @@ -559,9 +627,9 @@ void VariableDialog::onContainerContentsSelectionChanged() item = ui->containerContentsTable->item(row, 1); SCP_string newContainerDataText = (item) ? item->text().toStdString() : ""; - if (newContainerItemName != _currentContainerItem || _currentContainerItemData != newContainerDataText){ - _currentContainerItem = newContainerItemName; - _currentContainerItemData = newContainerDataText; + if (newContainerItemName != _currentContainerItemCol1 || _currentContainerItemCol2 != newContainerDataText){ + _currentContainerItemCol1 = newContainerItemName; + _currentContainerItemCol2 = newContainerDataText; applyModel(); } } @@ -1336,7 +1404,7 @@ void VariableDialog::updateContainerOptions() ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setRowCount(0); + // if there's no container, there's no container items ui->addContainerItemButton->setEnabled(false); @@ -1344,9 +1412,11 @@ void VariableDialog::updateContainerOptions() ui->deleteContainerItemButton->setEnabled(false); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setRowCount(0); ui->shiftItemDownButton->setEnabled(false); ui->shiftItemUpButton->setEnabled(false); + ui->containerContentsTable->clearSelection(); + ui->containerContentsTable->setRowCount(0); + } else { auto items = ui->containersTable->selectedItems(); @@ -1479,7 +1549,7 @@ void VariableDialog::updateContainerDataOptions(bool list) } // set selected and enable shifting functions - if (strings[x] == _currentContainerItem){ + if (strings[x] == _currentContainerItemCol1){ ui->containerContentsTable->clearSelection(); ui->containerContentsTable->item(x,0)->setSelected(true); @@ -1704,7 +1774,7 @@ void VariableDialog::preReject() void VariableDialog::checkValidModel() { - if (_model->checkValidModel()) { + if (ui->OkCancelButtons->button(QDialogButtonBox::Ok)->hasFocus() && _model->checkValidModel()){ accept(); } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 10b1704e3a1..ade50f77958 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -81,8 +81,8 @@ class VariableDialog : public QDialog { SCP_string _currentVariable = ""; SCP_string _currentVariableData = ""; SCP_string _currentContainer = ""; - SCP_string _currentContainerItem = ""; - SCP_string _currentContainerItemData = ""; + SCP_string _currentContainerItemCol1 = ""; + SCP_string _currentContainerItemCol2 = ""; }; From 87fd99f9f6fc4a6c4488d9ded538a2bd23b1b095 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 5 May 2024 00:18:47 -0400 Subject: [PATCH 116/153] Finish implementation of type formatting option --- .../mission/dialogs/VariableDialogModel.cpp | 12 ++-- .../src/mission/dialogs/VariableDialogModel.h | 4 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 67 ++++++++++++------- qtfred/src/ui/dialogs/VariableDialog.h | 1 + qtfred/ui/VariableDialog.ui | 26 +++++++ 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c7ca3506236..280d0c90a59 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -7,7 +7,7 @@ namespace fso { namespace fred { namespace dialogs { - + static int _textMode = 0; VariableDialogModel::VariableDialogModel(QObject* parent, EditorViewport* viewport) : AbstractDialogModel(parent, viewport) @@ -1797,7 +1797,7 @@ const SCP_vector> VariableDialogModel::getContainerNam SCP_string mapMidScript; SCP_string mapPostscript; - switch (_listTextMode) { + switch (_textMode) { case 1: listPrefix = ""; listPostscript = " List"; @@ -1831,13 +1831,13 @@ const SCP_vector> VariableDialogModel::getContainerNam default: // this takes care of weird cases. The logic should be simple enough to not have bugs, but just in case, switch back to default. - _listTextMode = 0; + _textMode = 0; listPrefix = "List of "; listPostscript = "s"; break; } - switch (_mapTextMode) { + switch (_textMode) { case 1: mapPrefix = ""; mapMidScript = "-keyed Map of "; @@ -1876,7 +1876,7 @@ const SCP_vector> VariableDialogModel::getContainerNam break; default: - _mapTextMode = 0; + _textMode = 0; mapPrefix = "Map with "; mapMidScript = " Keys and "; mapPostscript = " Values"; @@ -1936,6 +1936,8 @@ const SCP_vector> VariableDialogModel::getContainerNam return outStrings; } +void VariableDialogModel::setTextMode(int modeIn) { _textMode = modeIn;} + // This function is for cleaning up input strings that should be numbers. We could use std::stoi, // but this helps to not erase the entire string if user ends up mistyping just one digit. // If we ever allowed float types in sexp variables ... *shudder* ... we would definitely need a float diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index f10d73cd01b..50a2d1dea8d 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -125,6 +125,8 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); + void setTextMode(int modeIn); + bool checkValidModel(); bool apply() override; @@ -137,8 +139,6 @@ class VariableDialogModel : public AbstractDialogModel { private: SCP_vector _variableItems; SCP_vector _containerItems; - int _listTextMode = 0; - int _mapTextMode = 0; int _deleteWarningCount; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index de7d571f464..433d2466de9 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -208,6 +208,11 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) this, &VariableDialog::onSwapKeysAndValuesButtonPressed); + connect(ui->selectFormatCombobox, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &VariableDialog::onSelectFormatComboboxSelectionChanged); + ui->variablesTable->setColumnCount(3); ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); @@ -254,11 +259,17 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->containersTable->clearSelection(); ui->containerContentsTable->clearSelection(); + ui->selectFormatCombobox->addItem("Verbose"); + ui->selectFormatCombobox->addItem("Simplified"); + ui->selectFormatCombobox->addItem("Type and ()"); + ui->selectFormatCombobox->addItem("Type and <>"); + ui->selectFormatCombobox->addItem("Only ()"); + ui->selectFormatCombobox->addItem("Only <>"); + ui->selectFormatCombobox->addItem("No extra Marks"); + applyModel(); } -// TODO! make sure that when a variable is added that the whole model is reloaded. -// TODO! Fix me. This function does not work as intended because it must process both varaible and contents, not just one. void VariableDialog::onVariablesTableUpdated() { if (_applyingModel){ @@ -504,7 +515,7 @@ void VariableDialog::onContainerContentsTableUpdated() if (ui->containerContentsTable->item(row, 0)) { newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); - if (!newString.empty() && newString != "Add Item ..."){ + if (!newString.empty() && newString != "Add item ..."){ if (_model->getContainerListOrMap(containerRow)) { _model->addListItem(containerRow, newString); @@ -531,7 +542,7 @@ void VariableDialog::onContainerContentsTableUpdated() newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); // But we can only create a new map item here. Ignore if this container is a list. - if (!newString.empty() && newString.substr(0, 10) != "Add Item ..."){ + if (!newString.empty() && newString.substr(0, 10) != "Add item ..."){ if (!_model->getContainerListOrMap(containerRow)) { auto ret = _model->addMapItem(containerRow, "", newString); _currentContainerItemCol1 = ret.first; @@ -1139,6 +1150,12 @@ void VariableDialog::onSwapKeysAndValuesButtonPressed() applyModel(); } +void VariableDialog::onSelectFormatComboboxSelectionChanged() +{ + _model->setTextMode(ui->selectFormatCombobox->currentIndex()); + applyModel(); +} + VariableDialog::~VariableDialog(){}; // NOLINT @@ -1665,13 +1682,15 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 0, item); } - if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText(strings[x].c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); - } else { - QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); - item->setFlags(item->flags() | Qt::ItemIsEditable); - ui->containerContentsTable->setItem(x, 1, item); + if (x < static_cast(strings.size())){ + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(strings[x].c_str()); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(strings[x].c_str()); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); + } } } @@ -1689,28 +1708,30 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 0, item); } - if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText(std::to_string(numbers[x]).c_str()); - ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); - } else { - QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); - item->setFlags(item->flags() | Qt::ItemIsEditable); - ui->containerContentsTable->setItem(x, 1, item); + if (x < static_cast(numbers.size())){ + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(std::to_string(numbers[x]).c_str()); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(std::to_string(numbers[x]).c_str()); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); + } } } if (ui->containerContentsTable->item(x, 0)){ - ui->containerContentsTable->item(x, 0)->setText("Add key ..."); + ui->containerContentsTable->item(x, 0)->setText("Add item ..."); } else { - QTableWidgetItem* item = new QTableWidgetItem("Add key ..."); + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); ui->containerContentsTable->setItem(x, 0, item); } if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText("Add Value ..."); + ui->containerContentsTable->item(x, 1)->setText("Add item ..."); ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { - QTableWidgetItem* item = new QTableWidgetItem("Add Value ..."); + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } @@ -1752,7 +1773,7 @@ int VariableDialog::getCurrentContainerItemRow() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { - if (item && item->column() == 0 && item->text().toStdString() != "Add Item ...") { + if (item && item->column() == 0 && item->text().toStdString() != "Add item ...") { return item->row(); } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index ade50f77958..65a1ac5b7a1 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -72,6 +72,7 @@ class VariableDialog : public QDialog { void onShiftItemUpButtonPressed(); void onShiftItemDownButtonPressed(); void onSwapKeysAndValuesButtonPressed(); + void onSelectFormatComboboxSelectionChanged(); int getCurrentVariableRow(); int getCurrentContainerRow(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 20d19c58e92..0cc996e665f 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -573,6 +573,32 @@ false + + + + 550 + 140 + 81 + 20 + + + + Type Format + + + Qt::AlignCenter + + + + + + 540 + 160 + 101 + 24 + + + From b9b36d2a769af65789e3fc48f6378d81d0960785 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 5 May 2024 00:19:01 -0400 Subject: [PATCH 117/153] Fix Shift up and down buttons --- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 433d2466de9..1c968ce316e 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1571,11 +1571,11 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->item(x,0)->setSelected(true); // more than one item and not already at the top of the list. - if (x > 0 && x < static_cast(strings.size())){ + if (!(x > 0 && x < static_cast(strings.size()))){ ui->shiftItemUpButton->setEnabled(false); } - if (x > -1 && x < static_cast(strings.size()) - 1){ + if (!(x > -1 && x < static_cast(strings.size()) - 1)){ ui->shiftItemDownButton->setEnabled(false); } } From e4886db4d269128c4dbf65d964f6056eacccbbf2 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 5 May 2024 00:58:24 -0400 Subject: [PATCH 118/153] Fix shift up and down buttons --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 8 ++++---- qtfred/src/ui/dialogs/VariableDialog.cpp | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 280d0c90a59..1eb4f73aad7 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1466,8 +1466,8 @@ void VariableDialogModel::shiftListItemUp(int containerIndex, int itemIndex) } // handle itemIndex out of bounds - if ( (container->string && itemIndex <= static_cast(container->stringValues.size())) - || (!container->string && itemIndex <= static_cast(container->numberValues.size())) ){ + if ( (container->string && itemIndex >= static_cast(container->stringValues.size())) + || (!container->string && itemIndex >= static_cast(container->numberValues.size())) ){ return; } @@ -1490,8 +1490,8 @@ void VariableDialogModel::shiftListItemDown(int containerIndex, int itemIndex) } // handle itemIndex out of bounds. -1 is necessary. since the bottom item is cannot be moved down. - if ( (container->string && itemIndex <= static_cast(container->stringValues.size()) - 1) - || (!container->string && itemIndex <= static_cast(container->numberValues.size()) - 1) ){ + if ( (container->string && itemIndex >= static_cast(container->stringValues.size()) - 1) + || (!container->string && itemIndex >= static_cast(container->numberValues.size()) - 1) ){ return; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 1c968ce316e..30d1a16d423 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -315,8 +315,9 @@ void VariableDialog::onVariablesTableUpdated() // marking a variable as deleted failed, resync UI apply = true; } else { + _model->changeVariableName(item->row(), itemText); // now that we know that the variable was deleted - updateVariableOptions(); + applyModel(); } // if the user is restoring a deleted variable by inserting a name.... @@ -326,8 +327,9 @@ void VariableDialog::onVariablesTableUpdated() // marking a variable as deleted failed, resync UI apply = true; } else { + _model->changeVariableName(item->row(), itemText); // now that we know that the variable was deleted - updateVariableOptions(); + applyModel(); } } else if (itemText != _currentVariable){ @@ -1133,7 +1135,7 @@ void VariableDialog::onShiftItemDownButtonPressed() return; } - _model->shiftListItemUp(containerRow, itemRow); + _model->shiftListItemDown(containerRow, itemRow); applyModel(); } From 9b29e754ce9d88cc086dfb8a046ce9c139a73c31 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 5 May 2024 11:13:03 -0400 Subject: [PATCH 119/153] Fix overflow return values Previously on windows it was returning 0 because std::stol has a poor windows implementation. --- .../mission/dialogs/VariableDialogModel.cpp | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 1eb4f73aad7..da83297e8a5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1991,15 +1991,10 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) ret = "0"; } - return clampIntegerString(ret); -} - -// Helper function for trimIntegerString that makes sure we don't try to save a value that overflows or underflows -// I don't recommend using outside of there, as there can be data loss if the input string is not cleaned first. -SCP_string VariableDialogModel::clampIntegerString(SCP_string source) -{ + // here we deal with overflow values. try { - long test = std::stol(source); + // some OS's will deal with this properly. + long test = std::stol(ret); if (test > INT_MAX) { return "2147483647"; @@ -2007,14 +2002,25 @@ SCP_string VariableDialogModel::clampIntegerString(SCP_string source) return "-2147483648"; } - return source; + return ret; } - // most truly ludicrous cases should be caught before here in the calling function, so this should not cause much if any data loss + // Others will not, sadly. + // So down here, we can still return the right overflow values if stol derped out. Since we've already cleaned out non-digits, + // checking for length *really should* allow us to know if something overflowed catch (...){ - return "0"; + if (ret.size() > 9){ + if (ret[0] == '-'){ + return "-2147483648"; + } else { + return "2147483647"; + } + } + + return "0"; } } + } // dialogs } // fred } // fso From 621030a72016ec7859c14fedc751c346afe12f18 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 5 May 2024 13:30:24 -0400 Subject: [PATCH 120/153] Fix various issues --- .../mission/dialogs/VariableDialogModel.cpp | 14 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 155 +++++++++--------- 2 files changed, 81 insertions(+), 88 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index da83297e8a5..5ba9561fcff 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -472,11 +472,6 @@ SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName return ""; } - // no name means no variable - if (newName == "") { - variable->deleted = true; - } - // Truncate name if needed if (newName.length() >= TOKEN_LENGTH){ newName = newName.substr(0, TOKEN_LENGTH - 1); @@ -546,7 +541,7 @@ bool VariableDialogModel::removeVariable(int index, bool toDelete) } if (toDelete){ - if (_deleteWarningCount < 3){ + if (_deleteWarningCount < 2){ SCP_string question = "Are you sure you want to delete this variable? Any references to it will have to be changed."; SCP_string info = ""; @@ -1055,10 +1050,6 @@ SCP_string VariableDialogModel::copyContainer(int index) SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newName) { - if (newName == "") { - return ""; - } - auto container = lookupContainer(index); // nothing to change, or invalid entry @@ -1190,7 +1181,7 @@ std::pair VariableDialogModel::addMapItem(int index) } ret.first = newKey; - + container->keys.push_back(newKey); if (container->string){ ret.second = ""; @@ -2016,6 +2007,7 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) } } + // emergency return value return "0"; } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 30d1a16d423..09a153f3aa0 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -311,27 +311,20 @@ void VariableDialog::onVariablesTableUpdated() // so if the user just removed the name, mark it as deleted if (itemText.empty() && !_currentVariable.empty()) { - if (!_model->removeVariable(item->row(), true) ) { - // marking a variable as deleted failed, resync UI - apply = true; - } else { - _model->changeVariableName(item->row(), itemText); - // now that we know that the variable was deleted - applyModel(); - } + + _model->removeVariable(item->row(), true); + // these things need to be done whether the deletion failed or not. + _currentVariable = _model->changeVariableName(item->row(), itemText); + apply = true; // if the user is restoring a deleted variable by inserting a name.... } else if (!itemText.empty() && _currentVariable.empty()){ - if (!_model->removeVariable(item->row(), true) ) { - // marking a variable as deleted failed, resync UI - apply = true; - } else { - _model->changeVariableName(item->row(), itemText); - // now that we know that the variable was deleted - applyModel(); - } - + _model->removeVariable(item->row(), false); + // these things need to be done whether the restoration failed or not. + _currentVariable =_model->changeVariableName(item->row(), itemText); + apply = true; + } else if (itemText != _currentVariable){ auto ret = _model->changeVariableName(item->row(), itemText); @@ -464,11 +457,18 @@ void VariableDialog::onContainersTableUpdated() // are they editing an existing container name? } else if (ui->containersTable->item(row, 0)){ - _currentContainer = ui->containersTable->item(row,0)->text().toStdString(); - - if (_currentContainer != _model->changeContainerName(row, ui->containersTable->item(row,0)->text().toStdString())){ - applyModel(); - } + SCP_string newName = ui->containersTable->item(row,0)->text().toStdString(); + + // Restoring a deleted container? + if (_currentContainer.empty()){ + _model->removeContainer(row, false); + // Removing a container? + } else if (newName.empty()) { + _model->removeContainer(row, true); + } + + _currentContainer = _model->changeContainerName(row, newName); + applyModel(); } } @@ -1262,7 +1262,7 @@ void VariableDialog::applyModel() } // check if this is the current variable. - if (selectedRow < 0 && !_currentContainer.empty() && containers[x][0] == _currentContainer){ + if (selectedRow < 0 && containers[x][0] == _currentContainer){ selectedRow = x; } @@ -1284,6 +1284,14 @@ void VariableDialog::applyModel() // do we need to switch the delete button to a restore button? if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "Deleted") { ui->deleteContainerButton->setText("Restore"); + + // We can't restore empty container names. + if (ui->containersTable->item(selectedRow, 0) && ui->containersTable->item(selectedRow, 0)->text().toStdString().empty()){ + ui->deleteContainerButton->setEnabled(false); + } else { + ui->deleteContainerButton->setEnabled(true); + } + } else { ui->deleteContainerButton->setText("Delete"); } @@ -1373,6 +1381,14 @@ void VariableDialog::updateVariableOptions() // do we need to switch the delete button to a restore button? if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Deleted"){ ui->deleteVariableButton->setText("Restore"); + + // We can't restore empty variable names. + if (ui->variablesTable->item(row, 0) && ui->variablesTable->item(row, 0)->text().toStdString().empty()){ + ui->deleteVariableButton->setEnabled(false); + } else { + ui->deleteVariableButton->setEnabled(true); + } + } else { ui->deleteVariableButton->setText("Delete"); } @@ -1551,14 +1567,16 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->swapKeysAndValuesButton->setEnabled(false); - + + int x; // with string contents if (_model->getContainerValueType(row)){ - auto strings = _model->getStringValues(row); + auto& strings = _model->getStringValues(row); + int containerItemsRow = -1; ui->containerContentsTable->setRowCount(static_cast(strings.size()) + 1); - int x; + for (x = 0; x < static_cast(strings.size()); ++x){ if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(strings[x].c_str()); @@ -1568,7 +1586,7 @@ void VariableDialog::updateContainerDataOptions(bool list) } // set selected and enable shifting functions - if (strings[x] == _currentContainerItemCol1){ + if (containerItemsRow < 0 && strings[x] == _currentContainerItemCol1){ ui->containerContentsTable->clearSelection(); ui->containerContentsTable->item(x,0)->setSelected(true); @@ -1593,28 +1611,11 @@ void VariableDialog::updateContainerDataOptions(bool list) } } - if (ui->containerContentsTable->item(x, 0)){ - ui->containerContentsTable->item(x, 0)->setText("Add item ..."); - } else { - QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); - ui->containerContentsTable->setItem(x, 0, item); - } - - if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); - } else { - QTableWidgetItem* item = new QTableWidgetItem(""); - item->setFlags(item->flags() & ~Qt::ItemIsEditable); - ui->containerContentsTable->setItem(x, 1, item); - } - // list with number contents } else { - auto numbers = _model->getNumberValues(row); + auto& numbers = _model->getNumberValues(row); ui->containerContentsTable->setRowCount(static_cast(numbers.size()) + 1); - int x; for (x = 0; x < static_cast(numbers.size()); ++x){ if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(std::to_string(numbers[x]).c_str()); @@ -1633,23 +1634,24 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 1, item); } } + } - if (ui->containerContentsTable->item(x, 0)){ - ui->containerContentsTable->item(x, 0)->setText("Add item ..."); - } else { - QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); - ui->containerContentsTable->setItem(x, 0, item); - } - - if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText(""); - ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); - } else { - QTableWidgetItem* item = new QTableWidgetItem(""); - item->setFlags(item->flags() & ~Qt::ItemIsEditable); - ui->containerContentsTable->setItem(x, 1, item); - } + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText("Add item ..."); + ui->containerContentsTable->item(x, 0)->setFlags(ui->containerContentsTable->item(x, 0)->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 0, item); + } + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() & ~Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() & ~Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } // or it could be a map container @@ -1667,7 +1669,8 @@ void VariableDialog::updateContainerDataOptions(bool list) // keys I didn't bother to make separate. Should have done the same with values. auto& keys = _model->getMapKeys(row); - + + int x; // string valued map. if (_model->getContainerValueType(row)){ auto& strings = _model->getStringValues(row); @@ -1675,7 +1678,6 @@ void VariableDialog::updateContainerDataOptions(bool list) // use the map as the size because map containers are only as good as their keys anyway. ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); - int x; for (x = 0; x < static_cast(keys.size()); ++x){ if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); @@ -1701,7 +1703,6 @@ void VariableDialog::updateContainerDataOptions(bool list) auto& numbers = _model->getNumberValues(row); ui->containerContentsTable->setRowCount(static_cast(keys.size()) + 1); - int x; for (x = 0; x < static_cast(keys.size()); ++x){ if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText(keys[x].c_str()); @@ -1721,22 +1722,22 @@ void VariableDialog::updateContainerDataOptions(bool list) } } } + } - if (ui->containerContentsTable->item(x, 0)){ - ui->containerContentsTable->item(x, 0)->setText("Add item ..."); - } else { - QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); - ui->containerContentsTable->setItem(x, 0, item); - } + if (ui->containerContentsTable->item(x, 0)){ + ui->containerContentsTable->item(x, 0)->setText("Add item ..."); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + ui->containerContentsTable->setItem(x, 0, item); + } - if (ui->containerContentsTable->item(x, 1)){ - ui->containerContentsTable->item(x, 1)->setText("Add item ..."); - ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); - } else { - QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); - item->setFlags(item->flags() | Qt::ItemIsEditable); - ui->containerContentsTable->setItem(x, 1, item); - } + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText("Add item ..."); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); } } } From bc5f986d7609211300cc70c697926c7bd8a51347 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 10 May 2024 22:18:54 -0400 Subject: [PATCH 121/153] Bug fixes from testing --- .../mission/dialogs/VariableDialogModel.cpp | 7 +++- qtfred/src/ui/dialogs/VariableDialog.cpp | 32 ++++++++++++++++++- qtfred/ui/VariableDialog.ui | 4 +-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 5ba9561fcff..55a60ff3fb1 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -751,6 +751,8 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) ++current; } + container->stringKeys = string; + return container->stringKeys; } // filter out current keys @@ -759,6 +761,9 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) key = trimIntegerString(key); } + container->stringKeys = string; + return container->stringKeys; + // cancel the operation case QMessageBox::HelpRole: return !string; @@ -1259,7 +1264,7 @@ SCP_string VariableDialogModel::copyListItem(int containerIndex, int index) { auto container = lookupContainer(containerIndex); - if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (!container->string && index >= static_cast(container->numberValues.size()))){ return ""; } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 09a153f3aa0..66f01db9565 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1110,7 +1110,8 @@ void VariableDialog::onShiftItemUpButtonPressed() int itemRow = getCurrentContainerItemRow(); - if (itemRow < 0){ + // item row being 0 is bad here since we're shifting up. + if (itemRow < 1){ applyModel(); return; } @@ -1614,6 +1615,7 @@ void VariableDialog::updateContainerDataOptions(bool list) // list with number contents } else { auto& numbers = _model->getNumberValues(row); + int containerItemsRow = -1; ui->containerContentsTable->setRowCount(static_cast(numbers.size()) + 1); for (x = 0; x < static_cast(numbers.size()); ++x){ @@ -1624,6 +1626,32 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setItem(x, 0, item); } + // set selected and enable shifting functions + if (containerItemsRow < 0 ){ + + SCP_string temp; + + if (numbers[x] == 0){ + temp = "0"; + } else { + sprintf(temp, "%i", numbers[x]); + } + + if (temp == _currentContainerItemCol1){ + ui->containerContentsTable->clearSelection(); + ui->containerContentsTable->item(x,0)->setSelected(true); + + // more than one item and not already at the top of the list. + if (!(x > 0 && x < static_cast(numbers.size()))){ + ui->shiftItemUpButton->setEnabled(false); + } + + if (!(x > -1 && x < static_cast(numbers.size()) - 1)){ + ui->shiftItemDownButton->setEnabled(false); + } + } + } + // empty out the second column as it's not needed in list mode if (ui->containerContentsTable->item(x, 1)){ ui->containerContentsTable->item(x, 1)->setText(""); @@ -1726,8 +1754,10 @@ void VariableDialog::updateContainerDataOptions(bool list) if (ui->containerContentsTable->item(x, 0)){ ui->containerContentsTable->item(x, 0)->setText("Add item ..."); + ui->containerContentsTable->item(x, 0)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); } else { QTableWidgetItem* item = new QTableWidgetItem("Add item ..."); + item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 0, item); } diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 0cc996e665f..1eaaa34c35b 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -235,7 +235,7 @@ 10 210 631 - 221 + 211 @@ -439,7 +439,7 @@ 650 210 191 - 221 + 211 From cd3464d331055b88b6001c471e1591c187ad00dd Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 10 May 2024 22:52:56 -0400 Subject: [PATCH 122/153] Make sure string items can be deleted --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 55a60ff3fb1..dbd275980d3 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1319,7 +1319,7 @@ bool VariableDialogModel::removeListItem(int containerIndex, int index) { auto container = lookupContainer(containerIndex); - if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (container->string && index >= static_cast(container->numberValues.size()))){ + if (!container || index < 0 || (container->string && index >= static_cast(container->stringValues.size())) || (!container->string && index >= static_cast(container->numberValues.size()))){ return false; } From e66803af09014321cf96af6a2eb99b182d85eb4b Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 10 May 2024 23:17:54 -0400 Subject: [PATCH 123/153] Further Bug fixes based on testing --- .../mission/dialogs/VariableDialogModel.cpp | 24 ++++++++----------- .../src/mission/dialogs/VariableDialogModel.h | 2 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 21 ++++++++-------- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index dbd275980d3..84937f5a6be 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1550,23 +1550,21 @@ bool VariableDialogModel::removeMapItem(int index, int itemIndex) return true; } -SCP_string VariableDialogModel::changeMapItemKey(int index, SCP_string oldKey, SCP_string newKey) +SCP_string VariableDialogModel::changeMapItemKey(int index, int keyRow, SCP_string newKey) { auto container = lookupContainer(index); - if (!container){ + if (!container || container->list){ return ""; } - for (auto& key : container->keys){ - if (key == oldKey) { - key = newKey; - return newKey; - } + if (container->stringKeys){ + container->keys[keyRow] = newKey; + } else { + container->keys[keyRow] = trimIntegerString(newKey); } - // Failure - return oldKey; + return container->keys[keyRow]; } SCP_string VariableDialogModel::changeMapItemStringValue(int index, int itemIndex, SCP_string newValue) @@ -2004,12 +2002,10 @@ SCP_string VariableDialogModel::trimIntegerString(SCP_string source) // So down here, we can still return the right overflow values if stol derped out. Since we've already cleaned out non-digits, // checking for length *really should* allow us to know if something overflowed catch (...){ - if (ret.size() > 9){ - if (ret[0] == '-'){ - return "-2147483648"; - } else { + if (ret.size() > 10 && ret[0] == '-'){ + return "-2147483648"; + } else if (ret.size() > 9) { return "2147483647"; - } } // emergency return value diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 50a2d1dea8d..95968e84252 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -113,7 +113,7 @@ class VariableDialogModel : public AbstractDialogModel { void shiftListItemUp(int containerIndex, int itemIndex); void shiftListItemDown(int containerIndex, int itemIndex); - SCP_string changeMapItemKey(int index, SCP_string oldKey, SCP_string newKey); + SCP_string changeMapItemKey(int index, int keyIndex, SCP_string newKey); SCP_string changeMapItemStringValue(int index, int itemIndex, SCP_string newValue); SCP_string changeMapItemNumberValue(int index, int itemIndex, int newValue); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 66f01db9565..8668786feb5 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -575,17 +575,7 @@ void VariableDialog::onContainerContentsTableUpdated() } } else if (newText != _currentContainerItemCol1){ - - if (!_model->getContainerKeyType(containerRow)){ - - if (!_model->getContainerKeyType(containerRow)){ - newText = _model->trimIntegerString(newText); - } - - // TODO! Write a key change function so you can put something here. - - } - + _model->changeMapItemKey(containerRow, row, newText); return; } } @@ -1748,6 +1738,15 @@ void VariableDialog::updateContainerDataOptions(bool list) item->setFlags(item->flags() | Qt::ItemIsEditable); ui->containerContentsTable->setItem(x, 1, item); } + } else { + if (ui->containerContentsTable->item(x, 1)){ + ui->containerContentsTable->item(x, 1)->setText(""); + ui->containerContentsTable->item(x, 1)->setFlags(ui->containerContentsTable->item(x, 1)->flags() | Qt::ItemIsEditable); + } else { + QTableWidgetItem* item = new QTableWidgetItem(""); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->containerContentsTable->setItem(x, 1, item); + } } } } From d557a6eff4d8ded84c55ed2fe45c4214d72ef90c Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 11 May 2024 00:19:18 -0400 Subject: [PATCH 124/153] More Bug fixes --- .../mission/dialogs/VariableDialogModel.cpp | 11 +++++-- qtfred/src/ui/dialogs/VariableDialog.cpp | 29 +++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 84937f5a6be..175f169cef5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1210,7 +1210,7 @@ std::pair VariableDialogModel::addMapItem(int index, SCP return ret; } - bool conflict; + bool conflict = false; int count = 0; SCP_string newKey; @@ -1234,7 +1234,11 @@ std::pair VariableDialogModel::addMapItem(int index, SCP ++count; } while (conflict && count < 101); } else { - newKey = key; + if (container->stringKeys){ + newKey = key; + } else { + newKey = trimIntegerString(key); + } } if (conflict) { @@ -1248,7 +1252,8 @@ std::pair VariableDialogModel::addMapItem(int index, SCP ret.second = value; } else { try { - container->numberValues.push_back(std::stoi(value)); + ret.second = trimIntegerString(value); + container->numberValues.push_back(std::stoi(ret.second)); ret.second = value; } catch (...) { diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 8668786feb5..767389fe78f 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -521,13 +521,13 @@ void VariableDialog::onContainerContentsTableUpdated() if (_model->getContainerListOrMap(containerRow)) { _model->addListItem(containerRow, newString); - } else { - _model->addMapItem(containerRow, newString, ""); } - _currentContainer = newString; + _currentContainerItemCol1 = newString; + _currentContainerItemCol2 = ""; + applyModel(); return; } @@ -535,9 +535,24 @@ void VariableDialog::onContainerContentsTableUpdated() } if (!ui->containerContentsTable->item(row, 1)) { - // At this point there's nothing else we can do and something may be off, anyway. - applyModel(); - return; + newString = ui->containerContentsTable->item(row, 1)->text().toStdString(); + + if (!newString.empty() && newString != "Add item ..."){ + + // This should not be a list container. + if (_model->getContainerListOrMap(containerRow)) { + applyModel(); + return; + } else { + _model->addMapItem(containerRow, "", newString); + } + + _currentContainerItemCol1 = newString; + _currentContainerItemCol2 = ""; + + applyModel(); + return; + } } // if we got here, we know that the second cell is valid. @@ -571,11 +586,13 @@ void VariableDialog::onContainerContentsTableUpdated() // Finally change the list item _currentContainerItemCol1 = _model->changeListItem(containerRow, row, newText); + applyModel(); return; } } else if (newText != _currentContainerItemCol1){ _model->changeMapItemKey(containerRow, row, newText); + applyModel(); return; } } From 20f992fe54515ecefa0d4f83af79760592177710 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Sat, 11 May 2024 00:43:36 -0400 Subject: [PATCH 125/153] Fix Not being able to add map items by value --- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 767389fe78f..969195128bf 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -502,6 +502,8 @@ void VariableDialog::onContainerContentsTableUpdated() int containerRow = getCurrentContainerRow(); int row = getCurrentContainerItemRow(); + + // just in case something is goofy, return if (row < 0 || containerRow < 0){ applyModel(); @@ -1822,7 +1824,7 @@ int VariableDialog::getCurrentContainerItemRow() // yes, selected items returns a list, but we really should only have one item because multiselect will be off. for (const auto& item : items) { - if (item && item->column() == 0 && item->text().toStdString() != "Add item ...") { + if (item && ((item->column() == 0 && item->text().toStdString() != "Add item ...") || (item->column() == 1 && item->text().toStdString() != "Add item ..."))) { return item->row(); } } From df77615473dbbf687080f649cf25b12d61699b7a Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 12 May 2024 01:42:36 -0400 Subject: [PATCH 126/153] Various Fixes Based on Testing --- .../mission/dialogs/VariableDialogModel.cpp | 51 +++++++++++-------- qtfred/src/ui/dialogs/VariableDialog.cpp | 39 ++++---------- qtfred/ui/VariableDialog.ui | 46 ++++++++--------- 3 files changed, 65 insertions(+), 71 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 175f169cef5..1e06687bef5 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -551,7 +551,7 @@ bool VariableDialogModel::removeVariable(int index, bool toDelete) return variable->deleted; } - // adjust to the user's actions. If they are deleting variable after variable, allow after a while. + // adjust to the user's actions. If they are deleting variable after variable, allow after a while. No one expects Cybog the Careless ++_deleteWarningCount; } @@ -719,7 +719,7 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) } catch (...) { quickConvert = false; - nprintf(("Cyborg", "This is Cyborg. Long story short, I don't need this variable, but c++ thinks I do. Last good number on conversion was: %i\n", test)); + nprintf(("Cyborg", "This is Cyborg. Long story short, I don't need this variable, but c++ and its linters think I do. So who knows, maybe you can use this. Last good number on conversion was: %i\n", test)); } } @@ -731,15 +731,16 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) // If we couldn't convert easily, then we need some input from the user // now ask about data - QMessageBox msgBoxListToMapRetainData; - msgBoxListToMapRetainData.setWindowTitle("Key Type Conversion"); - msgBoxListToMapRetainData.setText("Fred could not convert all string keys to numbers automatically. Would you like to use default keys, filter out integers from the current keys or cancel the operation?"); - msgBoxListToMapRetainData.setInformativeText("Current keys will be overwritten unless you cancel and cannot be restored. Filtering will keep *any* numerical digits and starting \"-\" in the string. Filtering also does not prevent duplicate keys."); - msgBoxListToMapRetainData.addButton("Use Default Keys", QMessageBox::ActionRole); // No, these categories don't make sense, but QT makes underlying assumptions about where each button will be - msgBoxListToMapRetainData.addButton("Filter Current Keys ", QMessageBox::RejectRole); - auto defaultButton = msgBoxListToMapRetainData.addButton("Cancel", QMessageBox::HelpRole); - msgBoxListToMapRetainData.setDefaultButton(defaultButton); - auto ret = msgBoxListToMapRetainData.exec(); + QMessageBox msgBoxContainerKeyTypeSwitch; + msgBoxContainerKeyTypeSwitch.setWindowTitle("Key Type Conversion"); + msgBoxContainerKeyTypeSwitch.setText("Fred could not convert all string keys to numbers automatically. Would you like to use default keys, filter out integers from the current keys or cancel the operation?"); + msgBoxContainerKeyTypeSwitch.setInformativeText("Current keys will be overwritten unless you cancel and cannot be restored. Filtering will keep *any* numerical digits and starting \"-\" in the string. Filtering also does not prevent duplicate keys."); + msgBoxContainerKeyTypeSwitch.addButton("Use Default Keys", QMessageBox::ActionRole); // No, these categories don't make sense, but QT makes underlying assumptions about where each button will be + msgBoxContainerKeyTypeSwitch.addButton("Filter Current Keys ", QMessageBox::RejectRole); + auto defaultButton = msgBoxContainerKeyTypeSwitch.addButton("Cancel", QMessageBox::HelpRole); + msgBoxContainerKeyTypeSwitch.setDefaultButton(defaultButton); + msgBoxContainerKeyTypeSwitch.exec(); + auto ret = msgBoxContainerKeyTypeSwitch.buttonRole(msgBoxContainerKeyTypeSwitch.clickedButton()); switch(ret){ // just use default keys @@ -846,7 +847,8 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) msgBoxListToMapRetainData.addButton("Purge", QMessageBox::ApplyRole); auto defaultButton = msgBoxListToMapRetainData.addButton("Cancel", QMessageBox::HelpRole); msgBoxListToMapRetainData.setDefaultButton(defaultButton); - ret = msgBoxListToMapRetainData.exec(); + msgBoxListToMapRetainData.exec(); + ret = msgBoxListToMapRetainData.buttonRole(msgBoxListToMapRetainData.clickedButton()); switch (ret) { case QMessageBox::RejectRole: @@ -869,8 +871,10 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) } container->numberValues.clear(); + container->numberValues.resize(container->keys.size(), 0); container->list = list; return container->list; + break; case QMessageBox::ActionRole: { @@ -896,12 +900,12 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) container->numberValues.resize(container->keys.size(), 0); } - } - else { + } else { // here currentSize must be greater than the key size, because we already dealt with equal size. // So let's add a few keys to make them level. + int keyIndex = 0; + while (currentSize > container->keys.size()) { - int keyIndex = 0; SCP_string newKey; if (container->stringKeys) { @@ -923,7 +927,9 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) container->list = list; return container->list; } - case QMessageBox::ApplyRole: + break; + + case QMessageBox::ApplyRole: container->list = list; container->stringValues.clear(); @@ -1190,12 +1196,13 @@ std::pair VariableDialogModel::addMapItem(int index) if (container->string){ ret.second = ""; - container->stringValues.push_back(""); - } else { + } else { ret.second = "0"; - container->numberValues.push_back(0); } + container->stringValues.push_back(""); + container->numberValues.push_back(0); + return ret; } @@ -1250,6 +1257,8 @@ std::pair VariableDialogModel::addMapItem(int index, SCP if (container->string) { ret.second = value; + container->stringValues.push_back(ret.second); + container->numberValues.push_back(0); } else { try { ret.second = trimIntegerString(value); @@ -1260,6 +1269,8 @@ std::pair VariableDialogModel::addMapItem(int index, SCP ret.second = "0"; container->numberValues.push_back(0); } + + container->stringValues.emplace_back(""); } return ret; @@ -1308,7 +1319,7 @@ SCP_string VariableDialogModel::changeListItem(int containerIndex, int index, SC } try{ - *listItem = std::stoi(newString); + *listItem = std::stoi(trimIntegerString(newString)); } catch(...){ SCP_string temp; diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 969195128bf..577a47feac8 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -217,16 +217,16 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) ui->variablesTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->variablesTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); ui->variablesTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); - ui->variablesTable->setColumnWidth(0, 190); - ui->variablesTable->setColumnWidth(1, 190); - ui->variablesTable->setColumnWidth(2, 120); + ui->variablesTable->setColumnWidth(0, 200); + ui->variablesTable->setColumnWidth(1, 200); + ui->variablesTable->setColumnWidth(2, 130); ui->containersTable->setColumnCount(3); ui->containersTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); ui->containersTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Types")); ui->containersTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Notes")); ui->containersTable->setColumnWidth(0, 190); - ui->containersTable->setColumnWidth(1, 190); + ui->containersTable->setColumnWidth(1, 220); ui->containersTable->setColumnWidth(2, 120); ui->containerContentsTable->setColumnCount(2); @@ -234,8 +234,8 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Default to list ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - ui->containerContentsTable->setColumnWidth(0, 225); - ui->containerContentsTable->setColumnWidth(1, 225); + ui->containerContentsTable->setColumnWidth(0, 245); + ui->containerContentsTable->setColumnWidth(1, 245); // set radio buttons to manually toggled, as some of these have the same parent widgets and some don't // and I don't mind just manually toggling them. @@ -513,7 +513,6 @@ void VariableDialog::onContainerContentsTableUpdated() // Are they adding a new item? if (row == ui->containerContentsTable->rowCount() - 1){ - bool newItemCreated = false; SCP_string newString; if (ui->containerContentsTable->item(row, 0)) { @@ -536,7 +535,7 @@ void VariableDialog::onContainerContentsTableUpdated() } - if (!ui->containerContentsTable->item(row, 1)) { + if (ui->containerContentsTable->item(row, 1)) { newString = ui->containerContentsTable->item(row, 1)->text().toStdString(); if (!newString.empty() && newString != "Add item ..."){ @@ -545,34 +544,18 @@ void VariableDialog::onContainerContentsTableUpdated() if (_model->getContainerListOrMap(containerRow)) { applyModel(); return; - } else { - _model->addMapItem(containerRow, "", newString); } + + auto ret = _model->addMapItem(containerRow, "", newString); - _currentContainerItemCol1 = newString; - _currentContainerItemCol2 = ""; + _currentContainerItemCol1 = ret.first; + _currentContainerItemCol2 = ret.second; applyModel(); return; } } - // if we got here, we know that the second cell is valid. - newString = ui->containerContentsTable->item(row, 0)->text().toStdString(); - - // But we can only create a new map item here. Ignore if this container is a list. - if (!newString.empty() && newString.substr(0, 10) != "Add item ..."){ - if (!_model->getContainerListOrMap(containerRow)) { - auto ret = _model->addMapItem(containerRow, "", newString); - _currentContainerItemCol1 = ret.first; - _currentContainerItemCol2 = ret.second; - } - } - - // nothing else to determine at this point. - applyModel(); - return; - // are they editing an existing container item column 1? } else if (ui->containerContentsTable->item(row, 0)){ SCP_string newText = ui->containerContentsTable->item(row, 0)->text().toStdString(); diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 1eaaa34c35b..2545a683016 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -42,7 +42,7 @@ - 550 + 580 120 81 101 @@ -83,7 +83,7 @@ 10 30 - 521 + 551 191 @@ -121,7 +121,7 @@ - 650 + 680 20 191 201 @@ -181,7 +181,7 @@ - 550 + 580 30 82 86 @@ -234,7 +234,7 @@ 10 210 - 631 + 661 211 @@ -246,7 +246,7 @@ 10 30 - 471 + 511 171 @@ -278,7 +278,7 @@ - 520 + 550 30 106 175 @@ -338,7 +338,7 @@ - 550 + 580 30 82 85 @@ -376,7 +376,7 @@ - 650 + 680 20 191 181 @@ -436,7 +436,7 @@ - 650 + 680 210 191 211 @@ -481,23 +481,23 @@ - + - Data Type + Key Type - + - + String - + Number @@ -506,23 +506,23 @@ - + - Key Type + Data Type - + - + String - + Number @@ -538,7 +538,7 @@ 10 30 - 521 + 551 171 @@ -576,7 +576,7 @@ - 550 + 580 140 81 20 @@ -592,7 +592,7 @@ - 540 + 570 160 101 24 From e855fc81e9cd646f8bf159f1faeefc5e84625336 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sun, 12 May 2024 01:50:45 -0400 Subject: [PATCH 127/153] Check for conversion availability with same algo --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 1e06687bef5..7c1f87bc8c3 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -712,15 +712,12 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) if (container->stringKeys) { // Ok, this is the complicated type. First check if all keys can just quickly be transferred to numbers. bool quickConvert = true; - int test; + for (auto& key : container->keys) { - try { - test = std::stoi(key); - } - catch (...) { - quickConvert = false; - nprintf(("Cyborg", "This is Cyborg. Long story short, I don't need this variable, but c++ and its linters think I do. So who knows, maybe you can use this. Last good number on conversion was: %i\n", test)); - } + if(key != trimIntegerString(key)){ + quickConvert = false; + break; + } } // Don't even notify the user. Switching back is exceedingly easy. From e502cdfe76bb81560eff5daa67d474e0a677b3d3 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 13 May 2024 09:48:40 -0400 Subject: [PATCH 128/153] Finish the validation function --- .../mission/dialogs/VariableDialogModel.cpp | 48 ++++++++++++++++++- qtfred/src/ui/dialogs/VariableDialog.cpp | 1 - 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7c1f87bc8c3..fe0436659a4 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -27,9 +27,15 @@ bool VariableDialogModel::checkValidModel() std::unordered_set namesTaken; std::unordered_set duplicates; + int emptyVarNames = 0; + for (const auto& variable : _variableItems){ if (!namesTaken.insert(variable.name).second) { duplicates.insert(variable.name); + } + + if (variable.name.empty()){ + ++emptyVarNames; } } @@ -45,27 +51,43 @@ bool VariableDialogModel::checkValidModel() } } - sprintf(messageOut, "There are %zu duplicate variables:\n", duplicates.size()); + sprintf(messageOut, "There are %zu duplicate variable names:\n", duplicates.size()); messageOut += messageBuffer + "\n\n"; } duplicates.clear(); std::unordered_set namesTakenContainer; SCP_vector duplicateKeys; + int emptyContainerNames = 0; + int emptyKeys = 0; + int notNumberKeys = 0; for (const auto& container : _containerItems){ if (!namesTakenContainer.insert(container.name).second) { duplicates.insert(container.name); } + if (container.name.empty()){ + ++emptyContainerNames; + } + if (!container.list){ std::unordered_set keysTakenContainer; for (const auto& key : container.keys){ if (!keysTakenContainer.insert(key).second) { - SCP_string temp = key + "in map" + container.name + ", "; + SCP_string temp = "\"" + key + "\" in map \"" + container.name + "\", "; duplicateKeys.push_back(temp); } + + if (key.empty()){ + ++emptyKeys; + } else if (!container->stringKeys){ + if (key != trimNumberString(key)){ + ++notNumberKeys; + } + } + } } } } @@ -100,6 +122,28 @@ bool VariableDialogModel::checkValidModel() messageOut += messageBuffer + "\n"; } + if (emptyVarNames > 0){ + messageBuffer.clear(); + sprintf(messageBuffer, "There are %i empty variable names which must be populated.\n", emptyVarNames); + + messageOut += messageBuffer; + } + + if (emptyContainerNames > 0){ + messageBuffer.clear(); + sprintf(messageBuffer, "There are %i empty container names which must be populated.\n", emptyContainerNames); + + messageOut += messageBuffer; + } + + if (emptyKeys > 0){ + messageBuffer.clear(); + sprintf(messageBuffer, "There are %i empty keys which must be populated.\n", emptyKeys); + + messageOut += messageBuffer; + } + + if (messageOut.empty()){ return true; } else { diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 577a47feac8..0cc7de7fde3 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -491,7 +491,6 @@ void VariableDialog::onContainersSelectionChanged() applyModel(); } -// TODO, finish this function void VariableDialog::onContainerContentsTableUpdated() { if (_applyingModel){ From b053131e7124b0dccae8efbc3f19d81ce25c89a5 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 13 May 2024 10:18:29 -0400 Subject: [PATCH 129/153] Connect the x with prereject instead of reject. Because the x is not connected to the cancel button, it has to be connected to preReject first. --- qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 0cc7de7fde3..d7cf8e48f5d 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -26,7 +26,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Reject if the user wants to. connect(ui->OkCancelButtons, &QDialogButtonBox::rejected, this, &VariableDialog::preReject); connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); - connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::reject); + connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::preReject); connect(ui->variablesTable, &QTableWidget::itemChanged, From 455d2c9681516e2f3da4959653a344a9618069c4 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 13 May 2024 20:57:39 -0400 Subject: [PATCH 130/153] Add to Apply() And start safeguarding changes that would not be safe to make without cleaning references. --- .../mission/dialogs/VariableDialogModel.cpp | 79 +++++++++++++++---- .../src/mission/dialogs/VariableDialogModel.h | 3 + qtfred/src/ui/dialogs/VariableDialog.cpp | 2 +- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index fe0436659a4..45bfca5956e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -83,10 +83,10 @@ bool VariableDialogModel::checkValidModel() if (key.empty()){ ++emptyKeys; } else if (!container->stringKeys){ - if (key != trimNumberString(key)){ - ++notNumberKeys; - } + if (key != trimNumberString(key)){ + ++notNumberKeys; } + } } } @@ -143,6 +143,10 @@ bool VariableDialogModel::checkValidModel() messageOut += messageBuffer; } + if (_variableItems.size() >= MAX_SEXP_VARIABLES){ + messageOut += "There are more than the max of 250 variables.\n" + } + if (messageOut.empty()){ return true; @@ -176,10 +180,7 @@ bool VariableDialogModel::apply() for (int i = 0; i < MAX_SEXP_VARIABLES; ++i) { if (!stricmp(Sexp_variables[i].variable_name, variable.originalName.c_str())){ if (variable.deleted) { - memset(Sexp_variables[i].variable_name, 0, NAME_LENGTH); - memset(Sexp_variables[i].text, 0, NAME_LENGTH); - Sexp_variables[i].type = 0; - + sexp_variable_delete(i); deletedVariables.insert(variable.originalName); } else { if (variable.name != variable.originalName) { @@ -202,10 +203,25 @@ bool VariableDialogModel::apply() break; } } + } else { + if (variable.string){ + variable.flags |= SEXP_VARIABLE_STRING; + sexp_add_variable(variable.stringValue.c_str(), variable.name.c_str(), variable.flags, -1); + } else { + variable.flags |= SEXP_VARIABLE_NUMBER; + sexp_add_variable(std::to_string(variable.numberValue).c_str(), variable.name.c_str(), variable.flags, -1); + } } + // just in case if (!found) { - // TODO! Lookup how FRED adds new variables. (look for an empty slot maybe?) + if (variable.string){ + variable.flags |= SEXP_VARIABLE_STRING; + sexp_add_variable(variable.stringValue.c_str(), variable.name.c_str(), variable.flags, -1); + } else { + variable.flags |= SEXP_VARIABLE_NUMBER; + sexp_add_variable(std::to_string(variable.numberValue).c_str(), variable.name.c_str(), variable.flags, -1); + } } } @@ -355,6 +371,10 @@ bool VariableDialogModel::setVariableType(int index, bool string) return !string; } + if (!safeToAlterVariable(index)){ + return variable->string; + } + // Here we change the variable type! // this variable is currently a string if (variable->string) { @@ -459,7 +479,11 @@ SCP_string VariableDialogModel::setVariableStringValue(int index, SCP_string val if (!variable || !variable->string){ return ""; } - + + if (!safeToAlterVariable(index)){ + return variable->stringValue; + } + variable->stringValue = value; return value; } @@ -473,6 +497,10 @@ int VariableDialogModel::setVariableNumberValue(int index, int value) return 0; } + if (!safeToAlterVariable(index)){ + return variable->numberValue; + } + variable->numberValue = value; return value; @@ -484,13 +512,16 @@ SCP_string VariableDialogModel::addNewVariable() int count = 1; SCP_string name; + if (atMaxVariables()){ + return ""; + } + do { name = ""; sprintf(name, "newVar%i", count); variable = lookupVariableByName(name); ++count; - } while (variable != nullptr && count < 51); - + } while (variable != nullptr && count < MAX_SEXP_VARIABLES); if (variable){ return ""; @@ -501,9 +532,14 @@ SCP_string VariableDialogModel::addNewVariable() return name; } -SCP_string VariableDialogModel::addNewVariable(SCP_string nameIn){ +SCP_string VariableDialogModel::addNewVariable(SCP_string nameIn) +{ + if (atMaxVariables()){ + return ""; + } + _variableItems.emplace_back(); - _variableItems.back().name = nameIn; + _variableItems.back().name.substr(0, TOKEN_LENGTH - 1) = nameIn; return _variableItems.back().name; } @@ -516,6 +552,10 @@ SCP_string VariableDialogModel::changeVariableName(int index, SCP_string newName return ""; } + if (!safeToAlterVariable(index)){ + return variable->name; + } + // Truncate name if needed if (newName.length() >= TOKEN_LENGTH){ newName = newName.substr(0, TOKEN_LENGTH - 1); @@ -535,6 +575,10 @@ SCP_string VariableDialogModel::copyVariable(int index) return ""; } + if (atMaxVariables()){ + return ""; + } + int count = 1; variableInfo* variableSearch; SCP_string newName; @@ -580,7 +624,7 @@ bool VariableDialogModel::removeVariable(int index, bool toDelete) return false; } - if (variable->deleted == toDelete){ + if (variable->deleted == toDelete || !safeToAlterVariable(index)){ return variable->deleted; } @@ -608,6 +652,9 @@ bool VariableDialogModel::removeVariable(int index, bool toDelete) } } +bool safeToAlterVariable(int /*index*/){ + return true; +} // Container Section @@ -1737,6 +1784,10 @@ void VariableDialogModel::swapKeyAndValues(int index) } } +bool safeToAlterContainer(int /*index*/){ + return true; +} + SCP_string VariableDialogModel::changeMapItemNumberValue(int index, int itemIndex, int newValue) { auto mapItem = lookupContainerNumberItem(index, itemIndex); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 95968e84252..8caba47d53e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -72,6 +72,7 @@ class VariableDialogModel : public AbstractDialogModel { SCP_string copyVariable(int index); // returns whether it succeeded bool removeVariable(int index, bool toDelete); + bool safeToAlterVariable(int index); // Container Section @@ -122,6 +123,8 @@ class VariableDialogModel : public AbstractDialogModel { const SCP_vector& getNumberValues(int index); void swapKeyAndValues(int index); + + bool safeToAlterContainer(int index); const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index d7cf8e48f5d..657d271824f 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -26,7 +26,7 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Reject if the user wants to. connect(ui->OkCancelButtons, &QDialogButtonBox::rejected, this, &VariableDialog::preReject); connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); - connect(this, &QDialog::rejected, _model.get(), &VariableDialogModel::preReject); + connect(this, &QDialog::rejected, this, &VariableDialog::preReject); connect(ui->variablesTable, &QTableWidget::itemChanged, From e7f6fa3c9148bde628bf593ce00200804cdbc6cb Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Mon, 13 May 2024 22:31:30 -0400 Subject: [PATCH 131/153] Upgrade Container Copying --- .../mission/dialogs/VariableDialogModel.cpp | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 45bfca5956e..441f1763781 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -584,7 +584,7 @@ SCP_string VariableDialogModel::copyVariable(int index) SCP_string newName; do { - sprintf(newName, "%i_%s", count, variable->name.substr(0, TOKEN_LENGTH - 4).c_str()); + sprintf(newName, "%s_%i", variable->name.substr(0, TOKEN_LENGTH - 4).c_str(), count); variableSearch = lookupVariableByName(newName); // open slot found! @@ -609,7 +609,7 @@ SCP_string VariableDialogModel::copyVariable(int index) } ++count; - } while (variableSearch != nullptr && count < 100); + } while (variableSearch != nullptr && count < MAX_SEXP_VARIABLES); return ""; } @@ -716,7 +716,7 @@ bool VariableDialogModel::setContainerValueType(int index, bool type) return true; } - if (container->string == type){ + if (container->string == type || !safeToAlterContainer(index)){ return container->string; } @@ -796,7 +796,7 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) return false; } - if (container->stringKeys == string){ + if (container->stringKeys == string || !safeToAlterContainer(index)){ return container->stringKeys; } @@ -818,7 +818,7 @@ bool VariableDialogModel::setContainerKeyType(int index, bool string) } // If we couldn't convert easily, then we need some input from the user - // now ask about data + // now ask about data QMessageBox msgBoxContainerKeyTypeSwitch; msgBoxContainerKeyTypeSwitch.setWindowTitle("Key Type Conversion"); msgBoxContainerKeyTypeSwitch.setText("Fred could not convert all string keys to numbers automatically. Would you like to use default keys, filter out integers from the current keys or cancel the operation?"); @@ -879,8 +879,8 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) return !list; } - if (container->list == list){ - return list; + if (container->list == list || !safeToAlterContainer(index)){ + return container->list; } if (container->list) { @@ -1127,7 +1127,7 @@ SCP_string VariableDialogModel::addContainer() SCP_string VariableDialogModel::addContainer(SCP_string nameIn) { _containerItems.emplace_back(); - _containerItems.back().name = nameIn; + _containerItems.back().name = nameIn.substr(0, TOKEN_LENGTH - 1); return _containerItems.back().name; } @@ -1140,9 +1140,25 @@ SCP_string VariableDialogModel::copyContainer(int index) return ""; } - // K.I.S.S. We could guarantee the names be unique, but so can the user, and there will definitely be a lower number of containers + // searching for a duplicate is not that hard. _containerItems.push_back(*container); - _containerItems.back().name = "copy_" + _containerItems.back().name; + container = &_containerItems.back(); + + SCP_string newName; + int count = 0; + + do { + sprintf(newName, "%s_%i", container->name.substr(0, TOKEN_LENGTH - 4).c_str(), count); + auto containerSearch = lookupVariableByName(newName); + + // open slot found! + if (!containerSearch){ + break; + } + ++count; + } + + _containerItems.back().name = newName; _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH - 1); return _containerItems.back().name; } @@ -1152,13 +1168,13 @@ SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newNam auto container = lookupContainer(index); // nothing to change, or invalid entry - if (!container){ + if (!container || !safeToAlterContainer(index)){ return ""; } - // We cannot have two containers with the same name, but we need to check this somewhere else (like on accept attempt). - container->name = newName; - return newName; + // We cannot have two containers with the same name, but we need to check that somewhere else (like on accept attempt). + container->name = newName.substring(0, TOKEN_LENGTH - 1); + return container->name; } bool VariableDialogModel::removeContainer(int index, bool toDelete) @@ -1169,7 +1185,7 @@ bool VariableDialogModel::removeContainer(int index, bool toDelete) return false; } - if (container->deleted == toDelete){ + if (container->deleted == toDelete || !safeToAlterContainer(index)){ return container->deleted; } @@ -1689,7 +1705,7 @@ void VariableDialogModel::swapKeyAndValues(int index) auto container = lookupContainer(index); // bogus cases - if (!container || container->list){ + if (!container || container->list || !safeToAlterContainer(index)){ return; } From c53e6b1487f283c6480b5c79021e8b585e9d788f Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 14 May 2024 00:14:48 -0400 Subject: [PATCH 132/153] Finish Safe to Alter Options in Model Update --- qtfred/src/ui/dialogs/VariableDialog.cpp | 77 +++++++++++++++--------- qtfred/src/ui/dialogs/VariableDialog.h | 6 +- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 657d271824f..ece10c9981c 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -398,7 +398,7 @@ void VariableDialog::onVariablesSelectionChanged() int row = getCurrentVariableRow(); if (row < 0){ - updateVariableOptions(); + updateVariableOptions(false); return; } @@ -482,7 +482,7 @@ void VariableDialog::onContainersSelectionChanged() int row = getCurrentContainerRow(); if (row < 0) { - updateContainerOptions(); + updateContainerOptions(false); return; } @@ -1165,6 +1165,7 @@ void VariableDialog::applyModel() int x = 0, selectedRow = -1; ui->variablesTable->setRowCount(static_cast(variables.size()) + 1); + bool safeToAlter = false; for (x = 0; x < static_cast(variables.size()); ++x){ if (ui->variablesTable->item(x, 0)){ @@ -1180,6 +1181,10 @@ void VariableDialog::applyModel() // there's a deletion. if (selectedRow < 0 && !_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; + + if (_model->!safeToAlterVariable(selectedRow)){ + safeToAlter = true; + } } if (ui->variablesTable->item(x, 1)){ @@ -1237,7 +1242,7 @@ void VariableDialog::applyModel() } } - updateVariableOptions(); + updateVariableOptions(safeToAlter); auto containers = _model->getContainerNames(); ui->containersTable->setRowCount(static_cast(containers.size() + 1)); @@ -1314,21 +1319,25 @@ void VariableDialog::applyModel() ui->containersTable->setItem(x, 2, item); } + bool safeToAlterContainer = false; + if (selectedRow < 0 && ui->containersTable->rowCount() > 1) { if (ui->containersTable->item(0, 0)){ _currentContainer = ui->containersTable->item(0, 0)->text().toStdString(); ui->containersTable->clearSelection(); ui->containersTable->item(0, 0)->setSelected(true); } + } else if (selectedRow > -1){ + safeToAlterContainer = _model->safeToAlterContainer(selectedRow); } // this will update the list/map items. - updateContainerOptions(); + updateContainerOptions(safeToAlterContainer); _applyingModel = false; }; -void VariableDialog::updateVariableOptions() +void VariableDialog::updateVariableOptions(bool safeToAlter) { int row = getCurrentVariableRow(); @@ -1348,21 +1357,23 @@ void VariableDialog::updateVariableOptions() return; } + // options that are always safe ui->copyVariableButton->setEnabled(true); - ui->deleteVariableButton->setEnabled(true); - ui->setVariableAsStringRadio->setEnabled(true); - ui->setVariableAsNumberRadio->setEnabled(true); ui->doNotSaveVariableRadio->setEnabled(true); ui->saveVariableOnMissionCompletedRadio->setEnabled(true); ui->saveVariableOnMissionCloseRadio->setEnabled(true); ui->setVariableAsEternalcheckbox->setEnabled(true); ui->networkVariableCheckbox->setEnabled(true); - // if nothing is selected, but something could be selected, make it so. - if (row < 0 && ui->variablesTable->rowCount() > 1) { - row = 0; - ui->variablesTable->item(row, 0)->setSelected(true); - _currentVariable = ui->variablesTable->item(row, 0)->text().toStdString(); + // options that are only safe if there are no references + if (safeToAlter){ + ui->deleteVariableButton->setEnabled(true); + ui->setVariableAsStringRadio->setEnabled(true); + ui->setVariableAsNumberRadio->setEnabled(true); + } else { + ui->deleteVariableButton->setEnabled(false); + ui->setVariableAsStringRadio->setEnabled(false); + ui->setVariableAsNumberRadio->setEnabled(false); } // start populating values @@ -1372,7 +1383,7 @@ void VariableDialog::updateVariableOptions() // do we need to switch the delete button to a restore button? if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Deleted"){ - ui->deleteVariableButton->setText("Restore"); + ui->deleteVariableButton->setText("Restore"); // We can't restore empty variable names. if (ui->variablesTable->item(row, 0) && ui->variablesTable->item(row, 0)->text().toStdString().empty()){ @@ -1406,7 +1417,7 @@ void VariableDialog::updateVariableOptions() } -void VariableDialog::updateContainerOptions() +void VariableDialog::updateContainerOptions(bool safeToAlter) { int row = getCurrentContainerRow(); @@ -1448,18 +1459,21 @@ void VariableDialog::updateContainerOptions() } else { auto items = ui->containersTable->selectedItems(); + // options that should always be turned on ui->copyContainerButton->setEnabled(true); - ui->deleteContainerButton->setEnabled(true); - ui->setContainerAsStringRadio->setEnabled(true); - ui->setContainerAsNumberRadio->setEnabled(true); ui->doNotSaveContainerRadio->setEnabled(true); ui->saveContainerOnMissionCompletedRadio->setEnabled(true); ui->saveContainerOnMissionCloseRadio->setEnabled(true); ui->setContainerAsEternalCheckbox->setEnabled(true); - ui->setContainerAsMapRadio->setEnabled(true); - ui->setContainerAsListRadio->setEnabled(true); ui->networkContainerCheckbox->setEnabled(true); + // options that require it be safe to alter because the container is not referenced + ui->deleteContainerButton->setEnabled(safeToAlter); + ui->setContainerAsStringRadio->setEnabled(safeToAlter); + ui->setContainerAsNumberRadio->setEnabled(safeToAlter); + ui->setContainerAsMapRadio->setEnabled(safeToAlter); + ui->setContainerAsListRadio->setEnabled(safeToAlter); + if (_model->getContainerValueType(row)){ ui->setContainerAsStringRadio->setChecked(true); ui->setContainerAsNumberRadio->setChecked(false); @@ -1480,15 +1494,15 @@ void VariableDialog::updateContainerOptions() ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); - updateContainerDataOptions(true); + updateContainerDataOptions(true, safeToAlter); } else { ui->setContainerAsListRadio->setChecked(false); ui->setContainerAsMapRadio->setChecked(true); // Enable Key Controls - ui->setContainerKeyAsStringRadio->setEnabled(true); - ui->setContainerKeyAsNumberRadio->setEnabled(true); + ui->setContainerKeyAsStringRadio->setEnabled(safeToAlter); + ui->setContainerKeyAsNumberRadio->setEnabled(safeToAlter); // string keys if (_model->getContainerKeyType(row)){ @@ -1504,7 +1518,7 @@ void VariableDialog::updateContainerOptions() // Don't forget to change headings ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); - updateContainerDataOptions(false); + updateContainerDataOptions(false, safeToAlter); } ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); @@ -1529,7 +1543,7 @@ void VariableDialog::updateContainerOptions() } } -void VariableDialog::updateContainerDataOptions(bool list) +void VariableDialog::updateContainerDataOptions(bool list, bool safeToAlter) { int row = getCurrentContainerRow(); @@ -1553,13 +1567,14 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->addContainerItemButton->setEnabled(true); ui->copyContainerItemButton->setEnabled(true); ui->deleteContainerItemButton->setEnabled(true); - ui->containerContentsTable->setRowCount(0); ui->shiftItemDownButton->setEnabled(true); ui->shiftItemUpButton->setEnabled(true); ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Value")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("")); ui->swapKeysAndValuesButton->setEnabled(false); - + + ui->containerContentsTable->setRowCount(0); + int x; // with string contents @@ -1681,12 +1696,14 @@ void VariableDialog::updateContainerDataOptions(bool list) ui->containerContentsTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Key")); ui->containerContentsTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); - // Enable shift up and down buttons are off in Map mode. + // Enable shift up and down buttons are off in Map mode, because order makes no difference ui->shiftItemUpButton->setEnabled(false); ui->shiftItemDownButton->setEnabled(false); - ui->swapKeysAndValuesButton->setEnabled(true); - // keys I didn't bother to make separate. Should have done the same with values. + // we can swap if it's safe or if the data types match. If the data types *don't* match, then we run into reference issues. + ui->swapKeysAndValuesButton->setEnabled(safeToAlter || _containerItems[row].stringKeys == _containerItems[row].string); + + // keys I didn't bother to make separate. Should have done the same with values, ah regrets. auto& keys = _model->getMapKeys(row); int x; diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 65a1ac5b7a1..66922b26b48 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -31,9 +31,9 @@ class VariableDialog : public QDialog { void checkValidModel(); // Helper functions for this - void updateVariableOptions(); - void updateContainerOptions(); - void updateContainerDataOptions(bool list); + void updateVariableOptions(bool safeToAlter); + void updateContainerOptions(bool safeToAlter); + void updateContainerDataOptions(bool list, bool safeToAlter); void onVariablesTableUpdated(); void onVariablesSelectionChanged(); From 492683db2a44ba1d62b33f7894892f9d20a56d34 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Tue, 14 May 2024 13:18:11 -0400 Subject: [PATCH 133/153] Add A check to safeToAlter functions And Add more notes to the notes column in the UI --- .../mission/dialogs/VariableDialogModel.cpp | 68 ++++++++++++++----- .../src/mission/dialogs/VariableDialogModel.h | 7 +- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 441f1763781..2daee3470dc 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -162,12 +162,9 @@ bool VariableDialogModel::checkValidModel() } } -// TODO! This function in general just needs a lot of work. bool VariableDialogModel::apply() { - // what did we delete from the original list? We need to check these references and clean them. - std::unordered_set deletedVariables; SCP_vector> nameChangedVariables; bool found; @@ -181,7 +178,6 @@ bool VariableDialogModel::apply() if (!stricmp(Sexp_variables[i].variable_name, variable.originalName.c_str())){ if (variable.deleted) { sexp_variable_delete(i); - deletedVariables.insert(variable.originalName); } else { if (variable.name != variable.originalName) { nameChangedVariables.emplace_back(i, variable.originalName); @@ -226,12 +222,9 @@ bool VariableDialogModel::apply() } - // TODO! containers + // TODO! containers need to be saved. std::unordered_set deletedContainers; - // TODO! Look for referenced variables and containers. - // Need a way to clean up references. I'm thinking making some pop ups to confirm replacements created in the editor. - return false; } @@ -652,10 +645,28 @@ bool VariableDialogModel::removeVariable(int index, bool toDelete) } } -bool safeToAlterVariable(int /*index*/){ +bool VariableDialogModel::safeToAlterVariable(int index) +{ + auto variable = lookupVariable(index); + if (!variable){ + return false; + } + + // FIXME! until we can actually count references (via a SEXP backend), this is the best way to go. + if (variable.orginalName != ""){ + return false; + } + return true; } +bool VariableDialogModel::safeToAlterVariable(const variableInfo& variableItem) +{ + // again, FIXME! Needs actally reference count. + return variableItem.originalName == ""; +} + + // Container Section // true on string, false on number @@ -1800,10 +1811,27 @@ void VariableDialogModel::swapKeyAndValues(int index) } } -bool safeToAlterContainer(int /*index*/){ +bool VariableDialogModel::safeToAlterContainer(int index) +{ auto container = lookupContainer(index); + + if (!container){ + return false; + } + + // FIXME! Until there's a sexp backend, we can only check if we just created the container. + if (container.originalName != ""){ + return false; + } + return true; } +bool VariableDialogModel::safeToAlterContainer(const containerInfo& containerItem) +{ + // again, FIXME! Needs actally reference count. + return containerItem.originalName == ""; +} + SCP_string VariableDialogModel::changeMapItemNumberValue(int index, int itemIndex, int newValue) { auto mapItem = lookupContainerNumberItem(index, itemIndex); @@ -1884,17 +1912,19 @@ const SCP_vector> VariableDialogModel::getVariableValu { SCP_vector> outStrings; - for (const auto& item : _variableItems) { + for (const auto& item : _variableItems){ SCP_string notes = ""; - if (item.deleted) { + if (!safeToAlterVariable(item)){ + notes = "Referenced"; + } else if (item.deleted){ notes = "Deleted"; - } else if (item.originalName == "") { + } else if (item.originalName == ""){ notes = "New"; } else if (item.name != item.originalName){ notes = "Renamed"; - } else if (item.string && item.stringValue == "") { - notes = "Defaulting to empty string"; + } else if (item.string && item.stringValue == "" || !item.string && item.numberValue == 0){ + notes = "At default"; } SCP_string temp; @@ -2040,12 +2070,18 @@ const SCP_vector> VariableDialogModel::getContainerNam } - if (item.deleted) { + if (!safeToAlterContainer(item)){ + notes = "Referenced" + } else if (item.deleted) { notes = "Deleted"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ notes = "Renamed"; + } else if (!item.list && item.keys.empty()){ + notes = "Empty Map"; + } else if (item.list && ((item.string && item.stringValues.empty()) || (!item.string && item.numberValues.empty()))){ + notes = "Empty List"; } outStrings.push_back(std::array{item.name, type, notes}); diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 8caba47d53e..485e894a528 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -32,7 +32,9 @@ struct containerInfo { SCP_string originalName = ""; // I found out that keys could be strictly typed as numbers *after* finishing the majority of the model.... - // So I am just going to store numerical keys as strings and use a bool to differentiate. + // So I am just going to store numerical keys as strings and use a bool to differentiate. + // Additionally the reason why these are separate and not in a map is to allow duplicates that the user can fix. + // Less friction than a popup telling them they did it wrong. SCP_vector keys; SCP_vector numberValues; SCP_vector stringValues; @@ -145,7 +147,8 @@ class VariableDialogModel : public AbstractDialogModel { int _deleteWarningCount; - static SCP_string clampIntegerString(SCP_string source); + void sortMap(int index); + SCP_string clampIntegerString(SCP_string source); variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ From 62a43512fd9cdc989951b67d7c2a72281737c872 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 15 May 2024 12:31:13 -0400 Subject: [PATCH 134/153] Finish safe to alter variable functions And sorting function. --- .../mission/dialogs/VariableDialogModel.cpp | 55 +++++++++++++++++++ .../src/mission/dialogs/VariableDialogModel.h | 2 + qtfred/src/ui/dialogs/VariableDialog.cpp | 2 - 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 2daee3470dc..eab37f8c510 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -2092,6 +2092,61 @@ const SCP_vector> VariableDialogModel::getContainerNam void VariableDialogModel::setTextMode(int modeIn) { _textMode = modeIn;} +void VariableDialogModel::sortMap(int index) +{ + auto container = lookupContainer(index); + + // No sorting of non maps, and no point to sort if size is less than 2 + if (container.list || static_cast(container.keys.size() < 2)){ + return; + } + + // Yes, a little inefficient, but I didn't realize this was done in the original dialog when I designed the model. + SCP_vector keyCopy = container->keys; + SCP_vector sortedStringValues; + SCP_vector sortedNumberValues; + + // code borrowed from jg18, but going to try simple sorting first. Just need to see what it does with numbers. +// if (container->string) { + std::sort(container->keys.begin(), container->keys.end()); +/* } else { + std::sort(container->keys.begin(), + container->keys.end(), + [](const SCP_string &str1, const SCP_string &str2) -> bool { + try{ + return std::atoi(str1.c_str()) < std::atoi(str2.c_str()); + } + catch(...) + } + ); +*/ + + int y = 0; + + for (int x = 0; static_cast(container.keys.size()); ++x){ + // look for the first match in the temporary copy. + for (; y < static_cast(keyCopy.size()); ++y){ + // copy the values over. + if (container->keys[x] == keyCopy[y]){ + sortedStringValues.push_back(container->stringValues[y]); + sortedNumberValues.push_back(container->numberValues[y]); + break; + } + } + + // only reset y if we *dont* have a duplicate key coming up next. The first part of this check is simply a bound check. + // If the last item is a duplicate, that was checked on the previous iteration. + if ((x >= static_cast(container.keys.size()) - 1) || container.keys[x] != container.keys[x + 1]){ + y = 0; + } + } + + // TODO! Switch to Assertion after testing. + Verification(container->keys.size() == sortedStringValues.size(), "Keys size %uz and values %uz have a size mismatch after sorting. Please report to the SCP.", container->keys.size(), sortedStringValues.size()); + container->stringValues = std::move(sortedStringValues); + container->numberValues = std::move(sortedNumberValues); +} + // This function is for cleaning up input strings that should be numbers. We could use std::stoi, // but this helps to not erase the entire string if user ends up mistyping just one digit. // If we ever allowed float types in sexp variables ... *shudder* ... we would definitely need a float diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 485e894a528..807a9d78e26 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -75,6 +75,7 @@ class VariableDialogModel : public AbstractDialogModel { // returns whether it succeeded bool removeVariable(int index, bool toDelete); bool safeToAlterVariable(int index); + bool safeToAlterVariable(const VariableInfo& variableItem); // Container Section @@ -127,6 +128,7 @@ class VariableDialogModel : public AbstractDialogModel { void swapKeyAndValues(int index); bool safeToAlterContainer(int index); + bool safeToAlterContainer(const containerInfo& containerItem); const SCP_vector> getVariableValues(); const SCP_vector> getContainerNames(); diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index ece10c9981c..b4136eeffa8 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1457,8 +1457,6 @@ void VariableDialog::updateContainerOptions(bool safeToAlter) } else { - auto items = ui->containersTable->selectedItems(); - // options that should always be turned on ui->copyContainerButton->setEnabled(true); ui->doNotSaveContainerRadio->setEnabled(true); From 7da79c174b8e68bb28f23ca7fd3bb81f9602d838 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Wed, 15 May 2024 13:01:13 -0400 Subject: [PATCH 135/153] Add sorting to other function calls --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index eab37f8c510..c222bb6f126 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1318,6 +1318,8 @@ std::pair VariableDialogModel::addMapItem(int index) container->stringValues.push_back(""); container->numberValues.push_back(0); + sortMap(index); + return ret; } @@ -1388,6 +1390,7 @@ std::pair VariableDialogModel::addMapItem(int index, SCP container->stringValues.emplace_back(""); } + sortMap(index); return ret; } @@ -1531,7 +1534,9 @@ std::pair VariableDialogModel::copyMapItem(int index, in container->keys.push_back(newKey); container->stringValues.push_back(copyValue); + container->numberValues.push_back(0); + sortMap(index); return std::make_pair(newKey, copyValue); } else { @@ -1572,10 +1577,12 @@ std::pair VariableDialogModel::copyMapItem(int index, in container->keys.push_back(newKey); container->numberValues.push_back(copyValue); + container->stringValues.push_back(""); SCP_string temp; sprintf(temp, "%i", copyValue); - + sortMap(index); + return std::make_pair(newKey, temp); } @@ -1695,6 +1702,7 @@ SCP_string VariableDialogModel::changeMapItemKey(int index, int keyRow, SCP_stri container->keys[keyRow] = trimIntegerString(newKey); } + sortMap(index); return container->keys[keyRow]; } @@ -1807,8 +1815,9 @@ void VariableDialogModel::swapKeyAndValues(int index) container->string = true; container->stringKeys = false; } - } + + sortMap(index); } bool VariableDialogModel::safeToAlterContainer(int index) From 3be4d0b15ad081a7f969e7d18888661d4ec8d6ca Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Thu, 16 May 2024 00:47:46 -0400 Subject: [PATCH 136/153] Fixes based on testing and linters --- .../mission/dialogs/VariableDialogModel.cpp | 84 ++++++++++++------- .../src/mission/dialogs/VariableDialogModel.h | 3 +- qtfred/src/ui/dialogs/VariableDialog.cpp | 19 +---- qtfred/src/ui/dialogs/VariableDialog.h | 13 ++- 4 files changed, 72 insertions(+), 47 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c222bb6f126..95fe37e7167 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -82,8 +82,8 @@ bool VariableDialogModel::checkValidModel() if (key.empty()){ ++emptyKeys; - } else if (!container->stringKeys){ - if (key != trimNumberString(key)){ + } else if (!container.stringKeys){ + if (key != trimIntegerString(key)){ ++notNumberKeys; } @@ -119,7 +119,7 @@ bool VariableDialogModel::checkValidModel() SCP_string temp; sprintf(temp, "There are %zu duplicate map keys:\n\n", duplicateKeys.size()); - messageOut += messageBuffer + "\n"; + messageOut += temp + messageBuffer + "\n"; } if (emptyVarNames > 0){ @@ -144,7 +144,7 @@ bool VariableDialogModel::checkValidModel() } if (_variableItems.size() >= MAX_SEXP_VARIABLES){ - messageOut += "There are more than the max of 250 variables.\n" + messageOut += "There are more than the max of 250 variables.\n"; } @@ -169,7 +169,7 @@ bool VariableDialogModel::apply() bool found; // first we have to edit known variables. - for (const auto& variable : _variableItems){ + for (auto& variable : _variableItems){ found = false; // set of instructions for updating variables @@ -653,7 +653,7 @@ bool VariableDialogModel::safeToAlterVariable(int index) } // FIXME! until we can actually count references (via a SEXP backend), this is the best way to go. - if (variable.orginalName != ""){ + if (variable->originalName != ""){ return false; } @@ -983,21 +983,23 @@ bool VariableDialogModel::setContainerListOrMap(int index, bool list) // to adjust keys. if (currentSize == container->keys.size()) { container->list = list; + + // we need all key related vectors to be size synced + if (container->string){ + container->numberValues.resize(container->keys.size(), 0); + } else { + container->stringValues.resize(container->keys.size(), ""); + } + return container->list; } // not enough data items. if (currentSize < container->keys.size()) { // just put the default value in them. Any string I specify for string values will - // be inconvenient to someone. - if (container->string) { - SCP_string newValue = ""; - container->stringValues.resize(container->keys.size(), newValue); - } - else { - // But differentiating numbers by having zero be the default is a good idea and does - container->numberValues.resize(container->keys.size(), 0); - } + // be inconvenient to someone. Zero is a good default, too. + container->stringValues.resize(container->keys.size(), ""); + container->numberValues.resize(container->keys.size(), 0); } else { // here currentSize must be greater than the key size, because we already dealt with equal size. @@ -1158,16 +1160,16 @@ SCP_string VariableDialogModel::copyContainer(int index) SCP_string newName; int count = 0; - do { + while(true) { sprintf(newName, "%s_%i", container->name.substr(0, TOKEN_LENGTH - 4).c_str(), count); - auto containerSearch = lookupVariableByName(newName); + auto containerSearch = lookupContainerByName(newName); // open slot found! if (!containerSearch){ break; } ++count; - } + } _containerItems.back().name = newName; _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH - 1); @@ -1184,7 +1186,7 @@ SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newNam } // We cannot have two containers with the same name, but we need to check that somewhere else (like on accept attempt). - container->name = newName.substring(0, TOKEN_LENGTH - 1); + container->name = newName.substr(0, TOKEN_LENGTH - 1); return container->name; } @@ -1828,7 +1830,7 @@ bool VariableDialogModel::safeToAlterContainer(int index) } // FIXME! Until there's a sexp backend, we can only check if we just created the container. - if (container.originalName != ""){ + if (container->originalName != ""){ return false; } @@ -2080,7 +2082,7 @@ const SCP_vector> VariableDialogModel::getContainerNam if (!safeToAlterContainer(item)){ - notes = "Referenced" + notes = "Referenced"; } else if (item.deleted) { notes = "Deleted"; } else if (item.originalName == "") { @@ -2106,7 +2108,7 @@ void VariableDialogModel::sortMap(int index) auto container = lookupContainer(index); // No sorting of non maps, and no point to sort if size is less than 2 - if (container.list || static_cast(container.keys.size() < 2)){ + if (container->list || static_cast(container->keys.size() < 2)){ return; } @@ -2116,23 +2118,26 @@ void VariableDialogModel::sortMap(int index) SCP_vector sortedNumberValues; // code borrowed from jg18, but going to try simple sorting first. Just need to see what it does with numbers. -// if (container->string) { - std::sort(container->keys.begin(), container->keys.end()); -/* } else { + if (container->string) { + std::sort(container->keys.begin(), container->keys.end()); + } else { std::sort(container->keys.begin(), container->keys.end(), [](const SCP_string &str1, const SCP_string &str2) -> bool { try{ return std::atoi(str1.c_str()) < std::atoi(str2.c_str()); } - catch(...) + catch(...){ + // we're up the creek if this happens anyway. + return true; + } } ); -*/ + } int y = 0; - for (int x = 0; static_cast(container.keys.size()); ++x){ + for (int x = 0; x < static_cast(container->keys.size()); ++x){ // look for the first match in the temporary copy. for (; y < static_cast(keyCopy.size()); ++y){ // copy the values over. @@ -2145,7 +2150,7 @@ void VariableDialogModel::sortMap(int index) // only reset y if we *dont* have a duplicate key coming up next. The first part of this check is simply a bound check. // If the last item is a duplicate, that was checked on the previous iteration. - if ((x >= static_cast(container.keys.size()) - 1) || container.keys[x] != container.keys[x + 1]){ + if ((x >= static_cast(container->keys.size()) - 1) || container->keys[x] != container->keys[x + 1]){ y = 0; } } @@ -2156,6 +2161,27 @@ void VariableDialogModel::sortMap(int index) container->numberValues = std::move(sortedNumberValues); } +bool VariableDialogModel::atMaxVariables() +{ + if (_variableItems.size() < MAX_SEXP_VARIABLES){ + return false; + } + + int count = 0; + + for (const auto& item : _variableItems){ + if (!item.deleted){ + ++count; + } + } + + if (count < MAX_SEXP_VARIABLES){ + return false; + } else { + return true; + } +} + // This function is for cleaning up input strings that should be numbers. We could use std::stoi, // but this helps to not erase the entire string if user ends up mistyping just one digit. // If we ever allowed float types in sexp variables ... *shudder* ... we would definitely need a float diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 807a9d78e26..0f2422d884e 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -75,7 +75,7 @@ class VariableDialogModel : public AbstractDialogModel { // returns whether it succeeded bool removeVariable(int index, bool toDelete); bool safeToAlterVariable(int index); - bool safeToAlterVariable(const VariableInfo& variableItem); + bool safeToAlterVariable(const variableInfo& variableItem); // Container Section @@ -150,6 +150,7 @@ class VariableDialogModel : public AbstractDialogModel { int _deleteWarningCount; void sortMap(int index); + bool atMaxVariables(); SCP_string clampIntegerString(SCP_string source); variableInfo* lookupVariable(int index){ diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index b4136eeffa8..c58f4cb825a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -24,9 +24,8 @@ VariableDialog::VariableDialog(FredView* parent, EditorViewport* viewport) // Here we need to check that there are no issues with variable names or container names, or with maps having duplicate keys. connect(ui->OkCancelButtons, &QDialogButtonBox::accepted, this, &VariableDialog::checkValidModel); // Reject if the user wants to. - connect(ui->OkCancelButtons, &QDialogButtonBox::rejected, this, &VariableDialog::preReject); + connect(ui->OkCancelButtons, &QDialogButtonBox::rejected, this, &VariableDialog::reject); connect(this, &QDialog::accepted, _model.get(), &VariableDialogModel::apply); - connect(this, &QDialog::rejected, this, &VariableDialog::preReject); connect(ui->variablesTable, &QTableWidget::itemChanged, @@ -1182,7 +1181,7 @@ void VariableDialog::applyModel() if (selectedRow < 0 && !_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; - if (_model->!safeToAlterVariable(selectedRow)){ + if (!_model->safeToAlterVariable(selectedRow)){ safeToAlter = true; } } @@ -1699,7 +1698,7 @@ void VariableDialog::updateContainerDataOptions(bool list, bool safeToAlter) ui->shiftItemDownButton->setEnabled(false); // we can swap if it's safe or if the data types match. If the data types *don't* match, then we run into reference issues. - ui->swapKeysAndValuesButton->setEnabled(safeToAlter || _containerItems[row].stringKeys == _containerItems[row].string); + ui->swapKeysAndValuesButton->setEnabled(safeToAlter || _model->getContainerKeyType(row) == _model->getContainerValueType(row)); // keys I didn't bother to make separate. Should have done the same with values, ah regrets. auto& keys = _model->getMapKeys(row); @@ -1829,18 +1828,6 @@ int VariableDialog::getCurrentContainerItemRow() return -1; } -void VariableDialog::preReject() -{ - QMessageBox msgBox; - msgBox.setText("Are you sure you want to discard your changes?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - int ret = msgBox.exec(); - - if (ret == QMessageBox::Yes) { - reject(); - } -} - void VariableDialog::checkValidModel() { if (ui->OkCancelButtons->button(QDialogButtonBox::Ok)->hasFocus() && _model->checkValidModel()){ diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 66922b26b48..14b870bda19 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -27,7 +27,6 @@ class VariableDialog : public QDialog { // basically UpdateUI, but called when there is an inconsistency between model and UI void applyModel(); - void preReject(); void checkValidModel(); // Helper functions for this @@ -84,6 +83,18 @@ class VariableDialog : public QDialog { SCP_string _currentContainer = ""; SCP_string _currentContainerItemCol1 = ""; SCP_string _currentContainerItemCol2 = ""; + + void VariableDialog::reject() + { + QMessageBox msgBox; + msgBox.setText("Are you sure you want to discard your changes?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int ret = msgBox.exec(); + + if (ret == QMessageBox::Yes) { + QDialog::reject(); + } + } }; From c51bc08d1d47dea40ac6f9dd166a66efa2c17449 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 11:11:07 -0400 Subject: [PATCH 137/153] linter fix --- qtfred/src/ui/dialogs/VariableDialog.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 14b870bda19..7c973366bd6 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -83,8 +83,8 @@ class VariableDialog : public QDialog { SCP_string _currentContainer = ""; SCP_string _currentContainerItemCol1 = ""; SCP_string _currentContainerItemCol2 = ""; - - void VariableDialog::reject() + + void reject() { QMessageBox msgBox; msgBox.setText("Are you sure you want to discard your changes?"); From d432f9b1e9095b10e847c594d765bb1ea31e0acd Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 11:21:14 -0400 Subject: [PATCH 138/153] Make to loop over the right constraint --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 95fe37e7167..e3d232152bd 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -233,7 +233,7 @@ void VariableDialogModel::initializeData() _variableItems.clear(); _containerItems.clear(); - for (int i = 0; i < static_cast(_variableItems.size()); ++i){ + for (int i = 0; i < MAX_SEXP_VARIABLES; ++i){ if (strlen(Sexp_variables[i].text)) { _variableItems.emplace_back(); auto& item = _variableItems.back(); From 039866d526f4bc49061bfff1fd180e0068b071ad Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 11:24:03 -0400 Subject: [PATCH 139/153] Linter Fixes --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index e3d232152bd..89ebe65d586 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1934,8 +1934,8 @@ const SCP_vector> VariableDialogModel::getVariableValu notes = "New"; } else if (item.name != item.originalName){ notes = "Renamed"; - } else if (item.string && item.stringValue == "" || !item.string && item.numberValue == 0){ - notes = "At default"; + } else if ((item.string && item.stringValue == "") || (!item.string && item.numberValue == 0)){ + notes = "Default Value"; } SCP_string temp; @@ -2156,7 +2156,7 @@ void VariableDialogModel::sortMap(int index) } // TODO! Switch to Assertion after testing. - Verification(container->keys.size() == sortedStringValues.size(), "Keys size %uz and values %uz have a size mismatch after sorting. Please report to the SCP.", container->keys.size(), sortedStringValues.size()); + Verification(container->keys.size() == sortedStringValues.size(), "Keys size %zu and values %zu have a size mismatch after sorting. Please report to the SCP.", container->keys.size(), sortedStringValues.size()); container->stringValues = std::move(sortedStringValues); container->numberValues = std::move(sortedNumberValues); } From e5e2729157a55e98ee6827702626296e35202b66 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 11:38:01 -0400 Subject: [PATCH 140/153] Add non-numeric keys to warning messages --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 89ebe65d586..c14211c7396 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -143,6 +143,13 @@ bool VariableDialogModel::checkValidModel() messageOut += messageBuffer; } + if (notNumberKeys > 0){ + messageBuffer.clear(); + sprintf(messageBuffer, "There are %i numeric keys that are not numbers.\n", notNumberKeys); + + messageOut += messageBuffer; + } + if (_variableItems.size() >= MAX_SEXP_VARIABLES){ messageOut += "There are more than the max of 250 variables.\n"; } From ad7e7136929d3f61702e1cf73e2e4063f66cde94 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 14:40:38 -0400 Subject: [PATCH 141/153] Override the virtual reject function --- qtfred/src/ui/dialogs/VariableDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 7c973366bd6..9f96ed6ee97 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -84,7 +84,7 @@ class VariableDialog : public QDialog { SCP_string _currentContainerItemCol1 = ""; SCP_string _currentContainerItemCol2 = ""; - void reject() + void override reject() { QMessageBox msgBox; msgBox.setText("Are you sure you want to discard your changes?"); From 87367d6b84a281fc6ea0802e53699533945daa0e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 15:19:03 -0400 Subject: [PATCH 142/153] Make sure Keys and Items are proper length --- .../mission/dialogs/VariableDialogModel.cpp | 45 +++++++++++-------- qtfred/src/ui/dialogs/VariableDialog.h | 2 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c14211c7396..403eb077829 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1179,7 +1179,6 @@ SCP_string VariableDialogModel::copyContainer(int index) } _containerItems.back().name = newName; - _containerItems.back().name = _containerItems.back().name.substr(0, TOKEN_LENGTH - 1); return _containerItems.back().name; } @@ -1193,6 +1192,7 @@ SCP_string VariableDialogModel::changeContainerName(int index, SCP_string newNam } // We cannot have two containers with the same name, but we need to check that somewhere else (like on accept attempt). + // Otherwise editing variables and containers becomes super annoying. container->name = newName.substr(0, TOKEN_LENGTH - 1); return container->name; } @@ -1258,7 +1258,7 @@ SCP_string VariableDialogModel::addListItem(int index, SCP_string item) } if (container->string) { - container->stringValues.push_back(item); + container->stringValues.push_back(item.substr(0, TOKEN_LENGTH - 1)); return container->stringValues.back(); } else { auto temp = trimIntegerString(item); @@ -1332,6 +1332,7 @@ std::pair VariableDialogModel::addMapItem(int index) return ret; } +// Overload for specified key and/or Value std::pair VariableDialogModel::addMapItem(int index, SCP_string key, SCP_string value) { auto container = lookupContainer(index); @@ -1368,7 +1369,7 @@ std::pair VariableDialogModel::addMapItem(int index, SCP } while (conflict && count < 101); } else { if (container->stringKeys){ - newKey = key; + newKey = key.substr(0, TOKEN_LENGTH - 1); } else { newKey = trimIntegerString(key); } @@ -1382,7 +1383,7 @@ std::pair VariableDialogModel::addMapItem(int index, SCP container->keys.push_back(ret.first); if (container->string) { - ret.second = value; + ret.second = value.substr(0, TOKEN_LENGTH - 1); container->stringValues.push_back(ret.second); container->numberValues.push_back(0); } else { @@ -1436,7 +1437,7 @@ SCP_string VariableDialogModel::changeListItem(int containerIndex, int index, SC return ""; } - *listItem = newString; + *listItem = newString.substr(0, TOKEN_LENGTH - 1); } else { auto listItem = lookupContainerNumberItem(containerIndex, index); @@ -1500,7 +1501,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in auto key = lookupContainerKey(index, mapIndex); - if (!key) { + if (key == nullptr) { return std::make_pair("", ""); } @@ -1509,13 +1510,14 @@ std::pair VariableDialogModel::copyMapItem(int index, in if (container->string){ auto value = lookupContainerStringItem(index, mapIndex); - // no valid value. - if (!value){ + // not a valid value. + if (value == nullptr){ return std::make_pair("", ""); } SCP_string copyValue = *value; - SCP_string newKey = *key + "0"; + SCP_string baseNewKey = key->substr(0, TOKEN_LENGTH - 4); + SCP_string newKey = baseNewKey + "0"; int count = 0; bool found; @@ -1531,10 +1533,10 @@ std::pair VariableDialogModel::copyMapItem(int index, in // attempt did not work, try next number if (found) { - sprintf(newKey, "%s%i", key->c_str(), ++count); + sprintf(newKey, "%s%i", baseNewKey.c_str(), ++count); } - } while (found && count < 100); + } while (found && count < 999); // we could not generate a new key .... somehow. if (found){ @@ -1557,7 +1559,8 @@ std::pair VariableDialogModel::copyMapItem(int index, in } int copyValue = *value; - SCP_string newKey = *key + "0"; + SCP_string baseNewKey = key->substr(0, TOKEN_LENGTH - 4); + SCP_string newKey = baseNewKey + "0"; int count = 0; bool found; @@ -1573,7 +1576,7 @@ std::pair VariableDialogModel::copyMapItem(int index, in // attempt did not work, try next number if (found) { - sprintf(newKey, "%s%i", key->c_str(), ++count); + sprintf(newKey, "%s%i", baseNewKey.c_str(), ++count); } } while (found && count < 100); @@ -1706,7 +1709,7 @@ SCP_string VariableDialogModel::changeMapItemKey(int index, int keyRow, SCP_stri } if (container->stringKeys){ - container->keys[keyRow] = newKey; + container->keys[keyRow] = newKey.substr(0, TOKEN_LENGTH - 1); } else { container->keys[keyRow] = trimIntegerString(newKey); } @@ -1723,7 +1726,7 @@ SCP_string VariableDialogModel::changeMapItemStringValue(int index, int itemInde return ""; } - *item = newValue; + *item = newValue.substr(0, TKEN_LENGTH - 1); return *item; } @@ -1936,13 +1939,15 @@ const SCP_vector> VariableDialogModel::getVariableValu if (!safeToAlterVariable(item)){ notes = "Referenced"; } else if (item.deleted){ - notes = "Deleted"; + notes = "To Be Deleted"; } else if (item.originalName == ""){ notes = "New"; - } else if (item.name != item.originalName){ - notes = "Renamed"; } else if ((item.string && item.stringValue == "") || (!item.string && item.numberValue == 0)){ notes = "Default Value"; + } else if (item.name != item.originalName){ + notes = "Renamed"; + } else { + notes = "Unreferenced"; } SCP_string temp; @@ -2091,7 +2096,7 @@ const SCP_vector> VariableDialogModel::getContainerNam if (!safeToAlterContainer(item)){ notes = "Referenced"; } else if (item.deleted) { - notes = "Deleted"; + notes = "To Be Deleted"; } else if (item.originalName == "") { notes = "New"; } else if (item.name != item.originalName){ @@ -2100,6 +2105,8 @@ const SCP_vector> VariableDialogModel::getContainerNam notes = "Empty Map"; } else if (item.list && ((item.string && item.stringValues.empty()) || (!item.string && item.numberValues.empty()))){ notes = "Empty List"; + } else { + notes = "Unreferenced"; } outStrings.push_back(std::array{item.name, type, notes}); diff --git a/qtfred/src/ui/dialogs/VariableDialog.h b/qtfred/src/ui/dialogs/VariableDialog.h index 9f96ed6ee97..6d37610faee 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.h +++ b/qtfred/src/ui/dialogs/VariableDialog.h @@ -84,7 +84,7 @@ class VariableDialog : public QDialog { SCP_string _currentContainerItemCol1 = ""; SCP_string _currentContainerItemCol2 = ""; - void override reject() + void reject() override { QMessageBox msgBox; msgBox.setText("Are you sure you want to discard your changes?"); From 07a389a5e8a26bf9154eac07c2035c412cb078bb Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Thu, 16 May 2024 15:45:53 -0400 Subject: [PATCH 143/153] Typo --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 403eb077829..ae08d5a7681 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1726,7 +1726,7 @@ SCP_string VariableDialogModel::changeMapItemStringValue(int index, int itemInde return ""; } - *item = newValue.substr(0, TKEN_LENGTH - 1); + *item = newValue.substr(0, TOKEN_LENGTH - 1); return *item; } From 860e28fbdb23e6d4c2745acbe3d3cf8ab6e41b9e Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 17 May 2024 15:33:11 -0400 Subject: [PATCH 144/153] Finish applying data from model to mission --- .../mission/dialogs/VariableDialogModel.cpp | 81 ++++++++++++++++++- .../src/mission/dialogs/VariableDialogModel.h | 3 +- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index ae08d5a7681..bef3bcf1ca8 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -169,6 +169,71 @@ bool VariableDialogModel::checkValidModel() } } +sexp_container VariableDialogModel::createContainerFromModel(const containerInfo& infoIn) +{ + sexp_container containerOut; + + containerOut.container_name = infoIn.name; + + // handle type info, which defaults to List + if (!infoIn.list) { + contianerOut.type &= ~ContainerType::LIST; + containerOut.type |= ContainerType::MAP; + + // Map Key type. This is not set by default, so we have explicity set it. + if (infoIn.stringKeys){ + containerOut.type |= ContainerType::STRING_KEYS; + } else { + containerOut.type |= ContainerType::NUMBER_KEYS; + } + } + + // New Containers also default to string data + if (!infoIn.String){ + containerOut.type &= ~ContainerType::STRING_DATA; + containerOut.type |= ContainerType::NUMBER_DATA; + } + + // Now flags + if (infoIn.flags & SEXP_VARIABLE_NETWORK){ + containerOut.type |= ContainerType::NETWORK; + } + + + if (infoIn.flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE){ + containerOut.type |= ContainerType::SAVE_TO_PLAYER_FILE; + } + + // No persistence means No flag, which is the default, but if anything else is true, then this has to be + if (infoIn.flags & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE){ + containerOut.type |= ContainerType::SAVE_ON_MISSION_CLOSE; + } else if (infoIn.flags & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS){ + containerOut.type |= ContainerType::SAVE_ON_MISSION_PROGRESS; + } else { + containerOut.type &= ~ContainerType::SAVE_TO_PLAYER_FILE; + } + + + // Handle contained data + if (infoIn.list){ + if (infoIn.string){ + containerOut.list_data = infoIn.stringValues; + } else { + for (const auto& number : infoIn.numberValues){ + containerOut.list_data.push_back(std::to_string(number)); + } + } + } else { + for (int x = 0; x < infoIn.keys; ++x){ + if (infoIn.string){ + map_data[infoIn.keys[x]] = infoIn.stringValues[x]; + } else { + map_data[infoIn.keys[x]] = std::to_string(infoIn.numberValues[x]); + } + } + } +} + bool VariableDialogModel::apply() { // what did we delete from the original list? We need to check these references and clean them. @@ -229,10 +294,20 @@ bool VariableDialogModel::apply() } - // TODO! containers need to be saved. - std::unordered_set deletedContainers; + SCP_vector newContainers; + SCP_unordered_map renamedContainers; + + for (const auto& container : _containerItems){ + newContainers.push_back(createContainerFromModel(container)); + + if (container.name != container.originalName){ + renamedContainers[container.originalName] = container.name; + } + } + + update_sexp_containers(newContainers, renamed_containers); - return false; + return true; } void VariableDialogModel::initializeData() diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 0f2422d884e..7f91c7a5abb 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -151,7 +151,8 @@ class VariableDialogModel : public AbstractDialogModel { void sortMap(int index); bool atMaxVariables(); - SCP_string clampIntegerString(SCP_string source); + + sexp_container& createContainerFromModel(const containerInfo& infoIn); variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ From d1829a9f10c94c92d169d448590e3716cf7ca94a Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 17 May 2024 17:29:40 -0400 Subject: [PATCH 145/153] Fix Eternal flags being set with no persistence --- .../mission/dialogs/VariableDialogModel.cpp | 14 +++++---- qtfred/src/ui/dialogs/VariableDialog.cpp | 29 ++++++++++++++----- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index bef3bcf1ca8..c9bfec1db59 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -200,15 +200,19 @@ sexp_container VariableDialogModel::createContainerFromModel(const containerInfo } - if (infoIn.flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE){ - containerOut.type |= ContainerType::SAVE_TO_PLAYER_FILE; - } - // No persistence means No flag, which is the default, but if anything else is true, then this has to be if (infoIn.flags & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE){ containerOut.type |= ContainerType::SAVE_ON_MISSION_CLOSE; + + if (infoIn.flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE){ + containerOut.type |= ContainerType::SAVE_TO_PLAYER_FILE; + } } else if (infoIn.flags & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS){ containerOut.type |= ContainerType::SAVE_ON_MISSION_PROGRESS; + + if (infoIn.flags & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE){ + containerOut.type |= ContainerType::SAVE_TO_PLAYER_FILE; + } } else { containerOut.type &= ~ContainerType::SAVE_TO_PLAYER_FILE; } @@ -300,7 +304,7 @@ bool VariableDialogModel::apply() for (const auto& container : _containerItems){ newContainers.push_back(createContainerFromModel(container)); - if (container.name != container.originalName){ + if (container.originalName != "" && container.name != container.originalName){ renamedContainers[container.originalName] = container.name; } } diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index c58f4cb825a..73b12ea4b40 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1361,7 +1361,6 @@ void VariableDialog::updateVariableOptions(bool safeToAlter) ui->doNotSaveVariableRadio->setEnabled(true); ui->saveVariableOnMissionCompletedRadio->setEnabled(true); ui->saveVariableOnMissionCloseRadio->setEnabled(true); - ui->setVariableAsEternalcheckbox->setEnabled(true); ui->networkVariableCheckbox->setEnabled(true); // options that are only safe if there are no references @@ -1400,20 +1399,28 @@ void VariableDialog::updateVariableOptions(bool safeToAlter) if (ret == 0){ ui->doNotSaveVariableRadio->setChecked(true); ui->saveVariableOnMissionCompletedRadio->setChecked(false); - ui->saveVariableOnMissionCloseRadio->setChecked(false); + ui->saveVariableOnMissionCloseRadio->setChecked(false); + + ui->setVariableAsEternalcheckbox->setChecked(false); + ui->setVariableAsEternalcheckbox->setEnabled(false); } else if (ret == 1) { ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCompletedRadio->setChecked(true); ui->saveVariableOnMissionCloseRadio->setChecked(false); + + ui->setVariableAsEternalcheckbox->setEnabled(true); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); } else { + ui->setVariableAsEternalcheckbox->setEnabled(true); ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(true); + + ui->setVariableAsEternalcheckbox->setEnabled(true); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); } ui->networkVariableCheckbox->setChecked(_model->getVariableNetworkStatus(row)); - ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); - } void VariableDialog::updateContainerOptions(bool safeToAlter) @@ -1461,7 +1468,6 @@ void VariableDialog::updateContainerOptions(bool safeToAlter) ui->doNotSaveContainerRadio->setEnabled(true); ui->saveContainerOnMissionCompletedRadio->setEnabled(true); ui->saveContainerOnMissionCloseRadio->setEnabled(true); - ui->setContainerAsEternalCheckbox->setEnabled(true); ui->networkContainerCheckbox->setEnabled(true); // options that require it be safe to alter because the container is not referenced @@ -1518,7 +1524,6 @@ void VariableDialog::updateContainerOptions(bool safeToAlter) updateContainerDataOptions(false, safeToAlter); } - ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); ui->networkContainerCheckbox->setChecked(_model->getContainerNetworkStatus(row)); int ret = _model->getContainerOnMissionCloseOrCompleteFlag(row); @@ -1526,15 +1531,25 @@ void VariableDialog::updateContainerOptions(bool safeToAlter) if (ret == 0){ ui->doNotSaveContainerRadio->setChecked(true); ui->saveContainerOnMissionCompletedRadio->setChecked(false); - ui->saveContainerOnMissionCloseRadio->setChecked(false); + ui->saveContainerOnMissionCloseRadio->setChecked(false); + + ui->setContainerAsEternalCheckbox->setChecked(false); + ui->setContainerAsEternalCheckbox->setEnabled(false); + } else if (ret == 1) { ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(true); ui->saveContainerOnMissionCloseRadio->setChecked(false); + + ui->setContainerAsEternalCheckbox->setEnabled(true); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); } else { ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(false); ui->saveContainerOnMissionCloseRadio->setChecked(true); + + ui->setContainerAsEternalCheckbox->setEnabled(true); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); } } From 768f88b135d99ce04e1d335fe560fef2ac39666b Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 17 May 2024 17:44:38 -0400 Subject: [PATCH 146/153] Linter Fixes --- .../mission/dialogs/VariableDialogModel.cpp | 33 +++++++++++-------- .../src/mission/dialogs/VariableDialogModel.h | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index c9bfec1db59..7e97e0d50a0 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -177,7 +177,7 @@ sexp_container VariableDialogModel::createContainerFromModel(const containerInfo // handle type info, which defaults to List if (!infoIn.list) { - contianerOut.type &= ~ContainerType::LIST; + containerOut.type &= ~ContainerType::LIST; containerOut.type |= ContainerType::MAP; // Map Key type. This is not set by default, so we have explicity set it. @@ -189,7 +189,7 @@ sexp_container VariableDialogModel::createContainerFromModel(const containerInfo } // New Containers also default to string data - if (!infoIn.String){ + if (!infoIn.string){ containerOut.type &= ~ContainerType::STRING_DATA; containerOut.type |= ContainerType::NUMBER_DATA; } @@ -220,19 +220,24 @@ sexp_container VariableDialogModel::createContainerFromModel(const containerInfo // Handle contained data if (infoIn.list){ - if (infoIn.string){ - containerOut.list_data = infoIn.stringValues; - } else { - for (const auto& number : infoIn.numberValues){ - containerOut.list_data.push_back(std::to_string(number)); - } - } + + if (infoIn.string){ + for (const auto& string : infoIn.stringValues){ + containerOut.list_data.push_back(string); + } + } else { + for (const auto& number : infoIn.numberValues){ + + containerOut.list_data.push_back(std::to_string(number)); + + } + } } else { - for (int x = 0; x < infoIn.keys; ++x){ + for (int x = 0; x < static_cast(infoIn.keys.size()); ++x){ if (infoIn.string){ - map_data[infoIn.keys[x]] = infoIn.stringValues[x]; + containerOut.map_data[infoIn.keys[x]] = infoIn.stringValues[x]; } else { - map_data[infoIn.keys[x]] = std::to_string(infoIn.numberValues[x]); + containerOut.map_data[infoIn.keys[x]] = std::to_string(infoIn.numberValues[x]); } } } @@ -298,7 +303,7 @@ bool VariableDialogModel::apply() } - SCP_vector newContainers; + SCP_vector newContainers; SCP_unordered_map renamedContainers; for (const auto& container : _containerItems){ @@ -309,7 +314,7 @@ bool VariableDialogModel::apply() } } - update_sexp_containers(newContainers, renamed_containers); + update_sexp_containers(newContainers, renamedContainers); return true; } diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 7f91c7a5abb..067dc7dd310 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -152,7 +152,7 @@ class VariableDialogModel : public AbstractDialogModel { void sortMap(int index); bool atMaxVariables(); - sexp_container& createContainerFromModel(const containerInfo& infoIn); + sexp_container createContainerFromModel(const containerInfo& infoIn); variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ From 2cf24cb27b26f0ed56986ce376b3cd39ef503b78 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Fri, 17 May 2024 17:58:48 -0400 Subject: [PATCH 147/153] Trying to fix this mystifying error --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 4 +++- qtfred/src/mission/dialogs/VariableDialogModel.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 7e97e0d50a0..40455bf0634 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -169,7 +169,7 @@ bool VariableDialogModel::checkValidModel() } } -sexp_container VariableDialogModel::createContainerFromModel(const containerInfo& infoIn) +sexp_container VariableDialogModel::createContainer(const containerInfo& infoIn) { sexp_container containerOut; @@ -241,6 +241,8 @@ sexp_container VariableDialogModel::createContainerFromModel(const containerInfo } } } + + return containerOut; } bool VariableDialogModel::apply() diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 067dc7dd310..6a01ef29cca 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -149,11 +149,11 @@ class VariableDialogModel : public AbstractDialogModel { int _deleteWarningCount; + sexp_container createContainer(const containerInfo& infoIn); + void sortMap(int index); bool atMaxVariables(); - sexp_container createContainerFromModel(const containerInfo& infoIn); - variableInfo* lookupVariable(int index){ if(index > -1 && index < static_cast(_variableItems.size()) ){ return &_variableItems[index]; From d8c7a63af75fb69a9cd1711023310dbbe0e18c11 Mon Sep 17 00:00:00 2001 From: John Fernandez Date: Fri, 17 May 2024 18:04:08 -0400 Subject: [PATCH 148/153] This should actually fix it. --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 3 +-- qtfred/src/mission/dialogs/VariableDialogModel.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 40455bf0634..ddf6546ea43 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -1,6 +1,5 @@ #include "VariableDialogModel.h" #include "parse/sexp.h" -#include "parse/sexp_container.h" #include #include @@ -309,7 +308,7 @@ bool VariableDialogModel::apply() SCP_unordered_map renamedContainers; for (const auto& container : _containerItems){ - newContainers.push_back(createContainerFromModel(container)); + newContainers.push_back(createContainer(container)); if (container.originalName != "" && container.name != container.originalName){ renamedContainers[container.originalName] = container.name; diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.h b/qtfred/src/mission/dialogs/VariableDialogModel.h index 6a01ef29cca..9dac7b37b17 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.h +++ b/qtfred/src/mission/dialogs/VariableDialogModel.h @@ -3,6 +3,7 @@ #include "globalincs/pstypes.h" #include "AbstractDialogModel.h" +#include "parse/sexp_container.h" #include namespace fso { From 7229fdc4239c32cd58751647a0ba5db01e2caf98 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 18 May 2024 15:58:19 -0400 Subject: [PATCH 149/153] Fix variable read and write --- .../mission/dialogs/VariableDialogModel.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index ddf6546ea43..dd3a25dffbc 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -281,18 +281,19 @@ bool VariableDialogModel::apply() break; } } - } else { - if (variable.string){ - variable.flags |= SEXP_VARIABLE_STRING; - sexp_add_variable(variable.stringValue.c_str(), variable.name.c_str(), variable.flags, -1); - } else { - variable.flags |= SEXP_VARIABLE_NUMBER; - sexp_add_variable(std::to_string(variable.numberValue).c_str(), variable.name.c_str(), variable.flags, -1); - } - } - // just in case - if (!found) { + // just in case + if (!found) { + if (variable.string){ + variable.flags |= SEXP_VARIABLE_STRING; + sexp_add_variable(variable.stringValue.c_str(), variable.name.c_str(), variable.flags, -1); + } else { + variable.flags |= SEXP_VARIABLE_NUMBER; + sexp_add_variable(std::to_string(variable.numberValue).c_str(), variable.name.c_str(), variable.flags, -1); + } + } + + } else { if (variable.string){ variable.flags |= SEXP_VARIABLE_STRING; sexp_add_variable(variable.stringValue.c_str(), variable.name.c_str(), variable.flags, -1); @@ -326,7 +327,7 @@ void VariableDialogModel::initializeData() _containerItems.clear(); for (int i = 0; i < MAX_SEXP_VARIABLES; ++i){ - if (strlen(Sexp_variables[i].text)) { + if (!(Sexp_variables[i].type & SEXP_VARIABLE_NOT_USED)) { _variableItems.emplace_back(); auto& item = _variableItems.back(); item.name = Sexp_variables[i].variable_name; From 77062e25714cfba3e6c048194b7d2e93b1b0b007 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 18 May 2024 16:17:32 -0400 Subject: [PATCH 150/153] Make sure check eternal boxes are properly enabled --- qtfred/src/ui/dialogs/VariableDialog.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 73b12ea4b40..a2928726b7a 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -733,6 +733,9 @@ void VariableDialog::onDoNotSaveVariableRadioSelected() } else { ui->saveVariableOnMissionCompletedRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(false); + + ui->setVariableAsEternalcheckbox->setChecked(false); + ui->setVariableAsEternalcheckbox->setEnabled(false); } } @@ -752,6 +755,9 @@ void VariableDialog::onSaveVariableOnMissionCompleteRadioSelected() } else { ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCloseRadio->setChecked(false); + + ui->setVariableAsEternalcheckbox->setEnabled(true); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); } } @@ -772,6 +778,9 @@ void VariableDialog::onSaveVariableOnMissionCloseRadioSelected() } else { ui->doNotSaveVariableRadio->setChecked(false); ui->saveVariableOnMissionCompletedRadio->setChecked(false); + + ui->setVariableAsEternalcheckbox->setEnabled(true); + ui->setVariableAsEternalcheckbox->setChecked(_model->getVariableEternalFlag(row)); } } @@ -784,7 +793,7 @@ void VariableDialog::onSaveVariableAsEternalCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(row, ui->setVariableAsEternalcheckbox->isChecked())) { + if (ui->setVariableAsEternalcheckbox->isChecked() != _model->setVariableEternalFlag(row, ui->setVariableAsEternalcheckbox->isChecked())) { applyModel(); } else { ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); @@ -800,7 +809,7 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(row, ui->networkVariableCheckbox->isChecked())) { + if (ui->networkVariableCheckbox->isChecked() != _model->setVariableNetworkStatus(row, ui->networkVariableCheckbox->isChecked())) { applyModel(); } else { ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); @@ -954,6 +963,9 @@ void VariableDialog::onDoNotSaveContainerRadioSelected() ui->doNotSaveContainerRadio->setChecked(true); ui->saveContainerOnMissionCloseRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(false); + + ui->setContainerAsEternalCheckbox->setChecked(false); + ui->setContainerAsEternalCheckbox->setEnabled(false); } } @@ -972,6 +984,9 @@ void VariableDialog::onSaveContainerOnMissionCompletedRadioSelected() ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCloseRadio->setChecked(false); ui->saveContainerOnMissionCompletedRadio->setChecked(true); + + ui->setContainerAsEternalCheckbox->setEnabled(true); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); } } @@ -990,6 +1005,9 @@ void VariableDialog::onSaveContainerOnMissionCloseRadioSelected() ui->doNotSaveContainerRadio->setChecked(false); ui->saveContainerOnMissionCloseRadio->setChecked(true); ui->saveContainerOnMissionCompletedRadio->setChecked(false); + + ui->setContainerAsEternalCheckbox->setEnabled(true); + ui->setContainerAsEternalCheckbox->setChecked(_model->getContainerEternalFlag(row)); } } @@ -1181,7 +1199,7 @@ void VariableDialog::applyModel() if (selectedRow < 0 && !_currentVariable.empty() && variables[x][0] == _currentVariable){ selectedRow = x; - if (!_model->safeToAlterVariable(selectedRow)){ + if (_model->safeToAlterVariable(selectedRow)){ safeToAlter = true; } } From ab7aa635692f2c883965a4fdcce4baa8f2dc11f9 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 18 May 2024 16:31:09 -0400 Subject: [PATCH 151/153] Whoops --- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index a2928726b7a..6defd288a4f 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -793,7 +793,7 @@ void VariableDialog::onSaveVariableAsEternalCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->setVariableAsEternalcheckbox->isChecked() != _model->setVariableEternalFlag(row, ui->setVariableAsEternalcheckbox->isChecked())) { + if (ui->setVariableAsEternalcheckbox->isChecked() == _model->setVariableEternalFlag(row, ui->setVariableAsEternalcheckbox->isChecked())) { applyModel(); } else { ui->setVariableAsEternalcheckbox->setChecked(!ui->setVariableAsEternalcheckbox->isChecked()); @@ -809,7 +809,7 @@ void VariableDialog::onNetworkVariableCheckboxClicked() } // If the model returns the old status, then the change failed and we're out of sync. - if (ui->networkVariableCheckbox->isChecked() != _model->setVariableNetworkStatus(row, ui->networkVariableCheckbox->isChecked())) { + if (ui->networkVariableCheckbox->isChecked() == _model->setVariableNetworkStatus(row, ui->networkVariableCheckbox->isChecked())) { applyModel(); } else { ui->networkVariableCheckbox->setChecked(!ui->networkVariableCheckbox->isChecked()); From 29fa8c4f9ee16bb026054a8d6e3a490a03812036 Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Sat, 18 May 2024 23:26:21 -0400 Subject: [PATCH 152/153] Final Fixes Implements container contents reading, as well --- .../mission/dialogs/VariableDialogModel.cpp | 49 +++++++++++++++++-- qtfred/src/ui/dialogs/VariableDialog.cpp | 4 +- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index dd3a25dffbc..94d824eff69 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -386,10 +386,47 @@ void VariableDialogModel::initializeData() } newContainer.list = container.is_list(); - } -} + if (any(container.type & ContainerType::LIST)) { + for (const auto& item : container.list_data){ + if (any(container.type & ContainerType::STRING_DATA)){ + newContainer.stringValues.push_back(item); + } else { + try { + newContainer.numberValues.push_back(std::stoi(item)); + } + catch (...){ + newContainer.numberValues.push_back(0); + } + } + } + } else { + if (any(container.type & ContainerType::STRING_KEYS)){ + newContainer.stringKeys = true; + } else { + newContainer.stringKeys = false; + } + for (const auto& item : container.map_data){ + newContainer.keys.push_back(item.first); + + if (any(container.type & ContainerType::STRING_DATA)){ + newContainer.stringValues.push_back(item.second); + newContainer.numberValues.push_back(0); + } else { + newContainer.stringValues.push_back(""); + + try{ + newContainer.numberValues.push_back(std::stoi(item.second)); + } + catch (...){ + newContainer.numberValues.push_back(0); + } + } + } + } + } +} // true on string, false on number bool VariableDialogModel::getVariableType(int index) @@ -747,7 +784,7 @@ bool VariableDialogModel::safeToAlterVariable(int index) // FIXME! until we can actually count references (via a SEXP backend), this is the best way to go. if (variable->originalName != ""){ - return false; + return true; } return true; @@ -1927,7 +1964,7 @@ bool VariableDialogModel::safeToAlterContainer(int index) // FIXME! Until there's a sexp backend, we can only check if we just created the container. if (container->originalName != ""){ - return false; + return true; } return true; @@ -2252,7 +2289,9 @@ void VariableDialogModel::sortMap(int index) // If the last item is a duplicate, that was checked on the previous iteration. if ((x >= static_cast(container->keys.size()) - 1) || container->keys[x] != container->keys[x + 1]){ y = 0; - } + } else { + ++y; + } } // TODO! Switch to Assertion after testing. diff --git a/qtfred/src/ui/dialogs/VariableDialog.cpp b/qtfred/src/ui/dialogs/VariableDialog.cpp index 6defd288a4f..ef73dbd6682 100644 --- a/qtfred/src/ui/dialogs/VariableDialog.cpp +++ b/qtfred/src/ui/dialogs/VariableDialog.cpp @@ -1296,7 +1296,7 @@ void VariableDialog::applyModel() } // do we need to switch the delete button to a restore button? - if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "Deleted") { + if (selectedRow > -1 && ui->containersTable->item(selectedRow, 2) && ui->containersTable->item(selectedRow, 2)->text().toStdString() == "To Be Deleted") { ui->deleteContainerButton->setText("Restore"); // We can't restore empty container names. @@ -1398,7 +1398,7 @@ void VariableDialog::updateVariableOptions(bool safeToAlter) ui->setVariableAsNumberRadio->setChecked(!string); // do we need to switch the delete button to a restore button? - if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "Deleted"){ + if (ui->variablesTable->item(row, 2) && ui->variablesTable->item(row, 2)->text().toStdString() == "To Be Deleted"){ ui->deleteVariableButton->setText("Restore"); // We can't restore empty variable names. From 23254c993eaa0d502760f68c8dc6a8450f7a221a Mon Sep 17 00:00:00 2001 From: JohnAFernandez Date: Wed, 22 May 2024 01:09:14 -0400 Subject: [PATCH 153/153] Allow the loadout dialog to open varaible dialog --- qtfred/src/mission/dialogs/VariableDialogModel.cpp | 3 +-- qtfred/src/ui/FredView.h | 4 +++- qtfred/src/ui/dialogs/LoadoutDialog.cpp | 3 +-- qtfred/ui/LoadoutDialog.ui | 3 +++ qtfred/ui/VariableDialog.ui | 3 +++ 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/qtfred/src/mission/dialogs/VariableDialogModel.cpp b/qtfred/src/mission/dialogs/VariableDialogModel.cpp index 94d824eff69..4d269d07ab2 100644 --- a/qtfred/src/mission/dialogs/VariableDialogModel.cpp +++ b/qtfred/src/mission/dialogs/VariableDialogModel.cpp @@ -2294,8 +2294,7 @@ void VariableDialogModel::sortMap(int index) } } - // TODO! Switch to Assertion after testing. - Verification(container->keys.size() == sortedStringValues.size(), "Keys size %zu and values %zu have a size mismatch after sorting. Please report to the SCP.", container->keys.size(), sortedStringValues.size()); + Assertion(container->keys.size() == sortedStringValues.size(), "Keys size %zu and values %zu have a size mismatch after sorting. Please report to the SCP.", container->keys.size(), sortedStringValues.size()); container->stringValues = std::move(sortedStringValues); container->numberValues = std::move(sortedNumberValues); } diff --git a/qtfred/src/ui/FredView.h b/qtfred/src/ui/FredView.h index d63095f02dd..a5b39b5dba2 100644 --- a/qtfred/src/ui/FredView.h +++ b/qtfred/src/ui/FredView.h @@ -43,6 +43,9 @@ class FredView: public QMainWindow, public IDialogProvider { void newMission(); + // this can be triggered by the loadout dialog and so needs to be public + void on_actionVariables_triggered(bool); + private slots: void on_actionSave_As_triggered(bool); void on_actionSave_triggered(bool); @@ -91,7 +94,6 @@ class FredView: public QMainWindow, public IDialogProvider { void on_actionCommand_Briefing_triggered(bool); void on_actionReinforcements_triggered(bool); void on_actionLoadout_triggered(bool); - void on_actionVariables_triggered(bool); void on_actionSelectionLock_triggered(bool enabled); diff --git a/qtfred/src/ui/dialogs/LoadoutDialog.cpp b/qtfred/src/ui/dialogs/LoadoutDialog.cpp index 83678409d45..6e9b2a2945b 100644 --- a/qtfred/src/ui/dialogs/LoadoutDialog.cpp +++ b/qtfred/src/ui/dialogs/LoadoutDialog.cpp @@ -516,8 +516,7 @@ void LoadoutDialog::onClearAllUsedWeaponsPressed() void LoadoutDialog::openEditVariablePressed() { - //TODO! FIX ME! - //viewport->on_actionVariables_triggered(); + reinterpret_cast(parent())->on_actionVariables_triggered(true); } void LoadoutDialog::onSelectionRequiredPressed() diff --git a/qtfred/ui/LoadoutDialog.ui b/qtfred/ui/LoadoutDialog.ui index a454de8ee09..1e8477915e2 100644 --- a/qtfred/ui/LoadoutDialog.ui +++ b/qtfred/ui/LoadoutDialog.ui @@ -2,6 +2,9 @@ fso::fred::dialogs::LoadoutDialog + + Qt::WindowModal + true diff --git a/qtfred/ui/VariableDialog.ui b/qtfred/ui/VariableDialog.ui index 2545a683016..6551fb54423 100644 --- a/qtfred/ui/VariableDialog.ui +++ b/qtfred/ui/VariableDialog.ui @@ -2,6 +2,9 @@ fso::fred::dialogs::VariableEditorDialog + + Qt::WindowModal + 0