From e77fcc6c86bf726a12814284ab475fffb3d07355 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sun, 29 Dec 2024 17:07:37 +0100 Subject: [PATCH] Rework combo boxes --- CHANGES.markdown | 3 +- meson.build | 30 ++- src/BtFieldType.h | 3 +- src/CMakeLists.txt | 16 +- src/MainWindow.cpp | 225 +++++++++--------- src/MainWindow.h | 39 +-- src/RecipeExtrasWidget.cpp | 24 +- src/database/ObjectStoreWrapper.h | 10 +- src/editors/EditorBaseField.h | 52 ++-- src/listModels/BoilListModel.cpp | 19 ++ .../BoilListModel.h} | 29 +-- src/listModels/FermentationListModel.cpp | 19 ++ src/listModels/FermentationListModel.h | 35 +++ src/listModels/ListModelBase.h | 16 +- .../BoilSortFilterProxyModel.cpp | 41 ++++ .../BoilSortFilterProxyModel.h | 39 +++ .../FermentationSortFilterProxyModel.cpp | 43 ++++ .../FermentationSortFilterProxyModel.h | 40 ++++ .../MashSortFilterProxyModel.cpp | 48 ++++ .../MashSortFilterProxyModel.h | 40 ++++ src/tableModels/BoilStepTableModel.cpp | 29 +-- src/tableModels/BoilStepTableModel.h | 35 +-- src/tableModels/BoilTableModel.cpp | 66 +++++ src/tableModels/BoilTableModel.h | 50 ++++ src/tableModels/EquipmentTableModel.cpp | 39 +-- src/tableModels/FermentableTableModel.cpp | 41 +--- .../FermentationStepTableModel.cpp | 21 +- src/tableModels/FermentationTableModel.cpp | 66 +++++ src/tableModels/FermentationTableModel.h | 51 ++++ src/tableModels/HopTableModel.cpp | 59 +---- src/tableModels/ItemDelegate.h | 28 +-- src/tableModels/MashStepTableModel.cpp | 26 +- src/tableModels/MashTableModel.cpp | 68 ++++++ src/tableModels/MashTableModel.h | 53 +++++ src/tableModels/MiscTableModel.cpp | 44 +--- .../RecipeAdditionFermentableTableModel.cpp | 53 +---- .../RecipeAdditionHopTableModel.cpp | 53 +---- .../RecipeAdditionMiscTableModel.cpp | 45 +--- .../RecipeAdditionYeastTableModel.cpp | 45 +--- .../RecipeAdjustmentSaltTableModel.cpp | 22 +- src/tableModels/SaltTableModel.cpp | 42 +--- src/tableModels/StyleTableModel.cpp | 37 +-- src/tableModels/TableModelBase.h | 168 +++++++++---- src/tableModels/WaterTableModel.cpp | 200 +--------------- src/tableModels/YeastTableModel.cpp | 46 +--- src/undoRedo/Undoable.cpp | 36 +++ src/undoRedo/Undoable.h | 69 ++++++ ...{BtBoolComboBox.cpp => BtComboBoxBool.cpp} | 36 +-- .../{BtBoolComboBox.h => BtComboBoxBool.h} | 50 ++-- .../{BtComboBox.cpp => BtComboBoxEnum.cpp} | 40 ++-- .../{BtComboBox.h => BtComboBoxEnum.h} | 24 +- ...ComboBox.cpp => BtComboBoxNamedEntity.cpp} | 46 ++-- src/widgets/BtComboBoxNamedEntity.h | 208 ++++++++++++++++ src/widgets/MashComboBox.cpp | 127 ---------- src/widgets/MashComboBox.h | 77 ------ translations/bt_ca.ts | 75 +++++- translations/bt_cs.ts | 75 +++++- translations/bt_da.ts | 70 +++++- translations/bt_de.ts | 75 +++++- translations/bt_el.ts | 75 +++++- translations/bt_en.ts | 81 +++++-- translations/bt_es.ts | 75 +++++- translations/bt_et.ts | 81 +++++-- translations/bt_eu.ts | 81 +++++-- translations/bt_fr.ts | 75 +++++- translations/bt_gl.ts | 81 +++++-- translations/bt_hu.ts | 75 +++++- translations/bt_it.ts | 75 +++++- translations/bt_lv.ts | 81 +++++-- translations/bt_nb.ts | 75 +++++- translations/bt_nl.ts | 75 +++++- translations/bt_pl.ts | 75 +++++- translations/bt_pt.ts | 75 +++++- translations/bt_ru.ts | 75 +++++- translations/bt_sr.ts | 77 ++++-- translations/bt_sv.ts | 75 +++++- translations/bt_tr.ts | 70 +++++- translations/bt_zh.ts | 75 +++++- ui/boilStepEditor.ui | 6 +- ui/fermentableEditor.ui | 10 +- ui/fermentationStepEditor.ui | 10 +- ui/hopEditor.ui | 10 +- ui/mainWindow.ui | 64 +++-- ui/mashStepEditor.ui | 6 +- ui/miscEditor.ui | 8 +- ui/namedMashEditor.ui | 6 +- ui/styleEditor.ui | 6 +- ui/waterDialog.ui | 8 +- ui/waterEditor.ui | 6 +- ui/yeastEditor.ui | 30 +-- 90 files changed, 3132 insertions(+), 1656 deletions(-) create mode 100644 src/listModels/BoilListModel.cpp rename src/{widgets/CustomComboBox.h => listModels/BoilListModel.h} (67%) mode change 100755 => 100644 create mode 100644 src/listModels/FermentationListModel.cpp create mode 100644 src/listModels/FermentationListModel.h create mode 100644 src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp create mode 100644 src/sortFilterProxyModels/BoilSortFilterProxyModel.h create mode 100644 src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp create mode 100644 src/sortFilterProxyModels/FermentationSortFilterProxyModel.h create mode 100644 src/sortFilterProxyModels/MashSortFilterProxyModel.cpp create mode 100644 src/sortFilterProxyModels/MashSortFilterProxyModel.h create mode 100644 src/tableModels/BoilTableModel.cpp create mode 100644 src/tableModels/BoilTableModel.h create mode 100644 src/tableModels/FermentationTableModel.cpp create mode 100644 src/tableModels/FermentationTableModel.h create mode 100644 src/tableModels/MashTableModel.cpp create mode 100644 src/tableModels/MashTableModel.h create mode 100644 src/undoRedo/Undoable.cpp create mode 100644 src/undoRedo/Undoable.h rename src/widgets/{BtBoolComboBox.cpp => BtComboBoxBool.cpp} (86%) rename src/widgets/{BtBoolComboBox.h => BtComboBoxBool.h} (81%) rename src/widgets/{BtComboBox.cpp => BtComboBoxEnum.cpp} (89%) rename src/widgets/{BtComboBox.h => BtComboBoxEnum.h} (94%) rename src/widgets/{CustomComboBox.cpp => BtComboBoxNamedEntity.cpp} (60%) create mode 100755 src/widgets/BtComboBoxNamedEntity.h delete mode 100755 src/widgets/MashComboBox.cpp delete mode 100755 src/widgets/MashComboBox.h diff --git a/CHANGES.markdown b/CHANGES.markdown index 56d80a65a..d1edffe64 100644 --- a/CHANGES.markdown +++ b/CHANGES.markdown @@ -23,10 +23,11 @@ Bug fixes and minor enhancements. * Buttons not displaying icons on Windows, and some missing button text [903](https://github.com/Brewtarget/brewtarget/issues/903) * Country flags not shown on Windows [907](https://github.com/Brewtarget/brewtarget/issues/907) * Ctrl-C copied recipe not shown in correct folder until after restart [909](https://github.com/Brewtarget/brewtarget/issues/909) +* Combo boxes not displaying properly on Windows [894](https://github.com/Brewtarget/brewtarget/issues/894) * Compiler warning: "'void QCheckBox::stateChanged(int)' is deprecated: Use checkStateChanged() instead" [884](https://github.com/Brewtarget/brewtarget/issues/884) ### Release Timestamp -Mon, 23 Dec 2024 04:00:13 +0100 +Sun, 29 Dec 2024 04:00:13 +0100 ## v4.0.12 Bug fixes and minor enhancements. diff --git a/meson.build b/meson.build index 93086c515..4524abe29 100644 --- a/meson.build +++ b/meson.build @@ -690,8 +690,10 @@ commonSourceFiles = files([ 'src/editors/StyleEditor.cpp', 'src/editors/WaterEditor.cpp', 'src/editors/YeastEditor.cpp', + 'src/listModels/BoilListModel.cpp', 'src/listModels/EquipmentListModel.cpp', 'src/listModels/FermentableListModel.cpp', + 'src/listModels/FermentationListModel.cpp', 'src/listModels/HopListModel.cpp', 'src/listModels/MashListModel.cpp', 'src/listModels/MashStepListModel.cpp', @@ -766,9 +768,12 @@ commonSourceFiles = files([ 'src/serialization/xml/XmlRecipeRecord.cpp', 'src/serialization/xml/XmlRecord.cpp', 'src/serialization/xml/XmlRecordDefinition.cpp', + 'src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/EquipmentSortFilterProxyModel.cpp', + 'src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/FermentableSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/HopSortFilterProxyModel.cpp', + 'src/sortFilterProxyModels/MashSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/MiscSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/RecipeAdditionFermentableSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/RecipeAdditionHopSortFilterProxyModel.cpp', @@ -778,12 +783,15 @@ commonSourceFiles = files([ 'src/sortFilterProxyModels/WaterSortFilterProxyModel.cpp', 'src/sortFilterProxyModels/YeastSortFilterProxyModel.cpp', 'src/tableModels/BoilStepTableModel.cpp', + 'src/tableModels/BoilTableModel.cpp', 'src/tableModels/BtTableModel.cpp', 'src/tableModels/EquipmentTableModel.cpp', 'src/tableModels/FermentableTableModel.cpp', 'src/tableModels/FermentationStepTableModel.cpp', + 'src/tableModels/FermentationTableModel.cpp', 'src/tableModels/HopTableModel.cpp', 'src/tableModels/MashStepTableModel.cpp', + 'src/tableModels/MashTableModel.cpp', 'src/tableModels/MiscTableModel.cpp', 'src/tableModels/RecipeAdditionFermentableTableModel.cpp', 'src/tableModels/RecipeAdditionHopTableModel.cpp', @@ -799,6 +807,7 @@ commonSourceFiles = files([ 'src/trees/TreeNode.cpp', 'src/trees/TreeView.cpp', 'src/undoRedo/SimpleUndoableUpdate.cpp', + 'src/undoRedo/Undoable.cpp', 'src/utils/BtException.cpp', 'src/utils/BtStringConst.cpp', 'src/utils/BtStringStream.cpp', @@ -814,13 +823,12 @@ commonSourceFiles = files([ 'src/utils/TimerUtils.cpp', 'src/utils/TypeLookup.cpp', 'src/widgets/Animator.cpp', - 'src/widgets/BtBoolComboBox.cpp', - 'src/widgets/BtComboBox.cpp', + 'src/widgets/BtComboBoxBool.cpp', + 'src/widgets/BtComboBoxEnum.cpp', + 'src/widgets/BtComboBoxNamedEntity.cpp', 'src/widgets/BtOptionalDateEdit.cpp', - 'src/widgets/CustomComboBox.cpp', 'src/widgets/InfoButton.cpp', 'src/widgets/InfoText.cpp', - 'src/widgets/MashComboBox.cpp', 'src/widgets/SelectionControl.cpp', 'src/widgets/SmartAmountSettings.cpp', 'src/widgets/SmartAmounts.cpp', @@ -915,8 +923,10 @@ mocHeaders = files([ 'src/editors/StyleEditor.h', 'src/editors/WaterEditor.h', 'src/editors/YeastEditor.h', + 'src/listModels/BoilListModel.h', 'src/listModels/EquipmentListModel.h', 'src/listModels/FermentableListModel.h', + 'src/listModels/FermentationListModel.h', 'src/listModels/HopListModel.h', 'src/listModels/MashListModel.h', 'src/listModels/MashStepListModel.h', @@ -968,9 +978,12 @@ mocHeaders = files([ 'src/model/Style.h', 'src/model/Water.h', 'src/model/Yeast.h', + 'src/sortFilterProxyModels/BoilSortFilterProxyModel.h', 'src/sortFilterProxyModels/EquipmentSortFilterProxyModel.h', 'src/sortFilterProxyModels/FermentableSortFilterProxyModel.h', + 'src/sortFilterProxyModels/FermentationSortFilterProxyModel.h', 'src/sortFilterProxyModels/HopSortFilterProxyModel.h', + 'src/sortFilterProxyModels/MashSortFilterProxyModel.h', 'src/sortFilterProxyModels/MiscSortFilterProxyModel.h', 'src/sortFilterProxyModels/RecipeAdditionFermentableSortFilterProxyModel.h', 'src/sortFilterProxyModels/RecipeAdditionHopSortFilterProxyModel.h', @@ -980,12 +993,15 @@ mocHeaders = files([ 'src/sortFilterProxyModels/WaterSortFilterProxyModel.h', 'src/sortFilterProxyModels/YeastSortFilterProxyModel.h', 'src/tableModels/BoilStepTableModel.h', + 'src/tableModels/BoilTableModel.h', 'src/tableModels/BtTableModel.h', 'src/tableModels/EquipmentTableModel.h', 'src/tableModels/FermentableTableModel.h', 'src/tableModels/FermentationStepTableModel.h', + 'src/tableModels/FermentationTableModel.h', 'src/tableModels/HopTableModel.h', 'src/tableModels/MashStepTableModel.h', + 'src/tableModels/MashTableModel.h', 'src/tableModels/MiscTableModel.h', 'src/tableModels/RecipeAdditionFermentableTableModel.h', 'src/tableModels/RecipeAdditionHopTableModel.h', @@ -1000,10 +1016,10 @@ mocHeaders = files([ 'src/trees/TreeModel.h', 'src/trees/TreeView.h', 'src/widgets/Animator.h', - 'src/widgets/BtBoolComboBox.h', - 'src/widgets/BtComboBox.h', + 'src/widgets/BtComboBoxBool.h', + 'src/widgets/BtComboBoxEnum.h', + 'src/widgets/BtComboBoxNamedEntity.h', 'src/widgets/BtOptionalDateEdit.h', - 'src/widgets/CustomComboBox.h', 'src/widgets/InfoButton.h', 'src/widgets/InfoText.h', 'src/widgets/SelectionControl.h', diff --git a/src/BtFieldType.h b/src/BtFieldType.h index d022424ff..8eb3d5357 100644 --- a/src/BtFieldType.h +++ b/src/BtFieldType.h @@ -35,8 +35,9 @@ enum class NonPhysicalQuantity { Date, String, Percentage, + //! This usually means we need either a \c QCheckBox or a \c BtComboBoxBool Bool, - //! This usually means we need a \c BtComboBox + //! This usually means we need a \c BtComboBoxEnum Enum, /** * This is for things like step number and other orderings where we have 1st, 2nd, 3rd etc (though its usually diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index acf21d914..e722e66ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,8 +121,10 @@ set(filesToCompile_cpp ${repoDir}/src/editors/StyleEditor.cpp ${repoDir}/src/editors/WaterEditor.cpp ${repoDir}/src/editors/YeastEditor.cpp + ${repoDir}/src/listModels/BoilListModel.cpp ${repoDir}/src/listModels/EquipmentListModel.cpp ${repoDir}/src/listModels/FermentableListModel.cpp + ${repoDir}/src/listModels/FermentationListModel.cpp ${repoDir}/src/listModels/HopListModel.cpp ${repoDir}/src/listModels/MashListModel.cpp ${repoDir}/src/listModels/MashStepListModel.cpp @@ -197,9 +199,12 @@ set(filesToCompile_cpp ${repoDir}/src/serialization/xml/XmlRecipeRecord.cpp ${repoDir}/src/serialization/xml/XmlRecord.cpp ${repoDir}/src/serialization/xml/XmlRecordDefinition.cpp + ${repoDir}/src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/EquipmentSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/FermentableSortFilterProxyModel.cpp + ${repoDir}/src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/HopSortFilterProxyModel.cpp + ${repoDir}/src/sortFilterProxyModels/MashSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/MiscSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/RecipeAdditionFermentableSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/RecipeAdditionHopSortFilterProxyModel.cpp @@ -209,12 +214,15 @@ set(filesToCompile_cpp ${repoDir}/src/sortFilterProxyModels/WaterSortFilterProxyModel.cpp ${repoDir}/src/sortFilterProxyModels/YeastSortFilterProxyModel.cpp ${repoDir}/src/tableModels/BoilStepTableModel.cpp + ${repoDir}/src/tableModels/BoilTableModel.cpp ${repoDir}/src/tableModels/BtTableModel.cpp ${repoDir}/src/tableModels/EquipmentTableModel.cpp ${repoDir}/src/tableModels/FermentableTableModel.cpp ${repoDir}/src/tableModels/FermentationStepTableModel.cpp + ${repoDir}/src/tableModels/FermentationTableModel.cpp ${repoDir}/src/tableModels/HopTableModel.cpp ${repoDir}/src/tableModels/MashStepTableModel.cpp + ${repoDir}/src/tableModels/MashTableModel.cpp ${repoDir}/src/tableModels/MiscTableModel.cpp ${repoDir}/src/tableModels/RecipeAdditionFermentableTableModel.cpp ${repoDir}/src/tableModels/RecipeAdditionHopTableModel.cpp @@ -230,6 +238,7 @@ set(filesToCompile_cpp ${repoDir}/src/trees/TreeNode.cpp ${repoDir}/src/trees/TreeView.cpp ${repoDir}/src/undoRedo/SimpleUndoableUpdate.cpp + ${repoDir}/src/undoRedo/Undoable.cpp ${repoDir}/src/utils/BtException.cpp ${repoDir}/src/utils/BtStringConst.cpp ${repoDir}/src/utils/BtStringStream.cpp @@ -245,13 +254,12 @@ set(filesToCompile_cpp ${repoDir}/src/utils/TimerUtils.cpp ${repoDir}/src/utils/TypeLookup.cpp ${repoDir}/src/widgets/Animator.cpp - ${repoDir}/src/widgets/BtBoolComboBox.cpp - ${repoDir}/src/widgets/BtComboBox.cpp + ${repoDir}/src/widgets/BtComboBoxBool.cpp + ${repoDir}/src/widgets/BtComboBoxEnum.cpp + ${repoDir}/src/widgets/BtComboBoxNamedEntity.cpp ${repoDir}/src/widgets/BtOptionalDateEdit.cpp - ${repoDir}/src/widgets/CustomComboBox.cpp ${repoDir}/src/widgets/InfoButton.cpp ${repoDir}/src/widgets/InfoText.cpp - ${repoDir}/src/widgets/MashComboBox.cpp ${repoDir}/src/widgets/SelectionControl.cpp ${repoDir}/src/widgets/SmartAmountSettings.cpp ${repoDir}/src/widgets/SmartAmounts.cpp diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index eeed1c136..3e39f8b82 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -153,6 +153,7 @@ #include "tableModels/RecipeAdditionMiscTableModel.h" #include "tableModels/RecipeAdditionYeastTableModel.h" #include "undoRedo/RelationalUndoableUpdate.h" +#include "undoRedo/Undoable.h" #include "undoRedo/UndoableAddOrRemove.h" #include "undoRedo/UndoableAddOrRemoveList.h" #include "utils/BtStringConst.h" @@ -236,7 +237,6 @@ class MainWindow::impl { impl(MainWindow & self) : m_self{self}, - m_undoStack{std::make_unique(&m_self)}, m_boilStepTableModel {nullptr}, m_fermentationStepTableModel {nullptr}, m_mashStepTableModel {nullptr}, @@ -247,8 +247,7 @@ class MainWindow::impl { m_fermentableAdditionsTableProxy{nullptr}, m_hopAdditionsTableProxy {nullptr}, m_miscAdditionsTableProxy {nullptr}, - m_yeastAdditionsTableProxy {nullptr}, - m_styleProxyModel {nullptr} { + m_yeastAdditionsTableProxy {nullptr} { return; } @@ -414,27 +413,17 @@ class MainWindow::impl { * Any new combo boxes, along with their list models, should be initialized here */ void setupComboBoxes() { - // Set equipment combo box model. - m_equipmentListModel = std::make_unique(m_self.equipmentComboBox); - m_self.equipmentComboBox->setModel(m_equipmentListModel.get()); - - // Set the style combo box - m_styleListModel = std::make_unique(m_self.styleComboBox); - m_styleProxyModel = std::make_unique(m_self.styleComboBox); - m_styleProxyModel->setDynamicSortFilter(true); - m_styleProxyModel->setSortLocaleAware(true); - m_styleProxyModel->setSourceModel(m_styleListModel.get()); - m_styleProxyModel->sort(0); - m_self.styleComboBox->setModel(m_styleProxyModel.get()); - - // Set the mash combo box - m_mashListModel = std::make_unique(m_self.mashComboBox); - m_self.mashComboBox->setModel(m_mashListModel.get()); + m_self.equipmentComboBox->init(); + m_self.styleComboBox->init(); + m_self.mashComboBox->init(); + m_self.boilComboBox->init(); + m_self.fermentationComboBox->init(); // Nothing to say. m_namedMashEditor = std::make_unique(&m_self, m_mashStepEditor.get()); // I don't think this is used yet m_singleNamedMashEditor = std::make_unique(&m_self, m_mashStepEditor.get(), true); + return; } /** @@ -477,7 +466,7 @@ class MainWindow::impl { void doRecipeAddition(std::shared_ptr ra) { Q_ASSERT(ra); - this->m_self.doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemove(*this->m_recipeObs, &Recipe::addAddition, ra, @@ -523,7 +512,7 @@ class MainWindow::impl { } for (auto item : itemsToRemove) { - this->m_self.doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemove(*this->m_recipeObs, &Recipe::removeAddition, item, @@ -651,7 +640,7 @@ class MainWindow::impl { auto & stepTableModel = this->getStepTableModel(); auto step = stepTableModel.getRow(row); - this->m_self.doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemove(*stepOwner, &StepClass::StepOwnerClass::remove, step, @@ -848,7 +837,6 @@ class MainWindow::impl { } void setBrewNote(BrewNote * bNote) { -/// QString tabname; BrewNoteWidget* ni = this->findBrewNoteWidget(bNote); if (ni) { this->m_self.tabWidget_recipeView->setCurrentWidget(ni); @@ -867,10 +855,6 @@ class MainWindow::impl { MainWindow & m_self; - // Undo / Redo, using the Qt Undo framework - std::unique_ptr m_undoStack; - - Recipe * m_recipeObs = nullptr; @@ -888,7 +872,6 @@ class MainWindow::impl { std::unique_ptr m_hopAdditionsTableProxy ; std::unique_ptr m_miscAdditionsTableProxy ; std::unique_ptr m_yeastAdditionsTableProxy ; - std::unique_ptr m_styleProxyModel ; // All initialised in setupDialogs std::unique_ptr m_aboutDialog ; @@ -931,17 +914,10 @@ class MainWindow::impl { std::unique_ptr m_yeastCatalog ; std::unique_ptr m_yeastEditor ; - // all things lists should go here - std::unique_ptr m_equipmentListModel; - std::unique_ptr m_mashListModel ; - std::unique_ptr m_styleListModel ; -// std::unique_ptr waterListModel; Appears to be unused... std::unique_ptr m_namedMashEditor; std::unique_ptr m_singleNamedMashEditor; QString highSS, lowSS, goodSS, boldSS; // Palette replacements -/// QPrinter * printer = nullptr; - }; @@ -1044,14 +1020,6 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), pimpl{std::make_u // Null out the recipe this->pimpl->m_recipeObs = nullptr; -/// // Set up the printer -/// this->pimpl->printer = new QPrinter; -///#if QT_VERSION < QT_VERSION_CHECK(5,15,0) -/// this->pimpl->printer->setPageSize(QPrinter::Letter); -///#else -/// this->pimpl->printer->setPageSize(QPageSize(QPageSize::Letter)); -///#endif - return; } @@ -1156,13 +1124,13 @@ void MainWindow::DeleteMainWindow() { } // Setup the keyboard shortcuts -void MainWindow::setupShortCuts() -{ - actionNewRecipe->setShortcut(QKeySequence::New); - actionCopySelected->setShortcut(QKeySequence::Copy); - actionDeleteSelected->setShortcut(QKeySequence::Delete); - actionUndo->setShortcut(QKeySequence::Undo); - actionRedo->setShortcut(QKeySequence::Redo); +void MainWindow::setupShortCuts() { + this->actionNewRecipe->setShortcut(QKeySequence::New); + this->actionCopySelected->setShortcut(QKeySequence::Copy); + this->actionDeleteSelected->setShortcut(QKeySequence::Delete); + this->actionUndo->setShortcut(QKeySequence::Undo); + this->actionRedo->setShortcut(QKeySequence::Redo); + return; } void MainWindow::setUpStateChanges() { @@ -1400,7 +1368,7 @@ void MainWindow::setupTriggers() { connect(actionExportToXml , &QAction::triggered, this , &MainWindow::exportRecipe ); // > File > Export Recipes connect(actionUndo , &QAction::triggered, this , &MainWindow::editUndo ); // > Edit > Undo connect(actionRedo , &QAction::triggered, this , &MainWindow::editRedo ); // > Edit > Redo - setUndoRedoEnable(); + this->setUndoRedoEnable(); connect(actionEquipments , &QAction::triggered, this->pimpl->m_equipCatalog.get() , &QWidget::show ); // > View > Equipments connect(actionMashs , &QAction::triggered, this->pimpl->m_namedMashEditor.get() , &QWidget::show ); // > View > Mashs connect(actionStyles , &QAction::triggered, this->pimpl->m_styleCatalog.get() , &QWidget::show ); // > View > Styles @@ -1454,9 +1422,8 @@ void MainWindow::setupClicks() { connect(this->equipmentButton , &QAbstractButton::clicked, this , &MainWindow::showEquipmentEditor); connect(this->styleButton , &QAbstractButton::clicked, this , &MainWindow::showStyleEditor ); connect(this->mashButton , &QAbstractButton::clicked, this->pimpl->m_mashEditor , &MashEditor::showEditor); - // TODO: Make these buttons! -// connect(this->boilButton , &QAbstractButton::clicked, this->pimpl->m_boilEditor , &BoilEditor::showEditor); -// connect(this->fermentationButton , &QAbstractButton::clicked, this->pimpl->m_fermentationEditor, &FermentationEditor::showEditor); + connect(this->boilButton , &QAbstractButton::clicked, this->pimpl->m_boilEditor , &BoilEditor::showEditor); + connect(this->fermentationButton , &QAbstractButton::clicked, this->pimpl->m_fermentationEditor, &FermentationEditor::showEditor); connect(this->pushButton_addFerm , &QAbstractButton::clicked, this->pimpl->m_fermCatalog , &QWidget::show ); connect(this->pushButton_addHop , &QAbstractButton::clicked, this->pimpl->m_hopCatalog , &QWidget::show ); connect(this->pushButton_addMisc , &QAbstractButton::clicked, this->pimpl->m_miscCatalog , &QWidget::show ); @@ -1748,31 +1715,35 @@ void MainWindow::setRecipe(Recipe* recipe) { // Tell some of our other widgets to observe the new recipe. this->pimpl->m_mashWizard->setRecipe(recipe); brewDayScrollWidget->setRecipe(recipe); - this->pimpl->m_equipmentListModel->observeRecipe(recipe); this->pimpl->m_recipeFormatter->setRecipe(recipe); this->pimpl->m_ogAdjuster->setRecipe(recipe); recipeExtrasWidget->setRecipe(recipe); this->pimpl->m_mashDesigner->setRecipe(recipe); - equipmentButton->setRecipe(recipe); + this->equipmentButton->setRecipe(recipe); + this->equipmentComboBox->setItem(recipe->equipment()); if (recipe->equipment()) { this->pimpl->m_equipEditor->setEditItem(recipe->equipment()); } - styleButton->setRecipe(recipe); + this->styleButton->setRecipe(recipe); + this->styleComboBox->setItem(recipe->style()); if (recipe->style()) { this->pimpl->m_styleEditor->setEditItem(recipe->style()); } - this->pimpl->m_mashEditor->setMash(this->pimpl->m_recipeObs->mash()); - this->pimpl->m_mashEditor->setRecipe(this->pimpl->m_recipeObs); + this->pimpl->m_mashEditor->setMash(recipe->mash()); + this->pimpl->m_mashEditor->setRecipe(recipe); + this->mashButton->setMash(recipe->mash()); + this->mashComboBox->setItem(recipe->mash()); - this->pimpl->m_boilEditor->setEditItem(this->pimpl->m_recipeObs->boil()); - this->pimpl->m_boilEditor->setRecipe(this->pimpl->m_recipeObs); + this->pimpl->m_boilEditor->setEditItem(recipe->boil()); + this->pimpl->m_boilEditor->setRecipe(recipe); + this->boilComboBox->setItem(recipe->boil()); - this->pimpl->m_fermentationEditor->setEditItem(this->pimpl->m_recipeObs->fermentation()); - this->pimpl->m_fermentationEditor->setRecipe(this->pimpl->m_recipeObs); + this->pimpl->m_fermentationEditor->setEditItem(recipe->fermentation()); + this->pimpl->m_fermentationEditor->setRecipe(recipe); + this->fermentationComboBox->setItem(recipe->fermentation()); - mashButton->setMash(this->pimpl->m_recipeObs->mash()); - this->pimpl->m_recipeScaler->setRecipe(this->pimpl->m_recipeObs); + this->pimpl->m_recipeScaler->setRecipe(recipe); // Set the locked flag as required checkBox_locked->setCheckState( recipe->locked() ? Qt::Checked : Qt::Unchecked ); @@ -2026,7 +1997,7 @@ void MainWindow::updateRecipeName() { return; } - this->doOrRedoUpdate(*this->pimpl->m_recipeObs, + Undoable::doOrRedoUpdate(*this->pimpl->m_recipeObs, TYPE_INFO(Recipe, NamedEntity, name), lineEdit_name->text(), tr("Change Recipe Name")); @@ -2053,24 +2024,23 @@ void MainWindow::displayRangesEtcForCurrentRecipeStyle() { this->styleRangeWidget_srm->setPreferredRange(this->colorSRMLabel->getRangeToDisplay(style->colorMin_srm(), style->colorMax_srm())); this->styleButton->setStyle(style); + this->styleComboBox->setItem(style); return; } // -// TODO: Would be good to harmonise how these updatRecipeFoo and dropRecipeFoo functions work +// TODO: Would be good to harmonise how these updateRecipeFoo and dropRecipeFoo functions work // void MainWindow::updateRecipeStyle() { - if (this->pimpl->m_recipeObs == nullptr) { + if (!this->pimpl->m_recipeObs) { return; } - QModelIndex proxyIndex( this->pimpl->m_styleProxyModel->index(styleComboBox->currentIndex(),0) ); - QModelIndex sourceIndex( this->pimpl->m_styleProxyModel->mapToSource(proxyIndex) ); - auto selected = ObjectStoreWrapper::getSharedFromRaw(this->pimpl->m_styleListModel->at(sourceIndex.row())); + auto selected = this->styleComboBox->getItem(); if (selected) { - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newRelationalUndoableUpdate(*this->pimpl->m_recipeObs, &Recipe::setStyle, this->pimpl->m_recipeObs->style(), @@ -2083,30 +2053,48 @@ void MainWindow::updateRecipeStyle() { } void MainWindow::updateRecipeMash() { - if (this->pimpl->m_recipeObs == nullptr) { + if (!this->pimpl->m_recipeObs) { return; } - auto selectedMash = ObjectStoreWrapper::getSharedFromRaw( - this->pimpl->m_mashListModel->at(mashComboBox->currentIndex()) - ); - if (selectedMash) { - // The Recipe will decide whether it needs to make a copy of the Mash, hence why we don't reuse "selectedMash" below - this->pimpl->m_recipeObs->setMash(selectedMash); - this->pimpl->m_mashEditor->setMash(this->pimpl->m_recipeObs->mash()); - mashButton->setMash(this->pimpl->m_recipeObs->mash()); + auto selected = this->mashComboBox->getItem(); + if (selected) { + Undoable::doOrRedoUpdate( + newRelationalUndoableUpdate(*this->pimpl->m_recipeObs, + &Recipe::setMash, + this->pimpl->m_recipeObs->mash(), + selected, + nullptr, + tr("Change Recipe Mash")) + ); } return; } void MainWindow::updateRecipeEquipment() { - droppedRecipeEquipment(this->pimpl->m_equipmentListModel->at(equipmentComboBox->currentIndex())); - return; + if (!this->pimpl->m_recipeObs) { + return; + } + + auto selected = this->equipmentComboBox->getItem(); + if (selected) { + Undoable::doOrRedoUpdate( + newRelationalUndoableUpdate(*this->pimpl->m_recipeObs, + &Recipe::setEquipment, + this->pimpl->m_recipeObs->equipment(), + selected, + &MainWindow::updateEquipmentSelector, + tr("Change Recipe Equipment")) + ); + } + return; } -void MainWindow::updateEquipmentButton() { +void MainWindow::updateEquipmentSelector() { if (this->pimpl->m_recipeObs != nullptr) { - this->equipmentButton->setEquipment(this->pimpl->m_recipeObs->equipment()); + auto equipment = this->pimpl->m_recipeObs->equipment(); + this->equipmentButton->setEquipment(equipment); + this->equipmentComboBox->setItem(equipment); } return; } @@ -2128,7 +2116,7 @@ void MainWindow::droppedRecipeEquipment(Equipment * kitRaw) { &Recipe::setEquipment, this->pimpl->m_recipeObs->equipment(), kit, - &MainWindow::updateEquipmentButton, + &MainWindow::updateEquipmentSelector, tr("Change Recipe Kit")); // Keep the mash tun weight and specific heat up to date. @@ -2159,7 +2147,7 @@ void MainWindow::droppedRecipeEquipment(Equipment * kitRaw) { } // This will do the equipment update and any related updates - see above - this->doOrRedoUpdate(equipmentUpdate); + Undoable::doOrRedoUpdate(equipmentUpdate); return; } @@ -2172,7 +2160,7 @@ void MainWindow::droppedRecipeStyle(Style * styleRaw) { // When the style is changed, we also need to update what is shown on the Style button qDebug() << Q_FUNC_INFO << "Do or redo"; auto style = ObjectStoreWrapper::getSharedFromRaw(styleRaw); - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newRelationalUndoableUpdate(*this->pimpl->m_recipeObs, &Recipe::setStyle, this->pimpl->m_recipeObs->style(), @@ -2197,7 +2185,7 @@ void MainWindow::droppedRecipeFermentable(QList fermentables) { QList> fermentableAdditions = RecipeAdditionFermentable::create(*this->pimpl->m_recipeObs, fermentables); - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemoveList(*this->pimpl->m_recipeObs, &Recipe::addAddition, fermentableAdditions, @@ -2218,7 +2206,7 @@ void MainWindow::droppedRecipeHop(QList hops) { auto hopAdditions = RecipeAdditionHop::create(*this->pimpl->m_recipeObs, hops); - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemoveList(*this->pimpl->m_recipeObs, &Recipe::addAddition, hopAdditions, @@ -2239,7 +2227,7 @@ void MainWindow::droppedRecipeMisc(QList miscs) { auto miscAdditions = RecipeAdditionMisc::create(*this->pimpl->m_recipeObs, miscs); - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemoveList(*this->pimpl->m_recipeObs, &Recipe::addAddition, miscAdditions, @@ -2260,7 +2248,7 @@ void MainWindow::droppedRecipeYeast(QList yeasts) { auto yeastAdditions = RecipeAdditionYeast::create(*this->pimpl->m_recipeObs, yeasts); - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemoveList(*this->pimpl->m_recipeObs, &Recipe::addAddition, yeastAdditions, @@ -2275,7 +2263,7 @@ void MainWindow::updateRecipeBatchSize() { return; } - this->doOrRedoUpdate(*this->pimpl->m_recipeObs, + Undoable::doOrRedoUpdate(*this->pimpl->m_recipeObs, TYPE_INFO(Recipe, batchSize_l), lineEdit_batchSize->getNonOptCanonicalQty(), tr("Change Batch Size")); @@ -2289,7 +2277,7 @@ void MainWindow::updateRecipeBatchSize() { /// /// // See comments in model/Boil.h for why boil size is, technically, optional /// auto boil = this->pimpl->m_recipeObs->nonOptBoil(); -/// this->doOrRedoUpdate(*boil, +/// Undoable::doOrRedoUpdate(*boil, /// TYPE_INFO(Boil, preBoilSize_l), /// lineEdit_boilSize->getOptCanonicalQty(), /// tr("Change Boil Size")); @@ -2308,10 +2296,10 @@ void MainWindow::updateRecipeBatchSize() { /// // this->pimpl->m_recipeObs->boilSize_l /// // NOTE: This works because kit is the recipe's equipment, not the generic equipment in the recipe drop down. /// if (kit) { -/// this->doOrRedoUpdate(*kit, TYPE_INFO(Equipment, boilTime_min), boilTime, tr("Change Boil Time")); +/// Undoable::doOrRedoUpdate(*kit, TYPE_INFO(Equipment, boilTime_min), boilTime, tr("Change Boil Time")); /// } else { /// auto boil = this->pimpl->m_recipeObs->nonOptBoil(); -/// this->doOrRedoUpdate(*boil, TYPE_INFO(Boil, boilTime_mins), boilTime, tr("Change Boil Time")); +/// Undoable::doOrRedoUpdate(*boil, TYPE_INFO(Boil, boilTime_mins), boilTime, tr("Change Boil Time")); /// } /// /// return; @@ -2323,7 +2311,7 @@ void MainWindow::updateRecipeEfficiency() { return; } - this->doOrRedoUpdate(*this->pimpl->m_recipeObs, + Undoable::doOrRedoUpdate(*this->pimpl->m_recipeObs, TYPE_INFO(Recipe, efficiency_pct), lineEdit_efficiency->getNonOptValue(), tr("Change Recipe Efficiency")); @@ -2393,7 +2381,7 @@ void MainWindow::addStepToStepOwner(StepOwnerClass & stepOwner, std::shared_ptr< qWarning() << Q_FUNC_INFO << step->metaObject()->className() << "unexpectedly not in DB, so inserting it now."; ObjectStoreWrapper::insert(step); } - this->doOrRedoUpdate( + Undoable::doOrRedoUpdate( newUndoableAddOrRemove(stepOwner, &StepOwnerClass::add, step, @@ -2406,6 +2394,13 @@ void MainWindow::addStepToStepOwner(StepOwnerClass & stepOwner, std::shared_ptr< return; } +// We need to directly instantiate the above so that it can be called from StepEditorBase. (Although we might expect it +// is indirectly instantiated by the MainWindow::addStepToStepOwner overloads below, that might not be visible outside +// this translation unit, because of compiler optimisations.) +template void MainWindow::addStepToStepOwner(Boil & stepOwner, std::shared_ptr< BoilStep> step); +template void MainWindow::addStepToStepOwner(Mash & stepOwner, std::shared_ptr< MashStep> step); +template void MainWindow::addStepToStepOwner(Fermentation & stepOwner, std::shared_ptr step); + template void MainWindow::addStepToStepOwner(std::shared_ptr stepOwner, std::shared_ptr step) { this->addStepToStepOwner(*stepOwner, step); @@ -2445,46 +2440,38 @@ Recipe* MainWindow::currentRecipe() { } void MainWindow::setUndoRedoEnable() { - Q_ASSERT(this->pimpl->m_undoStack != 0); - actionUndo->setEnabled(this->pimpl->m_undoStack->canUndo()); - actionRedo->setEnabled(this->pimpl->m_undoStack->canRedo()); + QUndoStack & undoStack { Undoable::getStack() }; + this->actionUndo->setEnabled(undoStack.canUndo()); + this->actionRedo->setEnabled(undoStack.canRedo()); - actionUndo->setText(QString(tr("Undo %1").arg(this->pimpl->m_undoStack->undoText()))); - actionRedo->setText(QString(tr("Redo %1").arg(this->pimpl->m_undoStack->redoText()))); - - return; -} + this->actionUndo->setText(QString(tr("Undo %1").arg(undoStack.undoText()))); + this->actionRedo->setText(QString(tr("Redo %1").arg(undoStack.redoText()))); -void MainWindow::doOrRedoUpdate(QUndoCommand * update) { - Q_ASSERT(this->pimpl->m_undoStack != nullptr); - Q_ASSERT(update != nullptr); - this->pimpl->m_undoStack->push(update); - this->setUndoRedoEnable(); return; } // For undo/redo, we use Qt's Undo framework void MainWindow::editUndo() { - Q_ASSERT(this->pimpl->m_undoStack != 0); - if ( !this->pimpl->m_undoStack->canUndo() ) { + QUndoStack & undoStack { Undoable::getStack() }; + if (!undoStack.canUndo()) { qDebug() << "Undo called but nothing to undo"; } else { - this->pimpl->m_undoStack->undo(); + undoStack.undo(); } - setUndoRedoEnable(); + this->setUndoRedoEnable(); return; } void MainWindow::editRedo() { - Q_ASSERT(this->pimpl->m_undoStack != 0); - if ( !this->pimpl->m_undoStack->canRedo() ) { + QUndoStack & undoStack { Undoable::getStack() }; + if (!undoStack.canRedo()) { qDebug() << "Redo called but nothing to redo"; } else { - this->pimpl->m_undoStack->redo(); + undoStack.redo(); } - setUndoRedoEnable(); + this->setUndoRedoEnable(); return; } diff --git a/src/MainWindow.h b/src/MainWindow.h index a9d5099c4..182d3f5c3 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -92,33 +92,10 @@ class MainWindow : public QMainWindow, public Ui::mainWindow { //! \brief Get the currently observed recipe. Recipe* currentRecipe(); -public: - //! \brief Doing updates via this method makes them undoable (and redoable). This is the simplified version - // which suffices for modifications to most individual non-relational attributes. - template - void doOrRedoUpdate(NamedEntity & updatee, - TypeInfo const & typeInfo, - T newValue, - QString const & description, - [[maybe_unused]] QUndoCommand * parent = nullptr) { - this->doOrRedoUpdate(new SimpleUndoableUpdate(updatee, typeInfo, newValue, description)); - return; - } + //! \brief Set whether undo / redo commands are enabled + void setUndoRedoEnable(); - /** - * \brief This version of \c doOrRedoUpdate is needed when updating a property that has (or might have) a non-trivial - * \c PropertyPath - */ - template - void doOrRedoUpdate(NamedEntity & updatee, - PropertyPath const & propertyPath, - TypeInfo const & typeInfo, - T newValue, - QString const & description, - [[maybe_unused]] QUndoCommand * parent = nullptr) { - this->doOrRedoUpdate(new SimpleUndoableUpdate(updatee, propertyPath, typeInfo, newValue, description)); - return; - } +public: /** * \brief Add given \c Fermentable / \c Hop / \c Misc / \c Yeast to the Recipe @@ -274,7 +251,7 @@ public slots: void showEquipmentEditor(); void showStyleEditor(); - void updateEquipmentButton(); + void updateEquipmentSelector(); //! \brief Set all the things based on a drop event void droppedRecipeEquipment(Equipment *kit); @@ -286,10 +263,6 @@ public slots: void versionedRecipe(Recipe* descendant); - //! \brief Doing updates via this method makes them undoable (and redoable). This is the most generic version - // which requires the caller to construct a QUndoCommand. - void doOrRedoUpdate(QUndoCommand * update); - //! \brief to lock or not was never the question before now. #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) void lockRecipe(Qt::CheckState state); @@ -322,10 +295,6 @@ public slots: //! \brief Overrides \c QWidget::closeEvent virtual void closeEvent(QCloseEvent* event) override; -private slots: - //! \brief Set whether undo / redo commands are enabled - void setUndoRedoEnable(); - signals: /** * \brief Emitted when \c MainWindow object is initialised (at end of \c MainWindow::initialiseAndMakeVisible). diff --git a/src/RecipeExtrasWidget.cpp b/src/RecipeExtrasWidget.cpp index c15fec2f4..858fe5668 100644 --- a/src/RecipeExtrasWidget.cpp +++ b/src/RecipeExtrasWidget.cpp @@ -23,9 +23,9 @@ #include #include -#include "MainWindow.h" #include "measurement/Unit.h" #include "model/Recipe.h" +#include "undoRedo/Undoable.h" #include "utils/OptionalHelpers.h" RecipeExtrasWidget::RecipeExtrasWidget(QWidget* parent) : @@ -82,14 +82,14 @@ void RecipeExtrasWidget::setRecipe(Recipe* rec) { void RecipeExtrasWidget::updateBrewer() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, brewer), lineEdit_brewer->text(), tr("Change Brewer")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, brewer), lineEdit_brewer->text(), tr("Change Brewer")); return; } void RecipeExtrasWidget::updateBrewerAsst() { if (!this->recipe) { return; } if ( lineEdit_asstBrewer->isModified() ) { - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, asstBrewer), lineEdit_asstBrewer->text(), tr("Change Assistant Brewer")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, asstBrewer), lineEdit_asstBrewer->text(), tr("Change Assistant Brewer")); } return; } @@ -100,7 +100,7 @@ void RecipeExtrasWidget::updateTasteRating() { if (!this->recipe) { return; } if ( ratingChanged ) { - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, tasteRating), spinBox_tasteRating->value(), tr("Change Taste Rating")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, tasteRating), spinBox_tasteRating->value(), tr("Change Taste Rating")); ratingChanged = false; } return; @@ -108,12 +108,12 @@ void RecipeExtrasWidget::updateTasteRating() { void RecipeExtrasWidget::updateAge() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, age_days), lineEdit_age->getNonOptValue(), tr("Change Age")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, age_days), lineEdit_age->getNonOptValue(), tr("Change Age")); } void RecipeExtrasWidget::updateAgeTemp() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, ageTemp_c), lineEdit_ageTemp->getNonOptCanonicalQty(), tr("Change Age Temp")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, ageTemp_c), lineEdit_ageTemp->getNonOptCanonicalQty(), tr("Change Age Temp")); } void RecipeExtrasWidget::updateDate(std::optional const date) { @@ -133,7 +133,7 @@ void RecipeExtrasWidget::updateDate(std::optional const date) { // signal that ends up calling this function to say the date on the Recipe has changed, which it hasn't. if (date != this->recipe->date()) { qDebug() << Q_FUNC_INFO; - MainWindow::instance().doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, date), date, tr("Change Date")); + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, date), date, tr("Change Date")); } return; } @@ -141,7 +141,7 @@ void RecipeExtrasWidget::updateDate(std::optional const date) { void RecipeExtrasWidget::updateCarbonation() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, carbonation_vols), lineEdit_carbVols->getNonOptCanonicalQty(), tr("Change Carbonation")); @@ -150,7 +150,7 @@ void RecipeExtrasWidget::updateCarbonation() { void RecipeExtrasWidget::updateTasteNotes() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, tasteNotes), btTextEdit_tasteNotes->toPlainText(), tr("Edit Taste Notes")); @@ -159,7 +159,7 @@ void RecipeExtrasWidget::updateTasteNotes() { void RecipeExtrasWidget::updateNotes() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, notes), btTextEdit_notes->toPlainText(), tr("Edit Notes")); @@ -168,7 +168,7 @@ void RecipeExtrasWidget::updateNotes() { void RecipeExtrasWidget::updateAcidity() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, beerAcidity_pH), lineEdit_acidity->getOptCanonicalQty(), tr("Change pH")); @@ -177,7 +177,7 @@ void RecipeExtrasWidget::updateAcidity() { void RecipeExtrasWidget::updateAttenuation() { if (!this->recipe) { return; } - MainWindow::instance().doOrRedoUpdate(*recipe, + Undoable::doOrRedoUpdate(*recipe, TYPE_INFO(Recipe, apparentAttenuation_pct), lineEdit_attenuation->getOptValue(), tr("Change Apparent Attenuation")); diff --git a/src/database/ObjectStoreWrapper.h b/src/database/ObjectStoreWrapper.h index 14dbcf07d..5671adf42 100644 --- a/src/database/ObjectStoreWrapper.h +++ b/src/database/ObjectStoreWrapper.h @@ -1,5 +1,5 @@ /*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ - * database/ObjectStoreWrapper.h is part of Brewtarget, and is copyright the following authors 2021-2022: + * database/ObjectStoreWrapper.h is part of Brewtarget, and is copyright the following authors 2021-2024: * • Matt Young * * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -72,6 +72,7 @@ namespace ObjectStoreWrapper { return ObjectStoreTyped::getInstance().getAll(); } + //! \brief Raw pointer version template QList getAllRaw() { return ObjectStoreTyped::getInstance().getAllRaw(); } @@ -82,6 +83,13 @@ namespace ObjectStoreWrapper { * - not marked deleted * - do not have a parent (ie are not "an instance of use of" */ + template QList> getAllDisplayable() { + return ObjectStoreTyped::getInstance().findAllMatching( + [](std::shared_ptr ne) { return (ne->display() && !ne->deleted() && ne->getParentKey() <= 0); } + ); + } + + //! \brief Raw pointer version template QList getAllDisplayableRaw() { return ObjectStoreTyped::getInstance().findAllMatching( [](NE const * ne) { return (ne->display() && !ne->deleted() && ne->getParentKey() <= 0); } diff --git a/src/editors/EditorBaseField.h b/src/editors/EditorBaseField.h index 53abc5ad6..c164a2742 100644 --- a/src/editors/EditorBaseField.h +++ b/src/editors/EditorBaseField.h @@ -19,8 +19,8 @@ #include -#include "widgets/BtBoolComboBox.h" -#include "widgets/BtComboBox.h" +#include "widgets/BtComboBoxBool.h" +#include "widgets/BtComboBoxEnum.h" // // This is only included from one place -- editors/EditorBase.h -- but I think it's a big enough block that there is @@ -85,8 +85,8 @@ struct EditorBaseField { std::optional precision = std::nullopt, WhenToWriteField whenToWrite = WhenToWriteField::Normal) requires (!std::same_as && - !std::same_as && - !std::same_as) : + !std::same_as && + !std::same_as) : labelName {labelName }, label {label }, editField {editField }, @@ -127,14 +127,14 @@ struct EditorBaseField { return; } - //! Constructor for when we have a BtComboBox + //! Constructor for when we have a BtComboBoxEnum EditorBaseField(char const * const editorClass, char const * const labelName, [[maybe_unused]] char const * const labelFqName, LabelType * label, char const * const editFieldName, char const * const editFieldFqName, - BtComboBox * editField, + BtComboBoxEnum * editField, BtStringConst const & property, TypeInfo const & typeInfo, EnumStringMapping const & nameMapping, @@ -142,7 +142,7 @@ struct EditorBaseField { std::vector const * restrictTo = nullptr, SmartLineEdit * controlledField = nullptr, WhenToWriteField whenToWrite = WhenToWriteField::Normal) - requires (std::same_as) : + requires (std::same_as) : labelName {labelName }, label {label }, editField {editField }, @@ -163,20 +163,20 @@ struct EditorBaseField { return; } - //! Constructor for when we have a BtBoolComboBox + //! Constructor for when we have a BtComboBoxBool EditorBaseField(char const * const editorClass, char const * const labelName, [[maybe_unused]] char const * const labelFqName, LabelType * label, char const * const editFieldName, char const * const editFieldFqName, - BtBoolComboBox * editField, + BtComboBoxBool * editField, BtStringConst const & property, TypeInfo const & typeInfo, QString const & unsetDisplay = QObject::tr("No"), QString const & setDisplay = QObject::tr("Yes"), WhenToWriteField whenToWrite = WhenToWriteField::Normal) - requires (std::same_as) : + requires (std::same_as) : labelName {labelName }, label {label }, editField {editField }, @@ -229,8 +229,8 @@ struct EditorBaseField { //! Combo boxes are slightly different template void connectFieldChanged(Derived * context, Functor functor) const - requires (std::same_as || - std::same_as) { + requires (std::same_as || + std::same_as) { // QOverload is needed on next line because the signal currentIndexChanged is overloaded in QComboBox - see // https://doc.qt.io/qt-5/qcombobox.html#currentIndexChanged context->connect(this->editField, QOverload::of(&QComboBox::currentIndexChanged), context, functor, Qt::AutoConnection); @@ -247,8 +247,8 @@ struct EditorBaseField { } QVariant getFieldValue() const requires (std::same_as || - std::same_as || - std::same_as) { + std::same_as || + std::same_as) { // Through the magic of templates, and naming conventions, one line suffices for all three types return this->editField->getAsVariant(); } @@ -256,7 +256,7 @@ struct EditorBaseField { /** * \brief Set property on supplied object from edit field */ - void setPropertyFromEditField(QObject & object) const requires (std::same_as) { + void setPropertyFromEditField(QObject & object) const requires (std::same_as) { // // The only "special case" we can't handle with template specialisation is where we have a combo-box that is // controlling the physical quantity for another field (eg whether an input field is mass or volume), there is @@ -268,7 +268,7 @@ struct EditorBaseField { } return; } - void setPropertyFromEditField(QObject & object) const requires (!std::same_as) { + void setPropertyFromEditField(QObject & object) const requires (!std::same_as) { object.setProperty(*property, this->getFieldValue()); return; } @@ -293,8 +293,8 @@ struct EditorBaseField { } void setEditField(QVariant const & val) const requires (std::same_as || - std::same_as || - std::same_as) { + std::same_as || + std::same_as) { this->editField->setFromVariant(val); return; } @@ -307,8 +307,8 @@ struct EditorBaseField { return; } void clearEditField() const requires (std::same_as || - std::same_as || - std::same_as) { + std::same_as || + std::same_as) { this->editField->setDefault(); return; } @@ -316,7 +316,7 @@ struct EditorBaseField { /** * \brief Set edit field from property on supplied object */ - void setEditFieldFromProperty(QObject & object) const requires (std::same_as) { + void setEditFieldFromProperty(QObject & object) const requires (std::same_as) { // // Similarly to setPropertyFromEditField, in the case of a combo-box that is controlling the physical quantity for // another field, we want to initialise from that controlled field. @@ -328,7 +328,7 @@ struct EditorBaseField { } return; } - void setEditFieldFromProperty(QObject & object) const requires (!std::same_as) { + void setEditFieldFromProperty(QObject & object) const requires (!std::same_as) { this->setEditField(object.property(*property)); return; } @@ -355,15 +355,15 @@ using EditorBaseFieldVariant = std::variant< EditorBaseField, EditorBaseField, EditorBaseField, - EditorBaseField, - EditorBaseField, + EditorBaseField, + EditorBaseField, EditorBaseField, // This is for tabs such as tab_notes containing a single QTextEdit with no separate QLabel EditorBaseField, // EditorBaseField, // EditorBaseField, EditorBaseField, - EditorBaseField, - EditorBaseField + EditorBaseField, + EditorBaseField >; /** diff --git a/src/listModels/BoilListModel.cpp b/src/listModels/BoilListModel.cpp new file mode 100644 index 000000000..9768005a6 --- /dev/null +++ b/src/listModels/BoilListModel.cpp @@ -0,0 +1,19 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * listModels/BoilListModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "listModels/BoilListModel.h" + +// Insert the boiler-plate stuff that we cannot do in ListModelBase +LIST_MODEL_COMMON_CODE(Boil, PropertyNames::Recipe::boil) diff --git a/src/widgets/CustomComboBox.h b/src/listModels/BoilListModel.h old mode 100755 new mode 100644 similarity index 67% rename from src/widgets/CustomComboBox.h rename to src/listModels/BoilListModel.h index 09d8bf92f..96bf130ff --- a/src/widgets/CustomComboBox.h +++ b/src/listModels/BoilListModel.h @@ -1,7 +1,6 @@ /*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ - * widgets/CustomComboBox.h is part of Brewtarget, and is copyright the following authors 2009-2023: + * listModels/BoilListModel.h is part of Brewtarget, and is copyright the following authors 2024: * • Matt Young - * • Philip Greggory Lee * * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later @@ -14,29 +13,23 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see * . ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ -#ifndef WIDGETS_CUSTOMCOMBOBOX_H -#define WIDGETS_CUSTOMCOMBOBOX_H +#ifndef LISTMODELS_BOILLISTMODEL_H +#define LISTMODELS_BOILLISTMODEL_H #pragma once -#include -#include +#include + +#include "listModels/ListModelBase.h" +#include "model/Boil.h" /*! - * \class CustomComboBox + * \class BoilListModel * - * \brief This class is a more flexible combo box. Does not show any text. + * \brief Model for a list of named mashes */ -class CustomComboBox : public QComboBox { +class BoilListModel : public QAbstractListModel, public ListModelBase { Q_OBJECT -public: - CustomComboBox(QWidget* parent = 0); - virtual ~CustomComboBox(); - - //! Reimplemented from QComboBox to allow the popup to be independently sized. - void showPopup(); - - //! Reimplemented from QComboBox to not show any text. - virtual void paintEvent(QPaintEvent*); + LIST_MODEL_COMMON_DECL(Boil) }; #endif diff --git a/src/listModels/FermentationListModel.cpp b/src/listModels/FermentationListModel.cpp new file mode 100644 index 000000000..9805a3218 --- /dev/null +++ b/src/listModels/FermentationListModel.cpp @@ -0,0 +1,19 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * listModels/FermentationListModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "listModels/FermentationListModel.h" + +// Insert the boiler-plate stuff that we cannot do in ListModelBase +LIST_MODEL_COMMON_CODE(Fermentation, PropertyNames::Recipe::fermentation) diff --git a/src/listModels/FermentationListModel.h b/src/listModels/FermentationListModel.h new file mode 100644 index 000000000..6efd6d1a5 --- /dev/null +++ b/src/listModels/FermentationListModel.h @@ -0,0 +1,35 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * listModels/FermentationListModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef LISTMODELS_FERMENTATIONLISTMODEL_H +#define LISTMODELS_FERMENTATIONLISTMODEL_H +#pragma once + +#include + +#include "listModels/ListModelBase.h" +#include "model/Fermentation.h" + +/*! + * \class FermentationListModel + * + * \brief Model for a list of named mashes + */ +class FermentationListModel : public QAbstractListModel, public ListModelBase { + Q_OBJECT + LIST_MODEL_COMMON_DECL(Fermentation) +}; + +#endif diff --git a/src/listModels/ListModelBase.h b/src/listModels/ListModelBase.h index ada27ba4e..93e585f0c 100755 --- a/src/listModels/ListModelBase.h +++ b/src/listModels/ListModelBase.h @@ -1,5 +1,5 @@ /*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ - * listModels/ListModelBase.h is part of Brewtarget, and is copyright the following authors 2023: + * listModels/ListModelBase.h is part of Brewtarget, and is copyright the following authors 2023-2024: * • Matt Young * * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -141,8 +141,18 @@ class ListModelBase : public CuriouslyRecurringTemplateBasename()); + if (index.column() == 0) { + // + // See https://doc.qt.io/qt-6/qt.html#ItemDataRole-enum for more on Qt::ItemDataRole. For our purposes: + // + // Qt::DisplayRole = we want the name of the stored object (to show on the screen) + // Qt::UserRole = we want the ID of the stored object (to uniquely identify it) + // + if (role == Qt::DisplayRole) { + return QVariant(m_items.at(index.row())->name()); + } else if (role == Qt::UserRole) { + return QVariant(m_items.at(index.row())->key()); + } } return QVariant(); } diff --git a/src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp b/src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp new file mode 100644 index 000000000..61f20f73e --- /dev/null +++ b/src/sortFilterProxyModels/BoilSortFilterProxyModel.cpp @@ -0,0 +1,41 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/BoilSortFilterProxyModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "sortFilterProxyModels/BoilSortFilterProxyModel.h" + +#include "measurement/Measurement.h" +#include "measurement/PhysicalQuantity.h" + +bool BoilSortFilterProxyModel::isLessThan(BoilTableModel::ColumnIndex const columnIndex, + QVariant const & leftItem, + QVariant const & rightItem) const { + switch (columnIndex) { + case BoilTableModel::ColumnIndex::Name : + return leftItem.toString() < rightItem.toString(); + + case BoilTableModel::ColumnIndex::PreBoilSize: + return Measurement::qStringToSI( leftItem.toString(), Measurement::PhysicalQuantity::Volume) < + Measurement::qStringToSI(rightItem.toString(), Measurement::PhysicalQuantity::Volume); + + // No default case as we want the compiler to warn us if we missed one + } + + // Should be unreachable + Q_ASSERT(false); + return true; +} + +// Insert the boiler-plate stuff that we cannot do in SortFilterProxyModelBase +SORT_FILTER_PROXY_MODEL_COMMON_CODE(Boil) diff --git a/src/sortFilterProxyModels/BoilSortFilterProxyModel.h b/src/sortFilterProxyModels/BoilSortFilterProxyModel.h new file mode 100644 index 000000000..c2c9332b4 --- /dev/null +++ b/src/sortFilterProxyModels/BoilSortFilterProxyModel.h @@ -0,0 +1,39 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/BoilSortFilterProxyModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef SORTFILTERPROXYMODELS_BOILSORTFILTERPROXYMODEL_H +#define SORTFILTERPROXYMODELS_BOILSORTFILTERPROXYMODEL_H +#pragma once + +#include + +#include "sortFilterProxyModels/SortFilterProxyModelBase.h" +#include "tableModels/BoilTableModel.h" +#include "listModels/BoilListModel.h" + +/*! + * \class BoilSortFilterProxyModel + * + * \brief Proxy model for sorting/filtering Boils. + */ +class BoilSortFilterProxyModel : public QSortFilterProxyModel, + public SortFilterProxyModelBase { + Q_OBJECT + SORT_FILTER_PROXY_MODEL_COMMON_DECL(Boil) +}; + +#endif diff --git a/src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp b/src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp new file mode 100644 index 000000000..0486ed921 --- /dev/null +++ b/src/sortFilterProxyModels/FermentationSortFilterProxyModel.cpp @@ -0,0 +1,43 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/FermentationSortFilterProxyModel.cpp is part of Brewtarget, and is copyright the following authors + * 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "sortFilterProxyModels/FermentationSortFilterProxyModel.h" + +#include "measurement/Measurement.h" +#include "measurement/PhysicalQuantity.h" + +bool FermentationSortFilterProxyModel::isLessThan(FermentationTableModel::ColumnIndex const columnIndex, + QVariant const & leftItem, + QVariant const & rightItem) const { + switch (columnIndex) { + case FermentationTableModel::ColumnIndex::Name: + return leftItem.toString() < rightItem.toString(); + + + case FermentationTableModel::ColumnIndex::NumSteps: + return Measurement::extractRawFromString( leftItem.toString()) < + Measurement::extractRawFromString(rightItem.toString()); + + // No default case as we want the compiler to warn us if we missed one + } + + // Should be unreachable + Q_ASSERT(false); + return true; +} + +// Insert the boiler-plate stuff that we cannot do in SortFilterProxyModelBase +SORT_FILTER_PROXY_MODEL_COMMON_CODE(Fermentation) diff --git a/src/sortFilterProxyModels/FermentationSortFilterProxyModel.h b/src/sortFilterProxyModels/FermentationSortFilterProxyModel.h new file mode 100644 index 000000000..2ca1dca21 --- /dev/null +++ b/src/sortFilterProxyModels/FermentationSortFilterProxyModel.h @@ -0,0 +1,40 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/FermentationSortFilterProxyModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef SORTFILTERPROXYMODELS_FERMENTATIONSORTFILTERPROXYMODEL_H +#define SORTFILTERPROXYMODELS_FERMENTATIONSORTFILTERPROXYMODEL_H +#pragma once + +#include + +#include "sortFilterProxyModels/SortFilterProxyModelBase.h" +#include "tableModels/FermentationTableModel.h" +#include "listModels/FermentationListModel.h" + +/*! + * \class FermentationSortFilterProxyModel + * + * \brief Proxy model for sorting/filtering Fermentations. + */ +class FermentationSortFilterProxyModel : public QSortFilterProxyModel, + public SortFilterProxyModelBase { + Q_OBJECT + + SORT_FILTER_PROXY_MODEL_COMMON_DECL(Fermentation) +}; + +#endif diff --git a/src/sortFilterProxyModels/MashSortFilterProxyModel.cpp b/src/sortFilterProxyModels/MashSortFilterProxyModel.cpp new file mode 100644 index 000000000..cdf83c5c4 --- /dev/null +++ b/src/sortFilterProxyModels/MashSortFilterProxyModel.cpp @@ -0,0 +1,48 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/MashSortFilterProxyModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "sortFilterProxyModels/MashSortFilterProxyModel.h" + +#include "measurement/Measurement.h" +#include "measurement/PhysicalQuantity.h" + +bool MashSortFilterProxyModel::isLessThan(MashTableModel::ColumnIndex const columnIndex, + QVariant const & leftItem, + QVariant const & rightItem) const { + switch (columnIndex) { + case MashTableModel::ColumnIndex::Name : + return leftItem.toString() < rightItem.toString(); + + case MashTableModel::ColumnIndex::InitialGrainTemp: + return Measurement::qStringToSI( leftItem.toString(), Measurement::PhysicalQuantity::Temperature) < + Measurement::qStringToSI(rightItem.toString(), Measurement::PhysicalQuantity::Temperature); + + case MashTableModel::ColumnIndex::TotalMashWater: + return Measurement::qStringToSI( leftItem.toString(), Measurement::PhysicalQuantity::Volume) < + Measurement::qStringToSI(rightItem.toString(), Measurement::PhysicalQuantity::Volume); + + case MashTableModel::ColumnIndex::TotalTime: + return Measurement::qStringToSI( leftItem.toString(), Measurement::PhysicalQuantity::Time) < + Measurement::qStringToSI(rightItem.toString(), Measurement::PhysicalQuantity::Time); + // No default case as we want the compiler to warn us if we missed one + } + + // Should be unreachable + Q_ASSERT(false); + return true; +} + +// Insert the boiler-plate stuff that we cannot do in SortFilterProxyModelBase +SORT_FILTER_PROXY_MODEL_COMMON_CODE(Mash) diff --git a/src/sortFilterProxyModels/MashSortFilterProxyModel.h b/src/sortFilterProxyModels/MashSortFilterProxyModel.h new file mode 100644 index 000000000..63b0291fe --- /dev/null +++ b/src/sortFilterProxyModels/MashSortFilterProxyModel.h @@ -0,0 +1,40 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * sortFilterProxyModels/MashSortFilterProxyModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef SORTFILTERPROXYMODELS_MASHSORTFILTERPROXYMODEL_H +#define SORTFILTERPROXYMODELS_MASHSORTFILTERPROXYMODEL_H +#pragma once + +#include + +#include "sortFilterProxyModels/SortFilterProxyModelBase.h" +#include "tableModels/MashTableModel.h" +#include "listModels/MashListModel.h" + +/*! + * \class MashSortFilterProxyModel + * + * \brief Proxy model for sorting/filtering Mashs. + */ +class MashSortFilterProxyModel : public QSortFilterProxyModel, + public SortFilterProxyModelBase { + Q_OBJECT + + SORT_FILTER_PROXY_MODEL_COMMON_DECL(Mash) +}; + +#endif diff --git a/src/tableModels/BoilStepTableModel.cpp b/src/tableModels/BoilStepTableModel.cpp index 96d183f8e..d65d4e806 100755 --- a/src/tableModels/BoilStepTableModel.cpp +++ b/src/tableModels/BoilStepTableModel.cpp @@ -21,9 +21,6 @@ #include #include -#include "database/ObjectStoreWrapper.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" #include "model/BoilStep.h" #include "tableModels/BtTableModel.h" @@ -47,7 +44,6 @@ BoilStepTableModel::BoilStepTableModel(QTableView * parent, bool editable) : }, TableModelBase{}, StepTableModelBase{} { - this->setObjectName("boilStepTableModel"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &BoilStepTableModel::contextMenu); @@ -69,37 +65,26 @@ BoilStepTableModel::~BoilStepTableModel() = default; void BoilStepTableModel::added ([[maybe_unused]] std::shared_ptr item) { return; } void BoilStepTableModel::removed([[maybe_unused]] std::shared_ptr item) { return; } -void BoilStepTableModel::updateTotals() { return; } - +void BoilStepTableModel::updateTotals() { return; } QVariant BoilStepTableModel::data(QModelIndex const & index, int role) const { - if (!this->m_stepOwnerObs || !this->indexAndRoleOk(index, role)) { + if (!this->m_stepOwnerObs) { return QVariant(); } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } -Qt::ItemFlags BoilStepTableModel::flags(const QModelIndex& index ) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == BoilStepTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags BoilStepTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); } bool BoilStepTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { - if (!this->m_stepOwnerObs || !this->indexAndRoleOk(index, role)) { + if (!this->m_stepOwnerObs) { return false; } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); + return this->doSetDataDefault(index, value, role); } -/////==========================CLASS BoilStepItemDelegate=============================== - // Insert the boiler-plate stuff that we cannot do in TableModelBase TABLE_MODEL_COMMON_CODE(BoilStep, boilStep, PropertyNames::Recipe::boilId) // Insert the boiler-plate stuff that we cannot do in StepTableModelBase diff --git a/src/tableModels/BoilStepTableModel.h b/src/tableModels/BoilStepTableModel.h index 0e110b61e..5ff874b9f 100755 --- a/src/tableModels/BoilStepTableModel.h +++ b/src/tableModels/BoilStepTableModel.h @@ -18,38 +18,23 @@ #pragma once #include -#include -#include -#include -#include -#include -#include -#include "measurement/Unit.h" #include "model/BoilStep.h" -#include "model/Boil.h" #include "tableModels/BtTableModel.h" #include "tableModels/ItemDelegate.h" #include "tableModels/StepTableModelBase.h" #include "tableModels/TableModelBase.h" -// You have to get the order of everything right with traits classes, but the end result is that we can refer to -// HopTableModel::ColumnIndex::Alpha etc. -class BoilStepTableModel; -template <> struct TableModelTraits { - enum class ColumnIndex { - Name , - StepTime , - StartTemp , - RampTime , - EndTemp , - StartAcidity, - EndAcidity , - StartGravity, - EndGravity , - ChillingType, - }; -}; +TABLE_MODEL_TRAITS(BoilStep, Name , + StepTime , + StartTemp , + RampTime , + EndTemp , + StartAcidity, + EndAcidity , + StartGravity, + EndGravity , + ChillingType,) /*! * \class BoilStepTableModel diff --git a/src/tableModels/BoilTableModel.cpp b/src/tableModels/BoilTableModel.cpp new file mode 100644 index 000000000..1fd90646a --- /dev/null +++ b/src/tableModels/BoilTableModel.cpp @@ -0,0 +1,66 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/BoilTableModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "tableModels/BoilTableModel.h" + +#include +#include +#include +#include +#include + +#include "model/Boil.h" + +BoilTableModel::BoilTableModel(QTableView * parent, bool editable) : + BtTableModel{ + parent, + editable, + { + TABLE_MODEL_HEADER(Boil, Name , tr("Name" ), PropertyNames:: NamedEntity::name ), + TABLE_MODEL_HEADER(Boil, PreBoilSize , tr("Pre-Boil Size"), PropertyNames:: Boil::preBoilSize_l , PrecisionInfo{1}), + } + }, + TableModelBase{} { + + QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); + connect(headerView, &QWidget::customContextMenuRequested, this, &BoilTableModel::contextMenu); + return; +} + +BoilTableModel::~BoilTableModel() = default; + +void BoilTableModel::added ([[maybe_unused]] std::shared_ptr item) { return; } +void BoilTableModel::removed([[maybe_unused]] std::shared_ptr item) { return; } +void BoilTableModel::updateTotals() { return; } + +QVariant BoilTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); +} + +Qt::ItemFlags BoilTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); +} + +bool BoilTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); +} + +// Insert the boiler-plate stuff that we cannot do in TableModelBase +TABLE_MODEL_COMMON_CODE(Boil, boil, PropertyNames::Recipe::boilId) + +//=============================================== CLASS BoilItemDelegate ================================================ + +// Insert the boiler-plate stuff that we cannot do in ItemDelegate +ITEM_DELEGATE_COMMON_CODE(Boil) diff --git a/src/tableModels/BoilTableModel.h b/src/tableModels/BoilTableModel.h new file mode 100644 index 000000000..794a35cf9 --- /dev/null +++ b/src/tableModels/BoilTableModel.h @@ -0,0 +1,50 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/BoilTableModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef TABLEMODELS_BOILTABLEMODEL_H +#define TABLEMODELS_BOILTABLEMODEL_H +#pragma once + +#include + +#include "model/Boil.h" +#include "tableModels/ItemDelegate.h" +#include "tableModels/TableModelBase.h" + +TABLE_MODEL_TRAITS(Boil, Name, + PreBoilSize) + +/*! + * \class BoilTableModel + * + * \brief Model class for a list of boils. + */ +class BoilTableModel : public BtTableModel, public TableModelBase { + Q_OBJECT + TABLE_MODEL_COMMON_DECL(Boil) +}; + +/** + * \class BoilItemDelegate + * + * \brief An item delegate for hop tables. + * \sa BoilTableModel + */ +class BoilItemDelegate : public QItemDelegate, public ItemDelegate { + Q_OBJECT + ITEM_DELEGATE_COMMON_DECL(Boil) +}; + +#endif diff --git a/src/tableModels/EquipmentTableModel.cpp b/src/tableModels/EquipmentTableModel.cpp index 87b4eae5b..1e89f0e05 100755 --- a/src/tableModels/EquipmentTableModel.cpp +++ b/src/tableModels/EquipmentTableModel.cpp @@ -1,5 +1,5 @@ /*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ - * tableModels/EquipmentTableModel.cpp is part of Brewtarget, and is copyright the following authors 2023: + * tableModels/EquipmentTableModel.cpp is part of Brewtarget, and is copyright the following authors 2023-2024: * • Matt Young * * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -15,19 +15,10 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/EquipmentTableModel.h" -#include #include -#include - -#include "database/ObjectStoreWrapper.h" -#include "MainWindow.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" -#include "model/Inventory.h" -#include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" -#include "widgets/BtComboBox.h" +#include +#include +#include EquipmentTableModel::EquipmentTableModel(QTableView* parent, bool editable) : BtTableModel{ @@ -42,7 +33,6 @@ EquipmentTableModel::EquipmentTableModel(QTableView* parent, bool editable) : }, TableModelBase{} { this->rows.clear(); - setObjectName("equipmentTableModel"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &EquipmentTableModel::contextMenu); @@ -56,30 +46,15 @@ void EquipmentTableModel::removed([[maybe_unused]] std::shared_ptr it void EquipmentTableModel::updateTotals() { return; } QVariant EquipmentTableModel::data(QModelIndex const & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } Qt::ItemFlags EquipmentTableModel::flags(QModelIndex const & index) const { - Qt::ItemFlags const defaults = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; - auto const columnIndex = static_cast(index.column()); - if (columnIndex == EquipmentTableModel::ColumnIndex::Name) { - return defaults; - } - return defaults | (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags); + return TableModelHelper::doFlags(index, this->m_editable); } bool EquipmentTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/FermentableTableModel.cpp b/src/tableModels/FermentableTableModel.cpp index b4984d27f..ebd2e1c8f 100644 --- a/src/tableModels/FermentableTableModel.cpp +++ b/src/tableModels/FermentableTableModel.cpp @@ -41,7 +41,7 @@ #include "model/Recipe.h" #include "tableModels/ItemDelegate.h" #include "utils/BtStringConst.h" -#include "widgets/BtComboBox.h" +#include "widgets/BtComboBoxEnum.h" //=====================CLASS FermentableTableModel============================== FermentableTableModel::FermentableTableModel(QTableView* parent, bool editable) : @@ -63,9 +63,6 @@ FermentableTableModel::FermentableTableModel(QTableView* parent, bool editable) }, TableModelBase{} { - // for units and scales - setObjectName("fermentableTable"); - QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &FermentableTableModel::contextMenu); connect(&ObjectStoreTyped::getInstance(), &ObjectStoreTyped::signalPropertyChanged, this, &FermentableTableModel::changedInventory); @@ -79,39 +76,19 @@ void FermentableTableModel::removed([[maybe_unused]] std::shared_ptrindexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } Qt::ItemFlags FermentableTableModel::flags(QModelIndex const & index) const { - Qt::ItemFlags constexpr defaults = Qt::ItemIsEnabled; - auto row = this->rows[index.row()]; - - auto const columnIndex = static_cast(index.column()); - switch (columnIndex) { - case FermentableTableModel::ColumnIndex::Name: - return (defaults | Qt::ItemIsSelectable); - case FermentableTableModel::ColumnIndex::TotalInventory: - return Qt::ItemIsEnabled | Qt::ItemIsEditable; - default: - return (defaults | Qt::ItemIsSelectable | (m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) ); - } + return TableModelHelper::doFlags( + index, + this->m_editable, + {{FermentableTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEditable}} + ); } - -bool FermentableTableModel::setData(QModelIndex const & index, - QVariant const & value, - int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); +bool FermentableTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/FermentationStepTableModel.cpp b/src/tableModels/FermentationStepTableModel.cpp index 8fe0d8c0d..ee96ae1a9 100755 --- a/src/tableModels/FermentationStepTableModel.cpp +++ b/src/tableModels/FermentationStepTableModel.cpp @@ -62,7 +62,6 @@ FermentationStepTableModel::FermentationStepTableModel(QTableView * parent, bool }, TableModelBase{}, StepTableModelBase{} { - this->setObjectName("fermentationStepTableModel"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &FermentationStepTableModel::contextMenu); @@ -88,29 +87,21 @@ void FermentationStepTableModel::removed([[maybe_unused]] std::shared_ptrm_stepOwnerObs || !this->indexAndRoleOk(index, role)) { + if (!this->m_stepOwnerObs) { return QVariant(); } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } -Qt::ItemFlags FermentationStepTableModel::flags(const QModelIndex& index ) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == FermentationStepTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags FermentationStepTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); } bool FermentationStepTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { - if (!this->m_stepOwnerObs || !this->indexAndRoleOk(index, role)) { + if (!this->m_stepOwnerObs) { return false; } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); + return this->doSetDataDefault(index, value, role); } /////==========================CLASS FermentationStepItemDelegate=============================== diff --git a/src/tableModels/FermentationTableModel.cpp b/src/tableModels/FermentationTableModel.cpp new file mode 100644 index 000000000..241a9f492 --- /dev/null +++ b/src/tableModels/FermentationTableModel.cpp @@ -0,0 +1,66 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/FermentationTableModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "tableModels/FermentationTableModel.h" + +#include +#include +#include +#include +#include + +#include "model/Fermentation.h" + +FermentationTableModel::FermentationTableModel(QTableView * parent, bool editable) : + BtTableModel{ + parent, + editable, + { + TABLE_MODEL_HEADER(Fermentation, Name , tr("Name" ), PropertyNames:: NamedEntity::name ), + TABLE_MODEL_HEADER(Fermentation, NumSteps, tr("Number of Steps"), PropertyNames::StepOwnerBase::numSteps), + } + }, + TableModelBase{} { + + QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); + connect(headerView, &QWidget::customContextMenuRequested, this, &FermentationTableModel::contextMenu); + return; +} + +FermentationTableModel::~FermentationTableModel() = default; + +void FermentationTableModel::added ([[maybe_unused]] std::shared_ptr item) { return; } +void FermentationTableModel::removed([[maybe_unused]] std::shared_ptr item) { return; } +void FermentationTableModel::updateTotals() { return; } + +QVariant FermentationTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); +} + +Qt::ItemFlags FermentationTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); +} + +bool FermentationTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); +} + +// Insert the boiler-plate stuff that we cannot do in TableModelBase +TABLE_MODEL_COMMON_CODE(Fermentation, fermentation, PropertyNames::Recipe::fermentationId) + +//=============================================== CLASS FermentationItemDelegate ================================================ + +// Insert the boiler-plate stuff that we cannot do in ItemDelegate +ITEM_DELEGATE_COMMON_CODE(Fermentation) diff --git a/src/tableModels/FermentationTableModel.h b/src/tableModels/FermentationTableModel.h new file mode 100644 index 000000000..fddd58491 --- /dev/null +++ b/src/tableModels/FermentationTableModel.h @@ -0,0 +1,51 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/FermentationTableModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef TABLEMODELS_FERMENTATIONTABLEMODEL_H +#define TABLEMODELS_FERMENTATIONTABLEMODEL_H +#pragma once + +#include + +#include "model/Fermentation.h" +#include "tableModels/BtTableModel.h" +#include "tableModels/ItemDelegate.h" +#include "tableModels/TableModelBase.h" + +TABLE_MODEL_TRAITS(Fermentation, Name, + NumSteps) + +/*! + * \class FermentationTableModel + * + * \brief Model class for a list of boils. + */ +class FermentationTableModel : public BtTableModel, public TableModelBase { + Q_OBJECT + TABLE_MODEL_COMMON_DECL(Fermentation) +}; + +/** + * \class FermentationItemDelegate + * + * \brief An item delegate for hop tables. + * \sa FermentationTableModel + */ +class FermentationItemDelegate : public QItemDelegate, public ItemDelegate { + Q_OBJECT + ITEM_DELEGATE_COMMON_DECL(Fermentation) +}; + +#endif diff --git a/src/tableModels/HopTableModel.cpp b/src/tableModels/HopTableModel.cpp index 6f0ba7bc3..d18876930 100644 --- a/src/tableModels/HopTableModel.cpp +++ b/src/tableModels/HopTableModel.cpp @@ -25,27 +25,11 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/HopTableModel.h" -#include -#include #include -#include -#include #include -#include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "Localization.h" -#include "MainWindow.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" -#include "model/Inventory.h" -#include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" - HopTableModel::HopTableModel(QTableView * parent, bool editable) : BtTableModel{ parent, @@ -62,7 +46,6 @@ HopTableModel::HopTableModel(QTableView * parent, bool editable) : TableModelBase{}, showIBUs(false) { this->rows.clear(); - this->setObjectName("hopTable"); QHeaderView * headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &HopTableModel::contextMenu); @@ -81,41 +64,21 @@ void HopTableModel::setShowIBUs(bool var) { showIBUs = var; } -QVariant HopTableModel::data(const QModelIndex & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); +QVariant HopTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); } -Qt::ItemFlags HopTableModel::flags(const QModelIndex & index) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == HopTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - if (columnIndex == HopTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::ItemIsEditable; - } - return Qt::ItemIsSelectable | - (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags HopTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags( + index, + this->m_editable, + {{HopTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEditable}} + ); } -bool HopTableModel::setData(const QModelIndex & index, const QVariant & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns... - bool const retVal = this->writeDataToModel(index, value, role); - - // ...but we might need to re-show header IBUs - if (retVal) { - headerDataChanged(Qt::Vertical, index.row(), index.row()); - } - - return retVal; +bool HopTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + // Template parameter is true as we might need to re-show header IBUs + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/ItemDelegate.h b/src/tableModels/ItemDelegate.h index c1c09768d..fb34b4d8b 100755 --- a/src/tableModels/ItemDelegate.h +++ b/src/tableModels/ItemDelegate.h @@ -21,8 +21,8 @@ #include "measurement/Measurement.h" #include "utils/NoCopy.h" -#include "widgets/BtBoolComboBox.h" -#include "widgets/BtComboBox.h" +#include "widgets/BtComboBoxBool.h" +#include "widgets/BtComboBoxEnum.h" #include "tableModels/BtTableModel.h" namespace { @@ -125,7 +125,7 @@ class ItemDelegate { Q_ASSERT(std::holds_alternative(*columnInfo.extras)); BtTableModel::EnumInfo const & enumInfo = std::get(*columnInfo.extras); - BtComboBox * comboBox = new BtComboBox(parent); + BtComboBoxEnum * comboBox = new BtComboBoxEnum(parent); comboBox->init(columnInfo.tableModelName, columnInfo.columnName, columnInfo.columnFqName, @@ -145,7 +145,7 @@ class ItemDelegate { Q_ASSERT(std::holds_alternative(*columnInfo.extras)); BtTableModel::BoolInfo const & boolInfo = std::get(*columnInfo.extras); - BtBoolComboBox * boolComboBox = new BtBoolComboBox(parent); + BtComboBoxBool * boolComboBox = new BtComboBoxBool(parent); boolComboBox->init(columnInfo.tableModelName, columnInfo.columnName, columnInfo.columnFqName, @@ -170,7 +170,7 @@ class ItemDelegate { // PrecisionInfo) in the extras field. // auto const validMeasures = std::get(*columnInfo.extras); - BtComboBox * comboBox = new BtComboBox(parent); + BtComboBoxEnum * comboBox = new BtComboBoxEnum(parent); comboBox->init(columnInfo.tableModelName, columnInfo.columnName, columnInfo.columnFqName, @@ -209,14 +209,14 @@ class ItemDelegate { auto const fieldType = std::get(*typeInfo.fieldType); if (fieldType == NonPhysicalQuantity::Enum) { - BtComboBox * comboBox = qobject_cast(editor); - setComboBoxValue(comboBox, typeInfo, modelData); + BtComboBoxEnum * comboBox = qobject_cast(editor); + setComboBoxValue(comboBox, typeInfo, modelData); return; } if (fieldType == NonPhysicalQuantity::Bool) { - BtBoolComboBox * boolComboBox = qobject_cast(editor); - setComboBoxValue(boolComboBox, typeInfo, modelData); + BtComboBoxBool * boolComboBox = qobject_cast(editor); + setComboBoxValue(boolComboBox, typeInfo, modelData); return; } } else if (std::holds_alternative(*typeInfo.fieldType) && @@ -224,8 +224,8 @@ class ItemDelegate { std::holds_alternative(*columnInfo.extras)) { // Selector for editable amount that can be more than one physical quantity. (See comment above in // getEditWidget() for more details.) - BtComboBox * comboBox = qobject_cast(editor); - setComboBoxValue(comboBox, typeInfo, modelData); + BtComboBoxEnum * comboBox = qobject_cast(editor); + setComboBoxValue(comboBox, typeInfo, modelData); return; } @@ -262,13 +262,13 @@ class ItemDelegate { auto const fieldType = std::get(*typeInfo.fieldType); if (fieldType == NonPhysicalQuantity::Enum) { - BtComboBox * comboBox = qobject_cast(editor); + BtComboBoxEnum * comboBox = qobject_cast(editor); model->setData(index, comboBox->getAsVariant(), Qt::EditRole); return; } if (fieldType == NonPhysicalQuantity::Bool) { - BtBoolComboBox * boolComboBox = qobject_cast(editor); + BtComboBoxBool * boolComboBox = qobject_cast(editor); model->setData(index, boolComboBox->getAsVariant(), Qt::EditRole); return; } @@ -294,7 +294,7 @@ class ItemDelegate { std::holds_alternative(*columnInfo.extras)) { // Selector for editable amount that can be more than one physical quantity. (See comment above in // getEditWidget() for more details.) - BtComboBox * comboBox = qobject_cast(editor); + BtComboBoxEnum * comboBox = qobject_cast(editor); model->setData(index, comboBox->getAsVariant(), Qt::EditRole); return; } diff --git a/src/tableModels/MashStepTableModel.cpp b/src/tableModels/MashStepTableModel.cpp index 8a48145a1..d88c9fe4b 100644 --- a/src/tableModels/MashStepTableModel.cpp +++ b/src/tableModels/MashStepTableModel.cpp @@ -21,24 +21,14 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/MashStepTableModel.h" -#include -#include #include -#include -#include #include -#include #include #include -#include #include -#include "database/ObjectStoreWrapper.h" -#include "MainWindow.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" #include "model/MashStep.h" -#include "PersistentSettings.h" +#include "tableModels/BtTableModel.h" MashStepTableModel::MashStepTableModel(QTableView * parent, bool editable) : BtTableModel{ @@ -96,21 +86,15 @@ QVariant MashStepTableModel::data(QModelIndex const & index, int role) const { return this->readDataFromModel(index, role); } -Qt::ItemFlags MashStepTableModel::flags(const QModelIndex& index ) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == MashStepTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags MashStepTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); } bool MashStepTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { - if (!this->m_stepOwnerObs || !this->indexAndRoleOk(index, role)) { + if (!this->m_stepOwnerObs) { return false; } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/MashTableModel.cpp b/src/tableModels/MashTableModel.cpp new file mode 100644 index 000000000..27b003377 --- /dev/null +++ b/src/tableModels/MashTableModel.cpp @@ -0,0 +1,68 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/MashTableModel.cpp is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#include "tableModels/MashTableModel.h" + +#include +#include +#include +#include +#include + +#include "model/Mash.h" + +MashTableModel::MashTableModel(QTableView * parent, bool editable) : + BtTableModel{ + parent, + editable, + { + TABLE_MODEL_HEADER(Mash, Name , tr("Name" ), PropertyNames:: NamedEntity::name ), + TABLE_MODEL_HEADER(Mash, InitialGrainTemp , tr("Initial Grain Temperature"), PropertyNames:: Mash::grainTemp_c , PrecisionInfo{1}), + TABLE_MODEL_HEADER(Mash, TotalMashWater , tr("Total Mash Water" ), PropertyNames:: Mash::totalMashWater_l, PrecisionInfo{1}), + TABLE_MODEL_HEADER(Mash, TotalTime , tr("Total Time" ), PropertyNames:: Mash::totalTime , PrecisionInfo{0}), + } + }, + TableModelBase{} { + + QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); + connect(headerView, &QWidget::customContextMenuRequested, this, &MashTableModel::contextMenu); + return; +} + +MashTableModel::~MashTableModel() = default; + +void MashTableModel::added ([[maybe_unused]] std::shared_ptr item) { return; } +void MashTableModel::removed([[maybe_unused]] std::shared_ptr item) { return; } +void MashTableModel::updateTotals() { return; } + +QVariant MashTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); +} + +Qt::ItemFlags MashTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags(index, this->m_editable); +} + +bool MashTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); +} + +// Insert the boiler-plate stuff that we cannot do in TableModelBase +TABLE_MODEL_COMMON_CODE(Mash, mash, PropertyNames::Recipe::mashId) + +//=============================================== CLASS MashItemDelegate ================================================ + +// Insert the boiler-plate stuff that we cannot do in ItemDelegate +ITEM_DELEGATE_COMMON_CODE(Mash) diff --git a/src/tableModels/MashTableModel.h b/src/tableModels/MashTableModel.h new file mode 100644 index 000000000..df91b3dd8 --- /dev/null +++ b/src/tableModels/MashTableModel.h @@ -0,0 +1,53 @@ +/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ + * tableModels/MashTableModel.h is part of Brewtarget, and is copyright the following authors 2024: + * • Matt Young + * + * Brewtarget is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Brewtarget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ +#ifndef TABLEMODELS_MASHTABLEMODEL_H +#define TABLEMODELS_MASHTABLEMODEL_H +#pragma once + +#include + +#include "model/Mash.h" +#include "tableModels/BtTableModel.h" +#include "tableModels/ItemDelegate.h" +#include "tableModels/TableModelBase.h" + +TABLE_MODEL_TRAITS(Mash, Name, + InitialGrainTemp, + TotalMashWater , + TotalTime ,) + +/*! + * \class MashTableModel + * + * \brief Model class for a list of boils. + */ +class MashTableModel : public BtTableModel, public TableModelBase { + Q_OBJECT + TABLE_MODEL_COMMON_DECL(Mash) +}; + +/** + * \class MashItemDelegate + * + * \brief An item delegate for hop tables. + * \sa MashTableModel + */ +class MashItemDelegate : public QItemDelegate, public ItemDelegate { + Q_OBJECT + ITEM_DELEGATE_COMMON_DECL(Mash) +}; + +#endif diff --git a/src/tableModels/MiscTableModel.cpp b/src/tableModels/MiscTableModel.cpp index 10dabbf05..c38aca4f6 100644 --- a/src/tableModels/MiscTableModel.cpp +++ b/src/tableModels/MiscTableModel.cpp @@ -23,19 +23,10 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/MiscTableModel.h" -#include #include -#include - -#include "database/ObjectStoreWrapper.h" -#include "MainWindow.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" -#include "model/Inventory.h" -#include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" -#include "widgets/BtComboBox.h" +#include +#include +#include MiscTableModel::MiscTableModel(QTableView* parent, bool editable) : BtTableModel{ @@ -52,7 +43,6 @@ MiscTableModel::MiscTableModel(QTableView* parent, bool editable) : }, TableModelBase{} { this->rows.clear(); - setObjectName("miscTableModel"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &MiscTableModel::contextMenu); @@ -70,33 +60,19 @@ void MiscTableModel::removed([[maybe_unused]] std::shared_ptr item) { retu void MiscTableModel::updateTotals() { return; } QVariant MiscTableModel::data(QModelIndex const & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } Qt::ItemFlags MiscTableModel::flags(QModelIndex const & index) const { - Qt::ItemFlags const defaults = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; - auto const columnIndex = static_cast(index.column()); - if (columnIndex == MiscTableModel::ColumnIndex::Name) { - return defaults; - } - if (columnIndex == MiscTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::ItemIsEditable; - } - return defaults | (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags); + return TableModelHelper::doFlags( + index, + this->m_editable, + {{MiscTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEditable}} + ); } bool MiscTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/RecipeAdditionFermentableTableModel.cpp b/src/tableModels/RecipeAdditionFermentableTableModel.cpp index 1af855132..0ef2ed23f 100755 --- a/src/tableModels/RecipeAdditionFermentableTableModel.cpp +++ b/src/tableModels/RecipeAdditionFermentableTableModel.cpp @@ -26,26 +26,16 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/RecipeAdditionFermentableTableModel.h" -#include -#include #include -#include -#include #include #include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "Localization.h" -#include "MainWindow.h" #include "measurement/Measurement.h" #include "measurement/Unit.h" #include "model/Inventory.h" #include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" RecipeAdditionFermentableTableModel::RecipeAdditionFermentableTableModel(QTableView * parent, bool editable) : BtTableModelRecipeObserver{ @@ -78,7 +68,6 @@ RecipeAdditionFermentableTableModel::RecipeAdditionFermentableTableModel(QTableV displayPercentages(false), totalFermMass_kg(0) { this->rows.clear(); - this->setObjectName("fermentableAdditionTable"); QHeaderView * headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &RecipeAdditionFermentableTableModel::contextMenu); @@ -110,13 +99,8 @@ void RecipeAdditionFermentableTableModel::setDisplayPercentages(bool var) { return; } -QVariant RecipeAdditionFermentableTableModel::data(const QModelIndex & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); +QVariant RecipeAdditionFermentableTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); } QVariant RecipeAdditionFermentableTableModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -139,32 +123,17 @@ QVariant RecipeAdditionFermentableTableModel::headerData(int section, Qt::Orient return QVariant(); } -Qt::ItemFlags RecipeAdditionFermentableTableModel::flags(const QModelIndex & index) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == RecipeAdditionFermentableTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - if (columnIndex == RecipeAdditionFermentableTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::NoItemFlags; - } - return Qt::ItemIsSelectable | - (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags RecipeAdditionFermentableTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags( + index, + this->m_editable, + {{RecipeAdditionFermentableTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEnabled}} + ); } -bool RecipeAdditionFermentableTableModel::setData(const QModelIndex & index, const QVariant & value, int role) { - if (!indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns... - bool const retVal = this->writeDataToModel(index, value, role); - - // ...but we might need to re-show header percentages - if (retVal) { - headerDataChanged(Qt::Vertical, index.row(), index.row()); - } - - return retVal; +bool RecipeAdditionFermentableTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + // Template parameter is true as we might need to re-show header percentages + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/RecipeAdditionHopTableModel.cpp b/src/tableModels/RecipeAdditionHopTableModel.cpp index 3a8bd4ee9..99213b436 100755 --- a/src/tableModels/RecipeAdditionHopTableModel.cpp +++ b/src/tableModels/RecipeAdditionHopTableModel.cpp @@ -25,26 +25,16 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/RecipeAdditionHopTableModel.h" -#include -#include #include -#include -#include #include #include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "Localization.h" -#include "MainWindow.h" #include "measurement/Measurement.h" #include "measurement/Unit.h" #include "model/Inventory.h" #include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" RecipeAdditionHopTableModel::RecipeAdditionHopTableModel(QTableView * parent, bool editable) : BtTableModelRecipeObserver{ @@ -76,7 +66,6 @@ RecipeAdditionHopTableModel::RecipeAdditionHopTableModel(QTableView * parent, bo TableModelBase{}, showIBUs(false) { this->rows.clear(); - this->setObjectName("hopAdditionTable"); QHeaderView * headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &RecipeAdditionHopTableModel::contextMenu); @@ -96,13 +85,8 @@ void RecipeAdditionHopTableModel::setShowIBUs(bool var) { return; } -QVariant RecipeAdditionHopTableModel::data(const QModelIndex & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); +QVariant RecipeAdditionHopTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); } QVariant RecipeAdditionHopTableModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -119,32 +103,17 @@ QVariant RecipeAdditionHopTableModel::headerData(int section, Qt::Orientation or return QVariant(); } -Qt::ItemFlags RecipeAdditionHopTableModel::flags(const QModelIndex & index) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == RecipeAdditionHopTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - if (columnIndex == RecipeAdditionHopTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::NoItemFlags; - } - return Qt::ItemIsSelectable | - (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags RecipeAdditionHopTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags( + index, + this->m_editable, + {{RecipeAdditionHopTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEnabled}} + ); } -bool RecipeAdditionHopTableModel::setData(const QModelIndex & index, const QVariant & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns... - bool const retVal = this->writeDataToModel(index, value, role); - - // ...but we might need to re-show header IBUs - if (retVal) { - headerDataChanged(Qt::Vertical, index.row(), index.row()); - } - - return retVal; +bool RecipeAdditionHopTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + // Template parameter is true as we might need to re-show header IBUs + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/RecipeAdditionMiscTableModel.cpp b/src/tableModels/RecipeAdditionMiscTableModel.cpp index 987d50839..21690f4de 100755 --- a/src/tableModels/RecipeAdditionMiscTableModel.cpp +++ b/src/tableModels/RecipeAdditionMiscTableModel.cpp @@ -25,26 +25,16 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/RecipeAdditionMiscTableModel.h" -#include -#include #include -#include -#include #include #include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "Localization.h" -#include "MainWindow.h" #include "measurement/Measurement.h" #include "measurement/Unit.h" #include "model/Inventory.h" #include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" RecipeAdditionMiscTableModel::RecipeAdditionMiscTableModel(QTableView * parent, bool editable) : BtTableModelRecipeObserver{ @@ -72,7 +62,6 @@ RecipeAdditionMiscTableModel::RecipeAdditionMiscTableModel(QTableView * parent, TableModelBase{}, showIBUs(false) { this->rows.clear(); - this->setObjectName("hopAdditionTable"); QHeaderView * headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &RecipeAdditionMiscTableModel::contextMenu); @@ -92,13 +81,8 @@ void RecipeAdditionMiscTableModel::setShowIBUs(bool var) { return; } -QVariant RecipeAdditionMiscTableModel::data(const QModelIndex & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); +QVariant RecipeAdditionMiscTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); } QVariant RecipeAdditionMiscTableModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -115,25 +99,16 @@ QVariant RecipeAdditionMiscTableModel::headerData(int section, Qt::Orientation o return QVariant(); } -Qt::ItemFlags RecipeAdditionMiscTableModel::flags(const QModelIndex & index) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == RecipeAdditionMiscTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - if (columnIndex == RecipeAdditionMiscTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::NoItemFlags; - } - return Qt::ItemIsSelectable | - (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags RecipeAdditionMiscTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags( + index, + this->m_editable, + {{RecipeAdditionMiscTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEnabled}} + ); } -bool RecipeAdditionMiscTableModel::setData(const QModelIndex & index, const QVariant & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); +bool RecipeAdditionMiscTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/RecipeAdditionYeastTableModel.cpp b/src/tableModels/RecipeAdditionYeastTableModel.cpp index 26eab70de..e5e85e1e6 100755 --- a/src/tableModels/RecipeAdditionYeastTableModel.cpp +++ b/src/tableModels/RecipeAdditionYeastTableModel.cpp @@ -26,26 +26,16 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/RecipeAdditionYeastTableModel.h" -#include -#include #include -#include -#include #include #include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "Localization.h" -#include "MainWindow.h" #include "measurement/Measurement.h" #include "measurement/Unit.h" #include "model/Inventory.h" #include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" RecipeAdditionYeastTableModel::RecipeAdditionYeastTableModel(QTableView * parent, bool editable) : BtTableModelRecipeObserver{ @@ -80,7 +70,6 @@ RecipeAdditionYeastTableModel::RecipeAdditionYeastTableModel(QTableView * parent }, TableModelBase{} { this->rows.clear(); - this->setObjectName("yeastAdditionTable"); QHeaderView * headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &RecipeAdditionYeastTableModel::contextMenu); @@ -95,34 +84,20 @@ void RecipeAdditionYeastTableModel::added ([[maybe_unused]] std::shared_ptr item) { return; } void RecipeAdditionYeastTableModel::updateTotals() { return; } -QVariant RecipeAdditionYeastTableModel::data(const QModelIndex & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); +QVariant RecipeAdditionYeastTableModel::data(QModelIndex const & index, int role) const { + return this->doDataDefault(index, role); } -Qt::ItemFlags RecipeAdditionYeastTableModel::flags(const QModelIndex & index) const { - auto const columnIndex = static_cast(index.column()); - if (columnIndex == RecipeAdditionYeastTableModel::ColumnIndex::Name) { - return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; - } - if (columnIndex == RecipeAdditionYeastTableModel::ColumnIndex::TotalInventory) { - return Qt::ItemIsEnabled | Qt::NoItemFlags; - } - return Qt::ItemIsSelectable | - (this->m_editable ? Qt::ItemIsEditable : Qt::NoItemFlags) | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; +Qt::ItemFlags RecipeAdditionYeastTableModel::flags(QModelIndex const & index) const { + return TableModelHelper::doFlags( + index, + this->m_editable, + {{RecipeAdditionYeastTableModel::ColumnIndex::TotalInventory, Qt::ItemIsEnabled}} + ); } -bool RecipeAdditionYeastTableModel::setData(const QModelIndex & index, const QVariant & value, int role) { - if (!this->indexAndRoleOk(index, role)) { - return false; - } - - // No special handling required for any of our columns - return this->writeDataToModel(index, value, role); +bool RecipeAdditionYeastTableModel::setData(QModelIndex const & index, QVariant const & value, int role) { + return this->doSetDataDefault(index, value, role); } // Insert the boiler-plate stuff that we cannot do in TableModelBase diff --git a/src/tableModels/RecipeAdjustmentSaltTableModel.cpp b/src/tableModels/RecipeAdjustmentSaltTableModel.cpp index c61c051fd..03bb8e441 100755 --- a/src/tableModels/RecipeAdjustmentSaltTableModel.cpp +++ b/src/tableModels/RecipeAdjustmentSaltTableModel.cpp @@ -20,29 +20,17 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/RecipeAdjustmentSaltTableModel.h" -#include -#include -#include #include -#include -#include -#include #include -#include -#include #include -#include #include #include -#include "database/ObjectStoreWrapper.h" #include "measurement/Measurement.h" #include "measurement/Unit.h" +#include "model/Inventory.h" #include "model/Mash.h" -#include "model/MashStep.h" #include "model/Recipe.h" -#include "PersistentSettings.h" -#include "WaterDialog.h" RecipeAdjustmentSaltTableModel::RecipeAdjustmentSaltTableModel(QTableView* parent, bool editable) : BtTableModelRecipeObserver{ @@ -72,7 +60,6 @@ RecipeAdjustmentSaltTableModel::RecipeAdjustmentSaltTableModel(QTableView* paren } }, TableModelBase{} { - setObjectName("saltTable"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); headerView->setMinimumSectionSize(parent->width()/this->columnCount()); @@ -239,12 +226,7 @@ double RecipeAdjustmentSaltTableModel::totalAcidWeight(Salt::Type type) const { } QVariant RecipeAdjustmentSaltTableModel::data(QModelIndex const & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } Qt::ItemFlags RecipeAdjustmentSaltTableModel::flags(const QModelIndex& index) const { diff --git a/src/tableModels/SaltTableModel.cpp b/src/tableModels/SaltTableModel.cpp index b1a2b5232..2e3b90366 100644 --- a/src/tableModels/SaltTableModel.cpp +++ b/src/tableModels/SaltTableModel.cpp @@ -19,30 +19,11 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/SaltTableModel.h" -#include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include #include #include -#include "database/ObjectStoreWrapper.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" -#include "model/Mash.h" -#include "model/MashStep.h" -#include "model/Recipe.h" -#include "PersistentSettings.h" -#include "WaterDialog.h" - SaltTableModel::SaltTableModel(QTableView* parent, bool editable) : BtTableModel{ parent, @@ -53,15 +34,12 @@ SaltTableModel::SaltTableModel(QTableView* parent, bool editable) : // // Note too that, for the purposes of these columns, the "name" of a Salt is not its "NamedEntity name" but actually its type TABLE_MODEL_HEADER(Salt, Name , tr("Name" ), PropertyNames::Salt::type , EnumInfo{Salt::typeStringMapping, Salt::typeDisplayNames}), -/// TABLE_MODEL_HEADER(Salt, Amount , tr("Amount" ), PropertyNames::Salt::amountWithUnits), -/// TABLE_MODEL_HEADER(Salt, AddTo , tr("Added To"), PropertyNames::Salt::whenToAdd , EnumInfo{Salt::whenToAddStringMapping, Salt::whenToAddDisplayNames}), TABLE_MODEL_HEADER(Salt, PctAcid, tr("% Acid" ), PropertyNames::Salt::percentAcid ), TABLE_MODEL_HEADER(Salt, TotalInventory , tr("Inventory" ), PropertyNames::Ingredient::totalInventory, PrecisionInfo{1}), TABLE_MODEL_HEADER(Salt, TotalInventoryType, tr("Amount Type"), PropertyNames::Ingredient::totalInventory, Salt::validMeasures), } }, TableModelBase{} { - setObjectName("saltTable"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); headerView->setMinimumSectionSize(parent->width()/this->columnCount()); @@ -77,12 +55,7 @@ void SaltTableModel::removed([[maybe_unused]] std::shared_ptr item) { retu void SaltTableModel::updateTotals() { return; } QVariant SaltTableModel::data(QModelIndex const & index, int role) const { - if (!this->indexAndRoleOk(index, role)) { - return QVariant(); - } - - // No special handling required for any of our columns - return this->readDataFromModel(index, role); + return this->doDataDefault(index, role); } Qt::ItemFlags SaltTableModel::flags(const QModelIndex& index) const { @@ -114,19 +87,6 @@ bool SaltTableModel::setData(QModelIndex const & index, QVariant const & value, return retVal; } -///void SaltTableModel::saveAndClose() { -/// // all of the writes should have been instantaneous unless -/// // we've added a new salt. Wonder if this will work? -/// for (auto salt : this->rows) { -/// if (salt->key() < 0 && -/// salt->whenToAdd() != Salt::WhenToAdd::NEVER) { -/// ObjectStoreWrapper::insert(salt); -/// this->recObs->add(salt); -/// } -/// } -/// return; -///} - // Insert the boiler-plate stuff that we cannot do in TableModelBase TABLE_MODEL_COMMON_CODE(Salt, salt, PropertyNames::None::none) //=============================================== CLASS SaltItemDelegate =============================================== diff --git a/src/tableModels/StyleTableModel.cpp b/src/tableModels/StyleTableModel.cpp index 685621aae..9829b312d 100755 --- a/src/tableModels/StyleTableModel.cpp +++ b/src/tableModels/StyleTableModel.cpp @@ -15,19 +15,10 @@ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌*/ #include "tableModels/StyleTableModel.h" -#include #include -#include - -#include "database/ObjectStoreWrapper.h" -#include "MainWindow.h" -#include "measurement/Measurement.h" -#include "measurement/Unit.h" -#include "model/Inventory.h" -#include "model/Recipe.h" -#include "PersistentSettings.h" -#include "utils/BtStringConst.h" -#include "widgets/BtComboBox.h" +#include +#include +#include StyleTableModel::StyleTableModel(QTableView* parent, bool editable) : BtTableModel{ @@ -44,7 +35,6 @@ StyleTableModel::StyleTableModel(QTableView* parent, bool editable) : }, TableModelBase{} { this->rows.clear(); - setObjectName("styleTableModel"); QHeaderView* headerView = m_parentTableWidget->horizontalHeader(); connect(headerView, &QWidget::customContextMenuRequested, this, &StyleTableModel::contextMenu); @@ -58,30 +48,15 @@ void StyleTableModel::removed([[maybe_unused]] std::shared_ptr