Undo: update filter flag when dives change

The filter code is strange: it actually only checks the
dive->hidden_by_filter flag. Thus, before propagating the dive
changed signal, this flag has to be updated. Do this in the
DiveTripModel. Ultimately, this should be refactored.

Moreover, if the filter-flag changed notify the frontend
of a changed trip so that the trip is hidden / unhidden.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-03-22 20:55:05 +01:00 committed by Dirk Hohndel
parent e7063b6b08
commit 9afea37e15
4 changed files with 46 additions and 3 deletions

View file

@ -7,6 +7,7 @@
#include "core/qthelper.h" #include "core/qthelper.h"
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include "qt-models/divelocationmodel.h" #include "qt-models/divelocationmodel.h"
#include "qt-models/filtermodels.h"
namespace Command { namespace Command {
@ -17,13 +18,16 @@ namespace Command {
static std::vector<dive_site *> addDiveSites(std::vector<OwningDiveSitePtr> &sites) static std::vector<dive_site *> addDiveSites(std::vector<OwningDiveSitePtr> &sites)
{ {
std::vector<dive_site *> res; std::vector<dive_site *> res;
std::vector<dive *> changedDives;
res.reserve(sites.size()); res.reserve(sites.size());
for (OwningDiveSitePtr &ds: sites) { for (OwningDiveSitePtr &ds: sites) {
// Readd the dives that belonged to this site // Readd the dives that belonged to this site
for (int i = 0; i < ds->dives.nr; ++i) { for (int i = 0; i < ds->dives.nr; ++i) {
// TODO: send dive site changed signal // TODO: send dive site changed signal
ds->dives.dives[i]->dive_site = ds.get(); struct dive *d = ds->dives.dives[i];
d->dive_site = ds.get();
changedDives.push_back(d);
} }
// Add dive site to core, but remember a non-owning pointer first. // Add dive site to core, but remember a non-owning pointer first.
@ -32,6 +36,10 @@ static std::vector<dive_site *> addDiveSites(std::vector<OwningDiveSitePtr> &sit
emit diveListNotifier.diveSiteAdded(res.back(), idx); // Inform frontend of new dive site. emit diveListNotifier.diveSiteAdded(res.back(), idx); // Inform frontend of new dive site.
} }
processByTrip(changedDives, [&](dive_trip *trip, const QVector<dive *> &divesInTrip) {
emit diveListNotifier.divesChanged(trip, divesInTrip, DiveField::DIVESITE);
});
// Clear vector of unused owning pointers // Clear vector of unused owning pointers
sites.clear(); sites.clear();
@ -44,13 +52,15 @@ static std::vector<dive_site *> addDiveSites(std::vector<OwningDiveSitePtr> &sit
static std::vector<OwningDiveSitePtr> removeDiveSites(std::vector<dive_site *> &sites) static std::vector<OwningDiveSitePtr> removeDiveSites(std::vector<dive_site *> &sites)
{ {
std::vector<OwningDiveSitePtr> res; std::vector<OwningDiveSitePtr> res;
std::vector<dive *> changedDives;
res.reserve(sites.size()); res.reserve(sites.size());
for (dive_site *ds: sites) { for (dive_site *ds: sites) {
// Reset the dive_site field of the affected dives // Reset the dive_site field of the affected dives
for (int i = 0; i < ds->dives.nr; ++i) { for (int i = 0; i < ds->dives.nr; ++i) {
// TODO: send dive site changed signal struct dive *d = ds->dives.dives[i];
ds->dives.dives[i]->dive_site = nullptr; d->dive_site = nullptr;
changedDives.push_back(d);
} }
// Remove dive site from core and take ownership. // Remove dive site from core and take ownership.
@ -59,6 +69,10 @@ static std::vector<OwningDiveSitePtr> removeDiveSites(std::vector<dive_site *> &
emit diveListNotifier.diveSiteDeleted(ds, idx); // Inform frontend of removed dive site. emit diveListNotifier.diveSiteDeleted(ds, idx); // Inform frontend of removed dive site.
} }
processByTrip(changedDives, [&](dive_trip *trip, const QVector<dive *> &divesInTrip) {
emit diveListNotifier.divesChanged(trip, divesInTrip, DiveField::DIVESITE);
});
sites.clear(); sites.clear();
return res; return res;
@ -344,6 +358,7 @@ void MergeDiveSites::undo()
} }
sitesToRemove = std::move(addDiveSites(sitesToAdd)); sitesToRemove = std::move(addDiveSites(sitesToAdd));
processByTrip(divesChanged, [&](dive_trip *trip, const QVector<dive *> &divesInTrip) { processByTrip(divesChanged, [&](dive_trip *trip, const QVector<dive *> &divesInTrip) {
emit diveListNotifier.divesChanged(trip, divesInTrip, DiveField::DIVESITE); emit diveListNotifier.divesChanged(trip, divesInTrip, DiveField::DIVESITE);
}); });

View file

@ -876,6 +876,12 @@ void DiveTripModelTree::divesDeleted(dive_trip *trip, bool deleteTrip, const QVe
void DiveTripModelTree::divesChanged(dive_trip *trip, const QVector<dive *> &dives) void DiveTripModelTree::divesChanged(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);
if (!trip) { if (!trip) {
// This is outside of a trip. Process top-level items range-wise. // This is outside of a trip. Process top-level items range-wise.
@ -910,6 +916,10 @@ void DiveTripModelTree::divesChanged(dive_trip *trip, const QVector<dive *> &div
// If necessary, move the trip // If necessary, move the trip
topLevelChanged(idx); topLevelChanged(idx);
// If a dive changed, re-render the trip in the list [or actually make it (in)visible].
if (diveChanged)
dataChanged(createIndex(idx, 0, noParent), createIndex(idx, 0, noParent));
} }
} }
@ -1161,6 +1171,11 @@ void DiveTripModelList::divesDeleted(dive_trip *trip, bool deleteTrip, const QVe
void DiveTripModelList::divesChanged(dive_trip *trip, const QVector<dive *> &dives) void DiveTripModelList::divesChanged(dive_trip *trip, const QVector<dive *> &dives)
{ {
// 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);
// Since we know that the dive list is sorted, we will only ever search for the first element // 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 // in dives as this must be the first that we encounter. Once we find a range, increase the
// index accordingly. // index accordingly.

View file

@ -249,6 +249,18 @@ void MultiFilterSortModel::myInvalidate()
#endif #endif
} }
bool MultiFilterSortModel::updateDive(struct dive *d)
{
bool oldStatus = !d->hidden_by_filter;
bool newStatus = showDive(d);
bool changed = oldStatus != newStatus;
if (changed) {
filter_dive(d, newStatus);
divesDisplayed += newStatus - oldStatus;
}
return changed;
}
void MultiFilterSortModel::clearFilter() void MultiFilterSortModel::clearFilter()
{ {
myInvalidate(); myInvalidate();

View file

@ -60,6 +60,7 @@ public:
static MultiFilterSortModel *instance(); static MultiFilterSortModel *instance();
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool showDive(const struct dive *d) const; bool showDive(const struct dive *d) const;
bool updateDive(struct dive *d); // returns true if visibility status changed
int divesDisplayed; int divesDisplayed;
bool lessThan(const QModelIndex &, const QModelIndex &) const override; bool lessThan(const QModelIndex &, const QModelIndex &) const override;
public public