summaryrefslogtreecommitdiffstats
path: root/qt-models
diff options
context:
space:
mode:
Diffstat (limited to 'qt-models')
-rw-r--r--qt-models/divetripmodel.cpp1
-rw-r--r--qt-models/filtermodels.cpp233
-rw-r--r--qt-models/filtermodels.h65
-rw-r--r--qt-models/maplocationmodel.cpp5
4 files changed, 12 insertions, 292 deletions
diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp
index 5fedd432f..7f9ca9e32 100644
--- a/qt-models/divetripmodel.cpp
+++ b/qt-models/divetripmodel.cpp
@@ -1,6 +1,7 @@
// 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"
#include "core/trip.h"
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();
diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h
index d4a03d134..d279470b1 100644
--- a/qt-models/filtermodels.h
+++ b/qt-models/filtermodels.h
@@ -11,67 +11,16 @@
#include <stdint.h>
#include <vector>
-struct dive;
-struct dive_trip;
-
-struct FilterData {
- // The mode ids are chosen such that they can be directly converted from / to combobox indices.
- enum class Mode {
- ALL_OF = 0,
- ANY_OF = 1,
- NONE_OF = 2
- };
-
- bool validFilter = false;
- int minVisibility = 0;
- int maxVisibility = 5;
- int minRating = 0;
- int maxRating = 5;
- // The default minimum and maximum temperatures are set such that all
- // physically reasonable dives are shown. Note that these values should
- // work for both Celcius and Fahrenheit scales.
- double minWaterTemp = -10;
- double maxWaterTemp = 200;
- double minAirTemp = -50;
- double maxAirTemp = 200;
- QDateTime fromDate = QDateTime(QDate(1980,1,1));
- QTime fromTime = QTime(0,0);
- QDateTime toDate = QDateTime::currentDateTime();
- QTime toTime = QTime::currentTime();
- QStringList tags;
- QStringList people;
- QStringList location;
- QStringList suit;
- QStringList dnotes;
- QStringList equipment;
- Mode tagsMode = Mode::ALL_OF;
- Mode peopleMode = Mode::ALL_OF;
- Mode locationMode = Mode::ANY_OF;
- Mode dnotesMode = Mode::ALL_OF;
- Mode suitMode = Mode::ANY_OF;
- Mode equipmentMode = Mode::ALL_OF;
- bool logged = true;
- bool planned = true;
-};
-
class MultiFilterSortModel : public QSortFilterProxyModel {
Q_OBJECT
public:
static MultiFilterSortModel *instance();
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
- bool showDive(const struct dive *d) const;
bool updateDive(struct dive *d); // returns true if visibility status changed
bool lessThan(const QModelIndex &, const QModelIndex &) const override;
- bool diveSiteMode() const; // returns true if we're filtering on dive site
- const QVector<dive_site *> &filteredDiveSites() const;
-public
-slots:
- void myInvalidate();
- void startFilterDiveSites(QVector<dive_site *> ds);
- void setFilterDiveSite(QVector<dive_site *> ds);
- void stopFilterDiveSites();
+
void resetModel(DiveTripModelBase::Layout layout);
- void filterDataChanged(const FilterData &data);
+ void myInvalidate();
signals:
void filterFinished();
@@ -79,17 +28,7 @@ signals:
private:
MultiFilterSortModel(QObject *parent = 0);
// Dive site filtering has priority over other filters
- QVector<dive_site *> dive_sites;
void countsChanged();
- FilterData filterData;
-
- // We use ref-counting for the dive site mode. The reason is that when switching
- // between two tabs that both need dive site mode, the following course of
- // events may happen:
- // 1) The new tab appears -> enter dive site mode.
- // 2) The old tab gets its hide() signal -> exit dive site mode.
- // The filter is now not in dive site mode, even if it should
- int diveSiteRefCount;
};
#endif
diff --git a/qt-models/maplocationmodel.cpp b/qt-models/maplocationmodel.cpp
index 9b21f7142..c123b19c5 100644
--- a/qt-models/maplocationmodel.cpp
+++ b/qt-models/maplocationmodel.cpp
@@ -2,6 +2,7 @@
#include "maplocationmodel.h"
#include "divelocationmodel.h"
#include "core/divesite.h"
+#include "core/divefilter.h"
#ifndef SUBSURFACE_MOBILE
#include "qt-models/filtermodels.h"
#include "desktop-widgets/mapwidget.h"
@@ -133,9 +134,9 @@ void MapLocationModel::reload(QObject *map)
// the dive site tab), we want to show all dive sites, not only those
// of the non-hidden dives. Moreover, the selected dive sites are those
// that we filter for.
- bool diveSiteMode = MultiFilterSortModel::instance()->diveSiteMode();
+ bool diveSiteMode = DiveFilter::instance()->diveSiteMode();
if (diveSiteMode)
- m_selectedDs = MultiFilterSortModel::instance()->filteredDiveSites();
+ m_selectedDs = DiveFilter::instance()->filteredDiveSites();
#endif
for (int i = 0; i < dive_site_table.nr; ++i) {
struct dive_site *ds = dive_site_table.dive_sites[i];