diff --git a/commands/command_divelist.cpp b/commands/command_divelist.cpp index eedac4b6e..908b366a6 100644 --- a/commands/command_divelist.cpp +++ b/commands/command_divelist.cpp @@ -68,11 +68,9 @@ dive *DiveListBase::addDive(DiveToAdd &d) } dive *res = d.dive.release(); // Give up ownership of dive - // Set the filter flag according to current filter settings - bool show = DiveFilter::instance()->showDive(res); - res->hidden_by_filter = !show; - if (show) - ++shown_dives; + // When we add dives, we start in hidden-by-filter status. Once all + // dives have been added, their status will be updated. + res->hidden_by_filter = true; int idx = dive_table_get_insertion_index(&dive_table, res); add_to_dive_table(&dive_table, idx, res); // Return ownership to backend @@ -185,19 +183,21 @@ DivesAndSitesToRemove DiveListBase::addDives(DivesAndTripsToAdd &toAdd) [](const DiveToAdd &d, const DiveToAdd &d2) { return dive_less_than(d.dive.get(), d2.dive.get()); }); - // Remember old number of shown dives - int oldShown = shown_dives; - // Now, add the dives // Note: the idiomatic STL-way would be std::transform, but let's use a loop since // that is closer to classical C-style. auto it2 = res.rbegin(); + QVector divesToFilter; + divesToFilter.reserve(toAdd.dives.size()); for (auto it = toAdd.dives.rbegin(); it != toAdd.dives.rend(); ++it, ++it2) { *it2 = addDive(*it); dives.push_back({ (*it2)->divetrip, *it2 }); + divesToFilter.push_back(*it2); } toAdd.dives.clear(); + ShownChange change = DiveFilter::instance()->update(divesToFilter); + // If the dives belong to new trips, add these as well. // Remember the pointers so that we can later check if a trip was newly added std::vector addedTrips; @@ -224,7 +224,7 @@ DivesAndSitesToRemove DiveListBase::addDives(DivesAndTripsToAdd &toAdd) emit diveListNotifier.divesAdded(trip, createTrip, divesInTrip); }); - if (oldShown != shown_dives) + if (!change.newShown.empty() || !change.newHidden.empty()) emit diveListNotifier.numShownChanged(); return { res, sites }; diff --git a/core/divefilter.cpp b/core/divefilter.cpp index 5bb05b947..7f47e45ac 100644 --- a/core/divefilter.cpp +++ b/core/divefilter.cpp @@ -8,10 +8,12 @@ DiveFilter::DiveFilter() { } -bool DiveFilter::showDive(const struct dive *d) const +ShownChange DiveFilter::update(const QVector &) const +{ +} + +ShownChange DiveFilter::updateAll() const { - // TODO: Do something useful - return true; } #else // SUBSURFACE_MOBILE @@ -24,6 +26,37 @@ bool DiveFilter::showDive(const struct dive *d) const #include "core/divesite.h" #include "qt-models/filtermodels.h" +void DiveFilter::updateDiveStatus(dive *d, ShownChange &change) const +{ + bool newStatus = showDive(d); + if (filter_dive(d, newStatus)) { + if (newStatus) + change.newShown.push_back(d); + else + change.newHidden.push_back(d); + } +} + +ShownChange DiveFilter::update(const QVector &dives) const +{ + dive *old_current = current_dive; + ShownChange res; + for (dive *d: dives) + updateDiveStatus(d, res); + res.currentChanged = old_current != current_dive; + return res; +} + +ShownChange DiveFilter::updateAll() const +{ + dive *old_current = current_dive; + ShownChange res; + for (int i = 0; i < dive_table.nr; ++i) + updateDiveStatus(get_dive(i), res); + res.currentChanged = old_current != current_dive; + return res; +} + namespace { // Pointer to function that takes two strings and returns whether // the first matches the second according to a criterion (substring, starts-with, exact). diff --git a/core/divefilter.h b/core/divefilter.h index 2ad3c4b9b..aa166d022 100644 --- a/core/divefilter.h +++ b/core/divefilter.h @@ -3,6 +3,16 @@ #ifndef DIVE_FILTER_H #define DIVE_FILTER_H +#include +struct dive; + +// Structure describing changes of shown status upon applying the filter +struct ShownChange { + QVector newShown; + QVector newHidden; + bool currentChanged; +}; + // The dive filter for mobile is currently much simpler than for desktop. // Therefore, for now we have two completely separate implementations. // This should be unified in the future. @@ -12,7 +22,8 @@ class DiveFilter { public: static DiveFilter *instance(); - bool showDive(const struct dive *d) const; + ShownChange update(const QVector &dives) const; // Update filter status of given dives and return dives whose status changed + ShownChange updateAll() const; // Update filter status of all dives and return dives whose status changed private: DiveFilter(); }; @@ -21,9 +32,7 @@ private: #include #include -#include -struct dive; struct dive_trip; struct dive_site; @@ -82,15 +91,18 @@ class DiveFilter { public: static DiveFilter *instance(); - bool showDive(const struct dive *d) const; bool diveSiteMode() const; // returns true if we're filtering on dive site const QVector &filteredDiveSites() const; void startFilterDiveSites(QVector ds); void setFilterDiveSite(QVector ds); void stopFilterDiveSites(); void setFilter(const FilterData &data); + ShownChange update(const QVector &dives) const; // Update filter status of given dives and return dives whose status changed + ShownChange updateAll() const; // Update filter status of all dives and return dives whose status changed private: DiveFilter(); + void updateDiveStatus(dive *d, ShownChange &change) const; + bool showDive(const struct dive *d) const; // Should that dive be shown? QVector dive_sites; FilterData filterData; diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp index e3b8266cf..ce4206cfb 100644 --- a/qt-models/divetripmodel.cpp +++ b/qt-models/divetripmodel.cpp @@ -432,41 +432,18 @@ bool DiveTripModelBase::setData(const QModelIndex &index, const QVariant &value, return true; } -// Structure describing changes of shown status -struct ShownChange { - QVector newShown; - QVector newHidden; - bool currentChanged; - void filterDive(dive *d, const DiveFilter *filter); -}; - -void ShownChange::filterDive(dive *d, const DiveFilter *filter) -{ - bool newStatus = filter->showDive(d); - if (filter_dive(d, newStatus)) { - if (newStatus) - newShown.push_back(d); - else - newHidden.push_back(d); - } -} - // Update visibility status of dive and return dives whose visibility changed. // Attention: the changed dives are removed from the original vector! static ShownChange updateShown(QVector &dives) { DiveFilter *filter = DiveFilter::instance(); - dive *old_current = current_dive; - ShownChange res; - for (dive *d: dives) - res.filterDive(d, filter); + ShownChange res = filter->update(dives); if (!res.newShown.empty() || !res.newHidden.empty()) emit diveListNotifier.numShownChanged(); for (dive *d: res.newHidden) dives.removeAll(d); for (dive *d: res.newShown) dives.removeAll(d); - res.currentChanged = old_current != current_dive; return res; } @@ -474,13 +451,9 @@ static ShownChange updateShown(QVector &dives) static ShownChange updateShownAll() { DiveFilter *filter = DiveFilter::instance(); - dive *old_current = current_dive; - ShownChange res; - for (int i = 0; i < dive_table.nr; ++i) - res.filterDive(get_dive(i), filter); + ShownChange res = filter->updateAll(); if (!res.newShown.empty() || !res.newHidden.empty()) emit diveListNotifier.numShownChanged(); - res.currentChanged = old_current != current_dive; return res; }