diff --git a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp index 1d7396206..6c912ae02 100644 --- a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp +++ b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp @@ -21,7 +21,7 @@ static bool ignoreHiddenFlag(int i) } TabDiveEquipment::TabDiveEquipment(QWidget *parent) : TabBase(parent), - cylindersModel(new CylindersModelFiltered(this)), + cylindersModel(new CylindersModel(false, true, this)), weightModel(new WeightModel(this)) { QCompleter *suitCompleter; @@ -39,7 +39,7 @@ TabDiveEquipment::TabDiveEquipment(QWidget *parent) : TabBase(parent), connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &TabDiveEquipment::divesChanged); connect(ui.cylinders, &TableView::itemClicked, this, &TabDiveEquipment::editCylinderWidget); connect(ui.weights, &TableView::itemClicked, this, &TabDiveEquipment::editWeightWidget); - connect(cylindersModel->model(), &CylindersModel::divesEdited, this, &TabDiveEquipment::divesEdited); + connect(cylindersModel, &CylindersModel::divesEdited, this, &TabDiveEquipment::divesEdited); connect(weightModel, &WeightModel::divesEdited, this, &TabDiveEquipment::divesEdited); // Current display of things on Gnome3 looks like shit, so @@ -174,9 +174,8 @@ void TabDiveEquipment::editCylinderWidget(const QModelIndex &index) return; if (index.column() == CylindersModel::REMOVE) { - int cylinder_id = cylindersModel->mapToSource(index).row(); for (dive *d: getDiveSelection()) { - if (cylinder_with_sensor_sample(d, cylinder_id)) { + if (cylinder_with_sensor_sample(d, index.row())) { if (QMessageBox::warning(this, tr("Remove cylinder?"), tr("The deleted cylinder has sensor readings, which will be lost.\n" "Do you want to continue?"), @@ -184,7 +183,7 @@ void TabDiveEquipment::editCylinderWidget(const QModelIndex &index) return; } } - divesEdited(Command::removeCylinder(cylindersModel->mapToSource(index).row(), false)); + divesEdited(Command::removeCylinder(index.row(), false)); } else { ui.cylinders->edit(index); } diff --git a/desktop-widgets/tab-widgets/TabDiveEquipment.h b/desktop-widgets/tab-widgets/TabDiveEquipment.h index 55eb21d1e..f70cd3f57 100644 --- a/desktop-widgets/tab-widgets/TabDiveEquipment.h +++ b/desktop-widgets/tab-widgets/TabDiveEquipment.h @@ -12,7 +12,7 @@ namespace Ui { }; class WeightModel; -class CylindersModelFiltered; +class CylindersModel; class TabDiveEquipment : public TabBase { Q_OBJECT @@ -36,7 +36,7 @@ private slots: private: Ui::TabDiveEquipment ui; SuitCompletionModel suitModel; - CylindersModelFiltered *cylindersModel; + CylindersModel *cylindersModel; WeightModel *weightModel; }; diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index cb1bbf1f7..325f53add 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -11,9 +11,11 @@ #include "core/subsurface-string.h" #include -CylindersModel::CylindersModel(bool planner, QObject *parent) : CleanerTableModel(parent), +CylindersModel::CylindersModel(bool planner, bool hideUnused, QObject *parent) : CleanerTableModel(parent), d(nullptr), inPlanner(planner), + hideUnused(hideUnused), + numRows(0), tempRow(-1), tempCyl(empty_cylinder) { @@ -150,12 +152,26 @@ bool CylindersModel::cylinderUsed(int i) const return false; } +// Calculate the number of displayed cylinders: If hideUnused +// is set, we don't show unused cylinders at the end of the list. +int CylindersModel::calcNumRows() const +{ + if (!d) + return 0; + if (!hideUnused || prefs.display_unused_tanks) + return d->cylinders.nr; + int res = d->cylinders.nr; + while (res > 0 && !cylinderUsed(res - 1)) + --res; + return res; +} + QVariant CylindersModel::data(const QModelIndex &index, int role) const { if (!d || !index.isValid()) return QVariant(); - if (index.row() >= d->cylinders.nr) { + if (index.row() >= numRows) { qWarning("CylindersModel and dive are out of sync!"); return QVariant(); } @@ -300,7 +316,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in return false; int row = index.row(); - if (row < 0 || row >= d->cylinders.nr) + if (row < 0 || row >= numRows) return false; // Here we handle a few cases that allow us to set / commit / revert @@ -480,9 +496,10 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in int CylindersModel::rowCount(const QModelIndex&) const { - return d ? d->cylinders.nr : 0; + return numRows; } +// Only invoked from planner. void CylindersModel::add() { if (!d) @@ -510,6 +527,7 @@ void CylindersModel::updateDive(dive *dIn) #endif beginResetModel(); d = dIn; + numRows = calcNumRows(); endResetModel(); } @@ -558,8 +576,12 @@ void CylindersModel::cylinderAdded(struct dive *changed, int pos) return; // The row was already inserted by the undo command. Just inform the model. - beginInsertRows(QModelIndex(), pos, pos); - endInsertRows(); + if (pos < numRows) { + beginInsertRows(QModelIndex(), pos, pos); + ++numRows; + endInsertRows(); + } + updateNumRows(); } void CylindersModel::cylinderRemoved(struct dive *changed, int pos) @@ -568,8 +590,12 @@ void CylindersModel::cylinderRemoved(struct dive *changed, int pos) return; // The row was already deleted by the undo command. Just inform the model. - beginRemoveRows(QModelIndex(), pos, pos); - endRemoveRows(); + if (pos < numRows) { + beginRemoveRows(QModelIndex(), pos, pos); + --numRows; + endRemoveRows(); + } + updateNumRows(); } void CylindersModel::cylinderEdited(struct dive *changed, int pos) @@ -577,9 +603,26 @@ void CylindersModel::cylinderEdited(struct dive *changed, int pos) if (d != changed) return; - dataChanged(index(pos, TYPE), index(pos, USE)); + if (pos < numRows) + dataChanged(index(pos, TYPE), index(pos, USE)); + updateNumRows(); } +void CylindersModel::updateNumRows() +{ + int numRowsNew = calcNumRows(); + if (numRowsNew < numRows) { + beginRemoveRows(QModelIndex(), numRowsNew, numRows - 1); + numRows = numRowsNew; + endRemoveRows(); + } else if (numRowsNew > numRows) { + beginInsertRows(QModelIndex(), numRows, numRowsNew - 1); + numRows = numRowsNew; + endInsertRows(); + } +} + +// Only invoked from planner. void CylindersModel::moveAtFirst(int cylid) { if (!d) @@ -607,9 +650,10 @@ void CylindersModel::moveAtFirst(int cylid) endMoveRows(); } +// Only invoked from planner. void CylindersModel::updateDecoDepths(pressure_t olddecopo2) { - if (!d) + if (!d || numRows <= 0) return; pressure_t decopo2; @@ -622,17 +666,18 @@ void CylindersModel::updateDecoDepths(pressure_t olddecopo2) cyl->depth = gas_mod(cyl->gasmix, decopo2, d, M_OR_FT(3, 10)); } } - emit dataChanged(createIndex(0, 0), createIndex(d->cylinders.nr - 1, COLUMNS - 1)); + emit dataChanged(createIndex(0, 0), createIndex(numRows - 1, COLUMNS - 1)); } void CylindersModel::updateTrashIcon() { - if (!d) + if (!d || numRows <= 0) return; - emit dataChanged(createIndex(0, 0), createIndex(d->cylinders.nr - 1, 0)); + emit dataChanged(createIndex(0, 0), createIndex(numRows - 1, 0)); } +// Only invoked from planner. bool CylindersModel::updateBestMixes() { if (!d) @@ -667,8 +712,9 @@ bool CylindersModel::updateBestMixes() return gasUpdated; } -void CylindersModel::emitDataChanged() { - emit dataChanged(createIndex(0, 0), createIndex(d->cylinders.nr - 1, COLUMNS - 1)); +void CylindersModel::emitDataChanged() +{ + emit dataChanged(createIndex(0, 0), createIndex(numRows - 1, COLUMNS - 1)); } void CylindersModel::cylindersReset(const QVector &dives) @@ -680,6 +726,7 @@ void CylindersModel::cylindersReset(const QVector &dives) // And update the model (the actual change was already performed in the backend).. beginResetModel(); + numRows = calcNumRows(); endResetModel(); } @@ -730,29 +777,3 @@ void CylindersModel::commitTempCyl(int row) free_cylinder(tempCyl); tempRow = -1; } - -CylindersModelFiltered::CylindersModelFiltered(QObject *parent) : QSortFilterProxyModel(parent), - source(false) // Currently, only the EquipmentTab uses the filtered model. -{ - setSourceModel(&source); -} - -void CylindersModelFiltered::updateDive(dive *d) -{ - source.updateDive(d); -} - -void CylindersModelFiltered::clear() -{ - source.clear(); -} - -CylindersModel *CylindersModelFiltered::model() -{ - return &source; -} - -bool CylindersModelFiltered::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - return prefs.display_unused_tanks || source.cylinderUsed(source_row); -} diff --git a/qt-models/cylindermodel.h b/qt-models/cylindermodel.h index e7477193e..0da08900b 100644 --- a/qt-models/cylindermodel.h +++ b/qt-models/cylindermodel.h @@ -35,7 +35,7 @@ public: COMMIT_ROLE, // Save the temporary data to the dive. Must be set with Column == TYPE. REVERT_ROLE // Revert to original data from dive. Must be set with Column == TYPE. }; - explicit CylindersModel(bool planner, QObject *parent = 0); // First argument: true if this model is used for the planner + explicit CylindersModel(bool planner, bool hideUnused, QObject *parent = 0); // First argument: true if this model is used for the planner QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; @@ -50,7 +50,6 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role) const override; bool updateBestMixes(); void emitDataChanged(); - bool cylinderUsed(int i) const; signals: void divesEdited(int num); @@ -66,6 +65,8 @@ slots: private: dive *d; bool inPlanner; + bool hideUnused; + int numRows; // Does not include unused cylinders at the end // Used if we temporarily change a line because the user is selecting a weight type int tempRow; cylinder_t tempCyl; @@ -74,20 +75,9 @@ private: void initTempCyl(int row); void clearTempCyl(); void commitTempCyl(int row); -}; - -// Cylinder model that hides unused cylinders if the pref.show_unused_cylinders flag is not set -class CylindersModelFiltered : public QSortFilterProxyModel { - Q_OBJECT -public: - CylindersModelFiltered(QObject *parent = 0); - CylindersModel *model(); // Access to unfiltered base model - - void clear(); - void updateDive(dive *d); -private: - CylindersModel source; - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; + bool cylinderUsed(int i) const; + int calcNumRows() const; + void updateNumRows(); }; #endif diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index cdf340a3f..74b3eac3f 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -446,7 +446,7 @@ int DivePlannerPointsModel::rowCount(const QModelIndex&) const DivePlannerPointsModel::DivePlannerPointsModel(QObject *parent) : QAbstractTableModel(parent), d(nullptr), - cylinders(true), + cylinders(true, false), mode(NOTHING) { memset(&diveplan, 0, sizeof(diveplan));