feat: Add Sorter.priority property

This commit is contained in:
grecko 2020-02-02 13:34:13 +01:00 committed by Pierre-Yves Siret
parent 314598ae54
commit 53c01b6ee3
5 changed files with 110 additions and 12 deletions

View File

@ -365,7 +365,13 @@ bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QM
if (QSortFilterProxyModel::lessThan(source_right, source_left))
return !m_ascendingSortOrder;
}
for(auto sorter : m_sorters) {
auto sortedSorters = m_sorters;
std::stable_sort(sortedSorters.begin(),
sortedSorters.end(),
[] (Sorter* a, Sorter* b) {
return a->priority() > b->priority();
});
for(auto sorter : sortedSorters) {
if (sorter->enabled()) {
int comparison = sorter->compareRows(source_left, source_right, *this);
if (comparison != 0)

View File

@ -79,6 +79,30 @@ void Sorter::setSortOrder(Qt::SortOrder sortOrder)
invalidate();
}
/*!
\qmlproperty int Sorter::priority
This property holds the sort priority of this sorter.
Sorters with a higher priority are applied first.
In case of equal priority, Sorters are ordered by their insertion order.
By default, the priority is 0.
*/
int Sorter::priority() const
{
return m_priority;
}
void Sorter::setPriority(int priority)
{
if (m_priority == priority)
return;
m_priority = priority;
Q_EMIT priorityChanged();
invalidate();
}
int Sorter::compareRows(const QModelIndex &source_left, const QModelIndex &source_right, const QQmlSortFilterProxyModel& proxyModel) const
{
int comparison = compare(source_left, source_right, proxyModel);

View File

@ -13,6 +13,7 @@ class Sorter : public QObject
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool ascendingOrder READ ascendingOrder WRITE setAscendingOrder NOTIFY sortOrderChanged)
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged)
public:
Sorter(QObject* parent = nullptr);
@ -27,6 +28,9 @@ public:
Qt::SortOrder sortOrder() const;
void setSortOrder(Qt::SortOrder sortOrder);
int priority() const;
void setPriority(int priority);
int compareRows(const QModelIndex& source_left, const QModelIndex& source_right, const QQmlSortFilterProxyModel& proxyModel) const;
virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel);
@ -34,6 +38,7 @@ public:
Q_SIGNALS:
void enabledChanged();
void sortOrderChanged();
void priorityChanged();
void invalidated();
@ -45,6 +50,7 @@ protected:
private:
bool m_enabled = true;
Qt::SortOrder m_sortOrder = Qt::AscendingOrder;
int m_priority = 0;
};
}

View File

@ -23,14 +23,12 @@ Item {
id: testModel
sourceModel: dataModel
}
ListModel {
id: sorterRoleModel
ListElement { roleName: "a" }
ListElement { roleName: "b" }
ListElement { roleName: "c" }
}
Instantiator {
id: sorterInstantiator
model: sorterRoleModel
@ -40,21 +38,41 @@ Item {
}
}
SortFilterProxyModel {
id: testModelPriority
sourceModel: dataModel
}
ListModel {
id: sorterRoleModelPriority
ListElement { roleName: "a" }
ListElement { roleName: "b" }
ListElement { roleName: "c" }
}
Instantiator {
id: sorterInstantiatorPriority
model: sorterRoleModelPriority
delegate: RoleSorter {
SorterContainer.container: testModelPriority
roleName: model.roleName
priority: -model.index
}
}
TestCase {
name: "SorterContainerAttached"
function modelValues() {
function modelValues(model) {
var modelValues = [];
for (var i = 0; i < testModel.count; i++)
modelValues.push(testModel.get(i));
for (var i = 0; i < model.count; i++)
modelValues.push(model.get(i));
return modelValues;
}
function test_sorterContainers() {
compare(sorterInstantiator.count, 3);
compare(modelValues(), [
compare(modelValues(testModel), [
{ a: 1, b: 7, c: 3 },
{ a: 1, b: 8, c: 5 },
{ a: 1, b: 8, c: 6 },
@ -68,7 +86,7 @@ Item {
sorterRoleModel.remove(0); // a, b, c --> b, c
wait(0);
compare(sorterInstantiator.count, 2);
compare(JSON.stringify(modelValues()), JSON.stringify([
compare(JSON.stringify(modelValues(testModel)), JSON.stringify([
{ a: 2, b: 1, c: 7 },
{ a: 3, b: 2, c: 8 },
{ a: 3, b: 2, c: 9 },
@ -80,5 +98,34 @@ Item {
{ a: 2, b: 9, c: 1 },
]));
}
function test_sorterContainersPriority() {
compare(sorterInstantiatorPriority.count, 3);
compare(JSON.stringify(modelValues(testModelPriority)), JSON.stringify([
{ a: 1, b: 7, c: 3 },
{ a: 1, b: 8, c: 5 },
{ a: 1, b: 8, c: 6 },
{ a: 2, b: 1, c: 7 },
{ a: 2, b: 6, c: 2 },
{ a: 2, b: 9, c: 1 },
{ a: 3, b: 2, c: 8 },
{ a: 3, b: 2, c: 9 },
{ a: 3, b: 5, c: 0 }
]));
sorterRoleModelPriority.move(0, 1, 1); // a, b, c --> b, a, c
wait(0);
compare(sorterInstantiatorPriority.count, 3);
compare(JSON.stringify(modelValues(testModelPriority)), JSON.stringify([
{ a: 2, b: 1, c: 7 },
{ a: 3, b: 2, c: 8 },
{ a: 3, b: 2, c: 9 },
{ a: 3, b: 5, c: 0 },
{ a: 2, b: 6, c: 2 },
{ a: 1, b: 7, c: 3 },
{ a: 1, b: 8, c: 5 },
{ a: 1, b: 8, c: 6 },
{ a: 2, b: 9, c: 1 }
]));
}
}
}

View File

@ -7,10 +7,10 @@ import SortFilterProxyModel.Test 0.2
Item {
ListModel {
id: listModel
ListElement { test: "first"; test2: "c" }
ListElement { test: "second"; test2: "a" }
ListElement { test: "third"; test2: "b" }
ListElement { test: "fourth"; test2: "b" }
ListElement { test: "first"; test2: "c"; test3: 1 }
ListElement { test: "second"; test2: "a"; test3: 0 }
ListElement { test: "third"; test2: "b"; test3: 2}
ListElement { test: "fourth"; test2: "b"; test3: 3 }
}
ListModel {
@ -74,6 +74,12 @@ Item {
RoleSorter { roleName: "test" }
]
property list<RoleSorter> sortersWithPriority: [
RoleSorter { roleName: "test3" },
RoleSorter { roleName: "test" },
RoleSorter { roleName: "test2"; priority: 1 }
]
SortFilterProxyModel {
id: testModel
sourceModel: listModel
@ -123,6 +129,15 @@ Item {
verifyModelValues(testModel, expectedValues);
}
function test_sortersWithPriority() {
testModel.sorters = sortersWithPriority;
var expectedValues = ["second", "third", "fourth", "first"];
verifyModelValues(testModel, expectedValues);
testModel.sorters[0].priority = 2;
expectedValues = ["second", "first", "third", "fourth"];
verifyModelValues(testModel, expectedValues);
}
function test_noRolesFirstModel() {
noRolesFirstListModel.append([{test: "b"}, {test: "a"}]);
var expectedValues = ["a", "b"];