Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions framework/uicomponents/qml/Muse/UiComponents/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ qt_add_qml_module(muse_uicomponents_qml
dropdownview.h
filepickermodel.cpp
filepickermodel.h
filter.cpp
filter.h
filteredflyoutmodel.cpp
filteredflyoutmodel.h
filtervalue.cpp
Expand Down Expand Up @@ -74,6 +76,8 @@ qt_add_qml_module(muse_uicomponents_qml
selectableitemlistmodel.h
selectmultipledirectoriesmodel.cpp
selectmultipledirectoriesmodel.h
sorter.cpp
sorter.h
sortervalue.cpp
sortervalue.h
sortfilterproxymodel.cpp
Expand Down
15 changes: 6 additions & 9 deletions framework/uicomponents/qml/Muse/UiComponents/ValueList.qml
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,18 @@ Item {
property real spacing: 4
property real sideMargin: 30

function toggleSorter(sorter) {
function toggleSorter(sorter: Sorter) {
if (!sorter.enabled) {
setSorterEnabled(sorter, true)
sorter.sortOrder = Qt.AscendingOrder
sorter.enabled = true
} else if (sorter.sortOrder === Qt.AscendingOrder) {
sorter.sortOrder = Qt.DescendingOrder
} else {
setSorterEnabled(sorter, false)
sorter.enabled = false
}

selectionModel.clear()
}

function setSorterEnabled(sorter, enable) {
sorter.enabled = enable
}
}

Rectangle {
Expand Down Expand Up @@ -187,7 +184,7 @@ Item {
}

prv.toggleSorter(keySorter)
prv.setSorterEnabled(valueSorter, false)
valueSorter.enabled = false
}
}

Expand Down Expand Up @@ -218,7 +215,7 @@ Item {
}

prv.toggleSorter(valueSorter)
prv.setSorterEnabled(keySorter, false)
keySorter.enabled = false
}
}
}
Expand Down
60 changes: 60 additions & 0 deletions framework/uicomponents/qml/Muse/UiComponents/filter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2026 MuseScore Limited and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "filter.h"

namespace muse::uicomponents {
Filter::Filter(QObject* parent)
: QObject(parent)
{
}

bool Filter::enabled() const
{
return m_enabled;
}

void Filter::setEnabled(const bool enabled)
{
if (m_enabled == enabled) {
return;
}

m_enabled = enabled;
emit dataChanged();
}

bool Filter::async() const
{
return m_async;
}

void Filter::setAsync(const bool async)
{
if (m_async == async) {
return;
}

m_async = async;
emit dataChanged();
}
}
62 changes: 62 additions & 0 deletions framework/uicomponents/qml/Muse/UiComponents/filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2026 MuseScore Limited and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include <QtQmlIntegration/qqmlintegration.h>

#include <QObject>

class QModelIndex;

namespace muse::uicomponents {
class SortFilterProxyModel;

class Filter : public QObject
{
Q_OBJECT
QML_ELEMENT;
QML_UNCREATABLE("")

Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY dataChanged)
/// Determines whether the SortFilterProxyModel should react asynchronously to the `dataChanged` signal.
Q_PROPERTY(bool async READ async WRITE setAsync NOTIFY dataChanged)

public:
explicit Filter(QObject* parent = nullptr);

virtual bool acceptsRow(int sourceRow, const QModelIndex& sourceParent, const SortFilterProxyModel&) = 0;

bool enabled() const;
void setEnabled(bool enabled);

bool async() const;
void setAsync(bool async);

signals:
void dataChanged();

private:
bool m_enabled = true;
bool m_async = false;
};
}
78 changes: 40 additions & 38 deletions framework/uicomponents/qml/Muse/UiComponents/filtervalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,50 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "filtervalue.h"

#include "global/log.h"

#include "sortfilterproxymodel.h"

using namespace muse::uicomponents;

FilterValue::FilterValue(QObject* parent)
: QObject(parent)
: Filter(parent)
{
}

QString FilterValue::roleName() const
bool FilterValue::acceptsRow(const int sourceRow, const QModelIndex& sourceParent,
const SortFilterProxyModel& proxyModel)
{
return m_roleName;
}
const int roleId = proxyModel.roleIdFromName(m_roleName);
if (roleId < 0) {
return true;
}

QVariant FilterValue::roleValue() const
{
return m_roleValue;
}
const QAbstractItemModel* sourceModel = proxyModel.sourceModel();
IF_ASSERT_FAILED(sourceModel) {
return true;
}

CompareType::Type FilterValue::compareType() const
{
return m_compareType;
const QModelIndex index = sourceModel->index(sourceRow, 0, sourceParent);
const QVariant data = sourceModel->data(index, roleId);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
switch (m_compareType) {
case CompareType::Equal:
return data == m_roleValue;
case CompareType::NotEqual:
return data != m_roleValue;
case CompareType::Contains:
return data.toString().contains(m_roleValue.toString(), Qt::CaseInsensitive);
}

return false;
}

bool FilterValue::enabled() const
QString FilterValue::roleName() const
{
return m_enabled;
return m_roleName;
}

void FilterValue::setRoleName(QString roleName)
Expand All @@ -58,47 +75,32 @@ void FilterValue::setRoleName(QString roleName)
emit dataChanged();
}

void FilterValue::setRoleValue(QVariant value)
{
if (m_roleValue == value) {
return;
}

m_roleValue = value;
emit dataChanged();
}

void FilterValue::setCompareType(CompareType::Type type)
QVariant FilterValue::roleValue() const
{
if (m_compareType == type) {
return;
}

m_compareType = type;
emit dataChanged();
return m_roleValue;
}

void FilterValue::setEnabled(bool enabled)
void FilterValue::setRoleValue(QVariant value)
{
if (m_enabled == enabled) {
if (m_roleValue == value) {
return;
}

m_enabled = enabled;
m_roleValue = value;
emit dataChanged();
}

bool FilterValue::async() const
CompareType::Type FilterValue::compareType() const
{
return m_async;
return m_compareType;
}

void FilterValue::setAsync(bool async)
void FilterValue::setCompareType(CompareType::Type type)
{
if (m_async == async) {
if (m_compareType == type) {
return;
}

m_async = async;
m_compareType = type;
emit dataChanged();
}
30 changes: 10 additions & 20 deletions framework/uicomponents/qml/Muse/UiComponents/filtervalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

#include <qqmlintegration.h>

#include <QObject>
#include <QString>
#include <QVariant>

#include "filter.h"

namespace muse::uicomponents {
namespace CompareType {
Q_NAMESPACE;
Expand All @@ -41,44 +43,32 @@ enum Type
Q_ENUM_NS(Type)
}

class FilterValue : public QObject
class FilterValue : public Filter
{
Q_OBJECT
QML_ELEMENT

Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY dataChanged)
Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY dataChanged)
Q_PROPERTY(muse::uicomponents::CompareType::Type compareType READ compareType WRITE setCompareType NOTIFY dataChanged)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY dataChanged)

/// Determines whether the SortFilterProxyModel should react asynchronously to the `dataChanged` signal.
Q_PROPERTY(bool async READ async WRITE setAsync NOTIFY dataChanged)

public:
explicit FilterValue(QObject* parent = nullptr);

QString roleName() const;
QVariant roleValue() const;
CompareType::Type compareType() const;
bool enabled() const;

bool async() const;
void setAsync(bool async);
bool acceptsRow(int sourceRow, const QModelIndex& sourceParent, const SortFilterProxyModel&) override;

public slots:
QString roleName() const;
void setRoleName(QString roleName);

QVariant roleValue() const;
void setRoleValue(QVariant roleValue);
void setCompareType(muse::uicomponents::CompareType::Type compareType);
void setEnabled(bool enabled);

signals:
void dataChanged();
CompareType::Type compareType() const;
void setCompareType(muse::uicomponents::CompareType::Type compareType);

private:
QString m_roleName;
QVariant m_roleValue;
CompareType::Type m_compareType = CompareType::Equal;
bool m_enabled = true;
bool m_async = false;
};
}
Loading