feat: Add FilterSorter sorter type
This commit is contained in:
parent
1ae65bca74
commit
2b3a368ae1
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -30,4 +30,5 @@ OTHER_FILES += \
|
|||
|
||||
DISTFILES += \
|
||||
tst_filtercontainers.qml \
|
||||
tst_regexprole.qml
|
||||
tst_regexprole.qml \
|
||||
tst_filtersorter.qml
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue