diff options
Diffstat (limited to 'qt-models/filtermodels.cpp')
-rw-r--r-- | qt-models/filtermodels.cpp | 233 |
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(); |