mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-05 16:55:25 +08:00
qt 6.5.1 original
This commit is contained in:
51
examples/widgets/itemviews/editabletreemodel/CMakeLists.txt
Normal file
51
examples/widgets/itemviews/editabletreemodel/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(editabletreemodel LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/editabletreemodel")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(editabletreemodel
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h mainwindow.ui
|
||||
treeitem.cpp treeitem.h
|
||||
treemodel.cpp treemodel.h
|
||||
)
|
||||
|
||||
set_target_properties(editabletreemodel PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(editabletreemodel PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(editabletreemodel_resource_files
|
||||
"default.txt"
|
||||
)
|
||||
|
||||
qt_add_resources(editabletreemodel "editabletreemodel"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${editabletreemodel_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS editabletreemodel
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
40
examples/widgets/itemviews/editabletreemodel/default.txt
Normal file
40
examples/widgets/itemviews/editabletreemodel/default.txt
Normal file
@ -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
|
@ -0,0 +1,16 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(treeview))
|
||||
|
||||
FORMS = mainwindow.ui
|
||||
HEADERS = mainwindow.h \
|
||||
treeitem.h \
|
||||
treemodel.h
|
||||
RESOURCES = editabletreemodel.qrc
|
||||
SOURCES = mainwindow.cpp \
|
||||
treeitem.cpp \
|
||||
treemodel.cpp \
|
||||
main.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/editabletreemodel
|
||||
INSTALLS += target
|
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>default.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
16
examples/widgets/itemviews/editabletreemodel/main.cpp
Normal file
16
examples/widgets/itemviews/editabletreemodel/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(editabletreemodel);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
137
examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
Normal file
137
examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "treemodel.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
const QStringList headers({tr("Title"), tr("Description")});
|
||||
|
||||
QFile file(":/default.txt");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
TreeModel *model = new TreeModel(headers, file.readAll(), this);
|
||||
file.close();
|
||||
|
||||
view->setModel(model);
|
||||
for (int column = 0; column < model->columnCount(); ++column)
|
||||
view->resizeColumnToContents(column);
|
||||
|
||||
connect(exitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
|
||||
|
||||
connect(view->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &MainWindow::updateActions);
|
||||
|
||||
connect(actionsMenu, &QMenu::aboutToShow, this, &MainWindow::updateActions);
|
||||
connect(insertRowAction, &QAction::triggered, this, &MainWindow::insertRow);
|
||||
connect(insertColumnAction, &QAction::triggered, this, &MainWindow::insertColumn);
|
||||
connect(removeRowAction, &QAction::triggered, this, &MainWindow::removeRow);
|
||||
connect(removeColumnAction, &QAction::triggered, this, &MainWindow::removeColumn);
|
||||
connect(insertChildAction, &QAction::triggered, this, &MainWindow::insertChild);
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::insertChild()
|
||||
{
|
||||
const 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) {
|
||||
const QModelIndex child = model->index(0, column, index);
|
||||
model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
|
||||
if (!model->headerData(column, Qt::Horizontal).isValid())
|
||||
model->setHeaderData(column, Qt::Horizontal, QVariant(tr("[No header]")), Qt::EditRole);
|
||||
}
|
||||
|
||||
view->selectionModel()->setCurrentIndex(model->index(0, 0, index),
|
||||
QItemSelectionModel::ClearAndSelect);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
bool MainWindow::insertColumn()
|
||||
{
|
||||
QAbstractItemModel *model = view->model();
|
||||
int column = view->selectionModel()->currentIndex().column();
|
||||
|
||||
// Insert a column in the parent item.
|
||||
bool changed = model->insertColumn(column + 1);
|
||||
if (changed)
|
||||
model->setHeaderData(column + 1, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);
|
||||
|
||||
updateActions();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void MainWindow::insertRow()
|
||||
{
|
||||
const 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) {
|
||||
const QModelIndex child = model->index(index.row() + 1, column, index.parent());
|
||||
model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::removeColumn()
|
||||
{
|
||||
QAbstractItemModel *model = view->model();
|
||||
const int column = view->selectionModel()->currentIndex().column();
|
||||
|
||||
// Insert columns in each child of the parent item.
|
||||
const bool changed = model->removeColumn(column);
|
||||
if (changed)
|
||||
updateActions();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void MainWindow::removeRow()
|
||||
{
|
||||
const QModelIndex index = view->selectionModel()->currentIndex();
|
||||
QAbstractItemModel *model = view->model();
|
||||
if (model->removeRow(index.row(), index.parent()))
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
const bool hasSelection = !view->selectionModel()->selection().isEmpty();
|
||||
removeRowAction->setEnabled(hasSelection);
|
||||
removeColumnAction->setEnabled(hasSelection);
|
||||
|
||||
const bool hasCurrent = view->selectionModel()->currentIndex().isValid();
|
||||
insertRowAction->setEnabled(hasCurrent);
|
||||
insertColumnAction->setEnabled(hasCurrent);
|
||||
|
||||
if (hasCurrent) {
|
||||
view->closePersistentEditor(view->selectionModel()->currentIndex());
|
||||
|
||||
const int row = view->selectionModel()->currentIndex().row();
|
||||
const int column = view->selectionModel()->currentIndex().column();
|
||||
if (view->selectionModel()->currentIndex().parent().isValid())
|
||||
statusBar()->showMessage(tr("Position: (%1,%2)").arg(row).arg(column));
|
||||
else
|
||||
statusBar()->showMessage(tr("Position: (%1,%2) in top level").arg(row).arg(column));
|
||||
}
|
||||
}
|
29
examples/widgets/itemviews/editabletreemodel/mainwindow.h
Normal file
29
examples/widgets/itemviews/editabletreemodel/mainwindow.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void updateActions();
|
||||
|
||||
private slots:
|
||||
void insertChild();
|
||||
bool insertColumn();
|
||||
void insertRow();
|
||||
bool removeColumn();
|
||||
void removeRow();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
128
examples/widgets/itemviews/editabletreemodel/mainwindow.ui
Normal file
128
examples/widgets/itemviews/editabletreemodel/mainwindow.ui
Normal file
@ -0,0 +1,128 @@
|
||||
<ui version="4.0" >
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>573</width>
|
||||
<height>468</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Editable Tree Model</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeView" name="view" >
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode" >
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="animated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>573</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="fileMenu" >
|
||||
<property name="title" >
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="exitAction" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="actionsMenu" >
|
||||
<property name="title" >
|
||||
<string>&Actions</string>
|
||||
</property>
|
||||
<addaction name="insertRowAction" />
|
||||
<addaction name="insertColumnAction" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="removeRowAction" />
|
||||
<addaction name="removeColumnAction" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="insertChildAction" />
|
||||
</widget>
|
||||
<addaction name="fileMenu" />
|
||||
<addaction name="actionsMenu" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar" />
|
||||
<action name="exitAction" >
|
||||
<property name="text" >
|
||||
<string>E&xit</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertRowAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Row</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+I, R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="removeRowAction" >
|
||||
<property name="text" >
|
||||
<string>Remove Row</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+R, R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertColumnAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Column</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+I, C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="removeColumnAction" >
|
||||
<property name="text" >
|
||||
<string>Remove Column</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+R, C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="insertChildAction" >
|
||||
<property name="text" >
|
||||
<string>Insert Child</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+N</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="editabletreemodel.qrc" />
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
141
examples/widgets/itemviews/editabletreemodel/treeitem.cpp
Normal file
141
examples/widgets/itemviews/editabletreemodel/treeitem.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
/*
|
||||
treeitem.cpp
|
||||
|
||||
A container for items of data supplied by the simple tree model.
|
||||
*/
|
||||
|
||||
#include "treeitem.h"
|
||||
|
||||
//! [0]
|
||||
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
|
||||
: itemData(data), parentItem(parent)
|
||||
{}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
TreeItem::~TreeItem()
|
||||
{
|
||||
qDeleteAll(childItems);
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
TreeItem *TreeItem::child(int number)
|
||||
{
|
||||
if (number < 0 || number >= childItems.size())
|
||||
return nullptr;
|
||||
return childItems.at(number);
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
int TreeItem::childCount() const
|
||||
{
|
||||
return childItems.count();
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
int TreeItem::childNumber() const
|
||||
{
|
||||
if (parentItem)
|
||||
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
|
||||
return 0;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
int TreeItem::columnCount() const
|
||||
{
|
||||
return itemData.count();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QVariant TreeItem::data(int column) const
|
||||
{
|
||||
if (column < 0 || column >= itemData.size())
|
||||
return QVariant();
|
||||
return itemData.at(column);
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
bool TreeItem::insertChildren(int position, int count, int columns)
|
||||
{
|
||||
if (position < 0 || position > childItems.size())
|
||||
return false;
|
||||
|
||||
for (int row = 0; row < count; ++row) {
|
||||
QList<QVariant> data(columns);
|
||||
TreeItem *item = new TreeItem(data, this);
|
||||
childItems.insert(position, item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
bool TreeItem::insertColumns(int position, int columns)
|
||||
{
|
||||
if (position < 0 || position > itemData.size())
|
||||
return false;
|
||||
|
||||
for (int column = 0; column < columns; ++column)
|
||||
itemData.insert(position, QVariant());
|
||||
|
||||
for (TreeItem *child : std::as_const(childItems))
|
||||
child->insertColumns(position, columns);
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
TreeItem *TreeItem::parent()
|
||||
{
|
||||
return parentItem;
|
||||
}
|
||||
//! [9]
|
||||
|
||||
//! [10]
|
||||
bool TreeItem::removeChildren(int position, int count)
|
||||
{
|
||||
if (position < 0 || position + count > childItems.size())
|
||||
return false;
|
||||
|
||||
for (int row = 0; row < count; ++row)
|
||||
delete childItems.takeAt(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
//! [10]
|
||||
|
||||
bool TreeItem::removeColumns(int position, int columns)
|
||||
{
|
||||
if (position < 0 || position + columns > itemData.size())
|
||||
return false;
|
||||
|
||||
for (int column = 0; column < columns; ++column)
|
||||
itemData.remove(position);
|
||||
|
||||
for (TreeItem *child : std::as_const(childItems))
|
||||
child->removeColumns(position, columns);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! [11]
|
||||
bool TreeItem::setData(int column, const QVariant &value)
|
||||
{
|
||||
if (column < 0 || column >= itemData.size())
|
||||
return false;
|
||||
|
||||
itemData[column] = value;
|
||||
return true;
|
||||
}
|
||||
//! [11]
|
36
examples/widgets/itemviews/editabletreemodel/treeitem.h
Normal file
36
examples/widgets/itemviews/editabletreemodel/treeitem.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef TREEITEM_H
|
||||
#define TREEITEM_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QList>
|
||||
|
||||
//! [0]
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
explicit TreeItem(const QList<QVariant> &data, TreeItem *parent = nullptr);
|
||||
~TreeItem();
|
||||
|
||||
TreeItem *child(int number);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
bool insertChildren(int position, int count, int columns);
|
||||
bool insertColumns(int position, int columns);
|
||||
TreeItem *parent();
|
||||
bool removeChildren(int position, int count);
|
||||
bool removeColumns(int position, int columns);
|
||||
int childNumber() const;
|
||||
bool setData(int column, const QVariant &value);
|
||||
|
||||
private:
|
||||
QList<TreeItem *> childItems;
|
||||
QList<QVariant> itemData;
|
||||
TreeItem *parentItem;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // TREEITEM_H
|
256
examples/widgets/itemviews/editabletreemodel/treemodel.cpp
Normal file
256
examples/widgets/itemviews/editabletreemodel/treemodel.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "treemodel.h"
|
||||
#include "treeitem.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
TreeModel::TreeModel(const QStringList &headers, const QString &data, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
QList<QVariant> rootData;
|
||||
for (const QString &header : headers)
|
||||
rootData << header;
|
||||
|
||||
rootItem = new TreeItem(rootData);
|
||||
setupModelData(data.split('\n'), rootItem);
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
TreeModel::~TreeModel()
|
||||
{
|
||||
delete rootItem;
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role != Qt::DisplayRole && role != Qt::EditRole)
|
||||
return QVariant();
|
||||
|
||||
TreeItem *item = getItem(index);
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
//! [3]
|
||||
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
TreeItem *TreeModel::getItem(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid()) {
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return rootItem;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
//! [5]
|
||||
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() != 0)
|
||||
return QModelIndex();
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
return QModelIndex();
|
||||
}
|
||||
//! [6]
|
||||
|
||||
bool TreeModel::insertColumns(int position, int columns, const QModelIndex &parent)
|
||||
{
|
||||
beginInsertColumns(parent, position, position + columns - 1);
|
||||
const bool success = rootItem->insertColumns(position, columns);
|
||||
endInsertColumns();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TreeModel::insertRows(int position, int rows, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return false;
|
||||
|
||||
beginInsertRows(parent, position, position + rows - 1);
|
||||
const bool success = parentItem->insertChildren(position,
|
||||
rows,
|
||||
rootItem->columnCount());
|
||||
endInsertRows();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//! [7]
|
||||
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *childItem = getItem(index);
|
||||
TreeItem *parentItem = childItem ? childItem->parent() : nullptr;
|
||||
|
||||
if (parentItem == rootItem || !parentItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->childNumber(), 0, parentItem);
|
||||
}
|
||||
//! [7]
|
||||
|
||||
bool TreeModel::removeColumns(int position, int columns, const QModelIndex &parent)
|
||||
{
|
||||
beginRemoveColumns(parent, position, position + columns - 1);
|
||||
const bool success = rootItem->removeColumns(position, columns);
|
||||
endRemoveColumns();
|
||||
|
||||
if (rootItem->columnCount() == 0)
|
||||
removeRows(0, rowCount());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TreeModel::removeRows(int position, int rows, const QModelIndex &parent)
|
||||
{
|
||||
TreeItem *parentItem = getItem(parent);
|
||||
if (!parentItem)
|
||||
return false;
|
||||
|
||||
beginRemoveRows(parent, position, position + rows - 1);
|
||||
const bool success = parentItem->removeChildren(position, rows);
|
||||
endRemoveRows();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//! [8]
|
||||
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
const TreeItem *parentItem = getItem(parent);
|
||||
|
||||
return parentItem ? parentItem->childCount() : 0;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
TreeItem *item = getItem(index);
|
||||
bool result = item->setData(index.column(), value);
|
||||
|
||||
if (result)
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TreeModel::setHeaderData(int section, Qt::Orientation orientation,
|
||||
const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole || orientation != Qt::Horizontal)
|
||||
return false;
|
||||
|
||||
const bool result = rootItem->setData(section, value);
|
||||
|
||||
if (result)
|
||||
emit headerDataChanged(orientation, section, section);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
|
||||
{
|
||||
QList<TreeItem *> parents;
|
||||
QList<int> indentations;
|
||||
parents << parent;
|
||||
indentations << 0;
|
||||
|
||||
int number = 0;
|
||||
|
||||
while (number < lines.count()) {
|
||||
int position = 0;
|
||||
while (position < lines[number].length()) {
|
||||
if (lines[number].at(position) != ' ')
|
||||
break;
|
||||
++position;
|
||||
}
|
||||
|
||||
const QString lineData = lines[number].mid(position).trimmed();
|
||||
|
||||
if (!lineData.isEmpty()) {
|
||||
// Read the column data from the rest of the line.
|
||||
const QStringList columnStrings =
|
||||
lineData.split(QLatin1Char('\t'), Qt::SkipEmptyParts);
|
||||
QList<QVariant> columnData;
|
||||
columnData.reserve(columnStrings.size());
|
||||
for (const QString &columnString : columnStrings)
|
||||
columnData << columnString;
|
||||
|
||||
if (position > indentations.last()) {
|
||||
// The last child of the current parent is now the new parent
|
||||
// unless the current parent has no children.
|
||||
|
||||
if (parents.last()->childCount() > 0) {
|
||||
parents << parents.last()->child(parents.last()->childCount()-1);
|
||||
indentations << position;
|
||||
}
|
||||
} else {
|
||||
while (position < indentations.last() && parents.count() > 0) {
|
||||
parents.pop_back();
|
||||
indentations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Append a new item to the current parent's list of children.
|
||||
TreeItem *parent = parents.last();
|
||||
parent->insertChildren(parent->childCount(), 1, rootItem->columnCount());
|
||||
for (int column = 0; column < columnData.size(); ++column)
|
||||
parent->child(parent->childCount() - 1)->setData(column, columnData[column]);
|
||||
}
|
||||
++number;
|
||||
}
|
||||
}
|
60
examples/widgets/itemviews/editabletreemodel/treemodel.h
Normal file
60
examples/widgets/itemviews/editabletreemodel/treemodel.h
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef TREEMODEL_H
|
||||
#define TREEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
|
||||
class TreeItem;
|
||||
|
||||
//! [0]
|
||||
class TreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TreeModel(const QStringList &headers, const QString &data,
|
||||
QObject *parent = nullptr);
|
||||
~TreeModel();
|
||||
//! [0] //! [1]
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
bool setHeaderData(int section, Qt::Orientation orientation,
|
||||
const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
bool insertColumns(int position, int columns,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool removeColumns(int position, int columns,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool insertRows(int position, int rows,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
bool removeRows(int position, int rows,
|
||||
const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
void setupModelData(const QStringList &lines, TreeItem *parent);
|
||||
TreeItem *getItem(const QModelIndex &index) const;
|
||||
|
||||
TreeItem *rootItem;
|
||||
};
|
||||
//! [2]
|
||||
|
||||
#endif // TREEMODEL_H
|
Reference in New Issue
Block a user