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 <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2018-10-22 14:00:53 +01:00
parent 51e7603d7e
commit 6248ddf529
2 changed files with 49 additions and 11 deletions

View file

@ -1,29 +1,58 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "qt-models/divelistmodel.h" #include "qt-models/divelistmodel.h"
#include "core/qthelper.h" #include "core/qthelper.h"
#include <QDateTime>
#include "core/settings/qPrefGeneral.h" #include "core/settings/qPrefGeneral.h"
#include <QDateTime>
DiveListSortModel::DiveListSortModel(QObject *parent) : QSortFilterProxyModel(parent) 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<DiveListModel *>(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) void DiveListSortModel::setFilter(QString f)
{ {
if (qPrefGeneral::filterFullTextNotes()) filterString = f;
setFilterRole(DiveListModel::FullTextRole); updateFilterState();
else invalidateFilter();
setFilterRole(DiveListModel::FullTextNoNotesRole);
setFilterRegExp(QString(".*%1.*").arg(f));
if (!qPrefGeneral::filterCaseSensitive())
setFilterCaseSensitivity(Qt::CaseInsensitive);
} }
void DiveListSortModel::resetFilter() 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() int DiveListSortModel::shown()
@ -52,12 +81,14 @@ void DiveListSortModel::clear()
{ {
DiveListModel *mySourceModel = qobject_cast<DiveListModel *>(sourceModel()); DiveListModel *mySourceModel = qobject_cast<DiveListModel *>(sourceModel());
mySourceModel->clear(); mySourceModel->clear();
filteredRows.clear();
} }
void DiveListSortModel::addAllDives() void DiveListSortModel::addAllDives()
{ {
DiveListModel *mySourceModel = qobject_cast<DiveListModel *>(sourceModel()); DiveListModel *mySourceModel = qobject_cast<DiveListModel *>(sourceModel());
mySourceModel->addAllDives(); mySourceModel->addAllDives();
updateFilterState();
} }
DiveListModel *DiveListModel::m_instance = NULL; DiveListModel *DiveListModel::m_instance = NULL;

View file

@ -12,6 +12,7 @@ class DiveListSortModel : public QSortFilterProxyModel
Q_OBJECT Q_OBJECT
public: public:
DiveListSortModel(QObject *parent = 0); DiveListSortModel(QObject *parent = 0);
void setSourceModel(QAbstractItemModel *sourceModel);
Q_INVOKABLE void addAllDives(); Q_INVOKABLE void addAllDives();
Q_INVOKABLE void clear(); Q_INVOKABLE void clear();
public slots: public slots:
@ -20,6 +21,12 @@ public slots:
void setFilter(QString f); void setFilter(QString f);
void resetFilter(); void resetFilter();
int shown(); int shown();
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
private:
std::vector<unsigned char> filteredRows; // using unsigned char because using 'bool' turns this into a bitfield
QString filterString;
void updateFilterState();
}; };
class DiveListModel : public QAbstractListModel class DiveListModel : public QAbstractListModel