From 6248ddf5296538fb7c3b092624c318ebf5f56027 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 22 Oct 2018 14:00:53 +0100 Subject: Mobile/filtering: roll our own filtering for performance reasons The regular expression based generic filtering made things very slow on a cell phone or other, slower device. With this the results seem more reasonable. Signed-off-by: Dirk Hohndel --- qt-models/divelistmodel.cpp | 51 ++++++++++++++++++++++++++++++++++++--------- qt-models/divelistmodel.h | 7 +++++++ 2 files changed, 48 insertions(+), 10 deletions(-) (limited to 'qt-models') diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp index 5a1cf1403..a12a1d9fa 100644 --- a/qt-models/divelistmodel.cpp +++ b/qt-models/divelistmodel.cpp @@ -1,29 +1,58 @@ // SPDX-License-Identifier: GPL-2.0 #include "qt-models/divelistmodel.h" #include "core/qthelper.h" -#include #include "core/settings/qPrefGeneral.h" +#include DiveListSortModel::DiveListSortModel(QObject *parent) : QSortFilterProxyModel(parent) { + updateFilterState(); +} + +void DiveListSortModel::updateFilterState() +{ + if (filterString.isEmpty()) { + filteredRows.clear(); + return; + } + // store this in local variables to avoid having to call these methods over and over + bool includeNotes = qPrefGeneral::filterFullTextNotes(); + Qt::CaseSensitivity cs = qPrefGeneral::filterCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; + // get the underlying model and re-calculate the filter value for each dive + DiveListModel *mySourceModel = qobject_cast(sourceModel()); + filteredRows.clear(); + filteredRows.resize(mySourceModel->rowCount()); + for (int i = 0; i < mySourceModel->rowCount(); i++) { + QString fullText = includeNotes? mySourceModel->at(i)->fullText() : mySourceModel->at(i)->fullTextNoNotes(); + filteredRows.at(i) = fullText.contains(filterString, cs); + } } +void DiveListSortModel::setSourceModel(QAbstractItemModel *sourceModel) +{ + QSortFilterProxyModel::setSourceModel(sourceModel); +} void DiveListSortModel::setFilter(QString f) { - if (qPrefGeneral::filterFullTextNotes()) - setFilterRole(DiveListModel::FullTextRole); - else - setFilterRole(DiveListModel::FullTextNoNotesRole); - - setFilterRegExp(QString(".*%1.*").arg(f)); - if (!qPrefGeneral::filterCaseSensitive()) - setFilterCaseSensitivity(Qt::CaseInsensitive); + filterString = f; + updateFilterState(); + invalidateFilter(); } void DiveListSortModel::resetFilter() { - setFilterRegExp(""); + filterString = ""; + filteredRows.clear(); + invalidateFilter(); +} + +// filtering is way too slow on mobile. Maybe we should roll our own? +bool DiveListSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + Q_UNUSED(source_parent) + + return filteredRows.size() > source_row ? filteredRows[source_row] : true; } int DiveListSortModel::shown() @@ -52,12 +81,14 @@ void DiveListSortModel::clear() { DiveListModel *mySourceModel = qobject_cast(sourceModel()); mySourceModel->clear(); + filteredRows.clear(); } void DiveListSortModel::addAllDives() { DiveListModel *mySourceModel = qobject_cast(sourceModel()); mySourceModel->addAllDives(); + updateFilterState(); } DiveListModel *DiveListModel::m_instance = NULL; diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h index caf2616a7..dcfc573ee 100644 --- a/qt-models/divelistmodel.h +++ b/qt-models/divelistmodel.h @@ -12,6 +12,7 @@ class DiveListSortModel : public QSortFilterProxyModel Q_OBJECT public: DiveListSortModel(QObject *parent = 0); + void setSourceModel(QAbstractItemModel *sourceModel); Q_INVOKABLE void addAllDives(); Q_INVOKABLE void clear(); public slots: @@ -20,6 +21,12 @@ public slots: void setFilter(QString f); void resetFilter(); int shown(); +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; +private: + std::vector filteredRows; // using unsigned char because using 'bool' turns this into a bitfield + QString filterString; + void updateFilterState(); }; class DiveListModel : public QAbstractListModel -- cgit v1.2.3-70-g09d2