aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models/filtermodels.cpp
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2019-11-17 18:13:55 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2019-11-19 21:13:40 -0800
commitb76f2071589d6a7f45ec2845afa8b49110da608b (patch)
tree1b7176f4bf706803160c9dc007a7c524dbc59bd2 /qt-models/filtermodels.cpp
parent6d6d10f03a92a9bac5394fc226c398af61f29d66 (diff)
downloadsubsurface-b76f2071589d6a7f45ec2845afa8b49110da608b.tar.gz
Filter: split out filter from model
Split out the actual filtering from the MultiFilterSortModel. Create a DiveFilter class that does the actual filtering. Currently, mobile and desktop have their own version of this class, though ultimately we may want to merge them. The idea here is that the trip-model and undo-commands have direct access to the filter-function and thus can take care of keeping track of the number of shown dives, etc. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'qt-models/filtermodels.cpp')
-rw-r--r--qt-models/filtermodels.cpp233
1 files changed, 6 insertions, 227 deletions
diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp
index 9736d3335..b04fce127 100644
--- a/qt-models/filtermodels.cpp
+++ b/qt-models/filtermodels.cpp
@@ -1,113 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
#include "qt-models/filtermodels.h"
-#include "qt-models/models.h"
#include "core/display.h"
#include "core/qthelper.h"
-#include "core/divesite.h"
#include "core/trip.h"
#include "core/subsurface-string.h"
#include "core/subsurface-qt/DiveListNotifier.h"
#include "qt-models/divetripmodel.h"
#if !defined(SUBSURFACE_MOBILE)
-#include "desktop-widgets/divelistview.h"
-#include "desktop-widgets/mainwindow.h"
-#include "desktop-widgets/mapwidget.h"
+#include "core/divefilter.h"
#endif
#include <QDebug>
#include <algorithm>
-namespace {
- // Check if a string-list contains at least one string containing the second argument.
- // Comparison is non case sensitive and removes white space.
- bool listContainsSuperstring(const QStringList &list, const QString &s)
- {
- return std::any_of(list.begin(), list.end(), [&s](const QString &s2)
- { return s2.trimmed().contains(s.trimmed(), Qt::CaseInsensitive); } );
- }
-
- // Check whether either all, any or none of the items of the first list is
- // in the second list as a super string.
- // The mode is controlled by the second argument
- bool check(const QStringList &items, const QStringList &list, FilterData::Mode mode)
- {
- bool negate = mode == FilterData::Mode::NONE_OF;
- bool any_of = mode == FilterData::Mode::ANY_OF;
- auto fun = [&list, negate](const QString &item)
- { return listContainsSuperstring(list, item) != negate; };
- return any_of ? std::any_of(items.begin(), items.end(), fun)
- : std::all_of(items.begin(), items.end(), fun);
- }
-
- bool hasTags(const QStringList &tags, const struct dive *d, FilterData::Mode mode)
- {
- if (tags.isEmpty())
- return true;
- QStringList dive_tags = get_taglist_string(d->tag_list).split(",");
- dive_tags.append(gettextFromC::tr(divemode_text_ui[d->dc.divemode]));
- return check(tags, dive_tags, mode);
- }
-
- bool hasPersons(const QStringList &people, const struct dive *d, FilterData::Mode mode)
- {
- if (people.isEmpty())
- return true;
- QStringList dive_people = QString(d->buddy).split(",", QString::SkipEmptyParts)
- + QString(d->divemaster).split(",", QString::SkipEmptyParts);
- return check(people, dive_people, mode);
- }
-
- bool hasLocations(const QStringList &locations, const struct dive *d, FilterData::Mode mode)
- {
- if (locations.isEmpty())
- return true;
- QStringList diveLocations;
- if (d->divetrip)
- diveLocations.push_back(QString(d->divetrip->location));
-
- if (d->dive_site)
- diveLocations.push_back(QString(d->dive_site->name));
-
- return check(locations, diveLocations, mode);
- }
-
- // TODO: Finish this implementation.
- bool hasEquipment(const QStringList &, const struct dive *, FilterData::Mode)
- {
- return true;
- }
-
- bool hasSuits(const QStringList &suits, const struct dive *d, FilterData::Mode mode)
- {
- if (suits.isEmpty())
- return true;
- QStringList diveSuits;
- if (d->suit)
- diveSuits.push_back(QString(d->suit));
- return check(suits, diveSuits, mode);
- }
-
- bool hasNotes(const QStringList &dnotes, const struct dive *d, FilterData::Mode mode)
- {
- if (dnotes.isEmpty())
- return true;
- QStringList diveNotes;
- if (d->notes)
- diveNotes.push_back(QString(d->notes));
- return check(dnotes, diveNotes, mode);
- }
-
-}
-
MultiFilterSortModel *MultiFilterSortModel::instance()
{
static MultiFilterSortModel self;
return &self;
}
-MultiFilterSortModel::MultiFilterSortModel(QObject *parent) : QSortFilterProxyModel(parent),
- diveSiteRefCount(0)
+MultiFilterSortModel::MultiFilterSortModel(QObject *parent) : QSortFilterProxyModel(parent)
{
setFilterKeyColumn(-1); // filter all columns
setFilterCaseSensitivity(Qt::CaseInsensitive);
@@ -121,73 +34,6 @@ void MultiFilterSortModel::resetModel(DiveTripModelBase::Layout layout)
setSourceModel(DiveTripModelBase::instance());
}
-bool MultiFilterSortModel::showDive(const struct dive *d) const
-{
- if (diveSiteMode())
- return dive_sites.contains(d->dive_site);
-
- if (!filterData.validFilter)
- return true;
-
- if (d->visibility < filterData.minVisibility || d->visibility > filterData.maxVisibility)
- return false;
-
- if (d->rating < filterData.minRating || d->rating > filterData.maxRating)
- return false;
-
- auto temp_comp = prefs.units.temperature == units::CELSIUS ? C_to_mkelvin : F_to_mkelvin;
- if (d->watertemp.mkelvin &&
- (d->watertemp.mkelvin < (*temp_comp)(filterData.minWaterTemp) || d->watertemp.mkelvin > (*temp_comp)(filterData.maxWaterTemp)))
- return false;
-
- if (d->airtemp.mkelvin &&
- (d->airtemp.mkelvin < (*temp_comp)(filterData.minAirTemp) || d->airtemp.mkelvin > (*temp_comp)(filterData.maxAirTemp)))
- return false;
-
- QDateTime t = filterData.fromDate;
- t.setTime(filterData.fromTime);
- if (filterData.fromDate.isValid() && filterData.fromTime.isValid() &&
- d->when < t.toMSecsSinceEpoch()/1000 + t.offsetFromUtc())
- return false;
-
- t = filterData.toDate;
- t.setTime(filterData.toTime);
- if (filterData.toDate.isValid() && filterData.toTime.isValid() &&
- d->when > t.toMSecsSinceEpoch()/1000 + t.offsetFromUtc())
- return false;
-
- // tags.
- if (!hasTags(filterData.tags, d, filterData.tagsMode))
- return false;
-
- // people
- if (!hasPersons(filterData.people, d, filterData.peopleMode))
- return false;
-
- // Location
- if (!hasLocations(filterData.location, d, filterData.locationMode))
- return false;
-
- // Suit
- if (!hasSuits(filterData.suit, d, filterData.suitMode))
- return false;
-
- // Notes
- if (!hasNotes(filterData.dnotes, d, filterData.dnotesMode))
- return false;
-
- if (!hasEquipment(filterData.equipment, d, filterData.equipmentMode))
- return false;
-
- // Planned/Logged
- if (!filterData.logged && !has_planned(d, true))
- return false;
- if (!filterData.planned && !has_planned(d, false))
- return false;
-
- return true;
-}
-
bool MultiFilterSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
QAbstractItemModel *m = sourceModel();
@@ -213,6 +59,7 @@ void MultiFilterSortModel::myInvalidate()
shown_dives = 0;
+ DiveFilter *filter = DiveFilter::instance();
for (int i = 0; i < m->rowCount(QModelIndex()); ++i) {
QModelIndex idx = m->index(i, 0, QModelIndex());
@@ -227,7 +74,7 @@ void MultiFilterSortModel::myInvalidate()
qWarning("MultiFilterSortModel::myInvalidate(): subitem not a dive!?");
continue;
}
- bool show = showDive(d);
+ bool show = filter->showDive(d);
if (show) {
shown_dives++;
showTrip = true;
@@ -237,7 +84,7 @@ void MultiFilterSortModel::myInvalidate()
m->setData(idx, showTrip, DiveTripModelBase::SHOWN_ROLE);
} else {
dive *d = m->data(idx, DiveTripModelBase::DIVE_ROLE).value<dive *>();
- bool show = (d != NULL) && showDive(d);
+ bool show = (d != NULL) && filter->showDive(d);
if (show)
shown_dives++;
m->setData(idx, show, DiveTripModelBase::SHOWN_ROLE);
@@ -251,26 +98,13 @@ void MultiFilterSortModel::myInvalidate()
countsChanged();
}
-#if !defined(SUBSURFACE_MOBILE)
- // The shown maps may have changed -> reload the map widget.
- // But don't do this in dive site mode, because then we show all
- // dive sites and only change the selected flag.
- if (!diveSiteMode())
- MapWidget::instance()->reload();
-#endif
-
emit filterFinished();
-
-#if !defined(SUBSURFACE_MOBILE)
- if (diveSiteMode())
- MainWindow::instance()->diveList->expandAll();
-#endif
}
bool MultiFilterSortModel::updateDive(struct dive *d)
{
bool oldStatus = !d->hidden_by_filter;
- bool newStatus = showDive(d);
+ bool newStatus = DiveFilter::instance()->showDive(d);
bool changed = oldStatus != newStatus;
if (changed) {
filter_dive(d, newStatus);
@@ -279,67 +113,12 @@ bool MultiFilterSortModel::updateDive(struct dive *d)
return changed;
}
-void MultiFilterSortModel::startFilterDiveSites(QVector<dive_site *> ds)
-{
- if (++diveSiteRefCount > 1) {
- setFilterDiveSite(ds);
- } else {
- std::sort(ds.begin(), ds.end());
- dive_sites = ds;
-#if !defined(SUBSURFACE_MOBILE)
- // When switching into dive site mode, reload the dive sites.
- // We won't do this in myInvalidate() once we are in dive site mode.
- MapWidget::instance()->reload();
-#endif
- myInvalidate();
- }
-}
-
-void MultiFilterSortModel::stopFilterDiveSites()
-{
- if (--diveSiteRefCount > 0)
- return;
- dive_sites.clear();
- myInvalidate();
-}
-
-void MultiFilterSortModel::setFilterDiveSite(QVector<dive_site *> ds)
-{
- // If the filter didn't change, return early to avoid a full
- // map reload. For a well-defined comparison, sort the vector first.
- std::sort(ds.begin(), ds.end());
- if (ds == dive_sites)
- return;
- dive_sites = ds;
-
-#if !defined(SUBSURFACE_MOBILE)
- MapWidget::instance()->setSelected(dive_sites);
-#endif
- myInvalidate();
-}
-
-const QVector<dive_site *> &MultiFilterSortModel::filteredDiveSites() const
-{
- return dive_sites;
-}
-
-bool MultiFilterSortModel::diveSiteMode() const
-{
- return diveSiteRefCount > 0;
-}
-
bool MultiFilterSortModel::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
{
// Hand sorting down to the source model.
return DiveTripModelBase::instance()->lessThan(i1, i2);
}
-void MultiFilterSortModel::filterDataChanged(const FilterData &data)
-{
- filterData = data;
- myInvalidate();
-}
-
void MultiFilterSortModel::countsChanged()
{
updateWindowTitle();