aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qt-models/divetripmodel.cpp59
-rw-r--r--qt-models/divetripmodel.h5
-rw-r--r--qt-models/filtermodels.cpp63
3 files changed, 97 insertions, 30 deletions
diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp
index ca1e4f73f..9fd323bcf 100644
--- a/qt-models/divetripmodel.cpp
+++ b/qt-models/divetripmodel.cpp
@@ -389,6 +389,9 @@ 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)
@@ -636,16 +639,19 @@ QModelIndex DiveTripModelTree::parent(const QModelIndex &index) const
}
DiveTripModelTree::Item::Item(dive_trip *t, const QVector<dive *> &divesIn) : d_or_t{nullptr, t},
- dives(divesIn.toStdVector())
+ dives(divesIn.toStdVector()),
+ shown(std::any_of(dives.begin(), dives.end(), [](dive *d){ return !d->hidden_by_filter; }))
{
}
DiveTripModelTree::Item::Item(dive_trip *t, dive *d) : d_or_t{nullptr, t},
- dives({ d })
+ dives({ d }),
+ shown(!d->hidden_by_filter)
{
}
-DiveTripModelTree::Item::Item(dive *d) : d_or_t{d, nullptr}
+DiveTripModelTree::Item::Item(dive *d) : d_or_t{d, nullptr},
+ shown(!d->hidden_by_filter)
{
}
@@ -683,8 +689,44 @@ 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);
+ }
+ } 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;
+}
+
QVariant DiveTripModelTree::data(const QModelIndex &index, int role) const
{
+ if (role == SHOWN_ROLE) {
+ QModelIndex parent = index.parent();
+ // An invalid parent means that we're at the top-level
+ if (!parent.isValid())
+ return items[index.row()].shown;
+ return !items[parent.row()].dives[index.row()]->hidden_by_filter;
+ }
+
// Set the font for all items alike
if (role == Qt::FontRole)
return defaultModelFont();
@@ -1135,6 +1177,15 @@ dive *DiveTripModelList::diveOrNull(const QModelIndex &index) const
return items[row];
}
+bool DiveTripModelList::setShown(const QModelIndex &idx, bool shown)
+{
+ dive *d = diveOrNull(idx);
+ if (!d)
+ return false;
+ filter_dive(d, shown);
+ return true;
+}
+
QVariant DiveTripModelList::data(const QModelIndex &index, int role) const
{
// Set the font for all items alike
@@ -1142,6 +1193,8 @@ QVariant DiveTripModelList::data(const QModelIndex &index, int role) const
return defaultModelFont();
dive *d = diveOrNull(index);
+ if (role == SHOWN_ROLE)
+ return d && !d->hidden_by_filter;
return d ? diveData(d, index.column(), role) : QVariant();
}
diff --git a/qt-models/divetripmodel.h b/qt-models/divetripmodel.h
index 236dbb1d2..592234917 100644
--- a/qt-models/divetripmodel.h
+++ b/qt-models/divetripmodel.h
@@ -52,6 +52,7 @@ public:
DIVE_ROLE,
TRIP_ROLE,
DIVE_IDX,
+ SHOWN_ROLE,
SELECTED_ROLE
};
enum Layout {
@@ -74,6 +75,7 @@ public:
DiveTripModelBase(QObject *parent = 0);
int columnCount(const QModelIndex&) const;
virtual void filterFinished() = 0;
+ virtual bool setShown(const QModelIndex &idx, bool shown) = 0;
// Used for sorting. This is a bit of a layering violation, as sorting should be performed
// by the higher-up QSortFilterProxyModel, but it makes things so much easier!
@@ -126,6 +128,7 @@ private:
bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const override;
void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select) override;
dive *diveOrNull(const QModelIndex &index) const override;
+ bool setShown(const QModelIndex &idx, bool shown);
// The tree model has two levels. At the top level, we have either trips or dives
// that do not belong to trips. Such a top-level item is represented by the "Item"
@@ -138,6 +141,7 @@ private:
struct Item {
dive_or_trip d_or_t;
std::vector<dive *> dives; // std::vector<> instead of QVector for insert() with three iterators
+ bool shown;
Item(dive_trip *t, const QVector<dive *> &dives);
Item(dive_trip *t, dive *d); // Initialize a trip with one dive
Item(dive *d); // Initialize a top-level dive
@@ -187,6 +191,7 @@ private:
bool lessThan(const QModelIndex &i1, const QModelIndex &i2) const override;
void changeDiveSelection(dive_trip *trip, const QVector<dive *> &dives, bool select) override;
dive *diveOrNull(const QModelIndex &index) const override;
+ bool setShown(const QModelIndex &idx, bool shown);
std::vector<dive *> items; // TODO: access core data directly
};
diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp
index 8e7239e35..9ef910def 100644
--- a/qt-models/filtermodels.cpp
+++ b/qt-models/filtermodels.cpp
@@ -194,25 +194,9 @@ bool MultiFilterSortModel::showDive(const struct dive *d) const
bool MultiFilterSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
- QModelIndex index0 = sourceModel()->index(source_row, 0, source_parent);
- struct dive *d = sourceModel()->data(index0, DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
-
- // For dives, simply check the hidden_by_filter flag
- if (d)
- return !d->hidden_by_filter;
-
- // Since this is not a dive, it must be a trip
- dive_trip *trip = sourceModel()->data(index0, DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
-
- if (!trip)
- return false; // Oops. Neither dive nor trip, something is seriously wrong.
-
- // Show the trip if any dive is visible
- for (int i = 0; i < trip->dives.nr; ++i) {
- if (!trip->dives.dives[i]->hidden_by_filter)
- return true;
- }
- return false;
+ QAbstractItemModel *m = sourceModel();
+ QModelIndex index0 = m->index(source_row, 0, source_parent);
+ return m->data(index0, DiveTripModelBase::SHOWN_ROLE).value<bool>();
}
void MultiFilterSortModel::filterChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles)
@@ -225,8 +209,9 @@ void MultiFilterSortModel::filterChanged(const QModelIndex &from, const QModelIn
void MultiFilterSortModel::myInvalidate()
{
- int i;
- struct dive *d;
+ QAbstractItemModel *m = sourceModel();
+ if (!m)
+ return;
{
// This marker prevents the UI from getting notifications on selection changes.
@@ -240,12 +225,36 @@ void MultiFilterSortModel::myInvalidate()
divesDisplayed = 0;
- // Apply filter for each dive
- for_each_dive (i, d) {
- bool show = showDive(d);
- filter_dive(d, show);
- if (show)
- divesDisplayed++;
+ for (int i = 0; i < m->rowCount(QModelIndex()); ++i) {
+ QModelIndex idx = m->index(i, 0, QModelIndex());
+
+ dive_trip *trip = m->data(idx, DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
+ if (trip) {
+ // This is a trip -> loop over all dives and see if any is selected
+
+ bool showTrip = false;
+ for (int j = 0; j < m->rowCount(idx); ++j) {
+ QModelIndex idx2 = m->index(j, 0, idx);
+ dive *d = m->data(idx2, DiveTripModelBase::DIVE_ROLE).value<dive *>();
+ if (!d) {
+ qWarning("MultiFilterSortModel::myInvalidate(): subitem not a dive!?");
+ continue;
+ }
+ bool show = showDive(d);
+ if (show) {
+ divesDisplayed++;
+ showTrip = true;
+ }
+ m->setData(idx2, show, DiveTripModelBase::SHOWN_ROLE);
+ }
+ m->setData(idx, showTrip, DiveTripModelBase::SHOWN_ROLE);
+ } else {
+ dive *d = m->data(idx, DiveTripModelBase::DIVE_ROLE).value<dive *>();
+ bool show = showDive(d);
+ if (show)
+ divesDisplayed++;
+ m->setData(idx, show, DiveTripModelBase::SHOWN_ROLE);
+ }
}
invalidateFilter();