feature: Add SwitchRole proxy role type
This commit is contained in:
parent
94a08b49ec
commit
9a475e52ac
112
proxyrole.cpp
112
proxyrole.cpp
|
@ -4,6 +4,8 @@
|
|||
#include <QQmlExpression>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QQmlInfo>
|
||||
#include "filter.h"
|
||||
|
||||
namespace qqsfpm {
|
||||
|
||||
|
@ -90,9 +92,119 @@ QVariant JoinRole::data(const QModelIndex &sourceIndex, const QQmlSortFilterProx
|
|||
return result;
|
||||
}
|
||||
|
||||
SwitchRoleAttached::SwitchRoleAttached(QObject* parent) : QObject (parent)
|
||||
{
|
||||
if (!qobject_cast<Filter*>(parent))
|
||||
qmlInfo(parent) << "SwitchRole must be attached to a Filter";
|
||||
}
|
||||
|
||||
QVariant SwitchRoleAttached::value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void SwitchRoleAttached::setValue(QVariant value)
|
||||
{
|
||||
if (m_value == value)
|
||||
return;
|
||||
|
||||
m_value = value;
|
||||
Q_EMIT valueChanged();
|
||||
}
|
||||
|
||||
QString SwitchRole::defaultRoleName() const
|
||||
{
|
||||
return m_defaultRoleName;
|
||||
}
|
||||
|
||||
void SwitchRole::setDefaultRoleName(QString defaultRoleName)
|
||||
{
|
||||
if (m_defaultRoleName == defaultRoleName)
|
||||
return;
|
||||
|
||||
m_defaultRoleName = defaultRoleName;
|
||||
Q_EMIT defaultRoleNameChanged();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
QQmlListProperty<Filter> SwitchRole::filters()
|
||||
{
|
||||
return QQmlListProperty<Filter>(this, &m_filters,
|
||||
&SwitchRole::append_filter,
|
||||
&SwitchRole::count_filter,
|
||||
&SwitchRole::at_filter,
|
||||
&SwitchRole::clear_filters);
|
||||
}
|
||||
|
||||
void SwitchRole::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
|
||||
{
|
||||
for (Filter* filter : m_filters)
|
||||
filter->proxyModelCompleted(proxyModel);
|
||||
}
|
||||
|
||||
SwitchRoleAttached* SwitchRole::qmlAttachedProperties(QObject* object)
|
||||
{
|
||||
return new SwitchRoleAttached(object);
|
||||
}
|
||||
|
||||
QVariant SwitchRole::data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel)
|
||||
{
|
||||
for (auto filter: m_filters) {
|
||||
if (!filter->enabled())
|
||||
continue;
|
||||
if (filter->filterAcceptsRow(sourceIndex, proxyModel)) {
|
||||
auto attached = static_cast<SwitchRoleAttached*>(qmlAttachedPropertiesObject<SwitchRole>(filter, false));
|
||||
if (!attached) {
|
||||
qWarning() << "No SwitchRole.value provided for this filter" << filter;
|
||||
continue;
|
||||
}
|
||||
QVariant value = attached->value();
|
||||
if (!value.isValid()) {
|
||||
qWarning() << "No SwitchRole.value provided for this filter" << filter;
|
||||
continue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return proxyModel.sourceData(sourceIndex, m_defaultRoleName);
|
||||
}
|
||||
|
||||
void SwitchRole::append_filter(QQmlListProperty<Filter>* list, Filter* filter)
|
||||
{
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
SwitchRole* that = static_cast<SwitchRole*>(list->object);
|
||||
that->m_filters.append(filter);
|
||||
connect(filter, &Filter::invalidated, that, &SwitchRole::invalidate);
|
||||
auto attached = static_cast<SwitchRoleAttached*>(qmlAttachedPropertiesObject<SwitchRole>(filter, true));
|
||||
connect(attached, &SwitchRoleAttached::valueChanged, that, &SwitchRole::invalidate);
|
||||
that->invalidate();
|
||||
}
|
||||
|
||||
int SwitchRole::count_filter(QQmlListProperty<Filter>* list)
|
||||
{
|
||||
QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
|
||||
return filters->count();
|
||||
}
|
||||
|
||||
Filter* SwitchRole::at_filter(QQmlListProperty<Filter>* list, int index)
|
||||
{
|
||||
QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
|
||||
return filters->at(index);
|
||||
}
|
||||
|
||||
void SwitchRole::clear_filters(QQmlListProperty<Filter> *list)
|
||||
{
|
||||
SwitchRole* that = static_cast<SwitchRole*>(list->object);
|
||||
that->m_filters.clear();
|
||||
that->invalidate();
|
||||
}
|
||||
|
||||
void registerProxyRoleTypes() {
|
||||
qmlRegisterUncreatableType<ProxyRole>("SortFilterProxyModel", 0, 2, "ProxyRole", "ProxyRole is an abstract class");
|
||||
qmlRegisterType<JoinRole>("SortFilterProxyModel", 0, 2, "JoinRole");
|
||||
qmlRegisterType<SwitchRole>("SortFilterProxyModel", 0, 2, "SwitchRole");
|
||||
}
|
||||
|
||||
Q_COREAPP_STARTUP_FUNCTION(registerProxyRoleTypes)
|
||||
|
|
52
proxyrole.h
52
proxyrole.h
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <qqml.h>
|
||||
#include "qqmlsortfilterproxymodel.h"
|
||||
|
||||
namespace qqsfpm {
|
||||
|
@ -62,6 +63,57 @@ private:
|
|||
QString m_separator = " ";
|
||||
};
|
||||
|
||||
class SwitchRoleAttached : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
|
||||
public:
|
||||
SwitchRoleAttached(QObject* parent);
|
||||
|
||||
QVariant value() const;
|
||||
void setValue(QVariant value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void valueChanged();
|
||||
|
||||
private:
|
||||
QVariant m_value;
|
||||
};
|
||||
|
||||
class SwitchRole : public ProxyRole
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString defaultRoleName READ defaultRoleName WRITE setDefaultRoleName NOTIFY defaultRoleNameChanged)
|
||||
Q_PROPERTY(QQmlListProperty<qqsfpm::Filter> filters READ filters)
|
||||
|
||||
public:
|
||||
using ProxyRole::ProxyRole;
|
||||
|
||||
QString defaultRoleName() const;
|
||||
void setDefaultRoleName(QString defaultRoleName);
|
||||
|
||||
QQmlListProperty<Filter> filters();
|
||||
void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override;
|
||||
|
||||
static SwitchRoleAttached* qmlAttachedProperties(QObject* object);
|
||||
|
||||
Q_SIGNALS:
|
||||
void defaultRoleNameChanged();
|
||||
|
||||
private:
|
||||
QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override;
|
||||
|
||||
static void append_filter(QQmlListProperty<Filter>* list, Filter* filter);
|
||||
static int count_filter(QQmlListProperty<Filter>* list);
|
||||
static Filter* at_filter(QQmlListProperty<Filter>* list, int index);
|
||||
static void clear_filters(QQmlListProperty<Filter>* list);
|
||||
|
||||
QString m_defaultRoleName;
|
||||
QList<Filter*> m_filters;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QML_DECLARE_TYPEINFO(qqsfpm::SwitchRole, QML_HAS_ATTACHED_PROPERTIES)
|
||||
|
||||
#endif // PROXYROLE_H
|
||||
|
|
|
@ -24,4 +24,5 @@ OTHER_FILES += \
|
|||
tst_rolesorter.qml \
|
||||
tst_stringsorter.qml \
|
||||
tst_proxyroles.qml \
|
||||
tst_joinrole.qml
|
||||
tst_joinrole.qml \
|
||||
tst_switchrole.qml
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
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
|
||||
|
||||
proxyRoles: SwitchRole {
|
||||
name: "switchRole"
|
||||
filters: [
|
||||
ValueFilter {
|
||||
id: valueFilter
|
||||
roleName: "favorite"
|
||||
value: true
|
||||
SwitchRole.value: "*"
|
||||
},
|
||||
ValueFilter {
|
||||
id: secondValueFilter
|
||||
roleName: "favorite"
|
||||
value: true
|
||||
SwitchRole.value: "%"
|
||||
},
|
||||
ValueFilter {
|
||||
id: thirdValueFilter
|
||||
roleName: "name"
|
||||
value: 3
|
||||
SwitchRole.value: "three"
|
||||
}
|
||||
]
|
||||
defaultRoleName: "name"
|
||||
}
|
||||
}
|
||||
|
||||
Instantiator {
|
||||
id: instantiator
|
||||
model: testModel
|
||||
QtObject {
|
||||
property var switchRole: model.switchRole
|
||||
}
|
||||
}
|
||||
|
||||
TestCase {
|
||||
name: "SwitchRole"
|
||||
|
||||
function test_data() {
|
||||
compare(testModel.get(0, "switchRole"), "*");
|
||||
compare(testModel.get(1, "switchRole"), "2");
|
||||
compare(testModel.get(2, "switchRole"), "three");
|
||||
compare(testModel.get(3, "switchRole"), "*");
|
||||
}
|
||||
|
||||
function test_valueChange() {
|
||||
compare(instantiator.object.switchRole, "*");
|
||||
valueFilter.SwitchRole.value = "test";
|
||||
compare(instantiator.object.switchRole, "test");
|
||||
valueFilter.SwitchRole.value = "*";
|
||||
}
|
||||
|
||||
function test_filterChange() {
|
||||
compare(instantiator.object.switchRole, "*");
|
||||
valueFilter.enabled = false;
|
||||
compare(instantiator.object.switchRole, "%");
|
||||
valueFilter.enabled = true;
|
||||
}
|
||||
|
||||
function test_defaultSourceChange() {
|
||||
compare(instantiator.object.switchRole, "*");
|
||||
listModel.setProperty(0, "favorite", false);
|
||||
compare(instantiator.object.switchRole, "1");
|
||||
compare(instantiator.objectAt(1).switchRole, "2");
|
||||
listModel.setProperty(1, "name", "test");
|
||||
compare(instantiator.objectAt(1).switchRole, "test");
|
||||
|
||||
listModel.setProperty(1, "name", "2");
|
||||
listModel.setProperty(0, "favorite", true);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue