C++ (Qt)#include <QtCore>#include <QtGui>#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)#include <QtWidgets>#endif struct Container{ QString s; QStringList children; Container(const QString &s_) : s(s_) {}}; class TreeModel : public QAbstractItemModel{public: TreeModel(QObject *parent = 0) : QAbstractItemModel(parent) { for (int i = 0; i < 5; ++i) { Container *c = new Container(QString("root %1").arg(i)); for (int j = 0; j < 4 - i; ++j) { c->children << QString("child %1").arg(j); } list << c; } } QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const { // сохраним указатель на родительский айтем для дальнейшего использования return createIndex(row, column, parent.isValid() ? list.at(parent.row()) : 0); } QModelIndex parent(const QModelIndex &child) const { // родительский индекс есть только у тех, для кого мы сохранили указатель в методе выше Container *c = static_cast<Container *>(child.internalPointer()); return c ? createIndex(list.indexOf(c), 0) : QModelIndex(); } int columnCount(const QModelIndex &parent = QModelIndex()) const { return 1; } int rowCount(const QModelIndex &parent = QModelIndex()) const { bool hasParent = parent.isValid(); // без этого условия получится бесконечная вложенность детей if (hasParent && parent.internalPointer()) return 0; return hasParent ? list.at(parent.row())->children.size() : list.size(); } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const { if (role != Qt::DisplayRole) return QVariant(); QModelIndex parent = index.parent(); return parent.isValid() ? list.at(parent.row())->children.at(index.row()) : list.at(index.row())->s; } private: QList<Container *> list;}; int main(int argc, char *argv[]){ QApplication a(argc, argv); QTreeView tv; tv.setModel(new TreeModel(&tv)); tv.show(); return a.exec();}