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,45 @@
|
||||
add_executable(proxymodeltestapp)
|
||||
|
||||
target_sources(proxymodeltestapp PRIVATE
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
|
||||
breadcrumbdirectionwidget.cpp
|
||||
breadcrumbnavigationwidget.cpp
|
||||
breadcrumbswidget.cpp
|
||||
checkablewidget.cpp
|
||||
descendantpmwidget.cpp
|
||||
dynamictreewidget.cpp
|
||||
kidentityproxymodelwidget.cpp
|
||||
kreparentingproxymodel.cpp
|
||||
lessthanwidget.cpp
|
||||
matchcheckingwidget.cpp
|
||||
modelcommanderwidget.cpp
|
||||
proxyitemselectionwidget.cpp
|
||||
proxymodeltestwidget.cpp
|
||||
selectionpmwidget.cpp
|
||||
# statesaverwidget.cpp
|
||||
)
|
||||
|
||||
if (TARGET Qt6::Qml)
|
||||
target_sources(proxymodeltestapp PRIVATE
|
||||
reparentingpmwidget.cpp
|
||||
scriptablereparentingwidget.cpp
|
||||
)
|
||||
target_link_libraries(proxymodeltestapp Qt6::Qml)
|
||||
endif()
|
||||
|
||||
if (TARGET Qt6::QuickWidgets)
|
||||
target_sources(proxymodeltestapp PRIVATE
|
||||
selectioninqmlwidget.cpp
|
||||
descendantqmltree.cpp
|
||||
)
|
||||
target_link_libraries(proxymodeltestapp Qt6::QuickWidgets)
|
||||
target_compile_definitions(proxymodeltestapp PRIVATE -DSRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
target_link_libraries(proxymodeltestapp
|
||||
KF6::ItemModels
|
||||
proxymodeltestsuite
|
||||
Qt6::Widgets
|
||||
)
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "breadcrumbdirectionwidget.h"
|
||||
|
||||
#include <dynamictreemodel.h>
|
||||
#include <kbreadcrumbselectionmodel.h>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QHBoxLayout>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
BreadcrumbDirectionWidget::BreadcrumbDirectionWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
|
||||
ModelInsertCommand ins(rootModel);
|
||||
ins.setStartRow(0);
|
||||
ins.interpret(
|
||||
QLatin1String("- 1"
|
||||
"- 2"
|
||||
"- - 3"
|
||||
"- - 3"
|
||||
"- - - 4"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 4"
|
||||
"- - 5"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 5"
|
||||
"- 6"
|
||||
"- 7"
|
||||
"- - 8"
|
||||
"- - - 9"
|
||||
"- - - 10"
|
||||
"- - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - - - - 9"
|
||||
"- - - - - - - - 10"
|
||||
"- - - - - - - - 9"
|
||||
"- - - - - - - 10"
|
||||
"- 20"
|
||||
"- 21"));
|
||||
ins.doCommand();
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *splitter1 = new QSplitter(Qt::Vertical, this);
|
||||
layout->addWidget(splitter1);
|
||||
QSplitter *splitter2 = new QSplitter(splitter1);
|
||||
QSplitter *splitter3 = new QSplitter(splitter1);
|
||||
|
||||
QTreeView *view1 = new QTreeView(splitter2);
|
||||
view1->setModel(rootModel);
|
||||
view1->expandAll();
|
||||
view1->viewport()->setBackgroundRole(QPalette::Button);
|
||||
QTreeView *view2 = new QTreeView(splitter2);
|
||||
view2->setModel(rootModel);
|
||||
view2->expandAll();
|
||||
view2->viewport()->installEventFilter(this);
|
||||
QTreeView *view3 = new QTreeView(splitter3);
|
||||
view3->setModel(rootModel);
|
||||
view3->expandAll();
|
||||
QTreeView *view4 = new QTreeView(splitter3);
|
||||
view4->setModel(rootModel);
|
||||
view4->expandAll();
|
||||
view4->viewport()->installEventFilter(this);
|
||||
view4->viewport()->setBackgroundRole(QPalette::Button);
|
||||
|
||||
KBreadcrumbSelectionModel *breadcrumbSelection1 = new KBreadcrumbSelectionModel(view2->selectionModel(), this);
|
||||
view1->setSelectionModel(breadcrumbSelection1);
|
||||
|
||||
KBreadcrumbSelectionModel *breadcrumbSelection2 =
|
||||
new KBreadcrumbSelectionModel(view3->selectionModel(), KBreadcrumbSelectionModel::MakeBreadcrumbSelectionInOther, this);
|
||||
view4->setSelectionModel(breadcrumbSelection2);
|
||||
}
|
||||
|
||||
bool BreadcrumbDirectionWidget::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick || e->type() == QEvent::MouseButtonRelease) {
|
||||
return true;
|
||||
}
|
||||
return QObject::eventFilter(o, e);
|
||||
}
|
||||
|
||||
#include "moc_breadcrumbdirectionwidget.cpp"
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef BREADCRUMBDIRECTIONWIDGET_H
|
||||
#define BREADCRUMBDIRECTIONWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class BreadcrumbDirectionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BreadcrumbDirectionWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "breadcrumbnavigationwidget.h"
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QListView>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "kbreadcrumbselectionmodel.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
|
||||
#define SON(object) object->setObjectName(QStringLiteral(#object))
|
||||
|
||||
CurrentItemLabel::CurrentItemLabel(QAbstractItemModel *model, QWidget *parent, Qt::WindowFlags f)
|
||||
: QLabel(parent, f)
|
||||
, m_model(model)
|
||||
{
|
||||
connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(dataChanged(QModelIndex, QModelIndex)));
|
||||
connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int)));
|
||||
connect(model, SIGNAL(rowsRemoved(QModelIndex, int, int)), SLOT(rowsRemoved(QModelIndex, int, int)));
|
||||
connect(model, SIGNAL(modelReset()), SLOT(modelReset()));
|
||||
|
||||
if (!m_model->hasChildren()) {
|
||||
setText(QStringLiteral("No selection"));
|
||||
}
|
||||
}
|
||||
|
||||
void CurrentItemLabel::dataChanged(const QModelIndex &, const QModelIndex &)
|
||||
{
|
||||
setText(m_model->index(0, 0).data().toString());
|
||||
}
|
||||
|
||||
void CurrentItemLabel::rowsInserted(const QModelIndex &, int, int)
|
||||
{
|
||||
setText(m_model->index(0, 0).data().toString());
|
||||
}
|
||||
|
||||
void CurrentItemLabel::rowsRemoved(const QModelIndex &, int, int)
|
||||
{
|
||||
if (!m_model->hasChildren()) {
|
||||
setText(QStringLiteral("No selection"));
|
||||
return;
|
||||
}
|
||||
setText(m_model->index(0, 0).data().toString());
|
||||
}
|
||||
|
||||
void CurrentItemLabel::modelReset()
|
||||
{
|
||||
if (!m_model->hasChildren()) {
|
||||
setText(QStringLiteral("No selection"));
|
||||
}
|
||||
setText(m_model->index(0, 0).data().toString());
|
||||
}
|
||||
|
||||
KBreadcrumbNavigationProxyModel::KBreadcrumbNavigationProxyModel(QItemSelectionModel *selectionModel, QObject *parent)
|
||||
: KSelectionProxyModel(selectionModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant KBreadcrumbNavigationProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (rowCount() > 2 && index.row() == 0 && role == Qt::DisplayRole) {
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
QStringList dataList;
|
||||
while (sourceIndex.isValid()) {
|
||||
dataList.prepend(sourceIndex.data().toString());
|
||||
sourceIndex = sourceIndex.parent();
|
||||
}
|
||||
return dataList.join(QLatin1String(" > "));
|
||||
}
|
||||
return KSelectionProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
void KBreadcrumbNavigationProxyModel::setShowHiddenAscendantData(bool showHiddenAscendantData)
|
||||
{
|
||||
m_showHiddenAscendantData = showHiddenAscendantData;
|
||||
}
|
||||
|
||||
bool KBreadcrumbNavigationProxyModel::showHiddenAscendantData() const
|
||||
{
|
||||
return m_showHiddenAscendantData;
|
||||
}
|
||||
|
||||
KNavigatingProxyModel::KNavigatingProxyModel(QItemSelectionModel *selectionModel, QObject *parent)
|
||||
: KSelectionProxyModel(selectionModel, parent)
|
||||
, m_selectionModel(selectionModel)
|
||||
{
|
||||
}
|
||||
|
||||
void KNavigatingProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(navigationSelectionChanged(QItemSelection, QItemSelection)));
|
||||
|
||||
KSelectionProxyModel::setSourceModel(sourceModel);
|
||||
updateNavigation();
|
||||
}
|
||||
|
||||
void KNavigatingProxyModel::navigationSelectionChanged(const QItemSelection &, const QItemSelection &)
|
||||
{
|
||||
updateNavigation();
|
||||
}
|
||||
|
||||
void KNavigatingProxyModel::updateNavigation()
|
||||
{
|
||||
if (!sourceModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_selectionModel->selection().isEmpty()) {
|
||||
setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
QModelIndex top = sourceModel()->index(0, 0);
|
||||
QModelIndex bottom = sourceModel()->index(sourceModel()->rowCount() - 1, 0);
|
||||
|
||||
disconnect(m_selectionModel,
|
||||
SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
|
||||
this,
|
||||
SLOT(navigationSelectionChanged(QItemSelection, QItemSelection)));
|
||||
m_selectionModel->select(QItemSelection(top, bottom), QItemSelectionModel::Select);
|
||||
connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(navigationSelectionChanged(QItemSelection, QItemSelection)));
|
||||
} else if (filterBehavior() != KSelectionProxyModel::ChildrenOfExactSelection) {
|
||||
setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection);
|
||||
}
|
||||
}
|
||||
|
||||
void KNavigatingProxyModel::modelReset()
|
||||
{
|
||||
updateNavigation();
|
||||
}
|
||||
|
||||
QVariant KNavigatingProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole && sourceModel()->hasChildren(mapToSource(index))) {
|
||||
return QString("+ " + KSelectionProxyModel::data(index, role).toString());
|
||||
}
|
||||
return KSelectionProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
KForwardingItemSelectionModel::KForwardingItemSelectionModel(QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent)
|
||||
: QItemSelectionModel(model, parent)
|
||||
, m_selectionModel(selectionModel)
|
||||
, m_direction(Forward)
|
||||
{
|
||||
Q_ASSERT(model == selectionModel->model());
|
||||
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(navigationSelectionChanged(QItemSelection, QItemSelection)));
|
||||
}
|
||||
|
||||
KForwardingItemSelectionModel::KForwardingItemSelectionModel(QAbstractItemModel *model,
|
||||
QItemSelectionModel *selectionModel,
|
||||
Direction direction,
|
||||
QObject *parent)
|
||||
: QItemSelectionModel(model, parent)
|
||||
, m_selectionModel(selectionModel)
|
||||
, m_direction(direction)
|
||||
{
|
||||
Q_ASSERT(model == selectionModel->model());
|
||||
if (m_direction == Forward) {
|
||||
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(navigationSelectionChanged(QItemSelection, QItemSelection)));
|
||||
}
|
||||
}
|
||||
|
||||
void KForwardingItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
if (m_direction == Reverse) {
|
||||
m_selectionModel->select(index, command);
|
||||
} else {
|
||||
QItemSelectionModel::select(index, command);
|
||||
}
|
||||
}
|
||||
|
||||
void KForwardingItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
if (m_direction == Reverse) {
|
||||
m_selectionModel->select(selection, command);
|
||||
} else {
|
||||
QItemSelectionModel::select(selection, command);
|
||||
}
|
||||
}
|
||||
|
||||
void KForwardingItemSelectionModel::navigationSelectionChanged(const QItemSelection &selected, const QItemSelection &)
|
||||
{
|
||||
select(selected, ClearAndSelect);
|
||||
}
|
||||
|
||||
BreadcrumbNavigationWidget::BreadcrumbNavigationWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
DynamicTreeWidget *dynamicTree = new DynamicTreeWidget(rootModel, splitter);
|
||||
dynamicTree->treeView()->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
dynamicTree->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- - - 3"
|
||||
"- - - - 4"
|
||||
"- - - - - 5"
|
||||
"- - 2"
|
||||
"- 6"
|
||||
"- 6"
|
||||
"- 6"
|
||||
"- - 7"
|
||||
"- - - 8"
|
||||
"- - - 8"
|
||||
"- - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - 8"
|
||||
"- - - 8"
|
||||
"- - 8"
|
||||
"- 16"
|
||||
"- - 17"
|
||||
"- - - 18"
|
||||
"- - - - 19"
|
||||
"- - - - - 20"));
|
||||
|
||||
QList<QItemSelectionModel *> selectionModelList;
|
||||
|
||||
QSplitter *vSplitter = new QSplitter(Qt::Vertical, splitter);
|
||||
|
||||
QItemSelectionModel *rootSelectionModel = new QItemSelectionModel(rootModel, this);
|
||||
SON(rootSelectionModel);
|
||||
|
||||
dynamicTree->treeView()->setSelectionModel(rootSelectionModel);
|
||||
|
||||
KBreadcrumbSelectionModel *breadcrumbOnlyProxySelector2 =
|
||||
new KBreadcrumbSelectionModel(rootSelectionModel, KBreadcrumbSelectionModel::MakeBreadcrumbSelectionInOther, this);
|
||||
SON(breadcrumbOnlyProxySelector2);
|
||||
breadcrumbOnlyProxySelector2->setActualSelectionIncluded(false);
|
||||
|
||||
KBreadcrumbNavigationProxyModel *breadcrumbNavigationModel = new KBreadcrumbNavigationProxyModel(breadcrumbOnlyProxySelector2, this);
|
||||
SON(breadcrumbNavigationModel);
|
||||
breadcrumbNavigationModel->setSourceModel(rootModel);
|
||||
breadcrumbNavigationModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QListView *breadcrumbView = new QListView(vSplitter);
|
||||
// SON(breadcrumbNavigationModel);
|
||||
breadcrumbView->setModel(breadcrumbNavigationModel);
|
||||
|
||||
// This shouldn't operate on rootSelectionModel. It should operate on oneway instead?
|
||||
KLinkItemSelectionModel *breadcrumbViewSelectionModel = new KLinkItemSelectionModel(breadcrumbNavigationModel, rootSelectionModel, this);
|
||||
SON(breadcrumbViewSelectionModel);
|
||||
|
||||
KForwardingItemSelectionModel *oneway2 =
|
||||
new KForwardingItemSelectionModel(breadcrumbNavigationModel, breadcrumbViewSelectionModel, KForwardingItemSelectionModel::Reverse);
|
||||
SON(oneway2);
|
||||
|
||||
breadcrumbView->setSelectionModel(oneway2);
|
||||
|
||||
KSelectionProxyModel *currentItemSelectionModel = new KSelectionProxyModel(rootSelectionModel, this);
|
||||
currentItemSelectionModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
currentItemSelectionModel->setSourceModel(rootModel);
|
||||
SON(currentItemSelectionModel);
|
||||
|
||||
new CurrentItemLabel(currentItemSelectionModel, vSplitter);
|
||||
|
||||
QListView *selectionView = new QListView(vSplitter);
|
||||
|
||||
// Need a one-way connection from rootSelectionModel to rootSelectionModel2
|
||||
|
||||
KForwardingItemSelectionModel *oneway = new KForwardingItemSelectionModel(rootModel, rootSelectionModel);
|
||||
|
||||
KNavigatingProxyModel *navigatingProxyModel = new KNavigatingProxyModel(oneway, this);
|
||||
SON(navigatingProxyModel);
|
||||
navigatingProxyModel->setSourceModel(rootModel);
|
||||
selectionView->setModel(navigatingProxyModel);
|
||||
|
||||
KLinkItemSelectionModel *selectedChildrenSelectionModel = new KLinkItemSelectionModel(navigatingProxyModel, rootSelectionModel, this);
|
||||
|
||||
selectionView->setSelectionModel(selectedChildrenSelectionModel);
|
||||
}
|
||||
|
||||
#include "moc_breadcrumbnavigationwidget.cpp"
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef BREADCRUMBNAVIGATION_WIDGET_H
|
||||
#define BREADCRUMBNAVIGATION_WIDGET_H
|
||||
|
||||
#include "klinkitemselectionmodel.h"
|
||||
#include <kselectionproxymodel.h>
|
||||
|
||||
#include <QItemSelection>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
class CurrentItemLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CurrentItemLabel(QAbstractItemModel *model, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
private Q_SLOTS:
|
||||
void rowsInserted(const QModelIndex &parent, int start, int end);
|
||||
void rowsRemoved(const QModelIndex &parent, int start, int end);
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
void modelReset();
|
||||
|
||||
private:
|
||||
QAbstractItemModel *m_model;
|
||||
};
|
||||
|
||||
class KBreadcrumbNavigationProxyModel : public KSelectionProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KBreadcrumbNavigationProxyModel(QItemSelectionModel *selectionModel, QObject *parent = nullptr);
|
||||
|
||||
void setShowHiddenAscendantData(bool showHiddenAscendantData);
|
||||
bool showHiddenAscendantData() const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
bool m_showHiddenAscendantData;
|
||||
};
|
||||
|
||||
class KNavigatingProxyModel : public KSelectionProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KNavigatingProxyModel(QItemSelectionModel *selectionModel, QObject *parent = nullptr);
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void modelReset();
|
||||
void updateNavigation();
|
||||
void navigationSelectionChanged(const QItemSelection &, const QItemSelection &);
|
||||
|
||||
private:
|
||||
private:
|
||||
using KSelectionProxyModel::setFilterBehavior;
|
||||
|
||||
QItemSelectionModel *m_selectionModel;
|
||||
};
|
||||
|
||||
class KForwardingItemSelectionModel : public QItemSelectionModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Direction {
|
||||
Forward,
|
||||
Reverse,
|
||||
};
|
||||
KForwardingItemSelectionModel(QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent = nullptr);
|
||||
KForwardingItemSelectionModel(QAbstractItemModel *model, QItemSelectionModel *selectionModel, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
void select(const QModelIndex &index, SelectionFlags command) override;
|
||||
void select(const QItemSelection &selection, SelectionFlags command) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void navigationSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
|
||||
private:
|
||||
QItemSelectionModel *m_selectionModel;
|
||||
Direction m_direction;
|
||||
};
|
||||
|
||||
class BreadcrumbNavigationWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BreadcrumbNavigationWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
};
|
||||
|
||||
#endif
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "breadcrumbswidget.h"
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QListView>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "kbreadcrumbselectionmodel.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
|
||||
MultiSelectionModel::MultiSelectionModel(QAbstractItemModel *model, QList<QItemSelectionModel *> selectionModels, QObject *parent)
|
||||
: QItemSelectionModel(model, parent)
|
||||
, m_selectionModels(selectionModels)
|
||||
{
|
||||
}
|
||||
|
||||
void MultiSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
for (QItemSelectionModel *selectionModel : std::as_const(m_selectionModels)) {
|
||||
selectionModel->select(index, command);
|
||||
}
|
||||
QItemSelectionModel::select(index, command);
|
||||
}
|
||||
|
||||
void MultiSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
|
||||
{
|
||||
for (QItemSelectionModel *selectionModel : std::as_const(m_selectionModels)) {
|
||||
selectionModel->select(selection, command);
|
||||
}
|
||||
QItemSelectionModel::select(selection, command);
|
||||
}
|
||||
|
||||
BreadcrumbsWidget::BreadcrumbsWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
DynamicTreeWidget *dynamicTree = new DynamicTreeWidget(rootModel, splitter);
|
||||
dynamicTree->treeView()->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
dynamicTree->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- - - 3"
|
||||
"- - - - 4"
|
||||
"- - - - - 5"
|
||||
"- - 2"
|
||||
"- 6"
|
||||
"- 6"
|
||||
"- 6"
|
||||
"- - 7"
|
||||
"- - - 8"
|
||||
"- - - 8"
|
||||
"- - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - 8"
|
||||
"- - - 8"
|
||||
"- - 8"
|
||||
"- 16"
|
||||
"- - 17"
|
||||
"- - - 18"
|
||||
"- - - - 19"
|
||||
"- - - - - 20"));
|
||||
|
||||
QList<QItemSelectionModel *> selectionModelList;
|
||||
QItemSelectionModel *fullBreadcrumbSelectionModel = new QItemSelectionModel(rootModel, this);
|
||||
|
||||
KBreadcrumbSelectionModel *fullBreadcrumbProxySelector = new KBreadcrumbSelectionModel(fullBreadcrumbSelectionModel, this);
|
||||
selectionModelList << fullBreadcrumbProxySelector;
|
||||
|
||||
KSelectionProxyModel *fullBreadCrumbSelectionProxyModel = new KSelectionProxyModel(fullBreadcrumbSelectionModel, this);
|
||||
fullBreadCrumbSelectionProxyModel->setSourceModel(rootModel);
|
||||
fullBreadCrumbSelectionProxyModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QListView *fullBreadcrumbProxyView = new QListView(splitter);
|
||||
fullBreadcrumbProxyView->setModel(fullBreadCrumbSelectionProxyModel);
|
||||
|
||||
QItemSelectionModel *breadcrumbOnlySelectionModel = new QItemSelectionModel(rootModel, this);
|
||||
|
||||
KBreadcrumbSelectionModel *breadcrumbOnlyProxySelector = new KBreadcrumbSelectionModel(breadcrumbOnlySelectionModel, this);
|
||||
breadcrumbOnlyProxySelector->setActualSelectionIncluded(false);
|
||||
selectionModelList << breadcrumbOnlyProxySelector;
|
||||
|
||||
KSelectionProxyModel *breadcrumbOnlySelectionProxyModel = new KSelectionProxyModel(breadcrumbOnlySelectionModel, this);
|
||||
breadcrumbOnlySelectionProxyModel->setSourceModel(rootModel);
|
||||
breadcrumbOnlySelectionProxyModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QListView *breadcrumbOnlyProxyView = new QListView(splitter);
|
||||
breadcrumbOnlyProxyView->setModel(breadcrumbOnlySelectionProxyModel);
|
||||
|
||||
int selectionDepth = 2;
|
||||
|
||||
QItemSelectionModel *thisAndAscendantsSelectionModel = new QItemSelectionModel(rootModel, this);
|
||||
|
||||
KBreadcrumbSelectionModel *thisAndAscendantsProxySelector = new KBreadcrumbSelectionModel(thisAndAscendantsSelectionModel, this);
|
||||
thisAndAscendantsProxySelector->setBreadcrumbLength(selectionDepth);
|
||||
selectionModelList << thisAndAscendantsProxySelector;
|
||||
|
||||
KSelectionProxyModel *thisAndAscendantsSelectionProxyModel = new KSelectionProxyModel(thisAndAscendantsSelectionModel, this);
|
||||
thisAndAscendantsSelectionProxyModel->setSourceModel(rootModel);
|
||||
thisAndAscendantsSelectionProxyModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QListView *thisAndAscendantsProxyView = new QListView(splitter);
|
||||
thisAndAscendantsProxyView->setModel(thisAndAscendantsSelectionProxyModel);
|
||||
|
||||
QItemSelectionModel *ascendantsOnlySelectionModel = new QItemSelectionModel(rootModel, this);
|
||||
|
||||
KBreadcrumbSelectionModel *ascendantsOnlyProxySelector = new KBreadcrumbSelectionModel(ascendantsOnlySelectionModel, this);
|
||||
ascendantsOnlyProxySelector->setActualSelectionIncluded(false);
|
||||
ascendantsOnlyProxySelector->setBreadcrumbLength(selectionDepth);
|
||||
selectionModelList << ascendantsOnlyProxySelector;
|
||||
|
||||
KSelectionProxyModel *ascendantsOnlySelectionProxyModel = new KSelectionProxyModel(ascendantsOnlySelectionModel, this);
|
||||
ascendantsOnlySelectionProxyModel->setSourceModel(rootModel);
|
||||
ascendantsOnlySelectionProxyModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QListView *ascendantsOnlyProxyView = new QListView(splitter);
|
||||
ascendantsOnlyProxyView->setModel(ascendantsOnlySelectionProxyModel);
|
||||
|
||||
MultiSelectionModel *multiSelectionModel = new MultiSelectionModel(rootModel, selectionModelList, this);
|
||||
dynamicTree->treeView()->setSelectionModel(multiSelectionModel);
|
||||
}
|
||||
|
||||
#include "moc_breadcrumbswidget.cpp"
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef BREADCRUMBS_WIDGET_H
|
||||
#define BREADCRUMBS_WIDGET_H
|
||||
|
||||
#include <QItemSelection>
|
||||
#include <QWidget>
|
||||
#include <kselectionproxymodel.h>
|
||||
|
||||
#include "klinkitemselectionmodel.h"
|
||||
|
||||
class MultiSelectionModel : public QItemSelectionModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MultiSelectionModel(QAbstractItemModel *model, QList<QItemSelectionModel *> selectionModels, QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
void select(const QModelIndex &index, SelectionFlags command) override;
|
||||
void select(const QItemSelection &selection, SelectionFlags command) override;
|
||||
|
||||
private:
|
||||
QList<QItemSelectionModel *> m_selectionModels;
|
||||
};
|
||||
|
||||
class BreadcrumbsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BreadcrumbsWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "checkablewidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include <kcheckableproxymodel.h>
|
||||
#include <kselectionproxymodel.h>
|
||||
|
||||
CheckableWidget::CheckableWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *vSplitter = new QSplitter(this);
|
||||
layout->addWidget(vSplitter);
|
||||
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
|
||||
ModelInsertCommand *insert = new ModelInsertCommand(rootModel, this);
|
||||
insert->setStartRow(0);
|
||||
insert->interpret(
|
||||
QLatin1String("- 1"
|
||||
"- 1"
|
||||
"- 1"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- 1"
|
||||
"- 1"
|
||||
"- 1"
|
||||
"- - 2"
|
||||
"- - - 3"
|
||||
"- - - - 4"
|
||||
"- - - - 4"
|
||||
"- - - 3"
|
||||
"- - - 3"
|
||||
"- - - 3"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- - 2"
|
||||
"- 1"
|
||||
"- 1"));
|
||||
insert->doCommand();
|
||||
|
||||
QItemSelectionModel *checkModel = new QItemSelectionModel(rootModel, this);
|
||||
KCheckableProxyModel *checkable = new KCheckableProxyModel(this);
|
||||
checkable->setSourceModel(rootModel);
|
||||
checkable->setSelectionModel(checkModel);
|
||||
|
||||
QTreeView *tree1 = new QTreeView(vSplitter);
|
||||
tree1->setModel(checkable);
|
||||
tree1->expandAll();
|
||||
|
||||
KSelectionProxyModel *selectionProxy = new KSelectionProxyModel(checkModel, this);
|
||||
selectionProxy->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
selectionProxy->setSourceModel(rootModel);
|
||||
|
||||
QTreeView *tree2 = new QTreeView(vSplitter);
|
||||
tree2->setModel(selectionProxy);
|
||||
}
|
||||
|
||||
#include "moc_checkablewidget.cpp"
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef CHECKABLEWIDGET_H
|
||||
#define CHECKABLEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class CheckableWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CheckableWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
};
|
||||
|
||||
#endif
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "descendantpmwidget.h"
|
||||
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "kdescendantsproxymodel.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "modeleventlogger.h"
|
||||
|
||||
DescendantProxyModelWidget::DescendantProxyModelWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *vSplitter = new QSplitter(this);
|
||||
layout->addWidget(vSplitter);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *dynTreeWidget = new DynamicTreeWidget(m_rootModel, vSplitter);
|
||||
|
||||
dynTreeWidget->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- 2"
|
||||
"- - 3"
|
||||
"- - 3"
|
||||
"- - - 4"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 4"
|
||||
"- - 5"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 5"
|
||||
"- 6"
|
||||
"- 7"
|
||||
"- - 8"
|
||||
"- - - 9"
|
||||
"- - - 10"
|
||||
"- - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - - - - 9"
|
||||
"- - - - - - - - 10"
|
||||
"- - - - - - - - 9"
|
||||
"- - - - - - - 10"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - 10"
|
||||
"- - 11"
|
||||
"- - 12"
|
||||
"- 13"
|
||||
"- 14"
|
||||
"- 15"
|
||||
"- - 16"
|
||||
"- - - 17"
|
||||
"- - - 18"
|
||||
"- 19"
|
||||
"- 20"
|
||||
"- 21"));
|
||||
|
||||
m_eventLogger = new ModelEventLogger(m_rootModel, this);
|
||||
|
||||
m_descProxyModel = new KDescendantsProxyModel(this);
|
||||
m_descProxyModel->setSourceModel(m_rootModel);
|
||||
|
||||
// KDescendantsProxyModel *descProxyModel2 = new KDescendantsProxyModel(this);
|
||||
// descProxyModel2->setSourceModel(m_rootModel);
|
||||
// descProxyModel2->setDisplayAncestorData(true);
|
||||
|
||||
// QTreeView *treeview = new QTreeView( vSplitter );
|
||||
// treeview->setModel(m_rootModel);
|
||||
// treeview->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
m_descView = new QTreeView(vSplitter);
|
||||
m_descView->setModel(m_descProxyModel);
|
||||
|
||||
// QTreeView *descView2 = new QTreeView( vSplitter );
|
||||
// descView2->setModel(descProxyModel2);
|
||||
|
||||
// QWidget *w = new QWidget(vSplitter);
|
||||
// QVBoxLayout *vLayout = new QVBoxLayout(w);
|
||||
// QTreeView *matchView = new QTreeView(w);
|
||||
// matchView->setModel(m_selectionProxyModel);
|
||||
// m_lineEdit = new QLineEdit(w);
|
||||
// connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(doMatch(QString)));
|
||||
// connect(m_descView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(refreshMatch()));
|
||||
|
||||
// vLayout->addWidget(m_lineEdit);
|
||||
// vLayout->addWidget(matchView);
|
||||
}
|
||||
|
||||
DescendantProxyModelWidget::~DescendantProxyModelWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void DescendantProxyModelWidget::doMatch(const QString &matchData)
|
||||
{
|
||||
Q_UNUSED(matchData);
|
||||
#if 0
|
||||
m_itemSelectionModel->clearSelection();
|
||||
|
||||
if (matchData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex start = m_descView->currentIndex();
|
||||
|
||||
if (!start.isValid()) {
|
||||
start = m_descProxyModel->index(0, 0);
|
||||
}
|
||||
|
||||
// TODO: get from user.
|
||||
int hits = -1;
|
||||
|
||||
QModelIndexList matches = m_descProxyModel->match(start, Qt::DisplayRole, matchData, hits, Qt::MatchContains);
|
||||
|
||||
Q_FOREACH (const QModelIndex &matchingIndex, matches) {
|
||||
m_itemSelectionModel->select(matchingIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DescendantProxyModelWidget::refreshMatch()
|
||||
{
|
||||
doMatch(m_lineEdit->text());
|
||||
}
|
||||
|
||||
#include "moc_descendantpmwidget.cpp"
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef DESCENDANTPM_WIDGET_H
|
||||
#define DESCENDANTPM_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class DynamicTreeModel;
|
||||
class QTreeView;
|
||||
class QLineEdit;
|
||||
class QItemSelectionModel;
|
||||
|
||||
class KDescendantsProxyModel;
|
||||
class KSelectionProxyModel;
|
||||
|
||||
class ModelEventLogger;
|
||||
|
||||
class DescendantProxyModelWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DescendantProxyModelWidget(QWidget *parent = nullptr);
|
||||
~DescendantProxyModelWidget() override;
|
||||
|
||||
protected Q_SLOTS:
|
||||
void doMatch(const QString &matchData);
|
||||
void refreshMatch();
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
ModelEventLogger *m_eventLogger;
|
||||
KDescendantsProxyModel *m_descProxyModel;
|
||||
KSelectionProxyModel *m_selectionProxyModel;
|
||||
QItemSelectionModel *m_itemSelectionModel;
|
||||
QTreeView *m_descView;
|
||||
QLineEdit *m_lineEdit;
|
||||
};
|
||||
|
||||
#endif
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "descendantqmltree.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
#include <QQuickWidget>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
|
||||
DescendantQmlTreeWidget::DescendantQmlTreeWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
new DynamicTreeWidget(m_rootModel, splitter);
|
||||
|
||||
qmlRegisterType<KSelectionProxyModel>("KF5ItemModels", 1, 0, "SelectionProxyModel");
|
||||
|
||||
QQuickWidget *quickView = new QQuickWidget(splitter);
|
||||
|
||||
quickView->engine()->rootContext()->setContextProperty(QStringLiteral("_model"), m_rootModel);
|
||||
|
||||
quickView->setSource(QUrl::fromLocalFile(QLatin1String(SRC_DIR "/tree.qml")));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef DESCENDANTQMLTREE_H
|
||||
#define DESCENDANTQMLTREE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTreeView;
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
class DescendantQmlTreeWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
DescendantQmlTreeWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "dynamictreewidget.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QTabWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
|
||||
static const char *const treePredefinesNames[] = {"Flat List", "Straight Line Tree", "Dragon Teeth 1", "Dragon Teeth 2", "Random Tree 1"};
|
||||
|
||||
static const char *const treePredefinesContent[] = {
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1"
|
||||
" - 1",
|
||||
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - - - - - 1"
|
||||
" - - - - - - 1"
|
||||
" - - - - - - - 1"
|
||||
" - - - - - - - - 1"
|
||||
" - - - - - - - - - 1"
|
||||
" - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - - - - - 1"
|
||||
" - - - - - - - - - - - - - - - - 1",
|
||||
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1",
|
||||
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - - - - - 1"
|
||||
" - 1"
|
||||
" - - 1"
|
||||
" - - - 1"
|
||||
" - - - - 1"
|
||||
" - - - - - 1",
|
||||
|
||||
" - 1"
|
||||
" - 2"
|
||||
" - - 3"
|
||||
" - - - 4"
|
||||
" - 5"
|
||||
" - 6"
|
||||
" - 7"
|
||||
" - - 8"
|
||||
" - - - 9"
|
||||
" - - - 10"
|
||||
" - - - - 11"
|
||||
" - - - 12"
|
||||
" - - - - 13"
|
||||
" - 14"
|
||||
" - 15"};
|
||||
|
||||
static const char *const insertSubTreePredefinesNames[] = {"Flat List", "Straight Line Tree", "Dragon Teeth 1", "Dragon Teeth 2", "Random Tree 1"};
|
||||
|
||||
static const char *const insertSubTreePredefinesContent[] = {
|
||||
" - 1\n"
|
||||
" - 1\n"
|
||||
" - 1\n"
|
||||
" - 1\n",
|
||||
|
||||
" - 1\n"
|
||||
" - - 1\n"
|
||||
" - - - 1\n"
|
||||
" - - - - 1\n",
|
||||
|
||||
" - 1\n"
|
||||
" - - 1\n"
|
||||
" - 1\n"
|
||||
" - - 1\n",
|
||||
|
||||
" - 1\n"
|
||||
" - - 1\n"
|
||||
" - - - 1\n"
|
||||
" - 1\n"
|
||||
" - - 1\n"
|
||||
" - - - 1\n",
|
||||
|
||||
" - 1\n"
|
||||
" - 2\n"
|
||||
" - - 3\n"
|
||||
" - - - 4\n"
|
||||
" - 5\n"};
|
||||
|
||||
DynamicTreeWidget::DynamicTreeWidget(DynamicTreeModel *rootModel, QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
, m_dynamicTreeModel(rootModel)
|
||||
{
|
||||
QTabWidget *tabWidget = new QTabWidget(this);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(tabWidget);
|
||||
|
||||
QWidget *editContainer = new QWidget(tabWidget);
|
||||
QVBoxLayout *editLayout = new QVBoxLayout(editContainer);
|
||||
|
||||
m_treePredefines = new QComboBox(editContainer);
|
||||
for (uint i = 0; i < sizeof treePredefinesNames / sizeof *treePredefinesNames; ++i) {
|
||||
m_treePredefines->addItem(*(treePredefinesNames + i), *(treePredefinesContent + i));
|
||||
}
|
||||
editLayout->addWidget(m_treePredefines);
|
||||
connect(m_treePredefines, &QComboBox::currentIndexChanged, this, &DynamicTreeWidget::setTreePredefine);
|
||||
|
||||
m_textEdit = new QPlainTextEdit(editContainer);
|
||||
editLayout->addWidget(m_textEdit);
|
||||
|
||||
QWidget *viewContainer = new QWidget(tabWidget);
|
||||
|
||||
QVBoxLayout *viewLayout = new QVBoxLayout(viewContainer);
|
||||
|
||||
m_treeView = new QTreeView(tabWidget);
|
||||
m_treeView->setModel(rootModel);
|
||||
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_treeView->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
m_treeView->setDragEnabled(true);
|
||||
m_treeView->setAcceptDrops(true);
|
||||
m_treeView->setDropIndicatorShown(true);
|
||||
|
||||
QPushButton *m_removeButton = new QPushButton(QStringLiteral("Remove"), tabWidget);
|
||||
|
||||
connect(m_removeButton, &QAbstractButton::clicked, this, &DynamicTreeWidget::removeSelected);
|
||||
|
||||
m_insertSubTreePredefines = new QComboBox(this);
|
||||
for (uint i = 0; i < sizeof insertSubTreePredefinesNames / sizeof *insertSubTreePredefinesNames; ++i) {
|
||||
m_insertSubTreePredefines->addItem(*(insertSubTreePredefinesNames + i), *(insertSubTreePredefinesContent + i));
|
||||
}
|
||||
editLayout->addWidget(m_insertSubTreePredefines);
|
||||
connect(m_insertSubTreePredefines, &QComboBox::currentIndexChanged, this, &DynamicTreeWidget::setInsertSubTreePredefine);
|
||||
|
||||
m_insertPatternTextEdit = new QPlainTextEdit(tabWidget);
|
||||
m_insertPatternTextEdit->setMaximumHeight(100);
|
||||
|
||||
m_insertChildren = new QRadioButton(QStringLiteral("Insert Children"), tabWidget);
|
||||
m_insertSiblingsAbove = new QRadioButton(QStringLiteral("Insert Siblings Above"), tabWidget);
|
||||
m_insertSiblingsBelow = new QRadioButton(QStringLiteral("Insert Siblings Below"), tabWidget);
|
||||
|
||||
m_insertChildren->setChecked(true);
|
||||
|
||||
QPushButton *m_insertButton = new QPushButton(QStringLiteral("Insert"), tabWidget);
|
||||
|
||||
connect(m_insertButton, &QAbstractButton::clicked, this, &DynamicTreeWidget::insertSelected);
|
||||
|
||||
QPushButton *m_resetButton = new QPushButton(QStringLiteral("Reset"), tabWidget);
|
||||
|
||||
connect(m_resetButton, &QAbstractButton::clicked, this, &DynamicTreeWidget::resetModel);
|
||||
|
||||
viewLayout->addWidget(m_treeView);
|
||||
|
||||
viewLayout->addWidget(m_removeButton);
|
||||
|
||||
viewLayout->addWidget(m_insertSubTreePredefines);
|
||||
viewLayout->addWidget(m_insertPatternTextEdit);
|
||||
viewLayout->addWidget(m_insertChildren);
|
||||
viewLayout->addWidget(m_insertSiblingsAbove);
|
||||
viewLayout->addWidget(m_insertSiblingsBelow);
|
||||
viewLayout->addWidget(m_insertButton);
|
||||
viewLayout->addWidget(m_resetButton);
|
||||
|
||||
tabWidget->addTab(editContainer, QStringLiteral("Edit"));
|
||||
tabWidget->addTab(viewContainer, QStringLiteral("View"));
|
||||
|
||||
tabWidget->setCurrentIndex(ViewTab);
|
||||
|
||||
connect(tabWidget, &QTabWidget::currentChanged, this, &DynamicTreeWidget::currentChanged);
|
||||
stringToModel(
|
||||
QLatin1String(" - 1"
|
||||
" - 2"
|
||||
" - - 3"
|
||||
" - - 4"
|
||||
" - - 5"
|
||||
" - 6"
|
||||
" - 7"
|
||||
" - - 8"
|
||||
" - - - 9"
|
||||
" - - - 10"
|
||||
" - - 11"
|
||||
" - - 12"
|
||||
" - 13"
|
||||
" - 14"
|
||||
" - 15"
|
||||
" - - 16"
|
||||
" - - - 17"
|
||||
" - - - 18"
|
||||
" - 19"
|
||||
" - 20"
|
||||
" - 21"));
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::setInitialTree(const QString &treeString)
|
||||
{
|
||||
stringToModel(treeString);
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::currentChanged(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case EditTab:
|
||||
m_textEdit->setPlainText(modelTreeToString(0, QModelIndex()));
|
||||
break;
|
||||
case ViewTab:
|
||||
if (m_textEdit->document()->isModified()) {
|
||||
stringToModel(m_textEdit->toPlainText());
|
||||
}
|
||||
m_textEdit->document()->setModified(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::stringToModel(const QString &treeString)
|
||||
{
|
||||
if (treeString.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_dynamicTreeModel->clear();
|
||||
ModelInsertCommand *command = new ModelInsertCommand(m_dynamicTreeModel, this);
|
||||
command->setStartRow(0);
|
||||
command->interpret(treeString);
|
||||
command->doCommand();
|
||||
m_treeView->expandAll();
|
||||
}
|
||||
|
||||
QString DynamicTreeWidget::modelTreeToString(int depth, const QModelIndex &parent)
|
||||
{
|
||||
QString result;
|
||||
QModelIndex idx;
|
||||
static const int column = 0;
|
||||
QString prefix;
|
||||
|
||||
for (int i = 0; i <= depth; ++i) {
|
||||
prefix.append(" -");
|
||||
}
|
||||
|
||||
for (int row = 0; row < m_dynamicTreeModel->rowCount(parent); ++row) {
|
||||
idx = m_dynamicTreeModel->index(row, column, parent);
|
||||
result.append(prefix + " " + idx.data().toString() + "\n");
|
||||
if (m_dynamicTreeModel->hasChildren(idx)) {
|
||||
result.append(modelTreeToString(depth + 1, idx));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::removeSelected()
|
||||
{
|
||||
QModelIndex parent;
|
||||
ModelRemoveCommand *removeCommand = new ModelRemoveCommand(m_dynamicTreeModel, this);
|
||||
QItemSelection selection = m_treeView->selectionModel()->selection();
|
||||
while (!selection.isEmpty()) {
|
||||
const QItemSelectionRange range = selection.takeFirst(); // The selection model will take care of updating persistent indexes.
|
||||
Q_ASSERT(range.isValid());
|
||||
qDebug() << range.parent() << range.top() << range.bottom();
|
||||
removeCommand->setAncestorRowNumbers(m_dynamicTreeModel->indexToPath(range.parent()));
|
||||
removeCommand->setStartRow(range.top());
|
||||
removeCommand->setEndRow(range.bottom());
|
||||
|
||||
qDebug() << m_dynamicTreeModel->indexToPath(range.parent());
|
||||
|
||||
removeCommand->doCommand();
|
||||
selection = m_treeView->selectionModel()->selection();
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::insertSelected()
|
||||
{
|
||||
const QModelIndexList selectedRows = m_treeView->selectionModel()->selectedRows();
|
||||
|
||||
if (selectedRows.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QModelIndex selectedRow = selectedRows.first();
|
||||
|
||||
ModelInsertCommand *ins = new ModelInsertCommand(m_dynamicTreeModel, this);
|
||||
if (m_insertChildren->isChecked()) {
|
||||
ins->setAncestorRowNumbers(m_dynamicTreeModel->indexToPath(selectedRow));
|
||||
ins->setStartRow(0);
|
||||
} else if (m_insertSiblingsAbove->isChecked()) {
|
||||
ins->setAncestorRowNumbers(m_dynamicTreeModel->indexToPath(selectedRow.parent()));
|
||||
ins->setStartRow(selectedRow.row());
|
||||
} else {
|
||||
Q_ASSERT(m_insertSiblingsBelow->isChecked());
|
||||
ins->setAncestorRowNumbers(m_dynamicTreeModel->indexToPath(selectedRow.parent()));
|
||||
ins->setStartRow(selectedRow.row() + 1);
|
||||
}
|
||||
ins->interpret(m_insertPatternTextEdit->toPlainText());
|
||||
ins->doCommand();
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::resetModel()
|
||||
{
|
||||
ModelResetCommand *resetCommand = new ModelResetCommand(m_dynamicTreeModel, this);
|
||||
|
||||
resetCommand->setInitialTree(m_insertPatternTextEdit->toPlainText().trimmed());
|
||||
resetCommand->doCommand();
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::setTreePredefine(int index)
|
||||
{
|
||||
stringToModel(m_treePredefines->itemData(index).toString());
|
||||
m_textEdit->setPlainText(modelTreeToString(0, QModelIndex()));
|
||||
}
|
||||
|
||||
void DynamicTreeWidget::setInsertSubTreePredefine(int index)
|
||||
{
|
||||
m_insertPatternTextEdit->setPlainText(m_insertSubTreePredefines->itemData(index).toString());
|
||||
}
|
||||
|
||||
#include "moc_dynamictreewidget.cpp"
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef DYNAMICTREEWIDGET_H
|
||||
#define DYNAMICTREEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
class QComboBox;
|
||||
class QPlainTextEdit;
|
||||
class QTreeView;
|
||||
class QRadioButton;
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
class DynamicTreeWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DynamicTreeWidget(DynamicTreeModel *rootModel, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
void setInitialTree(const QString &treeString);
|
||||
|
||||
DynamicTreeModel *model() const
|
||||
{
|
||||
return m_dynamicTreeModel;
|
||||
}
|
||||
QTreeView *treeView() const
|
||||
{
|
||||
return m_treeView;
|
||||
}
|
||||
QPlainTextEdit *textEdit() const
|
||||
{
|
||||
return m_textEdit;
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void currentChanged(int index);
|
||||
void setTreePredefine(int index);
|
||||
void setInsertSubTreePredefine(int index);
|
||||
|
||||
void removeSelected();
|
||||
void insertSelected();
|
||||
void resetModel();
|
||||
|
||||
private:
|
||||
void stringToModel(const QString &treeString);
|
||||
QString modelTreeToString(int depth, const QModelIndex &parent);
|
||||
|
||||
private:
|
||||
enum Tab {
|
||||
EditTab,
|
||||
ViewTab,
|
||||
};
|
||||
|
||||
QString m_initialString;
|
||||
DynamicTreeModel *m_dynamicTreeModel;
|
||||
QTreeView *m_treeView;
|
||||
QPlainTextEdit *m_textEdit;
|
||||
|
||||
QPlainTextEdit *m_insertPatternTextEdit;
|
||||
QRadioButton *m_insertChildren;
|
||||
QRadioButton *m_insertSiblingsAbove;
|
||||
QRadioButton *m_insertSiblingsBelow;
|
||||
QComboBox *m_insertSubTreePredefines;
|
||||
QComboBox *m_treePredefines;
|
||||
};
|
||||
|
||||
#endif
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kidentityproxymodelwidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QIdentityProxyModel>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
#include <dynamictreemodel.h>
|
||||
#include <kbreadcrumbselectionmodel.h>
|
||||
|
||||
#include "dynamictreewidget.h"
|
||||
|
||||
#include "modeltest.h"
|
||||
|
||||
KIdentityProxyModelWidget::KIdentityProxyModelWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *treeWidget = new DynamicTreeWidget(rootModel, splitter);
|
||||
treeWidget->setInitialTree(
|
||||
QLatin1String(" - 1"
|
||||
" - 2"
|
||||
" - - 3"
|
||||
" - - 4"
|
||||
" - - 5"
|
||||
" - 6"
|
||||
" - 7"
|
||||
" - - 8"
|
||||
" - - - 9"
|
||||
" - - - 10"
|
||||
" - - 11")
|
||||
// " - - 12"
|
||||
// " - 13"
|
||||
// " - 14"
|
||||
// " - 15"
|
||||
// " - - 16"
|
||||
// " - - - 17"
|
||||
// " - - - 18"
|
||||
// " - 19"
|
||||
// " - 20"
|
||||
// " - 21"
|
||||
);
|
||||
|
||||
QIdentityProxyModel *proxy = new QIdentityProxyModel(this);
|
||||
proxy->setSourceModel(rootModel);
|
||||
|
||||
QTreeView *view1 = new QTreeView(splitter);
|
||||
view1->setModel(proxy);
|
||||
view1->expandAll();
|
||||
}
|
||||
|
||||
#include "moc_kidentityproxymodelwidget.cpp"
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KIDENTITYPROXYMODELWIDGET_H
|
||||
#define KIDENTITYPROXYMODELWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class KIdentityProxyModelWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KIdentityProxyModelWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
};
|
||||
|
||||
#endif
|
||||
+1498
File diff suppressed because it is too large
Load Diff
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KREPARENTINGPROXYMODEL_H
|
||||
#define KREPARENTINGPROXYMODEL_H
|
||||
|
||||
#include <QAbstractProxyModel>
|
||||
|
||||
class KReparentingProxyModelPrivate;
|
||||
|
||||
/**
|
||||
@brief Restructures a source model, changing the parents of items.
|
||||
|
||||
Subclasses can change the structure of a source model by reimplementing
|
||||
the isDescendantOf method.
|
||||
|
||||
For example, if the source model is a list,
|
||||
|
||||
@verbatim
|
||||
0
|
||||
- A
|
||||
- B
|
||||
- C
|
||||
- D
|
||||
- E
|
||||
@endverbatim
|
||||
|
||||
It could be converted to a tree by an implementation something like:
|
||||
|
||||
@code
|
||||
bool MyReparentingModel::isDescedantOf(const QModelIndex& ancestor, const QModelIndex& descendant ) const
|
||||
{
|
||||
return (
|
||||
(ancestor.data().toString() == "A" && descendant.data().toString() == "B")
|
||||
|| (ancestor.data().toString() == "A" && descendant.data().toString() == "C")
|
||||
|| (ancestor.data().toString() == "B" && descendant.data().toString() == "C")
|
||||
|| (ancestor.data().toString() == "A" && descendant.data().toString() == "D")
|
||||
)
|
||||
? true : KReparentingProxyModel::isDescendantOf(ancestor, descendant);
|
||||
}
|
||||
@endcode
|
||||
|
||||
to get this result:
|
||||
|
||||
@verbatim
|
||||
0
|
||||
- A
|
||||
- - B
|
||||
- - - C
|
||||
- - D
|
||||
- E
|
||||
@endverbatim
|
||||
|
||||
Note that the implementation returns true for a query if "C" is a descendant of "A".
|
||||
The implementation must return the correct value for all of its descendants, not only its direct parent.
|
||||
The actual location to insert the descendant in the tree is determined internally by a binary find algorithm.
|
||||
|
||||
The KReparentingProxyModel performs movement of items in the left-right directions, but not the up-down directions.
|
||||
|
||||
\image html reparenting1.png "KReparentingProxyModel moving rows left to right"
|
||||
|
||||
\image html reparenting2.png "KReparentingProxyModel can not move items both left-right and up-down"
|
||||
|
||||
Reordering the rows in a model is the domain of QSortFilterProxyModel. An intermediate QSortFilterProxyModel
|
||||
can be used to achieve the desired result.
|
||||
|
||||
\image html reparenting3.png "KReparentingProxyModel and QSortFilterProxyModel working in concert to move items both left-right and up-down"
|
||||
|
||||
@code
|
||||
QAbstractItemModel *model = getModel();
|
||||
|
||||
QSortFilterProxyModel *sorter = getSorter();
|
||||
sorter->setSourceModel(model);
|
||||
|
||||
KReparentingProxyModel *reparenter = getReparenter();
|
||||
reparenter->setSourceModel(sorter);
|
||||
|
||||
QTreeView *view = getView();
|
||||
view->setModel(reparenter);
|
||||
@endcode
|
||||
|
||||
*/
|
||||
class KReparentingProxyModel : public QAbstractProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KReparentingProxyModel(QObject *parent = nullptr);
|
||||
|
||||
~KReparentingProxyModel() override;
|
||||
|
||||
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
|
||||
|
||||
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
/**
|
||||
Reimplement this to return whether @p descendant is a descendant of @p ancestor.
|
||||
*/
|
||||
virtual bool isDescendantOf(const QModelIndex &ancestor, const QModelIndex &descendant) const;
|
||||
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
|
||||
protected:
|
||||
void beginChangeRule();
|
||||
void endChangeRule();
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(KReparentingProxyModel)
|
||||
//@cond PRIVATE
|
||||
KReparentingProxyModelPrivate *d_ptr;
|
||||
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &, int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &, int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &, int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceModelAboutToBeReset())
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceModelReset())
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceLayoutAboutToBeChanged())
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceLayoutChanged())
|
||||
Q_PRIVATE_SLOT(d_func(), void sourceDataChanged(const QModelIndex &, const QModelIndex &))
|
||||
|
||||
//@endcond
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "lessthanwidget.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
ColoredTreeModel::ColoredTreeModel(QObject *parent)
|
||||
: DynamicTreeModel(parent)
|
||||
, m_selectionModel(nullptr)
|
||||
, m_lessThanColour(Qt::yellow)
|
||||
, m_greaterThanColour(Qt::red)
|
||||
{
|
||||
}
|
||||
|
||||
void ColoredTreeModel::setSelectionModel(QItemSelectionModel *selectionModel)
|
||||
{
|
||||
m_selectionModel = selectionModel;
|
||||
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(recolor()));
|
||||
}
|
||||
|
||||
void ColoredTreeModel::recolor(const QModelIndex &parent)
|
||||
{
|
||||
const QModelIndex topLeft = index(0, 0, parent);
|
||||
const int _rowCount = rowCount(parent);
|
||||
const QModelIndex bottomRight = index(_rowCount - 1, columnCount(parent) - 1, parent);
|
||||
Q_EMIT dataChanged(topLeft, bottomRight);
|
||||
|
||||
static const int column = 0;
|
||||
QModelIndex idx;
|
||||
for (int row = 0; row < _rowCount; ++row) {
|
||||
idx = index(row, column, parent);
|
||||
if (hasChildren(idx)) {
|
||||
recolor(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ColoredTreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::BackgroundRole || !m_selectionModel || m_selectionModel->selection().indexes().size() != 1) {
|
||||
return DynamicTreeModel::data(index, role);
|
||||
}
|
||||
|
||||
const QModelIndex selectedIndex = m_selectionModel->selection().indexes().first();
|
||||
|
||||
if (index == selectedIndex) {
|
||||
return DynamicTreeModel::data(index, role);
|
||||
}
|
||||
|
||||
if (index < selectedIndex) {
|
||||
return m_lessThanColour;
|
||||
}
|
||||
|
||||
Q_ASSERT(selectedIndex < index);
|
||||
|
||||
return m_greaterThanColour;
|
||||
}
|
||||
|
||||
void LessThanWidget::insertGrid(QList<int> address)
|
||||
{
|
||||
ModelInsertCommand *ins = new ModelInsertCommand(m_coloredTreeModel, this);
|
||||
ins->setAncestorRowNumbers(address);
|
||||
ins->setNumCols(5);
|
||||
ins->setStartRow(0);
|
||||
ins->setEndRow(5);
|
||||
ins->doCommand();
|
||||
}
|
||||
|
||||
LessThanWidget::LessThanWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QLabel *explanation = new QLabel(this);
|
||||
explanation->setText(
|
||||
QLatin1String("The yellow items are 'less than' the selected item according to QModelIndex::operator<().\n"
|
||||
"The red items are greater than the selected item (i.e, not less than and not equal)."));
|
||||
|
||||
m_coloredTreeModel = new ColoredTreeModel(this);
|
||||
QTreeView *treeView = new QTreeView(this);
|
||||
treeView->setModel(m_coloredTreeModel);
|
||||
treeView->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
treeView->setSelectionMode(QTreeView::SingleSelection);
|
||||
|
||||
m_coloredTreeModel->setSelectionModel(treeView->selectionModel());
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(explanation);
|
||||
layout->addWidget(treeView);
|
||||
|
||||
insertGrid(QList<int>());
|
||||
insertGrid(QList<int>() << 2);
|
||||
insertGrid(QList<int>() << 3);
|
||||
insertGrid(QList<int>() << 4);
|
||||
insertGrid(QList<int>() << 3 << 2);
|
||||
insertGrid(QList<int>() << 3 << 3);
|
||||
insertGrid(QList<int>() << 3 << 4);
|
||||
}
|
||||
|
||||
#include "moc_lessthanwidget.cpp"
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef LESSTHANWIDGET_H
|
||||
#define LESSTHANWIDGET_H
|
||||
|
||||
#include <QItemSelectionModel>
|
||||
#include <QWidget>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
|
||||
class ColoredTreeModel : public DynamicTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColoredTreeModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void setSelectionModel(QItemSelectionModel *selectionModel);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void recolor(const QModelIndex &parent = QModelIndex());
|
||||
|
||||
private:
|
||||
QItemSelectionModel *m_selectionModel;
|
||||
QColor m_lessThanColour;
|
||||
QColor m_greaterThanColour;
|
||||
};
|
||||
|
||||
class LessThanWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LessThanWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
void insertGrid(QList<int> address);
|
||||
|
||||
private:
|
||||
ColoredTreeModel *m_coloredTreeModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
MainWindow *mw = new MainWindow();
|
||||
mw->show();
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QTabWidget>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
|
||||
#include "breadcrumbdirectionwidget.h"
|
||||
#include "breadcrumbnavigationwidget.h"
|
||||
#include "breadcrumbswidget.h"
|
||||
#include "checkablewidget.h"
|
||||
#include "descendantpmwidget.h"
|
||||
#include "selectionpmwidget.h"
|
||||
// #include "statesaverwidget.h"
|
||||
#include "descendantqmltree.h"
|
||||
#include "proxyitemselectionwidget.h"
|
||||
#include "proxymodeltestwidget.h"
|
||||
#ifdef QT_QML_LIB
|
||||
#include "reparentingpmwidget.h"
|
||||
#endif
|
||||
#include "kidentityproxymodelwidget.h"
|
||||
#include "lessthanwidget.h"
|
||||
#include "matchcheckingwidget.h"
|
||||
#ifdef QT_QUICKWIDGETS_LIB
|
||||
#include "selectioninqmlwidget.h"
|
||||
#endif
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: QMainWindow()
|
||||
{
|
||||
QTabWidget *tabWidget = new QTabWidget(this);
|
||||
|
||||
tabWidget->addTab(new MatchCheckingWidget(), QStringLiteral("Match Checking PM"));
|
||||
tabWidget->addTab(new DescendantProxyModelWidget(), QStringLiteral("descendant PM"));
|
||||
tabWidget->addTab(new SelectionProxyWidget(), QStringLiteral("selection PM"));
|
||||
#ifdef QT_QUICKWIDGETS_LIB
|
||||
tabWidget->addTab(new SelectionInQmlWidget(), QStringLiteral("selection PM in QML"));
|
||||
#endif
|
||||
tabWidget->addTab(new KIdentityProxyModelWidget(), QStringLiteral("Identity PM"));
|
||||
tabWidget->addTab(new CheckableWidget(), QStringLiteral("Checkable"));
|
||||
tabWidget->addTab(new BreadcrumbsWidget(), QStringLiteral("Breadcrumbs"));
|
||||
tabWidget->addTab(new BreadcrumbNavigationWidget(), QStringLiteral("Breadcrumb Navigation"));
|
||||
tabWidget->addTab(new BreadcrumbDirectionWidget(), QStringLiteral("Breadcrumb Direction"));
|
||||
tabWidget->addTab(new ProxyItemSelectionWidget(), QStringLiteral("Proxy Item selection"));
|
||||
#ifdef QT_QML_LIB
|
||||
tabWidget->addTab(new ReparentingProxyModelWidget(), QStringLiteral("reparenting PM"));
|
||||
#endif
|
||||
#ifdef QT_QUICKWIDGETS_LIB
|
||||
tabWidget->addTab(new DescendantQmlTreeWidget(), QStringLiteral("QML Trees"));
|
||||
#endif
|
||||
tabWidget->addTab(new LessThanWidget(), QStringLiteral("Less Than"));
|
||||
tabWidget->addTab(new ProxyModelTestWidget(), QStringLiteral("Proxy Model Test"));
|
||||
// tabWidget->addTab(new StateSaverWidget(), "State Saver Test");
|
||||
|
||||
setCentralWidget(tabWidget);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_mainwindow.cpp"
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef TESTAPPLICATION_H
|
||||
#define TESTAPPLICATION_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
//@cond PRIVATE
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Test Application for proxy models.
|
||||
*/
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow();
|
||||
~MainWindow() override;
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
// ContactsWidget* cw;
|
||||
};
|
||||
|
||||
//@endcond
|
||||
|
||||
#endif
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "matchcheckingwidget.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QRadioButton>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include <kselectionproxymodel.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
MatchCheckingWidget::MatchCheckingWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
m_lineEdit = new QLineEdit();
|
||||
|
||||
connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(matchChanged(QString)));
|
||||
|
||||
m_dynamicTreeRadioButton = new QRadioButton(QStringLiteral("Dynamic Tree Model"), this);
|
||||
m_selectionModelRadioButton = new QRadioButton(QStringLiteral("Selection Model"), this);
|
||||
|
||||
layout->addWidget(m_lineEdit);
|
||||
layout->addWidget(m_dynamicTreeRadioButton);
|
||||
layout->addWidget(m_selectionModelRadioButton);
|
||||
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
layout->addWidget(splitter);
|
||||
DynamicTreeModel *dynamicTreeModel = new DynamicTreeModel(this);
|
||||
|
||||
m_dynamicTreeWidget = new DynamicTreeWidget(dynamicTreeModel, this);
|
||||
|
||||
splitter->addWidget(m_dynamicTreeWidget);
|
||||
|
||||
KSelectionProxyModel *selectionProxyModel = new KSelectionProxyModel(m_dynamicTreeWidget->treeView()->selectionModel(), this);
|
||||
selectionProxyModel->setSourceModel(dynamicTreeModel);
|
||||
|
||||
m_selectionTreeView = new QTreeView(this);
|
||||
m_selectionTreeView->setModel(selectionProxyModel);
|
||||
splitter->addWidget(m_selectionTreeView);
|
||||
}
|
||||
|
||||
void MatchCheckingWidget::matchChanged(const QString &matchData)
|
||||
{
|
||||
bool ok;
|
||||
int id = matchData.toInt(&ok);
|
||||
qDebug() << matchData << id << DynamicTreeModel::DynamicTreeModelId;
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList list;
|
||||
if (m_dynamicTreeRadioButton->isChecked()) {
|
||||
m_dynamicTreeWidget->treeView()->selectionModel()->clearSelection();
|
||||
list = m_dynamicTreeWidget->model()->match(m_dynamicTreeWidget->model()->index(0, 0), DynamicTreeModel::DynamicTreeModelId, id);
|
||||
qDebug() << list;
|
||||
for (const QModelIndex &idx : std::as_const(list)) {
|
||||
m_dynamicTreeWidget->treeView()->selectionModel()->select(idx, QItemSelectionModel::SelectCurrent);
|
||||
}
|
||||
} else if (m_selectionModelRadioButton->isChecked()) {
|
||||
m_selectionTreeView->selectionModel()->clearSelection();
|
||||
list = m_selectionTreeView->model()->match(m_selectionTreeView->model()->index(0, 0), DynamicTreeModel::DynamicTreeModelId, id);
|
||||
qDebug() << list;
|
||||
for (const QModelIndex &idx : std::as_const(list)) {
|
||||
m_selectionTreeView->selectionModel()->select(idx, QItemSelectionModel::SelectCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_matchcheckingwidget.cpp"
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef MATCHCHECKINGWIDGET_H343434
|
||||
#define MATCHCHECKINGWIDGET_H343434
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTreeView;
|
||||
class QLineEdit;
|
||||
class QRadioButton;
|
||||
|
||||
class DynamicTreeWidget;
|
||||
|
||||
class MatchCheckingWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MatchCheckingWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
private Q_SLOTS:
|
||||
void matchChanged(const QString &matchData);
|
||||
|
||||
private:
|
||||
QLineEdit *m_lineEdit;
|
||||
DynamicTreeWidget *m_dynamicTreeWidget;
|
||||
QTreeView *m_selectionTreeView;
|
||||
QRadioButton *m_dynamicTreeRadioButton;
|
||||
QRadioButton *m_selectionModelRadioButton;
|
||||
};
|
||||
|
||||
#endif
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "modelcommanderwidget.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QTreeWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "modelcommander.h"
|
||||
#include <QMetaMethod>
|
||||
|
||||
ModelCommanderWidget::ModelCommanderWidget(DynamicTreeModel *dynamicTreeModel, QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
, m_dynamicTreeModel(dynamicTreeModel)
|
||||
, m_modelCommander(new ModelCommander(m_dynamicTreeModel, this))
|
||||
, m_treeWidget(new QTreeWidget)
|
||||
, m_executeButton(new QPushButton(QStringLiteral("Execute")))
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_treeWidget);
|
||||
layout->addWidget(m_executeButton);
|
||||
|
||||
init();
|
||||
|
||||
connect(m_treeWidget, &QTreeWidget::currentItemChanged, this, &ModelCommanderWidget::currentItemChanged);
|
||||
|
||||
connect(m_executeButton, &QPushButton::clicked, this, &ModelCommanderWidget::executeCurrentTest);
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::init()
|
||||
{
|
||||
const QMetaObject *mo = m_modelCommander->metaObject();
|
||||
QMetaMethod mm;
|
||||
for (int i = 0; i < mo->methodCount(); ++i) {
|
||||
mm = mo->method(i);
|
||||
QString signature = mm.methodSignature();
|
||||
if (signature.startsWith(QLatin1String("init_")) && signature.endsWith(QLatin1String("(QString)"))) {
|
||||
QTreeWidgetItem *testFunctionItem = new QTreeWidgetItem(m_treeWidget, QStringList() << signature.mid(5, signature.length() - 14));
|
||||
m_treeWidget->addTopLevelItem(testFunctionItem);
|
||||
|
||||
QStringList testData;
|
||||
QMetaObject::invokeMethod(m_modelCommander,
|
||||
QByteArray("execute_" + testFunctionItem->text(0).toLatin1()).constData(),
|
||||
Q_RETURN_ARG(QStringList, testData),
|
||||
Q_ARG(QString, QString()));
|
||||
|
||||
for (const QString &testRun : std::as_const(testData)) {
|
||||
new QTreeWidgetItem(testFunctionItem, QStringList() << testRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
|
||||
{
|
||||
Q_UNUSED(previous);
|
||||
initTest(current);
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::executeCurrentTest()
|
||||
{
|
||||
executeTest(m_treeWidget->currentItem());
|
||||
|
||||
disconnect(m_executeButton, &QPushButton::clicked, this, &ModelCommanderWidget::executeCurrentTest);
|
||||
m_executeButton->setText(QStringLiteral("Reset"));
|
||||
connect(m_executeButton, &QPushButton::clicked, this, &ModelCommanderWidget::resetCurrentTest);
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::resetCurrentTest()
|
||||
{
|
||||
initTest(m_treeWidget->currentItem());
|
||||
|
||||
disconnect(m_executeButton, &QPushButton::clicked, this, &ModelCommanderWidget::resetCurrentTest);
|
||||
m_executeButton->setText(QStringLiteral("Execute"));
|
||||
connect(m_executeButton, &QPushButton::clicked, this, &ModelCommanderWidget::executeCurrentTest);
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::initTest(QTreeWidgetItem *item)
|
||||
{
|
||||
if (!item->parent()) {
|
||||
return; // m_dynamicTreeModel->clear();
|
||||
}
|
||||
m_dynamicTreeModel->clear();
|
||||
bool success =
|
||||
QMetaObject::invokeMethod(m_modelCommander, QByteArray("init_" + item->parent()->text(0).toLatin1()).constData(), Q_ARG(QString, item->text(0)));
|
||||
Q_ASSERT(success);
|
||||
}
|
||||
|
||||
void ModelCommanderWidget::executeTest(QTreeWidgetItem *item)
|
||||
{
|
||||
if (!item->parent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool success =
|
||||
QMetaObject::invokeMethod(m_modelCommander, QByteArray("execute_" + item->parent()->text(0).toLatin1()).constData(), Q_ARG(QString, item->text(0)));
|
||||
Q_ASSERT(success);
|
||||
}
|
||||
|
||||
#include "moc_modelcommanderwidget.cpp"
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef MODELCOMMANDERWIDGET_H
|
||||
#define MODELCOMMANDERWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTreeWidget;
|
||||
class QTreeWidgetItem;
|
||||
class QPushButton;
|
||||
|
||||
class DynamicTreeModel;
|
||||
class ModelCommander;
|
||||
|
||||
class ModelCommanderWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ModelCommanderWidget(DynamicTreeModel *dynamicTreeModel, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTest(QTreeWidgetItem *item);
|
||||
void executeTest(QTreeWidgetItem *item);
|
||||
void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
void executeCurrentTest();
|
||||
void resetCurrentTest();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_dynamicTreeModel;
|
||||
ModelCommander *m_modelCommander;
|
||||
QTreeWidget *m_treeWidget;
|
||||
QPushButton *m_executeButton;
|
||||
};
|
||||
|
||||
#endif
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "proxyitemselectionwidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "klinkitemselectionmodel.h"
|
||||
|
||||
#define SON(object) object->setObjectName(QStringLiteral(#object))
|
||||
|
||||
ProxyItemSelectionWidget::ProxyItemSelectionWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
DynamicTreeModel *rootModel = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *dynamicTreeWidget = new DynamicTreeWidget(rootModel, splitter);
|
||||
|
||||
dynamicTreeWidget->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- 2"
|
||||
"- - 3"
|
||||
"- - - 4"
|
||||
"- 5"
|
||||
"- 6"
|
||||
"- 7"));
|
||||
|
||||
QSplitter *vSplitter = new QSplitter(Qt::Vertical, splitter);
|
||||
QSplitter *hSplitter1 = new QSplitter(vSplitter);
|
||||
QSplitter *hSplitter2 = new QSplitter(vSplitter);
|
||||
|
||||
QSortFilterProxyModel *proxy1 = new QSortFilterProxyModel(this);
|
||||
SON(proxy1);
|
||||
QSortFilterProxyModel *proxy2 = new QSortFilterProxyModel(this);
|
||||
SON(proxy2);
|
||||
QSortFilterProxyModel *proxy3 = new QSortFilterProxyModel(this);
|
||||
SON(proxy3);
|
||||
QSortFilterProxyModel *proxy4 = new QSortFilterProxyModel(this);
|
||||
SON(proxy4);
|
||||
QSortFilterProxyModel *proxy5 = new QSortFilterProxyModel(this);
|
||||
SON(proxy5);
|
||||
|
||||
QTreeView *view1 = new QTreeView(hSplitter1);
|
||||
QTreeView *view2 = new QTreeView(hSplitter1);
|
||||
QTreeView *view3 = new QTreeView(hSplitter2);
|
||||
QTreeView *view4 = new QTreeView(hSplitter2);
|
||||
|
||||
proxy1->setSourceModel(rootModel);
|
||||
proxy2->setSourceModel(proxy1);
|
||||
proxy3->setSourceModel(proxy2);
|
||||
|
||||
proxy4->setSourceModel(rootModel);
|
||||
proxy5->setSourceModel(proxy4);
|
||||
|
||||
view1->setModel(proxy3);
|
||||
view2->setModel(proxy5);
|
||||
view3->setModel(proxy2);
|
||||
view4->setModel(proxy1);
|
||||
|
||||
QItemSelectionModel *rootSelectionModel = dynamicTreeWidget->treeView()->selectionModel();
|
||||
|
||||
KLinkItemSelectionModel *view1SelectionModel = new KLinkItemSelectionModel(view1->model(), rootSelectionModel, this);
|
||||
view1->setSelectionModel(view1SelectionModel);
|
||||
|
||||
KLinkItemSelectionModel *view2SelectionModel = new KLinkItemSelectionModel(view2->model(), view1->selectionModel(), this);
|
||||
view2->setSelectionModel(view2SelectionModel);
|
||||
|
||||
KLinkItemSelectionModel *view3SelectionModel = new KLinkItemSelectionModel(view3->model(), view4->selectionModel(), this);
|
||||
view3->setSelectionModel(view3SelectionModel);
|
||||
|
||||
view1->expandAll();
|
||||
view2->expandAll();
|
||||
view3->expandAll();
|
||||
view4->expandAll();
|
||||
}
|
||||
|
||||
#include "moc_proxyitemselectionwidget.cpp"
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PROXYITEMSELECTIONWIDGET_H
|
||||
#define PROXYITEMSELECTIONWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ProxyItemSelectionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProxyItemSelectionWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
};
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "proxymodeltestwidget.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
#include "modelcommander.h"
|
||||
#if 0
|
||||
#include "kdescendantsproxymodel.h"
|
||||
#endif
|
||||
#include "modelcommanderwidget.h"
|
||||
|
||||
ProxyModelTestWidget::ProxyModelTestWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
(void)new ModelCommanderWidget(m_rootModel, splitter);
|
||||
|
||||
QTreeView *rootModelView = new QTreeView(splitter);
|
||||
rootModelView->setModel(m_rootModel);
|
||||
rootModelView->setSelectionMode(QTreeView::ExtendedSelection);
|
||||
|
||||
KSelectionProxyModel *selProxyModel = new KSelectionProxyModel(rootModelView->selectionModel(), this);
|
||||
selProxyModel->setSourceModel(m_rootModel);
|
||||
selProxyModel->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection);
|
||||
|
||||
QTreeView *selModelView = new QTreeView(splitter);
|
||||
selModelView->setModel(selProxyModel);
|
||||
|
||||
#if 0
|
||||
KDescendantsProxyModel *descProxyModel = new KDescendantsProxyModel(this);
|
||||
descProxyModel->setSourceModel(m_rootModel);
|
||||
QTreeView *descProxyModelView = new QTreeView(splitter);
|
||||
descProxyModelView ->setModel(descProxyModel);
|
||||
#endif
|
||||
|
||||
// Your Proxy Here?
|
||||
|
||||
layout->addWidget(splitter);
|
||||
}
|
||||
|
||||
#include "moc_proxymodeltestwidget.cpp"
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef PROXYMODELTESTWIDGET_H
|
||||
#define PROXYMODELTESTWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class DynamicTreeModel;
|
||||
class ModelCommander;
|
||||
class QPushButton;
|
||||
|
||||
class ProxyModelTestWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProxyModelTestWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "reparentingpmwidget.h"
|
||||
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "scriptablereparentingwidget.h"
|
||||
|
||||
ReparentingProxyModelWidget::ReparentingProxyModelWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
QSplitter *vSplitter = new QSplitter(this);
|
||||
layout->addWidget(vSplitter);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *dynamicTreeWidget = new DynamicTreeWidget(m_rootModel, vSplitter);
|
||||
dynamicTreeWidget->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- 2"
|
||||
"- - 3"
|
||||
"- - - 4"
|
||||
"- 5"
|
||||
"- 6"
|
||||
"- 7"));
|
||||
|
||||
new ScriptableReparentingWidget(m_rootModel, vSplitter);
|
||||
}
|
||||
|
||||
#include "moc_reparentingpmwidget.cpp"
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef REPARENTINGPM_WIDGET_H
|
||||
#define REPARENTINGPM_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "kreparentingproxymodel.h"
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
class ReparentingProxyModelWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReparentingProxyModelWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "scriptablereparentingwidget.h"
|
||||
|
||||
#include <QJSEngine>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QSplitter>
|
||||
|
||||
static const char *const threadingFunctionNames[] = {"None", "Flat List", "Straight Line Tree", "Dragon Teeth 1", "Dragon Teeth 2", "Specified parents 1"};
|
||||
|
||||
static const char *const threadingFunctionBodies[] = {"",
|
||||
"return false;",
|
||||
"return true;",
|
||||
"if (descendant % 3 ==1)\n"
|
||||
" return false;\n"
|
||||
"return true;",
|
||||
"if (descendant % 4 ==1)\n"
|
||||
" return false;\n"
|
||||
"return true;",
|
||||
"var threaddata = [[1, 2, 3, 4],\n"
|
||||
" [13, 14, 15],\n"
|
||||
" [13, 16, 17],\n"
|
||||
" [5, 6]];\n"
|
||||
"\n"
|
||||
"for (var i = 0; i < threaddata.length; ++i)\n"
|
||||
"{\n"
|
||||
" var a = threaddata[i].indexOf(ancestor);\n"
|
||||
" var d = threaddata[i].indexOf(descendant);\n"
|
||||
" if (a >= 0 && d >= 0)\n"
|
||||
" return a < d;\n"
|
||||
"}\n"
|
||||
"return false;"};
|
||||
|
||||
ScriptableReparentingProxyModel::ScriptableReparentingProxyModel(QObject *parent)
|
||||
: KReparentingProxyModel(parent)
|
||||
, m_scriptEngine(new QJSEngine(this))
|
||||
{
|
||||
}
|
||||
|
||||
bool ScriptableReparentingProxyModel::isDescendantOf(const QModelIndex &ancestor, const QModelIndex &descendant) const
|
||||
{
|
||||
if (!m_implementationFunction.isCallable()) {
|
||||
return KReparentingProxyModel::isDescendantOf(ancestor, descendant);
|
||||
}
|
||||
|
||||
QJSValue returnValue = m_implementationFunction.call({ancestor.data().toInt(), descendant.data().toInt()});
|
||||
|
||||
if (!returnValue.isBool()) {
|
||||
return KReparentingProxyModel::isDescendantOf(ancestor, descendant);
|
||||
}
|
||||
|
||||
return returnValue.toBool();
|
||||
}
|
||||
|
||||
void ScriptableReparentingProxyModel::setImplementation(const QString &implementation)
|
||||
{
|
||||
beginChangeRule();
|
||||
m_implementationFunction = m_scriptEngine->evaluate(implementation);
|
||||
m_implementationFunction = m_scriptEngine->globalObject().property(QStringLiteral("isDescendantOf"));
|
||||
endChangeRule();
|
||||
}
|
||||
|
||||
ScriptableReparentingWidget::ScriptableReparentingWidget(QAbstractItemModel *rootModel, QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
, m_reparentingProxyModel(new ScriptableReparentingProxyModel(this))
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(Qt::Vertical, this);
|
||||
mainLayout->addWidget(splitter);
|
||||
|
||||
m_treeView = new QTreeView(splitter);
|
||||
QWidget *container = new QWidget(splitter);
|
||||
QVBoxLayout *layout = new QVBoxLayout(container);
|
||||
m_textEdit = new QPlainTextEdit(container);
|
||||
m_textEdit->setFont(QFont(QStringLiteral("monospace")));
|
||||
|
||||
m_comboBox = new QComboBox(container);
|
||||
for (int i = 0; i < int(sizeof threadingFunctionNames / sizeof *threadingFunctionNames); ++i) {
|
||||
m_comboBox->addItem(*(threadingFunctionNames + i), *(threadingFunctionBodies + i));
|
||||
}
|
||||
layout->addWidget(m_comboBox);
|
||||
connect(m_comboBox, SIGNAL(currentIndexChanged(int)), SLOT(setExampleFunction(int)));
|
||||
|
||||
layout->addWidget(new QLabel(QStringLiteral("function isDescendantOf (ancestor, descendant) {"), container));
|
||||
QHBoxLayout *indentedLayout = new QHBoxLayout;
|
||||
indentedLayout->addSpacing(30);
|
||||
indentedLayout->addWidget(m_textEdit);
|
||||
layout->addLayout(indentedLayout);
|
||||
layout->addWidget(new QLabel(QStringLiteral("}"), container));
|
||||
|
||||
m_reparentingProxyModel->setSourceModel(rootModel);
|
||||
m_treeView->setModel(m_reparentingProxyModel);
|
||||
|
||||
splitter->setStretchFactor(0, 100);
|
||||
|
||||
connect(m_textEdit, SIGNAL(textChanged()), SLOT(textChanged()));
|
||||
textChanged();
|
||||
}
|
||||
|
||||
void ScriptableReparentingWidget::setExampleFunction(int index)
|
||||
{
|
||||
m_textEdit->setPlainText(m_comboBox->itemData(index).toString());
|
||||
}
|
||||
|
||||
void ScriptableReparentingWidget::textChanged()
|
||||
{
|
||||
m_reparentingProxyModel->setImplementation("function isDescendantOf (ancestor, descendant) { " + m_textEdit->toPlainText() + " }");
|
||||
m_treeView->expandAll();
|
||||
}
|
||||
|
||||
#include "moc_scriptablereparentingwidget.cpp"
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTABLEREPARENTINGWIDGET_H
|
||||
#define SCRIPTABLEREPARENTINGWIDGET_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QWidget>
|
||||
|
||||
#include "kreparentingproxymodel.h"
|
||||
|
||||
class QComboBox;
|
||||
class QTreeView;
|
||||
class QPlainTextEdit;
|
||||
class QJSEngine;
|
||||
|
||||
class ScriptableReparentingProxyModel : public KReparentingProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptableReparentingProxyModel(QObject *parent = nullptr);
|
||||
|
||||
bool isDescendantOf(const QModelIndex &ancestor, const QModelIndex &descendant) const override;
|
||||
|
||||
void setImplementation(const QString &implementation);
|
||||
|
||||
private:
|
||||
QJSEngine *m_scriptEngine;
|
||||
mutable QJSValue m_implementationFunction;
|
||||
};
|
||||
|
||||
class ScriptableReparentingWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptableReparentingWidget(QAbstractItemModel *rootModel, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
private Q_SLOTS:
|
||||
void textChanged();
|
||||
void setExampleFunction(int index);
|
||||
|
||||
private:
|
||||
QComboBox *m_comboBox;
|
||||
ScriptableReparentingProxyModel *m_reparentingProxyModel;
|
||||
QTreeView *m_treeView;
|
||||
QPlainTextEdit *m_textEdit;
|
||||
};
|
||||
|
||||
#endif // SCRIPTABLEREPARENTINGWIDGET_H
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2015 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.4
|
||||
|
||||
import KF5ItemModels 1.0
|
||||
|
||||
Item {
|
||||
width: 600
|
||||
height: 500
|
||||
|
||||
Component {
|
||||
id: labelledSelectionView
|
||||
|
||||
Column {
|
||||
id: column
|
||||
width : 200
|
||||
property var filterBehavior
|
||||
property var filterBehaviorName
|
||||
Text {
|
||||
id: label
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.bold: true
|
||||
font.pointSize: 10
|
||||
text: column.filterBehaviorName
|
||||
}
|
||||
SelectionProxyModel {
|
||||
id: selection
|
||||
sourceModel: _model
|
||||
selectionModel: _selectionModel
|
||||
filterBehavior: column.filterBehavior
|
||||
}
|
||||
Rectangle {
|
||||
height: parent.height - label.height
|
||||
width: parent.width
|
||||
border.width : 1
|
||||
border.color: "black"
|
||||
radius: 5
|
||||
ListView {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
y: 5
|
||||
x: 5
|
||||
model: selection
|
||||
delegate: Rectangle {
|
||||
x: 1
|
||||
y: 1
|
||||
height: 30
|
||||
width: 100
|
||||
color: model.index % 2 == 0 ? "lightsteelblue" : "white"
|
||||
Text {
|
||||
x: 5
|
||||
y: 5
|
||||
text: model.display
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loaderExactSelection
|
||||
width : 200
|
||||
height: 300
|
||||
sourceComponent: labelledSelectionView
|
||||
Binding {
|
||||
target: loaderExactSelection.item
|
||||
property: "filterBehavior"
|
||||
value: SelectionProxyModel.ExactSelection
|
||||
when: loaderExactSelection.status == Loader.Ready
|
||||
}
|
||||
Binding {
|
||||
target: loaderExactSelection.item
|
||||
property: "filterBehaviorName"
|
||||
value: "ExactSelection"
|
||||
when: loaderExactSelection.status == Loader.Ready
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loaderChildrenOfExactSelection
|
||||
x: 200
|
||||
width : 200
|
||||
height: 300
|
||||
sourceComponent: labelledSelectionView
|
||||
Binding {
|
||||
target: loaderChildrenOfExactSelection.item
|
||||
property: "filterBehavior"
|
||||
value: SelectionProxyModel.ChildrenOfExactSelection
|
||||
when: loaderChildrenOfExactSelection.status == Loader.Ready
|
||||
}
|
||||
Binding {
|
||||
target: loaderChildrenOfExactSelection.item
|
||||
property: "filterBehaviorName"
|
||||
value: "ChildrenOfExactSelection"
|
||||
when: loaderChildrenOfExactSelection.status == Loader.Ready
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loaderSubTreeRoots
|
||||
x: 400
|
||||
width : 200
|
||||
height: 300
|
||||
sourceComponent: labelledSelectionView
|
||||
Binding {
|
||||
target: loaderSubTreeRoots.item
|
||||
property: "filterBehavior"
|
||||
value: SelectionProxyModel.SubTreeRoots
|
||||
when: loaderSubTreeRoots.status == Loader.Ready
|
||||
}
|
||||
Binding {
|
||||
target: loaderSubTreeRoots.item
|
||||
property: "filterBehaviorName"
|
||||
value: "SubTreeRoots"
|
||||
when: loaderSubTreeRoots.status == Loader.Ready
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2015 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "selectioninqmlwidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
#include <QQuickWidget>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
|
||||
SelectionInQmlWidget::SelectionInQmlWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
new DynamicTreeWidget(m_rootModel, splitter);
|
||||
|
||||
QTreeView *selectionTree = new QTreeView(splitter);
|
||||
selectionTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
selectionTree->setModel(m_rootModel);
|
||||
selectionTree->expandAll();
|
||||
|
||||
qmlRegisterType<KSelectionProxyModel>("KF5ItemModels", 1, 0, "SelectionProxyModel");
|
||||
|
||||
QQuickWidget *quickView = new QQuickWidget(splitter);
|
||||
|
||||
quickView->engine()->rootContext()->setContextProperty(QStringLiteral("_model"), m_rootModel);
|
||||
quickView->engine()->rootContext()->setContextProperty(QStringLiteral("_selectionModel"), selectionTree->selectionModel());
|
||||
|
||||
quickView->setSource(QUrl::fromLocalFile(QLatin1String(SRC_DIR "/selection.qml")));
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2015 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef SELECTIONINQML_WIDGET_H
|
||||
#define SELECTIONINQML_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTreeView;
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
class SelectionInQmlWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
SelectionInQmlWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "selectionpmwidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
#include "kselectionproxymodel.h"
|
||||
|
||||
SelectionProxyWidget::SelectionProxyWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
m_rootModel = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *dynTreeWidget = new DynamicTreeWidget(m_rootModel, splitter);
|
||||
|
||||
dynTreeWidget->setInitialTree(
|
||||
QLatin1String("- 1"
|
||||
"- 2"
|
||||
"- - 3"
|
||||
"- - 3"
|
||||
"- - - 4"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 4"
|
||||
"- - 5"
|
||||
"- - - 4"
|
||||
"- - - - 4"
|
||||
"- - 5"
|
||||
"- 6"
|
||||
"- 7"
|
||||
"- - 8"
|
||||
"- - - 9"
|
||||
"- - - 10"
|
||||
"- - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - - - - 9"
|
||||
"- - - - - - - - 10"
|
||||
"- - - - - - - - 9"
|
||||
"- - - - - - - 10"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 9"
|
||||
"- - - - - 10"
|
||||
"- - - - - - 9"
|
||||
"- - - - - - 10"
|
||||
"- - - - 10"
|
||||
"- - 11"
|
||||
"- - 12"
|
||||
"- 13"
|
||||
"- 14"
|
||||
"- 15"
|
||||
"- - 16"
|
||||
"- - - 17"
|
||||
"- - - 18"
|
||||
"- 19"
|
||||
"- 20"
|
||||
"- 21"));
|
||||
|
||||
QTreeView *selectionTree = createLabelledView(QStringLiteral("Selection"), splitter);
|
||||
selectionTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
selectionTree->setModel(m_rootModel);
|
||||
selectionTree->expandAll();
|
||||
|
||||
#define SUBTREES
|
||||
#define SUBTREEROOTS
|
||||
#define SUBTREESWITHOUTROOTS
|
||||
#define EXACTSELECTION
|
||||
#define CHILDRENOFEXACTSELECTION
|
||||
|
||||
#ifdef SUBTREES
|
||||
KSelectionProxyModel *selectedBranchesModel = new KSelectionProxyModel(selectionTree->selectionModel(), this);
|
||||
selectedBranchesModel->setSourceModel(m_rootModel);
|
||||
selectedBranchesModel->setFilterBehavior(KSelectionProxyModel::SubTrees);
|
||||
|
||||
QTreeView *selectedBranchesView = createLabelledView(QStringLiteral("SubTrees"), splitter);
|
||||
selectedBranchesView->setModel(selectedBranchesModel);
|
||||
#endif
|
||||
|
||||
#ifdef SUBTREEROOTS
|
||||
KSelectionProxyModel *selectedBranchesRootsModel = new KSelectionProxyModel(selectionTree->selectionModel(), this);
|
||||
selectedBranchesRootsModel->setSourceModel(m_rootModel);
|
||||
selectedBranchesRootsModel->setFilterBehavior(KSelectionProxyModel::SubTreeRoots);
|
||||
|
||||
QTreeView *selectedBranchesRootsView = createLabelledView(QStringLiteral("SubTreeRoots"), splitter);
|
||||
selectedBranchesRootsView->setModel(selectedBranchesRootsModel);
|
||||
#endif
|
||||
|
||||
#ifdef SUBTREESWITHOUTROOTS
|
||||
KSelectionProxyModel *selectedBranchesChildrenModel = new KSelectionProxyModel(selectionTree->selectionModel(), this);
|
||||
selectedBranchesChildrenModel->setSourceModel(m_rootModel);
|
||||
selectedBranchesChildrenModel->setFilterBehavior(KSelectionProxyModel::SubTreesWithoutRoots);
|
||||
|
||||
QTreeView *selectedBranchesChildrenView = createLabelledView(QStringLiteral("SubTreesWithoutRoots"), splitter);
|
||||
selectedBranchesChildrenView->setModel(selectedBranchesChildrenModel);
|
||||
#endif
|
||||
|
||||
#ifdef EXACTSELECTION
|
||||
KSelectionProxyModel *onlySelectedModel = new KSelectionProxyModel(selectionTree->selectionModel(), this);
|
||||
onlySelectedModel->setSourceModel(m_rootModel);
|
||||
onlySelectedModel->setFilterBehavior(KSelectionProxyModel::ExactSelection);
|
||||
|
||||
QTreeView *onlySelectedView = createLabelledView(QStringLiteral("ExactSelection"), splitter);
|
||||
onlySelectedView->setModel(onlySelectedModel);
|
||||
#endif
|
||||
|
||||
#ifdef CHILDRENOFEXACTSELECTION
|
||||
KSelectionProxyModel *onlySelectedChildrenModel = new KSelectionProxyModel(selectionTree->selectionModel(), this);
|
||||
onlySelectedChildrenModel->setSourceModel(m_rootModel);
|
||||
onlySelectedChildrenModel->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection);
|
||||
|
||||
QTreeView *onlySelectedChildrenView = createLabelledView(QStringLiteral("ChildrenOfExactSelection"), splitter);
|
||||
onlySelectedChildrenView->setModel(onlySelectedChildrenModel);
|
||||
#endif
|
||||
}
|
||||
|
||||
QTreeView *SelectionProxyWidget::createLabelledView(const QString &labelText, QWidget *parent)
|
||||
{
|
||||
QWidget *labelledTreeWidget = new QWidget(parent);
|
||||
QVBoxLayout *layout = new QVBoxLayout(labelledTreeWidget);
|
||||
|
||||
QLabel *label = new QLabel(labelText, labelledTreeWidget);
|
||||
QTreeView *treeview = new QTreeView(labelledTreeWidget);
|
||||
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(treeview);
|
||||
return treeview;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
This file is part of the proxy model test suite.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef SELECTION_PM_WIDGET_H
|
||||
#define SELECTION_PM_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTreeView;
|
||||
|
||||
class DynamicTreeModel;
|
||||
|
||||
class SelectionProxyWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
SelectionProxyWidget(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
QTreeView *createLabelledView(const QString &labelText, QWidget *parent);
|
||||
|
||||
private:
|
||||
DynamicTreeModel *m_rootModel;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "statesaverwidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <ksharedconfig.h>
|
||||
|
||||
#include "dynamictreemodel.h"
|
||||
#include "dynamictreewidget.h"
|
||||
|
||||
QModelIndex DynamicTreeStateSaver::indexFromConfigString(const QAbstractItemModel *model, const QString &key) const
|
||||
{
|
||||
QModelIndexList list = model->match(model->index(0, 0), DynamicTreeModel::DynamicTreeModelId, key.toInt(), 1, Qt::MatchRecursive);
|
||||
if (list.isEmpty()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
return list.first();
|
||||
}
|
||||
|
||||
QString DynamicTreeStateSaver::indexToConfigString(const QModelIndex &index) const
|
||||
{
|
||||
return index.data(DynamicTreeModel::DynamicTreeModelId).toString();
|
||||
}
|
||||
|
||||
DynamicTreeStateSaver::DynamicTreeStateSaver(QObject *parent)
|
||||
: KViewStateSaver(parent)
|
||||
{
|
||||
}
|
||||
|
||||
StateSaverWidget::StateSaverWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f)
|
||||
{
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
DynamicTreeModel *model = new DynamicTreeModel(this);
|
||||
|
||||
DynamicTreeWidget *dynamicTreeWidget = new DynamicTreeWidget(model, splitter);
|
||||
|
||||
m_view = new QTreeView(splitter);
|
||||
m_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_view->setModel(model);
|
||||
|
||||
connect(model, SIGNAL(modelAboutToBeReset()), SLOT(saveState()));
|
||||
connect(model, SIGNAL(modelReset()), SLOT(restoreState()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(saveState()));
|
||||
|
||||
restoreState();
|
||||
}
|
||||
|
||||
StateSaverWidget::~StateSaverWidget()
|
||||
{
|
||||
saveState();
|
||||
}
|
||||
|
||||
void StateSaverWidget::saveState()
|
||||
{
|
||||
DynamicTreeStateSaver saver;
|
||||
saver.setView(m_view);
|
||||
|
||||
KConfigGroup cfg(KSharedConfig::openConfig(), "ExampleViewState");
|
||||
saver.saveState(cfg);
|
||||
cfg.sync();
|
||||
}
|
||||
|
||||
void StateSaverWidget::restoreState()
|
||||
{
|
||||
DynamicTreeStateSaver *saver = new DynamicTreeStateSaver;
|
||||
saver->setView(m_view);
|
||||
KConfigGroup cfg(KSharedConfig::openConfig(), "ExampleViewState");
|
||||
saver->restoreState(cfg);
|
||||
}
|
||||
|
||||
#include "moc_statesaverwidget.cpp"
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
||||
SPDX-FileContributor: Stephen Kelly <stephen@kdab.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef STATESAVERWIDGET_H
|
||||
#define STATESAVERWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <KViewStateSaver>
|
||||
|
||||
class QTreeView;
|
||||
|
||||
class DynamicTreeWidget;
|
||||
|
||||
class DynamicTreeStateSaver : public KViewStateSaver
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DynamicTreeStateSaver(QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
/* reimp */ QModelIndex indexFromConfigString(const QAbstractItemModel *model, const QString &key) const;
|
||||
/* reimp */ QString indexToConfigString(const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
class StateSaverWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
StateSaverWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
~StateSaverWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
void saveState();
|
||||
void restoreState();
|
||||
|
||||
private:
|
||||
DynamicTreeWidget *m_dynamicTreeWidget;
|
||||
QTreeView *m_view;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.4
|
||||
import QtQuick.Controls as QQC2
|
||||
import org.kde.kitemmodels 1.0
|
||||
import org.kde.qqc2desktopstyle.private 1.0 as StylePrivate
|
||||
|
||||
|
||||
QQC2.ScrollView {
|
||||
id: root
|
||||
width: 600
|
||||
height: 500
|
||||
|
||||
ListView {
|
||||
spacing: 0
|
||||
clip: true
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"; from: 0; to: 1; duration: 250 }
|
||||
}
|
||||
addDisplaced: Transition {
|
||||
NumberAnimation { properties: "y"; duration: 250 }
|
||||
}
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"; from: 1; to: 0; duration: 250 }
|
||||
}
|
||||
removeDisplaced: Transition {
|
||||
NumberAnimation { properties: "y"; duration: 250 }
|
||||
}
|
||||
model: KDescendantsProxyModel {
|
||||
id: descendantsModel
|
||||
expandsByDefault: false
|
||||
model: _model
|
||||
}
|
||||
|
||||
delegate: QQC2.ItemDelegate {
|
||||
id: delegate
|
||||
highlighted: false
|
||||
|
||||
contentItem: RowLayout {
|
||||
RowLayout {
|
||||
Layout.topMargin: -delegate.topPadding
|
||||
Layout.bottomMargin: -delegate.bottomPadding
|
||||
Repeater {
|
||||
|
||||
model: kDescendantLevel-1
|
||||
|
||||
delegate: StylePrivate.StyleItem {
|
||||
Layout.preferredWidth: controlRoot.width
|
||||
Layout.fillHeight: true
|
||||
visible: true
|
||||
// control: controlRoot
|
||||
elementType: "itembranchindicator"
|
||||
properties: {
|
||||
"isItem": false,
|
||||
"hasSibling": kDescendantHasSiblings[modelData]
|
||||
}
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
id: controlRoot
|
||||
Layout.preferredWidth: background.pixelMetric("treeviewindentation")
|
||||
Layout.fillHeight: true
|
||||
enabled: model.kDescendantExpandable
|
||||
text: model.kDescendantExpanded ? "-" : "+"
|
||||
onClicked: descendantsModel.toggleChildren(index)
|
||||
background: StylePrivate.StyleItem {
|
||||
id: styleitem
|
||||
control: controlRoot
|
||||
hover: controlRoot.hovered
|
||||
elementType: "itembranchindicator"
|
||||
on: model.kDescendantExpanded
|
||||
properties: {
|
||||
"isItem": true,
|
||||
"hasChildren": model.kDescendantExpandable,
|
||||
"hasSibling": model.kDescendantHasSiblings[model.kDescendantHasSiblings.length - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.display
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user