Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
ecm_add_qml_module(itemmodelsplugin
|
||||
URI "org.kde.kitemmodels"
|
||||
VERSION 1.0
|
||||
GENERATE_PLUGIN_SOURCE
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
)
|
||||
|
||||
target_sources(itemmodelsplugin PRIVATE
|
||||
kdescendantsproxymodel_qml.cpp
|
||||
kdescendantsproxymodel_qml.h
|
||||
krolenames.cpp
|
||||
krolenames.h
|
||||
ksortfilterproxymodel.cpp
|
||||
ksortfilterproxymodel.h
|
||||
types.h
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(itemmodelsplugin
|
||||
HEADER kitemmodels_debug.h
|
||||
IDENTIFIER KITEMMODELS_LOG
|
||||
CATEGORY_NAME kf.itemmodels.quick
|
||||
DESCRIPTION "KItemModels (QtQuick)"
|
||||
EXPORT KITEMMODELS
|
||||
)
|
||||
|
||||
target_link_libraries(itemmodelsplugin PRIVATE
|
||||
Qt6::Qml
|
||||
KF6::ItemModels
|
||||
)
|
||||
|
||||
ecm_finalize_qml_module(itemmodelsplugin DESTINATION ${KDE_INSTALL_QMLDIR} EXPORT KF6ItemModelsTargets)
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kdescendantsproxymodel_qml.h"
|
||||
#include <QDebug>
|
||||
|
||||
KDescendantsProxyModelQml::KDescendantsProxyModelQml(QObject *parent)
|
||||
: KDescendantsProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
KDescendantsProxyModelQml::~KDescendantsProxyModelQml()
|
||||
{
|
||||
}
|
||||
|
||||
void KDescendantsProxyModelQml::expandChildren(int row)
|
||||
{
|
||||
QModelIndex idx = mapToSource(index(row, 0));
|
||||
expandSourceIndex(idx);
|
||||
}
|
||||
|
||||
void KDescendantsProxyModelQml::collapseChildren(int row)
|
||||
{
|
||||
QModelIndex idx = mapToSource(index(row, 0));
|
||||
collapseSourceIndex(idx);
|
||||
}
|
||||
|
||||
void KDescendantsProxyModelQml::toggleChildren(int row)
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index(row, 0));
|
||||
|
||||
if (!sourceModel()->hasChildren(sourceIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSourceIndexExpanded(sourceIndex)) {
|
||||
collapseSourceIndex(sourceIndex);
|
||||
} else {
|
||||
expandSourceIndex(sourceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_kdescendantsproxymodel_qml.cpp"
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// This class exposes KDescendantsProxyModel in a more QML friendly way
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <KDescendantsProxyModel>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
|
||||
#include <qqmlregistration.h>
|
||||
|
||||
class KDescendantsProxyModelQml : public KDescendantsProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_NAMED_ELEMENT(KDescendantsProxyModel)
|
||||
|
||||
public:
|
||||
explicit KDescendantsProxyModelQml(QObject *parent = nullptr);
|
||||
~KDescendantsProxyModelQml() override;
|
||||
|
||||
Q_INVOKABLE void expandChildren(int row);
|
||||
Q_INVOKABLE void collapseChildren(int row);
|
||||
Q_INVOKABLE void toggleChildren(int row);
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "krolenames.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QQmlInfo>
|
||||
|
||||
class KRoleNamesPrivate
|
||||
{
|
||||
KRoleNames *const q;
|
||||
|
||||
public:
|
||||
explicit KRoleNamesPrivate(KRoleNames *qq)
|
||||
: q(qq)
|
||||
{
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
QAbstractItemModel *model() const;
|
||||
};
|
||||
|
||||
KRoleNames::KRoleNames(QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new KRoleNamesPrivate(this))
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
if (!d->model()) {
|
||||
qmlWarning(parent) << "KRoleNames must be attached to a QAbstractItemModel";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
KRoleNames::~KRoleNames() = default;
|
||||
|
||||
QByteArray KRoleNames::roleName(int role) const
|
||||
{
|
||||
const auto map = d->roleNames();
|
||||
return map.value(role, QByteArray());
|
||||
}
|
||||
|
||||
int KRoleNames::role(const QByteArray &roleName) const
|
||||
{
|
||||
const auto map = d->roleNames();
|
||||
return map.key(roleName, -1);
|
||||
}
|
||||
|
||||
KRoleNames *KRoleNames::qmlAttachedProperties(QObject *object)
|
||||
{
|
||||
return new KRoleNames(object);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> KRoleNamesPrivate::roleNames() const
|
||||
{
|
||||
if (const auto m = model()) {
|
||||
return m->roleNames();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QAbstractItemModel *KRoleNamesPrivate::model() const
|
||||
{
|
||||
return qobject_cast<QAbstractItemModel *>(q->parent());
|
||||
}
|
||||
|
||||
#include "moc_krolenames.cpp"
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KROLENAMES_H
|
||||
#define KROLENAMES_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qqml.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QAbstractItemModel;
|
||||
class KRoleNamesPrivate;
|
||||
|
||||
/**
|
||||
* @class KRoleNames
|
||||
*
|
||||
* @brief A mapper between roles and role names of an attachee model.
|
||||
*
|
||||
* KRoleNames exposes runtime-invokable methods to map from roles to role names
|
||||
* and vice-versa. It can be used to retrieve data from a model in an imperative
|
||||
* fashion when enum with roles is not available at runtime (i.e. not exported
|
||||
* via Q_ENUM macro) but role names are known; or just to maintain consistency
|
||||
* with view delegates (which use role names as properties).
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
class KRoleNames : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("KRoleNames can only be used as an attached property")
|
||||
QML_ATTACHED(KRoleNames)
|
||||
QML_ADDED_IN_MINOR_VERSION(1)
|
||||
public:
|
||||
explicit KRoleNames(QObject *parent = nullptr);
|
||||
~KRoleNames() override;
|
||||
|
||||
/**
|
||||
* Maps role number to role name.
|
||||
*
|
||||
* Returns an empty string if role is not found in attachee model's
|
||||
* roleNames() hash map.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
Q_INVOKABLE QByteArray roleName(int role) const;
|
||||
|
||||
/**
|
||||
* Maps role name to role number.
|
||||
*
|
||||
* Returns -1 if role name is not found in attachee model's
|
||||
* roleNames() hash map.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
Q_INVOKABLE int role(const QByteArray &roleName) const;
|
||||
|
||||
static KRoleNames *qmlAttachedProperties(QObject *object);
|
||||
|
||||
private:
|
||||
std::unique_ptr<KRoleNamesPrivate> const d;
|
||||
};
|
||||
|
||||
QML_DECLARE_TYPEINFO(KRoleNames, QML_HAS_ATTACHED_PROPERTIES)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010 Marco Martin <mart@kde.org>
|
||||
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "ksortfilterproxymodel.h"
|
||||
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "kitemmodels_debug.h"
|
||||
|
||||
KSortFilterProxyModel::KSortFilterProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_componentCompleted(false)
|
||||
, m_sortRoleSourceOfTruth(SourceOfTruthIsRoleID)
|
||||
, m_filterRoleSourceOfTruth(SourceOfTruthIsRoleID)
|
||||
, m_sortRoleGuard(false)
|
||||
, m_filterRoleGuard(false)
|
||||
{
|
||||
setDynamicSortFilter(true);
|
||||
connect(this, &KSortFilterProxyModel::modelReset, this, &KSortFilterProxyModel::rowCountChanged);
|
||||
connect(this, &KSortFilterProxyModel::rowsInserted, this, &KSortFilterProxyModel::rowCountChanged);
|
||||
connect(this, &KSortFilterProxyModel::rowsRemoved, this, &KSortFilterProxyModel::rowCountChanged);
|
||||
|
||||
connect(this, &KSortFilterProxyModel::sortRoleChanged, this, &KSortFilterProxyModel::syncSortRoleProperties);
|
||||
connect(this, &KSortFilterProxyModel::filterRoleChanged, this, &KSortFilterProxyModel::syncFilterRoleProperties);
|
||||
}
|
||||
|
||||
KSortFilterProxyModel::~KSortFilterProxyModel()
|
||||
{
|
||||
}
|
||||
|
||||
static void reverseStringIntHash(QHash<QString, int> &dst, const QHash<int, QByteArray> &src)
|
||||
{
|
||||
dst.clear();
|
||||
dst.reserve(src.count());
|
||||
for (auto i = src.constBegin(); i != src.constEnd(); ++i) {
|
||||
dst[QString::fromUtf8(i.value())] = i.key();
|
||||
}
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::syncRoleNames()
|
||||
{
|
||||
if (!sourceModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reverseStringIntHash(m_roleIds, roleNames());
|
||||
|
||||
m_sortRoleGuard = true;
|
||||
syncSortRoleProperties();
|
||||
m_sortRoleGuard = false;
|
||||
|
||||
m_filterRoleGuard = true;
|
||||
syncFilterRoleProperties();
|
||||
m_filterRoleGuard = false;
|
||||
}
|
||||
|
||||
int KSortFilterProxyModel::roleNameToId(const QString &name) const
|
||||
{
|
||||
return m_roleIds.value(name, Qt::DisplayRole);
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setSourceModel(QAbstractItemModel *model)
|
||||
{
|
||||
const auto oldModel = sourceModel();
|
||||
|
||||
if (model == oldModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldModel) {
|
||||
for (const auto &connection : std::as_const(m_sourceModelConnections)) {
|
||||
disconnect(connection);
|
||||
}
|
||||
}
|
||||
|
||||
QSortFilterProxyModel::setSourceModel(model);
|
||||
|
||||
// NOTE: some models actually fill their roleNames() only when they get some actual data, this works around the bad behavior
|
||||
if (model) {
|
||||
m_sourceModelConnections = {{
|
||||
connect(model, &QAbstractItemModel::modelReset, this, &KSortFilterProxyModel::syncRoleNames),
|
||||
connect(model, &QAbstractItemModel::rowsInserted, this, &KSortFilterProxyModel::syncRoleNames),
|
||||
connect(model, &QAbstractItemModel::rowsRemoved, this, &KSortFilterProxyModel::syncRoleNames),
|
||||
}};
|
||||
}
|
||||
|
||||
if (m_componentCompleted) {
|
||||
syncRoleNames();
|
||||
}
|
||||
}
|
||||
|
||||
bool KSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
if (m_filterRowCallback.isCallable()) {
|
||||
QJSEngine *engine = qjsEngine(this);
|
||||
QJSValueList args = {QJSValue(source_row), engine->toScriptValue(source_parent)};
|
||||
|
||||
QJSValue result = const_cast<KSortFilterProxyModel *>(this)->m_filterRowCallback.call(args);
|
||||
if (result.isError()) {
|
||||
qCWarning(KITEMMODELS_LOG) << "Row filter callback produced an error:";
|
||||
qCWarning(KITEMMODELS_LOG) << result.toString();
|
||||
return true;
|
||||
} else {
|
||||
return result.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
bool KSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
|
||||
{
|
||||
if (m_filterColumnCallback.isCallable()) {
|
||||
QJSEngine *engine = qjsEngine(this);
|
||||
QJSValueList args = {QJSValue(source_column), engine->toScriptValue(source_parent)};
|
||||
|
||||
QJSValue result = const_cast<KSortFilterProxyModel *>(this)->m_filterColumnCallback.call(args);
|
||||
if (result.isError()) {
|
||||
qCWarning(KITEMMODELS_LOG) << "Row filter callback produced an error:";
|
||||
qCWarning(KITEMMODELS_LOG) << result.toString();
|
||||
return true;
|
||||
} else {
|
||||
return result.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::filterAcceptsColumn(source_column, source_parent);
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setFilterString(const QString &filterString)
|
||||
{
|
||||
if (filterString == m_filterString) {
|
||||
return;
|
||||
}
|
||||
m_filterString = filterString;
|
||||
QSortFilterProxyModel::setFilterFixedString(filterString);
|
||||
Q_EMIT filterStringChanged();
|
||||
}
|
||||
|
||||
QString KSortFilterProxyModel::filterString() const
|
||||
{
|
||||
return m_filterString;
|
||||
}
|
||||
|
||||
QJSValue KSortFilterProxyModel::filterRowCallback() const
|
||||
{
|
||||
return m_filterRowCallback;
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setFilterRowCallback(const QJSValue &callback)
|
||||
{
|
||||
if (m_filterRowCallback.strictlyEquals(callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!callback.isNull() && !callback.isCallable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_filterRowCallback = callback;
|
||||
invalidateFilter();
|
||||
|
||||
Q_EMIT filterRowCallbackChanged(callback);
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setFilterColumnCallback(const QJSValue &callback)
|
||||
{
|
||||
if (m_filterColumnCallback.strictlyEquals(callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!callback.isNull() && !callback.isCallable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_filterColumnCallback = callback;
|
||||
invalidateFilter();
|
||||
|
||||
Q_EMIT filterColumnCallbackChanged(callback);
|
||||
}
|
||||
|
||||
QJSValue KSortFilterProxyModel::filterColumnCallback() const
|
||||
{
|
||||
return m_filterColumnCallback;
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::syncSortRoleProperties()
|
||||
{
|
||||
if (!sourceModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sortRoleGuard) {
|
||||
m_sortRoleSourceOfTruth = SourceOfTruthIsRoleID;
|
||||
}
|
||||
|
||||
if (m_sortRoleSourceOfTruth == SourceOfTruthIsRoleName) {
|
||||
if (m_sortRoleName.isEmpty()) {
|
||||
QSortFilterProxyModel::setSortRole(Qt::DisplayRole);
|
||||
sort(-1, Qt::AscendingOrder);
|
||||
} else {
|
||||
const auto role = roleNameToId(m_sortRoleName);
|
||||
QSortFilterProxyModel::setSortRole(role);
|
||||
sort(std::max(sortColumn(), 0), sortOrder());
|
||||
}
|
||||
} else {
|
||||
const QString roleName = QString::fromUtf8(roleNames().value(sortRole()));
|
||||
if (m_sortRoleName != roleName) {
|
||||
m_sortRoleName = roleName;
|
||||
Q_EMIT sortRoleNameChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::syncFilterRoleProperties()
|
||||
{
|
||||
if (!sourceModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_filterRoleGuard) {
|
||||
m_filterRoleSourceOfTruth = SourceOfTruthIsRoleID;
|
||||
}
|
||||
|
||||
if (m_filterRoleSourceOfTruth == SourceOfTruthIsRoleName) {
|
||||
const auto role = roleNameToId(m_filterRoleName);
|
||||
QSortFilterProxyModel::setFilterRole(role);
|
||||
} else {
|
||||
const QString roleName = QString::fromUtf8(roleNames().value(filterRole()));
|
||||
if (m_filterRoleName != roleName) {
|
||||
m_filterRoleName = roleName;
|
||||
Q_EMIT filterRoleNameChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setFilterRoleName(const QString &roleName)
|
||||
{
|
||||
if (m_filterRoleSourceOfTruth == SourceOfTruthIsRoleName && m_filterRoleName == roleName) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_filterRoleSourceOfTruth = SourceOfTruthIsRoleName;
|
||||
m_filterRoleName = roleName;
|
||||
|
||||
m_filterRoleGuard = true;
|
||||
syncFilterRoleProperties();
|
||||
m_filterRoleGuard = false;
|
||||
|
||||
Q_EMIT filterRoleNameChanged();
|
||||
}
|
||||
|
||||
QString KSortFilterProxyModel::filterRoleName() const
|
||||
{
|
||||
return m_filterRoleName;
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setSortRoleName(const QString &roleName)
|
||||
{
|
||||
if (m_sortRoleSourceOfTruth == SourceOfTruthIsRoleName && m_sortRoleName == roleName) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_sortRoleSourceOfTruth = SourceOfTruthIsRoleName;
|
||||
m_sortRoleName = roleName;
|
||||
|
||||
m_sortRoleGuard = true;
|
||||
syncSortRoleProperties();
|
||||
m_sortRoleGuard = false;
|
||||
|
||||
Q_EMIT sortRoleNameChanged();
|
||||
}
|
||||
|
||||
QString KSortFilterProxyModel::sortRoleName() const
|
||||
{
|
||||
return m_sortRoleName;
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setSortOrder(const Qt::SortOrder order)
|
||||
{
|
||||
sort(std::max(sortColumn(), 0), order);
|
||||
Q_EMIT sortOrderChanged();
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::setSortColumn(int column)
|
||||
{
|
||||
if (column == sortColumn()) {
|
||||
return;
|
||||
}
|
||||
sort(column, sortOrder());
|
||||
Q_EMIT sortColumnChanged();
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::classBegin()
|
||||
{
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::componentComplete()
|
||||
{
|
||||
m_componentCompleted = true;
|
||||
syncRoleNames();
|
||||
}
|
||||
|
||||
void KSortFilterProxyModel::invalidateFilter()
|
||||
{
|
||||
QSortFilterProxyModel::invalidateFilter();
|
||||
}
|
||||
|
||||
#include "moc_ksortfilterproxymodel.cpp"
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010 Marco Martin <mart@kde.org>
|
||||
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KSORTFILTERPROXYMODEL_H
|
||||
#define KSORTFILTERPROXYMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QJSValue>
|
||||
#include <QList>
|
||||
#include <QQmlParserStatus>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <qqmlregistration.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @class KSortFilterProxyModel
|
||||
* @short Filter and sort an existing QAbstractItemModel
|
||||
*
|
||||
* @since 5.67
|
||||
*/
|
||||
class KSortFilterProxyModel : public QSortFilterProxyModel, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
/**
|
||||
* The string for the filter, only rows with their filterRole matching filterString will be displayed
|
||||
*/
|
||||
Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
|
||||
/**
|
||||
* A JavaScript callable that can be used to perform advanced filters on a given row.
|
||||
* The callback is passed the source row, and source parent for a given row as arguments
|
||||
*
|
||||
* The callable's return value is evaluated as boolean to determine
|
||||
* whether the row is accepted (true) or filtered out (false). It overrides the default implementation
|
||||
* that uses filterRegExp or filterString; while filterCallback is set those two properties are
|
||||
* ignored. Attempts to write a non-callable to this property are silently ignored, but you can set
|
||||
* it to null.
|
||||
*
|
||||
* @code
|
||||
* filterRowCallback: function(source_row, source_parent) {
|
||||
* return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
|
||||
* };
|
||||
* @endcode
|
||||
*/
|
||||
Q_PROPERTY(QJSValue filterRowCallback READ filterRowCallback WRITE setFilterRowCallback NOTIFY filterRowCallbackChanged)
|
||||
|
||||
/**
|
||||
* A JavaScript callable that can be used to perform advanced filters on a given column.
|
||||
* The callback is passed the source column, and source parent for a given column as arguments.
|
||||
*
|
||||
* @see filterRowCallback
|
||||
*/
|
||||
Q_PROPERTY(QJSValue filterColumnCallback READ filterColumnCallback WRITE setFilterColumnCallback NOTIFY filterColumnCallbackChanged)
|
||||
|
||||
/**
|
||||
* The role of the sourceModel on which the filter will be applied.
|
||||
* This can either be the numerical role value or the role name as a string.
|
||||
*/
|
||||
Q_PROPERTY(QString filterRoleName READ filterRoleName WRITE setFilterRoleName NOTIFY filterRoleNameChanged)
|
||||
|
||||
/**
|
||||
* The role of the sourceModel that will be used for sorting. if empty the order will be left unaltered
|
||||
* This can either be the numerical role value or the role name as a string.
|
||||
*/
|
||||
Q_PROPERTY(QString sortRoleName READ sortRoleName WRITE setSortRoleName NOTIFY sortRoleNameChanged)
|
||||
|
||||
/**
|
||||
* One of Qt.AscendingOrder or Qt.DescendingOrder
|
||||
*/
|
||||
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
|
||||
|
||||
/**
|
||||
* Specify which column should be used for sorting
|
||||
* The default value is -1.
|
||||
* If \a sortRole is set, the default value is 0.
|
||||
*/
|
||||
Q_PROPERTY(int sortColumn READ sortColumn WRITE setSortColumn NOTIFY sortColumnChanged)
|
||||
|
||||
/**
|
||||
* The number of top level rows.
|
||||
*/
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY rowCountChanged)
|
||||
|
||||
public:
|
||||
explicit KSortFilterProxyModel(QObject *parent = nullptr);
|
||||
~KSortFilterProxyModel() override;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
void setFilterRowCallback(const QJSValue &callback);
|
||||
QJSValue filterRowCallback() const;
|
||||
|
||||
void setFilterString(const QString &filterString);
|
||||
QString filterString() const;
|
||||
|
||||
void setFilterColumnCallback(const QJSValue &callback);
|
||||
QJSValue filterColumnCallback() const;
|
||||
|
||||
void setFilterRoleName(const QString &roleName);
|
||||
QString filterRoleName() const;
|
||||
|
||||
void setSortRoleName(const QString &roleName);
|
||||
QString sortRoleName() const;
|
||||
|
||||
void setSortOrder(const Qt::SortOrder order);
|
||||
void setSortColumn(int column);
|
||||
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Invalidates the current filtering.
|
||||
*
|
||||
* This function should be called if you are implementing custom filtering through
|
||||
* filterRowCallback or filterColumnCallback, and your filter parameters have changed.
|
||||
*
|
||||
* @since 5.70
|
||||
*/
|
||||
void invalidateFilter();
|
||||
|
||||
Q_SIGNALS:
|
||||
void filterStringChanged();
|
||||
void filterRoleNameChanged();
|
||||
void sortRoleNameChanged();
|
||||
void sortOrderChanged();
|
||||
void sortColumnChanged();
|
||||
void filterRowCallbackChanged(const QJSValue &);
|
||||
void filterColumnCallbackChanged(const QJSValue &);
|
||||
void rowCountChanged();
|
||||
|
||||
protected:
|
||||
int roleNameToId(const QString &name) const;
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override;
|
||||
|
||||
protected Q_SLOTS:
|
||||
// This method is called whenever we suspect that role names mapping might have gone stale.
|
||||
// It must not alter the source of truth for sort/filter properties.
|
||||
void syncRoleNames();
|
||||
// These methods are dealing with individual pairs of properties. They are
|
||||
// called on various occasions, and need to check whether the invocation
|
||||
// has been caused by a standalone base type's property change
|
||||
// (switching source of truth to role ID) or as a side-effect of a sync.
|
||||
void syncSortRoleProperties();
|
||||
void syncFilterRoleProperties();
|
||||
|
||||
private:
|
||||
// conveniently, role ID is the default source of truth, turning it into
|
||||
// zero-initialization.
|
||||
enum SourceOfTruthForRoleProperty : bool {
|
||||
SourceOfTruthIsRoleID = false,
|
||||
SourceOfTruthIsRoleName = true,
|
||||
};
|
||||
|
||||
bool m_componentCompleted : 1;
|
||||
SourceOfTruthForRoleProperty m_sortRoleSourceOfTruth : 1;
|
||||
SourceOfTruthForRoleProperty m_filterRoleSourceOfTruth : 1;
|
||||
bool m_sortRoleGuard : 1;
|
||||
bool m_filterRoleGuard : 1;
|
||||
// default role name corresponds to the standard mapping of the default Qt::DisplayRole in QAbstractItemModel::roleNames
|
||||
QString m_sortRoleName{QStringLiteral("display")};
|
||||
QString m_filterRoleName{QStringLiteral("display")};
|
||||
QString m_filterString;
|
||||
QJSValue m_filterRowCallback;
|
||||
QJSValue m_filterColumnCallback;
|
||||
QHash<QString, int> m_roleIds;
|
||||
std::array<QMetaObject::Connection, 3> m_sourceModelConnections;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <KColumnHeadersModel>
|
||||
#include <KNumberModel>
|
||||
|
||||
struct KColumnHeadersModelForeign {
|
||||
Q_GADGET
|
||||
QML_NAMED_ELEMENT(KColumnHeadersModel)
|
||||
QML_FOREIGN(KColumnHeadersModel)
|
||||
};
|
||||
|
||||
struct KNumberModelForeign {
|
||||
Q_GADGET
|
||||
QML_NAMED_ELEMENT(KNumberModel)
|
||||
QML_FOREIGN(KNumberModel)
|
||||
};
|
||||
Reference in New Issue
Block a user