Qt MVC示例 simpletreemodel 树模型
从文本中读取树模型数据,缩进代表子项
TreeItem
表示一行字符串数据
treeitem.h
#ifndef TREEITEM_H
#define TREEITEM_H#include <QList>
#include <QVariant>//! [0]
class TreeItem
{
public:explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = 0);~TreeItem();void appendChild(TreeItem *child);TreeItem *child(int row);int childCount() const;int columnCount() const;QVariant data(int column) const;int row() const;TreeItem *parentItem();private:QList<TreeItem*> m_childItems;QList<QVariant> m_itemData;TreeItem *m_parentItem;
};
//! [0]#endif // TREEITEM_H
treeitem.cpp
/*treeitem.cppA container for items of data supplied by the simple tree model.
*/#include <QStringList>#include "treeitem.h"//! [0] 当前项数据data,父项parent
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
{m_parentItem = parent;m_itemData = data;
}
//! [0]//! [1]
TreeItem::~TreeItem()
{qDeleteAll(m_childItems);
}
//! [1]//! [2] 添加子项
void TreeItem::appendChild(TreeItem *item)
{m_childItems.append(item);
}
//! [2]//! [3] 子项,通过行索引返回
TreeItem *TreeItem::child(int row)
{return m_childItems.value(row);
}
//! [3]//! [4] 子项数
int TreeItem::childCount() const
{return m_childItems.count();
}
//! [4]//! [5] 列数
int TreeItem::columnCount() const
{return m_itemData.count();
}
//! [5]//! [6] 列数据,索引每一列的字符串单词
QVariant TreeItem::data(int column) const
{return m_itemData.value(column);
}
//! [6]//! [7] 父项
TreeItem *TreeItem::parentItem()
{return m_parentItem;
}
//! [7]//! [8] 默认返回0行,代表Item 只是1项
int TreeItem::row() const
{if (m_parentItem)return m_parentItem->m_childItems.indexOf(const_cast<TreeItem*>(this));return 0;
}
//! [8]
TreeModel
树模型
treemodel.h
#ifndef TREEMODEL_H
#define TREEMODEL_H#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>class TreeItem;//! [0]
class TreeModel : public QAbstractItemModel
{Q_OBJECTpublic:explicit TreeModel(const QString &data, QObject *parent = 0);~TreeModel();QVariant data(const QModelIndex &index, int role) const override;Qt::ItemFlags flags(const QModelIndex &index) 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;private:void setupModelData(const QStringList &lines, TreeItem *parent);TreeItem *rootItem;
};
//! [0]#endif // TREEMODEL_H
treemodel.cpp
/*treemodel.cppProvides a simple tree model to show how to create and use hierarchicalmodels.
*/#include "treeitem.h"
#include "treemodel.h"#include <QStringList>//! [0]
TreeModel::TreeModel(const QString &data, QObject *parent): QAbstractItemModel(parent)
{QList<QVariant> rootData;rootData << "Title" << "Summary";rootItem = new TreeItem(rootData);setupModelData(data.split(QString("\n")), rootItem);
}
//! [0]//! [1]
TreeModel::~TreeModel()
{delete rootItem;
}
//! [1]//! [2]
int TreeModel::columnCount(const QModelIndex &parent) const
{if (parent.isValid())return static_cast<TreeItem*>(parent.internalPointer())->columnCount();elsereturn rootItem->columnCount();
}
//! [2]//! [3]
QVariant TreeModel::data(const QModelIndex &index, int role) const
{if (!index.isValid())return QVariant();if (role != Qt::DisplayRole)return QVariant();TreeItem *item = static_cast<TreeItem*>(index.internalPointer());return item->data(index.column());
}
//! [3]//! [4]
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{if (!index.isValid())return 0;return QAbstractItemModel::flags(index);
}
//! [4]//! [5]
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]//! [6]
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)const
{if (!hasIndex(row, column, parent))return QModelIndex();TreeItem *parentItem;if (!parent.isValid())parentItem = rootItem;elseparentItem = static_cast<TreeItem*>(parent.internalPointer());TreeItem *childItem = parentItem->child(row);if (childItem)return createIndex(row, column, childItem);elsereturn QModelIndex();
}
//! [6]//! [7]
QModelIndex TreeModel::parent(const QModelIndex &index) const
{if (!index.isValid())return QModelIndex();TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());TreeItem *parentItem = childItem->parentItem();if (parentItem == rootItem)return QModelIndex();return createIndex(parentItem->row(), 0, parentItem);
}
//! [7]//! [8]
int TreeModel::rowCount(const QModelIndex &parent) const
{TreeItem *parentItem;if (parent.column() > 0)return 0;if (!parent.isValid())parentItem = rootItem;elseparentItem = static_cast<TreeItem*>(parent.internalPointer());return parentItem->childCount();
}
//! [8]void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
{QList<TreeItem*> parents;//父项QList<int> indentations;//代表行缩进索引位置parents << parent;indentations << 0;//默认缩进0位置int number = 0;//当前行号while (number < lines.count()) {int position = 0;//当前行的列索引while (position < lines[number].length()) {if (lines[number].at(position) != ' ')break;position++;}QString lineData = lines[number].mid(position).trimmed();if (!lineData.isEmpty()) {// Read the column data from the rest of the line.QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);QList<QVariant> columnData;for (int column = 0; column < columnStrings.count(); ++column)columnData << columnStrings[column];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.parents.last()->appendChild(new TreeItem(columnData, parents.last()));}++number;//更新行号}
}