feature: Add new basic ProxyRole functionality

Add a base ProxyRole type and proxyRoles handling
This commit is contained in:
Unknown 2017-09-16 16:44:21 +02:00 committed by unknown
parent 25b506a3d7
commit 400f453d91
5 changed files with 200 additions and 3 deletions

View File

@ -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

51
proxyrole.cpp Normal file
View File

@ -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)
}

40
proxyrole.h Normal file
View File

@ -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

View File

@ -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");
}

View File

@ -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;
};
}