summaryrefslogtreecommitdiffstats
path: root/qt-models/divetripmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt-models/divetripmodel.cpp')
-rw-r--r--qt-models/divetripmodel.cpp126
1 files changed, 69 insertions, 57 deletions
diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp
index 7ee09d2a7..2a83b61da 100644
--- a/qt-models/divetripmodel.cpp
+++ b/qt-models/divetripmodel.cpp
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "qt-models/divetripmodel.h"
-#include "qt-models/filtermodels.h"
#include "core/divefilter.h"
#include "core/gettextfromc.h"
#include "core/metrics.h"
@@ -400,9 +399,6 @@ Qt::ItemFlags DiveTripModelBase::flags(const QModelIndex &index) const
bool DiveTripModelBase::setData(const QModelIndex &index, const QVariant &value, int role)
{
- if (role == SHOWN_ROLE)
- return setShown(index, value.value<bool>());
-
// We only support setting of data for dives and there, only the number.
dive *d = diveOrNull(index);
if (!d)
@@ -688,34 +684,49 @@ dive *DiveTripModelTree::diveOrNull(const QModelIndex &index) const
return tripOrDive(index).dive;
}
-// Set the shown flag that marks whether an entry is shown or hidden by the filter.
-// The flag is cached for top-level items (trips and dives outside of trips).
-// For dives that belong to a trip (i.e. non-top-level items), the flag is
-// simply written through to the core.
-bool DiveTripModelTree::setShown(const QModelIndex &idx, bool shown)
-{
- if (!idx.isValid())
- return false;
-
- QModelIndex parent = idx.parent();
- if (!parent.isValid()) {
- // An invalid parent means that we're at the top-level
- Item &item = items[idx.row()];
- item.shown = shown; // Cache the flag.
- if (item.d_or_t.dive) {
- // This is a dive -> also register the flag in the core
- filter_dive(item.d_or_t.dive, shown);
+void DiveTripModelTree::recalculateFilter()
+{
+ {
+ // This marker prevents the UI from getting notifications on selection changes.
+ // It is active until the end of the scope.
+ // This was actually designed for the undo-commands, so that they can do their work
+ // without having the UI updated.
+ // Here, it is used because invalidating the filter can generate numerous
+ // selection changes, which do full ui reloads. Instead, do that all at once
+ // as a consequence of the filterReset signal right after the local scope.
+ auto marker = diveListNotifier.enterCommand();
+ DiveFilter *filter = DiveFilter::instance();
+ for (Item &item: items) {
+ if (item.d_or_t.dive) {
+ dive *d = item.d_or_t.dive;
+ item.shown = filter->showDive(item.d_or_t.dive);
+ filter_dive(d, item.shown);
+ } else {
+ // Trips are shown if any of the dives is shown
+ bool showTrip = false;
+ for (dive *d: item.dives) {
+ bool shown = filter->showDive(d);
+ filter_dive(d, shown);
+ showTrip |= shown;
+ }
+ item.shown = showTrip;
+ }
}
- } else {
- // We're not at the top-level. This must be a dive, therefore
- // simply write the flag through to the core.
- const Item &parentItem = items[parent.row()];
- filter_dive(parentItem.dives[idx.row()], shown);
}
- return true;
+
+ // Rerender all trip headers. TODO: be smarter about this and only rerender if the number
+ // of shown dives changed.
+ for (int idx = 0; idx < (int)items.size(); ++idx) {
+ QModelIndex tripIndex = createIndex(idx, 0, noParent);
+ dataChanged(tripIndex, tripIndex);
+ }
+
+ emit diveListNotifier.numShownChanged();
+ emit diveListNotifier.filterReset();
}
+
QVariant DiveTripModelTree::data(const QModelIndex &index, int role) const
{
if (role == SHOWN_ROLE) {
@@ -980,13 +991,23 @@ void DiveTripModelTree::divesChanged(const QVector<dive *> &dives)
{ divesChangedTrip(trip, divesInTrip); });
}
+// Update visibility status of dive and return true if visibility changed
+static bool updateShown(const QVector<dive *> &dives)
+{
+ bool changed = false;
+ DiveFilter *filter = DiveFilter::instance();
+ for (dive *d: dives) {
+ bool newStatus = filter->showDive(d);
+ changed |= filter_dive(d, newStatus);
+ }
+ if (changed)
+ emit diveListNotifier.numShownChanged();
+ return changed;
+}
+
void DiveTripModelTree::divesChangedTrip(dive_trip *trip, const QVector<dive *> &dives)
{
- // Update filter flags. TODO: The filter should update the flag by itself when
- // recieving the signals below.
- bool diveChanged = false;
- for (dive *d: dives)
- diveChanged |= MultiFilterSortModel::instance()->updateDive(d);
+ bool diveChanged = updateShown(dives);
if (!trip) {
// This is outside of a trip. Process top-level items range-wise.
@@ -1182,16 +1203,6 @@ void DiveTripModelTree::divesSelectedTrip(dive_trip *trip, const QVector<dive *>
}
}
-void DiveTripModelTree::filterFinished()
-{
- // If the filter finished, update all trip items to show the correct number of displayed dives
- // in each trip. Without doing this, only trip headers of expanded trips were updated.
- for (int idx = 0; idx < (int)items.size(); ++idx) {
- QModelIndex tripIndex = createIndex(idx, 0, noParent);
- dataChanged(tripIndex, tripIndex);
- }
-}
-
bool DiveTripModelTree::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
{
// In tree mode we don't support any sorting!
@@ -1248,13 +1259,22 @@ dive *DiveTripModelList::diveOrNull(const QModelIndex &index) const
return items[row];
}
-bool DiveTripModelList::setShown(const QModelIndex &idx, bool shown)
+void DiveTripModelList::recalculateFilter()
{
- dive *d = diveOrNull(idx);
- if (!d)
- return false;
- filter_dive(d, shown);
- return true;
+ {
+ // This marker prevents the UI from getting notifications on selection changes.
+ // It is active until the end of the scope. See comment in DiveTripModelTree::recalculateFilter().
+ auto marker = diveListNotifier.enterCommand();
+ DiveFilter *filter = DiveFilter::instance();
+
+ for (dive *d: items) {
+ bool shown = filter->showDive(d);
+ filter_dive(d, shown);
+ }
+ }
+
+ emit diveListNotifier.numShownChanged();
+ emit diveListNotifier.filterReset();
}
QVariant DiveTripModelList::data(const QModelIndex &index, int role) const
@@ -1308,10 +1328,7 @@ void DiveTripModelList::divesChanged(const QVector<dive *> &divesIn)
QVector<dive *> dives = divesIn;
std::sort(dives.begin(), dives.end(), dive_less_than);
- // Update filter flags. TODO: The filter should update the flag by itself when
- // recieving the signals below.
- for (dive *d: dives)
- MultiFilterSortModel::instance()->updateDive(d);
+ updateShown(dives);
// Since we know that the dive list is sorted, we will only ever search for the first element
// in dives as this must be the first that we encounter. Once we find a range, increase the
@@ -1372,11 +1389,6 @@ void DiveTripModelList::divesSelected(const QVector<dive *> &dives, dive *curren
emit newCurrentDive(createIndex(it - items.begin(), 0));
}
-void DiveTripModelList::filterFinished()
-{
- // In list mode, we don't have to change anything after filter finished.
-}
-
// Simple sorting helper for sorting against a criterium and if
// that is undefined against a different criterium.
// Return true if diff1 < 0, false if diff1 > 0.