feature: Add new basic ProxyRole functionality
Add a base ProxyRole type and proxyRoles handling
This commit is contained in:
parent
25b506a3d7
commit
400f453d91
|
@ -4,7 +4,9 @@ INCLUDEPATH += $$PWD
|
|||
|
||||
HEADERS += $$PWD/qqmlsortfilterproxymodel.h \
|
||||
$$PWD/filter.h \
|
||||
$$PWD/sorter.h
|
||||
$$PWD/sorter.h \
|
||||
$$PWD/proxyrole.h
|
||||
SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \
|
||||
$$PWD/filter.cpp \
|
||||
$$PWD/sorter.cpp
|
||||
$$PWD/sorter.cpp \
|
||||
$$PWD/proxyrole.cpp
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#include "proxyrole.h"
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlExpression>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
namespace qqsfpm {
|
||||
|
||||
ProxyRole::ProxyRole(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
const QString& ProxyRole::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void ProxyRole::setName(const QString& name)
|
||||
{
|
||||
if (m_name == name)
|
||||
return;
|
||||
|
||||
m_name = name;
|
||||
Q_EMIT nameChanged();
|
||||
}
|
||||
|
||||
QVariant ProxyRole::roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel)
|
||||
{
|
||||
if (m_mutex.tryLock()) {
|
||||
QVariant result = data(sourceIndex, proxyModel);
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
} else {
|
||||
return QVariant{};
|
||||
}
|
||||
}
|
||||
|
||||
void ProxyRole::invalidate()
|
||||
{
|
||||
Q_EMIT invalidated();
|
||||
}
|
||||
|
||||
|
||||
void registerProxyRoleTypes() {
|
||||
qmlRegisterUncreatableType<ProxyRole>("SortFilterProxyModel", 0, 2, "ProxyRole", "ProxyRole is an abstract class");
|
||||
}
|
||||
|
||||
Q_COREAPP_STARTUP_FUNCTION(registerProxyRoleTypes)
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef PROXYROLE_H
|
||||
#define PROXYROLE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include "qqmlsortfilterproxymodel.h"
|
||||
|
||||
namespace qqsfpm {
|
||||
|
||||
class ProxyRole : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
friend class QQmlSortFilterProxyModel;
|
||||
|
||||
public:
|
||||
explicit ProxyRole(QObject *parent = nullptr);
|
||||
|
||||
const QString& name() const;
|
||||
void setName(const QString& name);
|
||||
|
||||
QVariant roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel);
|
||||
|
||||
protected:
|
||||
void invalidate();
|
||||
|
||||
Q_SIGNALS:
|
||||
void nameChanged();
|
||||
void invalidated();
|
||||
|
||||
private:
|
||||
virtual QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) = 0;
|
||||
|
||||
QString m_name;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PROXYROLE_H
|
|
@ -3,6 +3,7 @@
|
|||
#include <algorithm>
|
||||
#include "filter.h"
|
||||
#include "sorter.h"
|
||||
#include "proxyrole.h"
|
||||
|
||||
namespace qqsfpm {
|
||||
|
||||
|
@ -186,6 +187,15 @@ QQmlListProperty<Sorter> QQmlSortFilterProxyModel::sorters()
|
|||
&QQmlSortFilterProxyModel::clear_sorters);
|
||||
}
|
||||
|
||||
QQmlListProperty<ProxyRole> QQmlSortFilterProxyModel::proxyRoles()
|
||||
{
|
||||
return QQmlListProperty<ProxyRole>(this, &m_proxyRoles,
|
||||
&QQmlSortFilterProxyModel::append_proxyRole,
|
||||
&QQmlSortFilterProxyModel::count_proxyRole,
|
||||
&QQmlSortFilterProxyModel::at_proxyRole,
|
||||
&QQmlSortFilterProxyModel::clear_proxyRoles);
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::classBegin()
|
||||
{
|
||||
|
||||
|
@ -208,7 +218,30 @@ QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex& sourceIndex, co
|
|||
|
||||
QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex &sourceIndex, int role) const
|
||||
{
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
if (ProxyRole* proxyRole = m_proxyRoleMap[role])
|
||||
return proxyRole->roleData(sourceIndex, *this);
|
||||
else
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
|
||||
{
|
||||
beginResetModel();
|
||||
if (this->sourceModel())
|
||||
disconnect(this->sourceModel(), &QAbstractItemModel::dataChanged, this, &QQmlSortFilterProxyModel::sourceDataChanged);
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
connect(this->sourceModel(), &QAbstractItemModel::dataChanged, this, &QQmlSortFilterProxyModel::sourceDataChanged);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant QQmlSortFilterProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
return sourceData(mapToSource(index), role);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> QQmlSortFilterProxyModel::roleNames() const
|
||||
{
|
||||
return m_roleNames;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -341,6 +374,18 @@ void QQmlSortFilterProxyModel::resetInternalData()
|
|||
connect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles);
|
||||
connect(this, &QAbstractItemModel::rowsAboutToBeInserted, this, &QQmlSortFilterProxyModel::initRoles);
|
||||
}
|
||||
m_roleNames = QSortFilterProxyModel::roleNames();
|
||||
m_proxyRoleMap.clear();
|
||||
|
||||
auto roles = m_roleNames.keys();
|
||||
auto maxIt = std::max_element(roles.cbegin(), roles.cend());
|
||||
int maxRole = maxIt != roles.cend() ? *maxIt : -1;
|
||||
for (auto proxyRole : m_proxyRoles) {
|
||||
++maxRole;
|
||||
m_roleNames[maxRole] = proxyRole->name().toUtf8();
|
||||
m_proxyRoleMap[maxRole] = proxyRole;
|
||||
connect(proxyRole, &ProxyRole::invalidated, this, &QQmlSortFilterProxyModel::emitProxyRolesChanged, Qt::UniqueConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::invalidateFilter()
|
||||
|
@ -388,6 +433,17 @@ void QQmlSortFilterProxyModel::initRoles()
|
|||
updateRoles();
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
|
||||
{
|
||||
Q_UNUSED(roles);
|
||||
Q_EMIT dataChanged(topLeft, bottomRight, m_proxyRoleMap.keys().toVector());
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::emitProxyRolesChanged()
|
||||
{
|
||||
Q_EMIT dataChanged(index(0, 0), index(rowCount()-1, columnCount()-1), m_proxyRoleMap.keys().toVector());
|
||||
}
|
||||
|
||||
QVariantMap QQmlSortFilterProxyModel::modelDataMap(const QModelIndex& modelIndex) const
|
||||
{
|
||||
QVariantMap map;
|
||||
|
@ -459,6 +515,37 @@ void QQmlSortFilterProxyModel::clear_sorters(QQmlListProperty<Sorter>* list)
|
|||
that->invalidate();
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::append_proxyRole(QQmlListProperty<ProxyRole>* list, ProxyRole* proxyRole)
|
||||
{
|
||||
if (!proxyRole)
|
||||
return;
|
||||
|
||||
auto that = static_cast<QQmlSortFilterProxyModel*>(list->object);
|
||||
that->beginResetModel();
|
||||
that->m_proxyRoles.append(proxyRole);
|
||||
that->endResetModel();
|
||||
}
|
||||
|
||||
int QQmlSortFilterProxyModel::count_proxyRole(QQmlListProperty<ProxyRole>* list)
|
||||
{
|
||||
auto proxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
|
||||
return proxyRoles->count();
|
||||
}
|
||||
|
||||
ProxyRole* QQmlSortFilterProxyModel::at_proxyRole(QQmlListProperty<ProxyRole>* list, int index)
|
||||
{
|
||||
auto proxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
|
||||
return proxyRoles->at(index);
|
||||
}
|
||||
|
||||
void QQmlSortFilterProxyModel::clear_proxyRoles(QQmlListProperty<ProxyRole>* list)
|
||||
{
|
||||
auto that = static_cast<QQmlSortFilterProxyModel*>(list->object);
|
||||
that->beginResetModel();
|
||||
that->m_proxyRoles.clear();
|
||||
that->endResetModel();
|
||||
}
|
||||
|
||||
void registerQQmlSortFilterProxyModelTypes() {
|
||||
qmlRegisterType<QQmlSortFilterProxyModel>("SortFilterProxyModel", 0, 2, "SortFilterProxyModel");
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace qqsfpm {
|
|||
|
||||
class Filter;
|
||||
class Sorter;
|
||||
class ProxyRole;
|
||||
|
||||
class QQmlSortFilterProxyModel : public QSortFilterProxyModel, public QQmlParserStatus
|
||||
{
|
||||
|
@ -27,6 +28,7 @@ class QQmlSortFilterProxyModel : public QSortFilterProxyModel, public QQmlParser
|
|||
|
||||
Q_PROPERTY(QQmlListProperty<qqsfpm::Filter> filters READ filters)
|
||||
Q_PROPERTY(QQmlListProperty<qqsfpm::Sorter> sorters READ sorters)
|
||||
Q_PROPERTY(QQmlListProperty<qqsfpm::ProxyRole> proxyRoles READ proxyRoles)
|
||||
|
||||
public:
|
||||
enum PatternSyntax {
|
||||
|
@ -62,6 +64,7 @@ public:
|
|||
|
||||
QQmlListProperty<Filter> filters();
|
||||
QQmlListProperty<Sorter> sorters();
|
||||
QQmlListProperty<ProxyRole> proxyRoles();
|
||||
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
@ -69,6 +72,10 @@ public:
|
|||
QVariant sourceData(const QModelIndex& sourceIndex, const QString& roleName) const;
|
||||
QVariant sourceData(const QModelIndex& sourceIndex, int role) const;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE int roleForName(const QString& roleName) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap get(int row) const;
|
||||
|
@ -104,6 +111,8 @@ private Q_SLOTS:
|
|||
void updateSortRole();
|
||||
void updateRoles();
|
||||
void initRoles();
|
||||
void sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles);
|
||||
void emitProxyRolesChanged();
|
||||
|
||||
private:
|
||||
QVariantMap modelDataMap(const QModelIndex& modelIndex) const;
|
||||
|
@ -118,13 +127,21 @@ private:
|
|||
static Sorter* at_sorter(QQmlListProperty<Sorter>* list, int index);
|
||||
static void clear_sorters(QQmlListProperty<Sorter>* list);
|
||||
|
||||
static void append_proxyRole(QQmlListProperty<ProxyRole>* list, ProxyRole* proxyRole);
|
||||
static int count_proxyRole(QQmlListProperty<ProxyRole>* list);
|
||||
static ProxyRole* at_proxyRole(QQmlListProperty<ProxyRole>* list, int index);
|
||||
static void clear_proxyRoles(QQmlListProperty<ProxyRole>* list);
|
||||
|
||||
QString m_filterRoleName;
|
||||
QVariant m_filterValue;
|
||||
QString m_sortRoleName;
|
||||
bool m_ascendingSortOrder = true;
|
||||
QList<Filter*> m_filters;
|
||||
QList<Sorter*> m_sorters;
|
||||
QList<ProxyRole*> m_proxyRoles;
|
||||
bool m_completed = false;
|
||||
QHash<int, QByteArray> m_roleNames;
|
||||
QHash<int, ProxyRole*> m_proxyRoleMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue