From 6ec82a3c80e0f362abc59a6df8ea793013f01c65 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 9 Dec 2019 15:37:26 +0100 Subject: [PATCH] Dive list: remove global pointer to DiveTrip model This part of the code had that horrible pattern, where reseting the model would invalidate all pointers to the DiveTrip model. Internalize these complexities in the MultiFilterSortModel. All accesses are now performed via that proxy model. Signed-off-by: Berthold Stoeger --- qt-models/divetripmodel.cpp | 16 ---------------- qt-models/divetripmodel.h | 15 --------------- qt-models/filtermodels.cpp | 22 ++++++++++++---------- qt-models/filtermodels.h | 4 ++++ 4 files changed, 16 insertions(+), 41 deletions(-) diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp index ae6dfe651..64bb28533 100644 --- a/qt-models/divetripmodel.cpp +++ b/qt-models/divetripmodel.cpp @@ -357,22 +357,6 @@ QVariant DiveTripModelBase::headerData(int section, Qt::Orientation orientation, return QVariant(); } -static std::unique_ptr currentModel; -DiveTripModelBase *DiveTripModelBase::instance() -{ - if (!currentModel) - resetModel(TREE); - return currentModel.get(); -} - -void DiveTripModelBase::resetModel(DiveTripModelBase::Layout layout) -{ - if (layout == TREE) - currentModel.reset(new DiveTripModelTree); - else - currentModel.reset(new DiveTripModelList); -} - // After resetting the model, the higher up model or view may call this // function to get informed on the current selection. // TODO: Currently, this reads and resets the selection. Make this more diff --git a/qt-models/divetripmodel.h b/qt-models/divetripmodel.h index 66af0a32a..eed6913cf 100644 --- a/qt-models/divetripmodel.h +++ b/qt-models/divetripmodel.h @@ -18,12 +18,6 @@ struct DiveFilter; // from DiveTripModelBase, which implements common features (e.g. // definition of the column types, access of data from the core // structures) and a common interface. -// -// The currently active model is set via DiveTripModelBase::resetModel(). -// This will create a new model. The model can be accessed with -// DiveTripModelBase::instance(). A pointer obtained by instance() -// is invalidated by a call to resetModel()! Yes, this is surprising -// behavior, so care must be taken. class DiveTripModelBase : public QAbstractItemModel { Q_OBJECT public: @@ -63,15 +57,6 @@ public: LIST, }; - // Functions implemented by base class - static DiveTripModelBase *instance(); - - // Reset the model using the given layout. After this call instance() will return - // a newly allocated object and the old model will have been destroyed! Thus, the - // caller is responsible for removing all references to any previous model obtained - // by instance(). - static void resetModel(Layout layout); - // Call after having set the model to be informed of the current selection. void initSelection(); diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp index 463276e13..d07de02c0 100644 --- a/qt-models/filtermodels.cpp +++ b/qt-models/filtermodels.cpp @@ -15,6 +15,7 @@ MultiFilterSortModel *MultiFilterSortModel::instance() MultiFilterSortModel::MultiFilterSortModel(QObject *parent) : QSortFilterProxyModel(parent) { + resetModel(DiveTripModelBase::TREE); setFilterKeyColumn(-1); // filter all columns setFilterRole(DiveTripModelBase::SHOWN_ROLE); // Let the proxy-model known that is has to react to change events involving SHOWN_ROLE setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -22,19 +23,20 @@ MultiFilterSortModel::MultiFilterSortModel(QObject *parent) : QSortFilterProxyMo void MultiFilterSortModel::resetModel(DiveTripModelBase::Layout layout) { - DiveTripModelBase::resetModel(layout); - // DiveTripModelBase::resetModel() generates a new instance. - // Thus, the source model must be reset and the connections must be reset. - DiveTripModelBase *m = DiveTripModelBase::instance(); - setSourceModel(m); - connect(m, &DiveTripModelBase::selectionChanged, this, &MultiFilterSortModel::selectionChangedSlot); - connect(m, &DiveTripModelBase::currentDiveChanged, this, &MultiFilterSortModel::currentDiveChangedSlot); - m->initSelection(); + if (layout == DiveTripModelBase::TREE) + model.reset(new DiveTripModelTree); + else + model.reset(new DiveTripModelList); + + setSourceModel(model.get()); + connect(model.get(), &DiveTripModelBase::selectionChanged, this, &MultiFilterSortModel::selectionChangedSlot); + connect(model.get(), &DiveTripModelBase::currentDiveChanged, this, &MultiFilterSortModel::currentDiveChangedSlot); + model->initSelection(); } void MultiFilterSortModel::clear() { - DiveTripModelBase::instance()->clear(); + model->clear(); } // Translate selection into local indexes and re-emit signal @@ -68,5 +70,5 @@ bool MultiFilterSortModel::filterAcceptsRow(int source_row, const QModelIndex &s bool MultiFilterSortModel::lessThan(const QModelIndex &i1, const QModelIndex &i2) const { // Hand sorting down to the source model. - return DiveTripModelBase::instance()->lessThan(i1, i2); + return model->lessThan(i1, i2); } diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h index fef39e0d5..33d17791b 100644 --- a/qt-models/filtermodels.h +++ b/qt-models/filtermodels.h @@ -5,7 +5,10 @@ #include "divetripmodel.h" #include +#include +// This proxy model sits on top of either a DiveTripList or DiveTripTree model +// and does filtering and/or sorting. class MultiFilterSortModel : public QSortFilterProxyModel { Q_OBJECT public: @@ -23,6 +26,7 @@ private slots: void currentDiveChangedSlot(QModelIndex index); private: MultiFilterSortModel(QObject *parent = 0); + std::unique_ptr model; }; #endif