feat: Add FilterSorter sorter type

This commit is contained in:
Grecko 2018-09-29 02:07:11 +02:00
parent 1ae65bca74
commit 2b3a368ae1
6 changed files with 163 additions and 3 deletions

View File

@ -25,7 +25,8 @@ HEADERS += $$PWD/qqmlsortfilterproxymodel.h \
$$PWD/proxyroles/switchrole.h \
$$PWD/proxyroles/expressionrole.h \
$$PWD/proxyroles/singlerole.h \
$$PWD/proxyroles/regexprole.h
$$PWD/proxyroles/regexprole.h \
$$PWD/sorters/filtersorter.h
SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \
$$PWD/filters/filter.cpp \
@ -53,4 +54,5 @@ SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \
$$PWD/proxyroles/expressionrole.cpp \
$$PWD/proxyroles/proxyrolesqmltypes.cpp \
$$PWD/proxyroles/singlerole.cpp \
$$PWD/proxyroles/regexprole.cpp
$$PWD/proxyroles/regexprole.cpp \
$$PWD/sorters/filtersorter.cpp

77
sorters/filtersorter.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "filtersorter.h"
#include "filters/filter.h"
namespace qqsfpm {
/*!
\qmltype FilterSorter
\inherits Sorter
\inqmlmodule SortFilterProxyModel
\brief Sorts rows based on if they match filters
A FilterSorter is a \l Sorter that orders row matching its filters before the rows not matching the filters.
In the following example, rows with their \c favorite role set to \c true will be ordered at the beginning :
\code
SortFilterProxyModel {
sourceModel: contactModel
sorters: FilterSorter {
ValueFilter { roleName: "favorite"; value: true }
}
}
\endcode
*/
/*!
\qmlproperty string FilterSorter::filters
This property holds the list of filters for this filter sorter.
If a row match all this FilterSorter's filters, it will be ordered before rows not matching all the filters.
\sa Filter
*/
int FilterSorter::compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel &proxyModel) const
{
bool leftIsAccepted = indexIsAccepted(sourceLeft, proxyModel);
bool rightIsAccepted = indexIsAccepted(sourceRight, proxyModel);
if (leftIsAccepted == rightIsAccepted)
return 0;
return leftIsAccepted ? -1 : 1;
}
void FilterSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
{
for (Filter* filter : m_filters)
filter->proxyModelCompleted(proxyModel);
}
void FilterSorter::onFilterAppended(Filter* filter)
{
connect(filter, &Filter::invalidated, this, &FilterSorter::invalidate);
invalidate();
}
void FilterSorter::onFilterRemoved(Filter* filter)
{
disconnect(filter, &Filter::invalidated, this, &FilterSorter::invalidate);
invalidate();
}
void FilterSorter::onFiltersCleared()
{
invalidate();
}
bool FilterSorter::indexIsAccepted(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const
{
return std::all_of(m_filters.begin(), m_filters.end(),
[&] (Filter* filter) {
return filter->filterAcceptsRow(sourceIndex, proxyModel);
}
);
}
}

33
sorters/filtersorter.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef FILTERSORTER_H
#define FILTERSORTER_H
#include "sorter.h"
#include "filters/filtercontainer.h"
namespace qqsfpm {
class FilterSorter : public Sorter, public FilterContainer
{
Q_OBJECT
Q_INTERFACES(qqsfpm::FilterContainer)
Q_PROPERTY(QQmlListProperty<qqsfpm::Filter> filters READ filtersListProperty)
Q_CLASSINFO("DefaultProperty", "filters")
public:
using Sorter::Sorter;
protected:
int compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const QQmlSortFilterProxyModel &proxyModel) const override;
private:
void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override;
void onFilterAppended(Filter *filter) override;
void onFilterRemoved(Filter *filter) override;
void onFiltersCleared() override;
bool indexIsAccepted(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel) const;
};
}
#endif // FILTERSORTER_H

View File

@ -1,6 +1,7 @@
#include "sorter.h"
#include "rolesorter.h"
#include "stringsorter.h"
#include "filtersorter.h"
#include "expressionsorter.h"
#include <QQmlEngine>
#include <QCoreApplication>
@ -11,6 +12,7 @@ void registerSorterTypes() {
qmlRegisterUncreatableType<Sorter>("SortFilterProxyModel", 0, 2, "Sorter", "Sorter is an abstract class");
qmlRegisterType<RoleSorter>("SortFilterProxyModel", 0, 2, "RoleSorter");
qmlRegisterType<StringSorter>("SortFilterProxyModel", 0, 2, "StringSorter");
qmlRegisterType<FilterSorter>("SortFilterProxyModel", 0, 2, "FilterSorter");
qmlRegisterType<ExpressionSorter>("SortFilterProxyModel", 0, 2, "ExpressionSorter");
}

View File

@ -30,4 +30,5 @@ OTHER_FILES += \
DISTFILES += \
tst_filtercontainers.qml \
tst_regexprole.qml
tst_regexprole.qml \
tst_filtersorter.qml

View File

@ -0,0 +1,45 @@
import QtQuick 2.0
import QtQml 2.2
import QtTest 1.1
import SortFilterProxyModel 0.2
import QtQml 2.2
Item {
ListModel {
id: listModel
ListElement { name: "1"; favorite: true }
ListElement { name: "2"; favorite: false }
ListElement { name: "3"; favorite: false }
ListElement { name: "4"; favorite: true }
}
SortFilterProxyModel {
id: testModel
sourceModel: listModel
sorters: FilterSorter {
ValueFilter {
id: favoriteFilter
roleName: "favorite"
value: true
}
}
}
TestCase {
name: "FilterSorter"
function test_filterSorter() {
compare(testModel.get(0, "name"), "1");
compare(testModel.get(1, "name"), "4");
compare(testModel.get(2, "name"), "2");
compare(testModel.get(3, "name"), "3");
favoriteFilter.value = false;
compare(testModel.get(0, "name"), "2");
compare(testModel.get(1, "name"), "3");
compare(testModel.get(2, "name"), "1");
compare(testModel.get(3, "name"), "4");
}
}
}