Skip to content

Commit

Permalink
Release v0.2
Browse files Browse the repository at this point in the history
Implemented data manipulation.
Added example to show the new feature
  • Loading branch information
Daguerreo committed Jan 17, 2022
2 parents 07414a6 + 5f58499 commit 876c832
Show file tree
Hide file tree
Showing 16 changed files with 397 additions and 32 deletions.
9 changes: 8 additions & 1 deletion QMLTreeView.pro
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ SUBDIRS += \
examples/CustomDelegateTreeView \
examples/JsonTreeView \
examples/SimpleTreeView \
examples/StyledTreeView
examples/StyledTreeView \
examples/TreeManipulation

HEADERS += \
plugin/treemanipulator.h

SOURCES += \
plugin/treemanipulator.cpp
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ Data access for row element is provided by the properties:
- ```currentData```: return the data for the selected element
- ```currentItem```: return the visual item of the selected element

## Node Manipulation

```TreeModel``` provides the methods ```addTopLevelItem,``` ```addItem```, ```removeItem``` and ```clear``` to add and remove node to the tree. ```setData``` instead provides a way to change the data of a given node.
Take a look at the **Manipulator Example** which show a way to manipulate the tree directly from QML.

![](img/manipulation.png)

## Customizing Models

Expand Down
35 changes: 14 additions & 21 deletions examples/SimpleTreeView/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,23 @@ import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
id: root
id: root

visible: true
width: 400
height: 400
title: qsTr("Simple TreeView")
visible: true
width: 400
height: 400
title: qsTr("Simple TreeView")

Rectangle {
anchors.fill: parent
border.width: 1
border.color: "black"
clip: true
TreeView {
id: defaultTreeView

TreeView {
id: defaultTreeView
anchors.fill: parent
anchors.margins: 1

anchors.fill: parent
anchors.margins: 1
model: treeModel

model: treeModel

onCurrentIndexChanged: console.log("current index is (row=" + currentIndex.row + ", depth=" + model.depth(currentIndex) + ")")
onCurrentDataChanged: console.log("current data is " + currentData)
onCurrentItemChanged: console.log("current item is " + currentItem)
}
}
onCurrentIndexChanged: console.log("current index is (row=" + currentIndex.row + ", depth=" + model.depth(currentIndex) + ")")
onCurrentDataChanged: console.log("current data is " + currentData)
onCurrentItemChanged: console.log("current item is " + currentItem)
}
}
31 changes: 31 additions & 0 deletions examples/TreeManipulation/TreeManipulation.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
QT += quick

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

RESOURCES += qml.qrc \
../../plugin/treeview.qrc \
qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

HEADERS += \
../../plugin/tree_item.h \
../../plugin/tree_model.h \
tree_manipulator.h

SOURCES += \
../../plugin/tree_item.cpp \
../../plugin/tree_model.cpp \
main.cpp \
tree_manipulator.cpp

INCLUDEPATH += \
../../plugin
31 changes: 31 additions & 0 deletions examples/TreeManipulation/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "tree_model.h"
#include "tree_manipulator.h"


int main(int argc, char *argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;

auto treeModel = new TreeModel(&engine);
auto treeManipulator = new TreeManipulator(*treeModel, &engine);

engine.rootContext()->setContextProperty("treeManipulator", QVariant::fromValue(treeManipulator));

const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);

return app.exec();
}
110 changes: 110 additions & 0 deletions examples/TreeManipulation/main.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12

Window {
width: 600
height: 400
visible: true
title: qsTr("Tree Manipulation")


ColumnLayout {
anchors.fill: parent


TreeView {
id: treeView

Layout.fillWidth: true
Layout.fillHeight: true

model: treeManipulator.sourceModel()
selectionEnabled: true

onCurrentIndexChanged: if(currentIndex) console.log("current index is (row=" + currentIndex.row + ", depth=" + model.depth(currentIndex) + ")")
onCurrentDataChanged: if(currentData) console.log("current data is " + currentData)
onCurrentItemChanged: if(currentItem) console.log("current item is " + currentItem)

}

ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true

MenuSeparator {
Layout.fillWidth: true
}

TextArea {
id: txtEdit

Layout.fillWidth: true

placeholderText: "Write data to add..."

function notEmpty() { return text !== ""}
function clear() { text = "" }
}

Row {
Layout.margins: 8
spacing: 16

Button {
id: addBtn
text: "Add top level item"
enabled: txtEdit.notEmpty()

onClicked: {
treeManipulator.addTopLevelItem(txtEdit.text)
txtEdit.clear()
}
}

Button {
id: addChildBtn
text: "Add child item"
enabled: txtEdit.notEmpty() && treeView.currentItem

onClicked: {
treeManipulator.addItem(treeView.currentIndex, txtEdit.text)
txtEdit.clear()
}
}

Button {
id: delBtn
text: "Remove item"
enabled: treeView.currentItem

onClicked: {
treeManipulator.removeItem(treeView.currentIndex)
}
}


Button {
id: editBtn
text: "Edit item"
enabled: txtEdit.notEmpty() && treeView.currentItem

onClicked: {
treeManipulator.editItem(treeView.currentIndex, txtEdit.text)
txtEdit.clear()
}
}

Button {
id: clearBtn
text: "Clear tree"

onClicked: {
treeManipulator.reset();
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions examples/TreeManipulation/qml.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
53 changes: 53 additions & 0 deletions examples/TreeManipulation/tree_manipulator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "tree_manipulator.h"
#include "tree_model.h"
#include "tree_item.h"

TreeManipulator::TreeManipulator(TreeModel& model, QObject* parent)
: QObject(parent),
_model(&model)
{
}

QVariant TreeManipulator::sourceModel() const
{
return QVariant::fromValue(_model);
}

void TreeManipulator::addTopLevelItem(const QString& data)
{
_model->addTopLevelItem(new TreeItem(data));
}

void TreeManipulator::addItem(const QModelIndex& index, const QString& data)
{
if(!index.isValid()){
return;
}

auto parent = static_cast<TreeItem*>(index.internalPointer());
_model->addItem(parent, new TreeItem(data));
}

void TreeManipulator::removeItem(const QModelIndex& index)
{
if(!index.isValid()){
return;
}

auto item = static_cast<TreeItem*>(index.internalPointer());
_model->removeItem(item);
}

void TreeManipulator::editItem(const QModelIndex& index, const QString& data)
{
if(!index.isValid()){
return;
}

_model->setData(index, data);
}

void TreeManipulator::reset()
{
_model->clear();
}
30 changes: 30 additions & 0 deletions examples/TreeManipulation/tree_manipulator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef TREE_MANIPULATOR_H
#define TREE_MANIPULATOR_H

#include <QObject>
#include <QVariant>

class TreeModel;

/*!
* Expose manipulation feature of the Tree Model to QML
*/
class TreeManipulator : public QObject
{
Q_OBJECT

public:
explicit TreeManipulator(TreeModel& model, QObject* parent = nullptr);

Q_INVOKABLE QVariant sourceModel() const;
Q_INVOKABLE void addTopLevelItem(const QString& data);
Q_INVOKABLE void addItem(const QModelIndex& index, const QString& data);
Q_INVOKABLE void removeItem(const QModelIndex& index);
Q_INVOKABLE void editItem(const QModelIndex& index, const QString& data);
Q_INVOKABLE void reset();

private:
TreeModel* _model;
};

#endif // TREE_MANIPULATOR_H
Binary file added img/manipulation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 21 additions & 9 deletions plugin/TreeView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import QtQml 2.15
Flickable {
id: root

implicitWidth: 400
implicitHeight: 400
clip: true

property var model
readonly property alias currentIndex: tree.selectedIndex
readonly property alias currentItem: tree.currentItem
Expand Down Expand Up @@ -70,11 +74,11 @@ Flickable {
property int handleStyle: TreeView.Handle.Triangle

contentHeight: tree.height
contentWidth: parent.width
contentWidth: width
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: ScrollBar {}

Connections { function onCurrentIndexChanged() { currentData = model.data(currentIndex) } }
Connections { function onCurrentIndexChanged() { if(currentIndex) currentData = model.data(currentIndex) } }

TreeViewItem {
id: tree
Expand All @@ -91,6 +95,14 @@ Flickable {
selectedItemColor: root.selectedItemColor
defaultIndicator: indicatorToString(handleStyle)
z: 1

Connections {
target: root.model
ignoreUnknownSignals: true
function onLayoutChanged() {
tree.childCount = root.model ? root.model.rowCount(tree.parentIndex) : 0
}
}
}

Loader {
Expand All @@ -112,13 +124,13 @@ Flickable {

function indicatorToString(handle){
switch (handle){
case TreeView.Handle.Triangle: return "";
case TreeView.Handle.TriangleSmall: return "";
case TreeView.Handle.TriangleOutline: return "";
case TreeView.Handle.TriangleSmallOutline: return "";
case TreeView.Handle.Chevron: return "";
case TreeView.Handle.Arrow: return "";
default: return "";
case TreeView.Handle.Triangle: return "";
case TreeView.Handle.TriangleSmall: return "";
case TreeView.Handle.TriangleOutline: return "";
case TreeView.Handle.TriangleSmallOutline: return "";
case TreeView.Handle.Chevron: return "";
case TreeView.Handle.Arrow: return "";
default: return "";
}
}
}
Loading

0 comments on commit 876c832

Please sign in to comment.