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:
2026-04-14 10:51:06 +01:00
parent 51f3c21121
commit cf12defd28
15214 changed files with 20594243 additions and 269 deletions
@@ -0,0 +1,19 @@
remove_definitions(-DQT_NO_CAST_TO_ASCII)
remove_definitions(-DQT_NO_CAST_FROM_ASCII)
add_subdirectory(proxymodeltestapp)
macro(kitemmodels_widgets_tests)
foreach(_testname ${ARGN})
add_executable(${_testname} ${_testname}.cpp)
target_link_libraries(${_testname}
KF6::ItemModels
Qt6::Widgets
)
ecm_mark_as_test(${_testname})
endforeach()
endmacro(kitemmodels_widgets_tests)
kitemmodels_widgets_tests(
rearrangecolumns
)
@@ -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
)
@@ -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"
@@ -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
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
@@ -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
@@ -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
@@ -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"
@@ -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
@@ -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"
@@ -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
@@ -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"
@@ -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
@@ -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"
@@ -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

@@ -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"
@@ -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
@@ -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"
@@ -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
}
}
}
@@ -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")));
}
@@ -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
@@ -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
}
}
}
}
}
@@ -0,0 +1,20 @@
import QtQuick
import org.kde.kitemmodels as KItemModels
// This test is somewhat lame in that it should only display a single "1".
// ListModel only has one column and no way of adding more. And there is not
// really another model that is simple to create from QML that does have columns
// and column headers.
ListView {
model: KItemModels.KColumnHeadersModel {
sourceModel: ListModel {
ListElement { display: "test1" }
ListElement { display: "test2" }
}
}
delegate: Text {
text: model.display
}
}
@@ -0,0 +1,48 @@
/*
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
SPDX-FileContributor: David Faure <david.faure@kdab.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include <KRearrangeColumnsProxyModel>
#include <QApplication>
#include <QStandardItemModel>
#include <QTimer>
#include <QTreeView>
// Prepares one row for a QStandardItemModel
inline QList<QStandardItem *> makeStandardItems(const QStringList &texts)
{
QList<QStandardItem *> items;
items.reserve(texts.count());
for (const QString &txt : texts) {
items << new QStandardItem(txt);
}
return items;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QStandardItemModel source;
source.insertRow(0, makeStandardItems({QStringLiteral("A0"), QStringLiteral("B0"), QStringLiteral("C0"), QStringLiteral("D0")}));
source.insertRow(1, makeStandardItems({QStringLiteral("A1"), QStringLiteral("B1"), QStringLiteral("C1"), QStringLiteral("D1")}));
source.insertRow(2, makeStandardItems({QStringLiteral("A2"), QStringLiteral("B2"), QStringLiteral("C2"), QStringLiteral("D2")}));
source.setHorizontalHeaderLabels({QStringLiteral("H1"), QStringLiteral("H2"), QStringLiteral("H3"), QStringLiteral("H4")});
KRearrangeColumnsProxyModel pm;
pm.setSourceColumns(QList<int>{2, 3, 1, 0});
pm.setSourceModel(&source);
QTreeView treeView;
treeView.setModel(&pm);
treeView.show();
QTimer::singleShot(500, &pm, [&]() {
pm.setSourceColumns(QList<int>{2, 1, 0, 3});
});
return app.exec();
}