# HG changeset patch # User mandel # Date 1245113498 0 # Node ID ea0861a37bf6c6b599491d214f35cb1cb46a7c2b # Parent 4d1c5d1d1bbffcf0bb969a5f6fbe341b31566c0b add editabletreemodel, still buggy diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/CMakeLists.txt Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,1 @@ +build_example(editabletreemodel main.d mainwindow.d treeitem.d treemodel.d ui_mainwindow.d qrc_editabletreemodel.d) \ No newline at end of file diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/build.bat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/build.bat Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,3 @@ +../../../tools/drcc/drcc editabletreemodel.qrc -o qrc_editabletreemodel.d +../../../tools/duic/duic mainwindow.ui -o ui_mainwindow.d +dmd main.d mainwindow.d treeitem.d treemodel.d ui_mainwindow.d qrc_editabletreemodel.d libqtdcore.lib libqtdgui.lib -I../../../ \ No newline at end of file diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/build.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/build.sh Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,5 @@ +#! /bin/bash + +../../../tools/drcc/drcc editabletreemodel.qrc -o qrc_editabletreemodel.d +../../../tools/duic/duic mainwindow.ui -o ui_mainwindow.d +ldc main.d mainwindow.d treeitem.d treemodel.d ui_mainwindow.d qrc_editabletreemodel.d -I../../../ -I../../../qt/d1 -L-L../../../lib -L-lqtdgui -L-lqtdcore -L-lQtCore -L-lQtGui -ofeditabletreemodel \ No newline at end of file diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/default.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/default.txt Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,40 @@ +Getting Started How to familiarize yourself with Qt Designer + Launching Designer Running the Qt Designer application + The User Interface How to interact with Qt Designer + +Designing a Component Creating a GUI for your application + Creating a Dialog How to create a dialog + Composing the Dialog Putting widgets into the dialog example + Creating a Layout Arranging widgets on a form + Signal and Slot Connections Making widget communicate with each other + +Using a Component in Your Application Generating code from forms + The Direct Approach Using a form without any adjustments + The Single Inheritance Approach Subclassing a form's base class + The Multiple Inheritance Approach Subclassing the form itself + Automatic Connections Connecting widgets using a naming scheme + A Dialog Without Auto-Connect How to connect widgets without a naming scheme + A Dialog With Auto-Connect Using automatic connections + +Form Editing Mode How to edit a form in Qt Designer + Managing Forms Loading and saving forms + Editing a Form Basic editing techniques + The Property Editor Changing widget properties + The Object Inspector Examining the hierarchy of objects on a form + Layouts Objects that arrange widgets on a form + Applying and Breaking Layouts Managing widgets in layouts + Horizontal and Vertical Layouts Standard row and column layouts + The Grid Layout Arranging widgets in a matrix + Previewing Forms Checking that the design works + +Using Containers How to group widgets together + General Features Common container features + Frames QFrame + Group Boxes QGroupBox + Stacked Widgets QStackedWidget + Tab Widgets QTabWidget + Toolbox Widgets QToolBox + +Connection Editing Mode Connecting widgets together with signals and slots + Connecting Objects Making connections in Qt Designer + Editing Connections Changing existing connections diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/editabletreemodel.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/editabletreemodel.qrc Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,5 @@ + + + default.txt + + diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/main.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/main.d Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +module main; + + +import qt.gui.QApplication; + +import mainwindow; + + +int main(string[] args) +{ + scope app = new QApplication(args); + scope window = new MainWindow; + window.show(); + return app.exec(); +} diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/mainwindow.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/mainwindow.d Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +module mainwindow; + + +import qt.core.QModelIndex; +import qt.core.QFile; +import qt.gui.QMainWindow; +import qt.gui.QAction; +import qt.gui.QTreeView; +import qt.gui.QWidget; + +import tango.text.convert.Format; + +import ui_mainwindow; +import mainwindow; +import treemodel; + + +class MainWindow : public QMainWindow +{ + +mixin Ui_MainWindow; + +public: + + this(QWidget parent = null) + { + super(parent); + setupUi(this); + + string[] headers; + headers ~= tr("Title"); + headers ~= tr("Description"); + + auto file = new QFile(":/default.txt"); + file.open(QIODevice.ReadOnly); + TreeModel model = new TreeModel(headers, file.readAll().data()[0..file.size()]); + file.close(); + + view.setModel(model); + for (int column = 0; column < model.columnCount(); ++column) + view.resizeColumnToContents(column); + + exitAction.triggered.connect(&QApplication.quit); + + view.selectionModel().selectionChanged.connect(&this.updateActions); + + actionsMenu.aboutToShow.connect(&this.updateActions); + insertRowAction.triggered.connect(&this.insertRow); + insertColumnAction.triggered.connect(&this.insertColumn); + removeRowAction.triggered.connect(&this.removeRow); + removeColumnAction.triggered.connect(&this.removeColumn); + insertChildAction.triggered.connect(&this.insertChild); + + updateActions(); + } + +public: + + void updateActions() + { + bool hasSelection = !view.selectionModel().selection().isEmpty(); + removeRowAction.setEnabled(hasSelection); + removeColumnAction.setEnabled(hasSelection); + + bool hasCurrent = view.selectionModel().currentIndex().isValid(); + insertRowAction.setEnabled(hasCurrent); + insertColumnAction.setEnabled(hasCurrent); + + if (hasCurrent) { + view.closePersistentEditor(view.selectionModel().currentIndex()); + + int row = view.selectionModel().currentIndex().row(); + int column = view.selectionModel().currentIndex().column(); + if (view.selectionModel().currentIndex().parent().isValid()) + statusBar().showMessage(Format(tr("Position: ({},{})"), row, column)); + else + statusBar().showMessage(Format(tr("Position: ({},{}) in top level"), row, column)); + } + } + +private: + + void insertChild() + { + QModelIndex index = view.selectionModel().currentIndex(); + QAbstractItemModel model = view.model(); + + if (model.columnCount(index) == 0) { + if (!model.insertColumn(0, index)) + return; + } + + if (!model.insertRow(0, index)) + return; + + for (int column = 0; column < model.columnCount(index); ++column) { + QModelIndex child = model.index(0, column, index); + model.setData(child, QVariant("[No data]"), Qt.EditRole); + if (!model.headerData(column, Qt.Horizontal).isValid()) + model.setHeaderData(column, Qt.Horizontal, QVariant("[No header]"), Qt.EditRole); + } + + view.selectionModel().setCurrentIndex(model.index(0, 0, index), QItemSelectionModel.ClearAndSelect); + updateActions(); + } + + bool insertColumn() + { + QModelIndex parent = QModelIndex(); //moved from method head + QAbstractItemModel model = view.model(); + int column = view.selectionModel().currentIndex().column(); + + // Insert a column in the parent item. + bool changed = model.insertColumn(column + 1, parent); + if (changed) + model.setHeaderData(column + 1, Qt.Horizontal, QVariant("[No header]"), Qt.EditRole); + + updateActions(); + + return changed; + } + + void insertRow() + { + QModelIndex index = view.selectionModel().currentIndex(); + QAbstractItemModel model = view.model(); + + if (!model.insertRow(index.row()+1, index.parent())) + return; + + updateActions(); + + for (int column = 0; column < model.columnCount(index.parent()); ++column) { + QModelIndex child = model.index(index.row()+1, column, index.parent()); + model.setData(child, QVariant("[No data]"), Qt.EditRole); + } + } + + bool removeColumn() + { + QModelIndex parent = QModelIndex(); //moved from method head + QAbstractItemModel model = view.model(); + int column = view.selectionModel().currentIndex().column(); + + // Insert columns in each child of the parent item. + bool changed = model.removeColumn(column, parent); + + if (!parent.isValid() && changed) + updateActions(); + + return changed; + } + + void removeRow() + { + QModelIndex index = view.selectionModel().currentIndex(); + QAbstractItemModel model = view.model(); + if (model.removeRow(index.row(), index.parent())) + updateActions(); + } + +} diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/mainwindow.ui --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/mainwindow.ui Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,128 @@ + + MainWindow + + + + 0 + 0 + 573 + 468 + + + + Editable Tree Model + + + + + 0 + + + 0 + + + + + true + + + QAbstractItemView::SelectItems + + + QAbstractItemView::ScrollPerPixel + + + false + + + true + + + + + + + + + 0 + 0 + 573 + 31 + + + + + &File + + + + + + &Actions + + + + + + + + + + + + + + + + E&xit + + + Ctrl+Q + + + + + Insert Row + + + Ctrl+I, R + + + + + Remove Row + + + Ctrl+R, R + + + + + Insert Column + + + Ctrl+I, C + + + + + Remove Column + + + Ctrl+R, C + + + + + Insert Child + + + Ctrl+N + + + + + + + + diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/treeitem.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/treeitem.d Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +module treeitem; + + +import qt.core.QVariant; + +import tango.core.Array; + + +//substitute for QList methods +void insert(T)(ref T[] items, int pos, T item) +{ + items = items[0..pos] ~ [item] ~ items[pos..$]; +} + +T takeAt(T)(ref T[] items, int pos) +{ + T item = items[pos]; + items = items[0..pos] ~ items[pos+1..$]; + return item; +} + +int indexOf(T)(T[] items, T item, int from = -1) +{ + assert(from < cast(int) items.length); + auto beg = (from < 0) ? 0 : from; + auto pos = beg + find(items[beg..$], item); + return (pos == items.length) ? -1 : pos; +} + +void remove(T)(ref T[] items, uint pos) +{ + items = items[0..pos] ~ items[pos+1..$]; +} + + +class TreeItem +{ +public: + + this(QVariant[] data, TreeItem parent = null) + { + parentItem = parent; + itemData = data; + } + + ~this() + { + delete childItems; + } + + TreeItem child(int number) + { + if(number < 0 || number >= childItems.length) + return null; + return childItems[number]; + } + + int childCount() + { + return childItems.length; + } + + int columnCount() + { + return itemData.length; + } + + QVariant data(int column) + { + if(column < 0 || column >= itemData.length) + return null; + return itemData[column]; + } + + bool insertChildren(int position, int count, int columns) + { + if (position < 0 || position > childItems.length) + return false; + + for (int row = 0; row < count; ++row) { + auto data = new QVariant[](columns); + TreeItem item = new TreeItem(data, this); + insert(childItems, position, item); + } + + return true; + } + + bool insertColumns(int position, int columns) + { + if (position < 0 || position > itemData.length) + return false; + + for (int column = 0; column < columns; ++column) + insert(itemData, position, new QVariant()); + + foreach (TreeItem child; childItems) + child.insertColumns(position, columns); + + return true; + } + + TreeItem parent() + { + return parentItem; + } + + bool removeChildren(int position, int count) + { + if (position < 0 || position + count > childItems.length) + return false; + + for (int row = 0; row < count; ++row) + { + auto tmp = takeAt(childItems, position); + delete tmp; + } + return true; + } + + bool removeColumns(int position, int columns) + { + if (position < 0 || position + columns > itemData.length) + return false; + + for (int column = 0; column < columns; ++column) + remove(itemData, position); + + foreach (TreeItem child; childItems) + child.removeColumns(position, columns); + + return true; + } + + int childNumber() + { + if (parentItem) + return indexOf(parentItem.childItems, cast(TreeItem) this); + + return 0; + } + + bool setData(int column, QVariant value) + { + if (column < 0 || column >= itemData.length) + return false; + + itemData[column] = value; + return true; + } + +private: + + TreeItem[] childItems; + QVariant[] itemData; + TreeItem parentItem; +} diff -r 4d1c5d1d1bbf -r ea0861a37bf6 examples/itemviews/editabletreemodel/treemodel.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/itemviews/editabletreemodel/treemodel.d Tue Jun 16 00:51:38 2009 +0000 @@ -0,0 +1,317 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +module treemodel; + + +import qt.core.QAbstractItemModel; +import qt.core.QModelIndex; +import qt.core.QVariant; + +import treeitem; + +import tango.core.Array : find; +import tango.text.Util : trim; + + +//replacement for QString.split +T[][] split(T)(T[] str, T[] match, bool keep_empty = true) +{ + uint pos, start = 0; + + T[][] values; + if(str.length == 0) + return values; + + while(true) + { + pos = start + find(str[start..$], match); + if(keep_empty) + { + if((pos - start) >= 0) + values ~= str[start..pos]; + } + else + { + if((pos - start) != 0) + values ~= str[start..pos]; + } + + if(pos == str.length) + break; + + start = pos + 1; + } + + return values; +} + + +class TreeModel : public QAbstractItemModel +{ +public: + + this(string[] headers, string data, QObject parent = null) + { + super(parent); + QVariant[] rootData; + foreach(string header; headers) + rootData ~= new QVariant(header); + + rootItem = new TreeItem(rootData); + setupModelData(split(data, "\n"), rootItem); + } + + ~this() + { + delete rootItem; + } + + QVariant data(QModelIndex index, int role) + { + if (!index.isValid()) + return new QVariant(); + + if (role != Qt.DisplayRole && role != Qt.EditRole) + return new QVariant(); + + TreeItem item = getItem(index); + return item.data(index.column()); + } + + QVariant headerData(int section, Qt.Orientation orientation, int role = Qt.DisplayRole) + { + if (orientation == Qt.Horizontal && role == Qt.DisplayRole) + return rootItem.data(section); + + return new QVariant(); + } + + QModelIndex index(int row, int column, QModelIndex parent = QModelIndex()) + { + if (parent.isValid() && parent.column() != 0) + return QModelIndex(); + + TreeItem parentItem = getItem(parent); + + TreeItem childItem = parentItem.child(row); + if (childItem) + return createIndex(row, column, cast(void*) childItem); + else + return QModelIndex(); + } + + QModelIndex parent(QModelIndex index) + { + if (!index.isValid()) + return QModelIndex(); + + TreeItem childItem = getItem(index); + TreeItem parentItem = childItem.parent(); + + if (parentItem == rootItem) + return QModelIndex(); + + return createIndex(parentItem.childNumber(), 0, cast(void*) parentItem); + } + + int rowCount(QModelIndex parent = QModelIndex()) + { + TreeItem parentItem = getItem(parent); + return parentItem.childCount(); + } + + int columnCount(QModelIndex parent = QModelIndex()) + { + return rootItem.columnCount(); + } + + int flags(QModelIndex index) + { + if (!index.isValid()) + return 0; + + return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable; + } + + + bool setData(QModelIndex index, QVariant value, int role = Qt.EditRole) + { + if (role != Qt.EditRole) + return false; + + TreeItem item = getItem(index); + bool result = item.setData(index.column(), value); + + if (result) + dataChanged.emit(index, index); + + return result; + } + + bool setHeaderData(int section, Qt.Orientation orientation, QVariant value, int role = Qt.EditRole) + { + if (role != Qt.EditRole || orientation != Qt.Horizontal) + return false; + + bool result = rootItem.setData(section, value); + + if (result) + headerDataChanged.emit(orientation, section, section); + + return result; + } + + bool insertColumns(int position, int columns, QModelIndex parent = QModelIndex()) + { + bool success; + + beginInsertColumns(parent, position, position + columns - 1); + success = rootItem.insertColumns(position, columns); + endInsertColumns(); + + return success; + } + + + bool removeColumns(int position, int columns, QModelIndex parent = QModelIndex()) + { + bool success; + + beginRemoveColumns(parent, position, position + columns - 1); + success = rootItem.removeColumns(position, columns); + endRemoveColumns(); + + if (rootItem.columnCount() == 0) + removeRows(0, rowCount()); + + return success; + } + + + bool insertRows(int position, int rows, QModelIndex parent = QModelIndex()) + { + TreeItem parentItem = getItem(parent); + bool success; + + beginInsertRows(parent, position, position + rows - 1); + success = parentItem.insertChildren(position, rows, rootItem.columnCount()); + endInsertRows(); + + return success; + } + + bool removeRows(int position, int rows, QModelIndex parent = QModelIndex()) + { + TreeItem parentItem = getItem(parent); + bool success = true; + + beginRemoveRows(parent, position, position + rows - 1); + success = parentItem.removeChildren(position, rows); + endRemoveRows(); + + return success; + } + +private: + + void setupModelData(string[] lines, TreeItem parent) + { + TreeItem[] parents; + int[] indentations; + parents ~= parent; + indentations ~= 0; + + int number = 0; + + while (number < lines.length) { + int position = 0; + while (position < lines[number].length) { + if (lines[number][position] != ' ') + break; + position++; + } + + string lineData = trim(lines[number][position..$]); + + if (lineData.length) { + // Read the column data from the rest of the line. + string[] columnStrings = split(lineData, "\t", false); + QVariant[] columnData; + for (int column = 0; column < columnStrings.length; ++column) + columnData ~= new QVariant(columnStrings[column]); + + if (position > indentations[$-1]) { + // The last child of the current parent is now the new parent + // unless the current parent has no children. + + if (parents[$-1].childCount() > 0) { + parents ~= parents[$-1].child(parents[$-1].childCount()-1); + indentations ~= position; + } + } else { + while (position < indentations[$-1] && parents.length > 0) { + parents = parents[0..$-1]; + indentations = indentations[0..$-1]; + } + } + + // Append a new item to the current parent's list of children. + parent = parents[$-1]; + parent.insertChildren(parent.childCount(), 1, rootItem.columnCount()); + for (int column = 0; column < columnData.length; ++column) + parent.child(parent.childCount() - 1).setData(column, columnData[column]); + } + + number++; + } + } + + TreeItem getItem(QModelIndex index) + { + if (index.isValid()) { + TreeItem item = cast(TreeItem) index.internalPointer(); + if (item) return item; + } + return rootItem; + } + + TreeItem rootItem; +}