Skip to content

Commit 08aa73f

Browse files
committed
fw/uicomponents: Add sorter base class
1 parent cfff874 commit 08aa73f

7 files changed

Lines changed: 165 additions & 70 deletions

File tree

src/framework/uicomponents/qml/Muse/UiComponents/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ qt_add_qml_module(muse_uicomponents_qml
7676
selectableitemlistmodel.h
7777
selectmultipledirectoriesmodel.cpp
7878
selectmultipledirectoriesmodel.h
79+
sorter.cpp
80+
sorter.h
7981
sortervalue.cpp
8082
sortervalue.h
8183
sortfilterproxymodel.cpp
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0-only
3+
* MuseScore-CLA-applies
4+
*
5+
* MuseScore
6+
* Music Composition & Notation
7+
*
8+
* Copyright (C) 2026 MuseScore Limited and others
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License version 3 as
12+
* published by the Free Software Foundation.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
#include "sorter.h"
24+
25+
namespace muse::uicomponents {
26+
Sorter::Sorter(QObject* parent)
27+
: QObject(parent)
28+
{
29+
}
30+
31+
Qt::SortOrder Sorter::sortOrder() const
32+
{
33+
return m_sortOrder;
34+
}
35+
36+
void Sorter::setSortOrder(const Qt::SortOrder sortOrder)
37+
{
38+
if (m_sortOrder == sortOrder) {
39+
return;
40+
}
41+
42+
m_sortOrder = sortOrder;
43+
emit dataChanged();
44+
}
45+
46+
bool Sorter::enabled() const
47+
{
48+
return m_enabled;
49+
}
50+
51+
void Sorter::setEnabled(const bool enabled)
52+
{
53+
if (m_enabled == enabled) {
54+
return;
55+
}
56+
57+
m_enabled = enabled;
58+
emit dataChanged();
59+
}
60+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0-only
3+
* MuseScore-CLA-applies
4+
*
5+
* MuseScore
6+
* Music Composition & Notation
7+
*
8+
* Copyright (C) 2026 MuseScore Limited and others
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License version 3 as
12+
* published by the Free Software Foundation.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
#pragma once
24+
25+
#include <QObject>
26+
27+
#include <QtQmlIntegration/qqmlintegration.h>
28+
29+
class QModelIndex;
30+
31+
namespace muse::uicomponents {
32+
class SortFilterProxyModel;
33+
34+
class Sorter : public QObject
35+
{
36+
Q_OBJECT
37+
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY dataChanged)
38+
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY dataChanged)
39+
40+
QML_ELEMENT;
41+
QML_UNCREATABLE("")
42+
43+
public:
44+
explicit Sorter(QObject* parent = nullptr);
45+
46+
virtual bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const SortFilterProxyModel&) = 0;
47+
48+
Qt::SortOrder sortOrder() const;
49+
void setSortOrder(Qt::SortOrder sortOrder);
50+
51+
bool enabled() const;
52+
void setEnabled(bool enabled);
53+
54+
signals:
55+
void dataChanged();
56+
57+
private:
58+
Qt::SortOrder m_sortOrder = Qt::AscendingOrder;
59+
bool m_enabled = false;
60+
};
61+
}

src/framework/uicomponents/qml/Muse/UiComponents/sortervalue.cpp

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,38 @@
1919
* You should have received a copy of the GNU General Public License
2020
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2121
*/
22+
2223
#include "sortervalue.h"
2324

25+
#include "global/types/val.h"
26+
27+
#include "sortfilterproxymodel.h"
28+
2429
using namespace muse::uicomponents;
2530

2631
SorterValue::SorterValue(QObject* parent)
27-
: QObject(parent)
32+
: Sorter(parent)
2833
{
2934
}
3035

31-
QString SorterValue::roleName() const
36+
bool SorterValue::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight,
37+
const SortFilterProxyModel& proxyModel)
3238
{
33-
return m_roleName;
34-
}
39+
const int role = proxyModel.roleFromRoleName(m_roleName);
40+
if (role == -1) {
41+
return sourceLeft < sourceRight;
42+
}
3543

36-
Qt::SortOrder SorterValue::sortOrder() const
37-
{
38-
return m_sortOrder;
44+
const QAbstractItemModel* sourceModel = proxyModel.sourceModel();
45+
const Val leftData = Val::fromQVariant(sourceModel->data(sourceLeft, role));
46+
const Val rightData = Val::fromQVariant(sourceModel->data(sourceRight, role));
47+
48+
return leftData < rightData;
3949
}
4050

41-
bool SorterValue::enabled() const
51+
QString SorterValue::roleName() const
4252
{
43-
return m_enabled;
53+
return m_roleName;
4454
}
4555

4656
void SorterValue::setRoleName(QString roleName)
@@ -52,28 +62,3 @@ void SorterValue::setRoleName(QString roleName)
5262
m_roleName = roleName;
5363
emit dataChanged();
5464
}
55-
56-
void SorterValue::setSortOrder(Qt::SortOrder sortOrder)
57-
{
58-
if (m_sortOrder == sortOrder) {
59-
return;
60-
}
61-
62-
m_sortOrder = sortOrder;
63-
emit dataChanged();
64-
}
65-
66-
void SorterValue::setEnabled(bool enabled)
67-
{
68-
if (m_enabled == enabled) {
69-
return;
70-
}
71-
72-
m_enabled = enabled;
73-
74-
if (!enabled) {
75-
m_sortOrder = Qt::AscendingOrder;
76-
}
77-
78-
emit dataChanged();
79-
}

src/framework/uicomponents/qml/Muse/UiComponents/sortervalue.h

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,31 @@
2222

2323
#pragma once
2424

25-
#include <qqmlintegration.h>
25+
#include <QString>
2626

27-
#include <QObject>
27+
#include <QtQmlIntegration/qqmlintegration.h>
28+
29+
#include "sorter.h"
2830

2931
namespace muse::uicomponents {
30-
class SorterValue : public QObject
32+
class SorterValue : public Sorter
3133
{
3234
Q_OBJECT
33-
QML_ELEMENT
34-
3535
Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY dataChanged)
36-
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY dataChanged)
37-
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY dataChanged)
36+
37+
QML_ELEMENT
3838

3939
public:
4040
explicit SorterValue(QObject* parent = nullptr);
4141

42+
bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const SortFilterProxyModel&) override;
43+
4244
QString roleName() const;
43-
Qt::SortOrder sortOrder() const;
44-
bool enabled() const;
4545

4646
public slots:
4747
void setRoleName(QString roleName);
48-
void setSortOrder(Qt::SortOrder sortOrder);
49-
void setEnabled(bool enabled);
50-
51-
signals:
52-
void dataChanged();
5348

5449
private:
5550
QString m_roleName;
56-
Qt::SortOrder m_sortOrder = Qt::SortOrder::AscendingOrder;
57-
bool m_enabled = false;
5851
};
5952
}

src/framework/uicomponents/qml/Muse/UiComponents/sortfilterproxymodel.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
#include <QTimer>
2626

27-
#include "global/types/val.h"
28-
2927
#include "uicomponents/view/modelutils.h"
3028

3129
using namespace muse::uicomponents;
@@ -70,10 +68,11 @@ SortFilterProxyModel::SortFilterProxyModel(QObject* parent)
7068
});
7169

7270
auto onSortersChanged = [this] {
73-
SorterValue* sorter = currentSorterValue();
71+
Sorter* sorter = currentSorter();
7472
invalidate();
7573

7674
if (!sorter) {
75+
sort(-1, Qt::AscendingOrder);
7776
return;
7877
}
7978

@@ -85,7 +84,7 @@ SortFilterProxyModel::SortFilterProxyModel(QObject* parent)
8584
connect(m_sorters.notifier(), &QmlListPropertyNotifier::appended, this, [this, onSortersChanged](int index) {
8685
onSortersChanged();
8786

88-
connect(m_sorters.at(index), &SorterValue::dataChanged, this, onSortersChanged);
87+
connect(m_sorters.at(index), &Sorter::dataChanged, this, onSortersChanged);
8988
});
9089

9190
connect(this, &SortFilterProxyModel::sourceModelRoleNamesChanged, this, [this]() {
@@ -98,7 +97,7 @@ QQmlListProperty<Filter> SortFilterProxyModel::filters()
9897
return m_filters.property();
9998
}
10099

101-
QQmlListProperty<SorterValue> SortFilterProxyModel::sorters()
100+
QQmlListProperty<Sorter> SortFilterProxyModel::sorters()
102101
{
103102
return m_sorters.property();
104103
}
@@ -203,23 +202,18 @@ bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& so
203202

204203
bool SortFilterProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
205204
{
206-
SorterValue* sorter = currentSorterValue();
205+
Sorter* sorter = currentSorter();
207206
if (!sorter) {
208207
return false;
209208
}
210209

211-
const int sorterRoleKey = roleFromRoleName(sorter->roleName());
212-
213-
Val leftData = Val::fromQVariant(sourceModel()->data(left, sorterRoleKey));
214-
Val rightData = Val::fromQVariant(sourceModel()->data(right, sorterRoleKey));
215-
216-
return leftData < rightData;
210+
return sorter->lessThan(left, right, *this);
217211
}
218212

219-
SorterValue* SortFilterProxyModel::currentSorterValue() const
213+
Sorter* SortFilterProxyModel::currentSorter() const
220214
{
221-
const QList<SorterValue*> sorterList = m_sorters.list();
222-
for (SorterValue* sorter : sorterList) {
215+
const QList<Sorter*> sorterList = m_sorters.list();
216+
for (Sorter* sorter : sorterList) {
223217
if (sorter->enabled()) {
224218
return sorter;
225219
}

src/framework/uicomponents/qml/Muse/UiComponents/sortfilterproxymodel.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@
3030
#include <QtQmlIntegration/qqmlintegration.h>
3131

3232
#include "filter.h"
33-
#include "sortervalue.h"
3433
#include "qmllistproperty.h"
34+
#include "sorter.h"
3535

3636
namespace muse::uicomponents {
3737
class SortFilterProxyModel : public QSortFilterProxyModel
3838
{
3939
Q_OBJECT
4040
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
4141
Q_PROPERTY(QQmlListProperty<muse::uicomponents::Filter> filters READ filters CONSTANT)
42-
Q_PROPERTY(QQmlListProperty<muse::uicomponents::SorterValue> sorters READ sorters CONSTANT)
42+
Q_PROPERTY(QQmlListProperty<muse::uicomponents::Sorter> sorters READ sorters CONSTANT)
4343
Q_PROPERTY(QList<int> alwaysIncludeIndices READ alwaysIncludeIndices WRITE setAlwaysIncludeIndices NOTIFY alwaysIncludeIndicesChanged)
4444
Q_PROPERTY(QList<int> alwaysExcludeIndices READ alwaysExcludeIndices WRITE setAlwaysExcludeIndices NOTIFY alwaysExcludeIndicesChanged)
4545

@@ -49,7 +49,7 @@ class SortFilterProxyModel : public QSortFilterProxyModel
4949
explicit SortFilterProxyModel(QObject* parent = nullptr);
5050

5151
QQmlListProperty<Filter> filters();
52-
QQmlListProperty<SorterValue> sorters();
52+
QQmlListProperty<Sorter> sorters();
5353

5454
QList<int> alwaysIncludeIndices() const;
5555
void setAlwaysIncludeIndices(const QList<int>& indices);
@@ -75,10 +75,10 @@ class SortFilterProxyModel : public QSortFilterProxyModel
7575
bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
7676

7777
private:
78-
SorterValue* currentSorterValue() const;
78+
Sorter* currentSorter() const;
7979

8080
QmlListProperty<Filter> m_filters;
81-
QmlListProperty<SorterValue> m_sorters;
81+
QmlListProperty<Sorter> m_sorters;
8282

8383
QList<int> m_alwaysIncludeIndices;
8484
QList<int> m_alwaysExcludeIndices;

0 commit comments

Comments
 (0)