Qt:在数据库表中存储树(QTreeView + QStandardItemModel)

问题描述 投票:0回答:2

从标题中可以看到,我使用 QStandardItemModel 来存储树结构。我在 QTreeView 中操作这个结构,然后我需要以这种格式将其保存在数据库中:

|id|Parent|Child |
| 1|      |ITEM01|
| 2|     1|ITEM02|
| 3|     2|ITEM03|
| 4|     3|ITEM04|
| 5|     4|ITEM05|
| 6|     5|ITEM06|
| 7|     6|ITEM07|
| 8|     3|ITEM08|
| 9|     3|ITEM09|
|10|     3|ITEM10|

代表这个结构:

ITEM01
 ║
 ╠═► ITEM02
 ║    ║
 ║    ╚═► ITEM03
 ║         ║
 ║         ╠═► ITEM04
 ║         ║    ║
 ║         ║    ╚═► ITEM05
 ║         ║         ║
 ║         ║         ╚═► ITEM06
 ║         ║              ║
 ║         ║              ╚═► ITEM07
 ║         ║
 ║         ╠═► ITEM08
 ║         ╠═► ITEM09
 ║         ╚═► ITEM10

换句话说,“id”唯一地代表一个节点,“parent”字段是对父节点的引用。根节点是一个空字段。

我的问题是:如何从 QStandardItemModel 获取唯一的 id(int 格式)? 我尝试过 QModelIndex::row() 和 QPersistentModelIndex::row() 但它似乎不是唯一的。

非常感谢。

sql qt qtreeview qstandarditemmodel qmodelindex
2个回答
1
投票

最简单的方法是当您以某种深度优先顺序遍历树时,从递增计数器分配索引,例如后序 - 左...右,根。

如果您将

id
parent
存储为元素的角色,则:

int assignIdsPostorder(QStandardItem * e, int idRole, int parentRole, int counter = 0) {
  auto const N = e->rowCount();
  for (int i = 0; i < N; ++i)
    counter = assignIdsDFS(e->child(i), idRole, parentRole, counter);
  if (e->setData(counter, idRole)) counter++;
  for (int i = 0; i < N; ++i)
    e->child(i)->setData(e->data(idRole), parentRole);
  return counter;
}

稍作修改即可将

id
parent
存储在单独的列中。

如果索引不需要始终有效,那么您可以通过记忆(缓存)来延迟生成它们。

QStandardItem
派生元素将重新实现
data()
以执行部分树遍历以生成其
ids
。如果您想避免可能必须在单个 id 查询上注释整个树的情况,则需要根据树的属性调整遍历顺序。


0
投票

您可以使用

this
方法迭代 QAbstractItemModel

void iterate(const QModelIndex & index, const QAbstractItemModel * model,
             const std::function<void(const QModelIndex&, int)> & fun,
             int depth = 0)
{
    if (index.isValid())
        fun(index, depth);
    if ((index.flags() & Qt::ItemNeverHasChildren) || !model->hasChildren(index)) return;
    auto rows = model->rowCount(index);
    auto cols = model->columnCount(index);
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            iterate(model->index(i, j, index), model, fun, depth+1);
}
void dumpData(QAbstractItemView * view) {
    iterate(view->rootIndex(), view->model(), [](const QModelIndex & idx, int depth){
        qDebug() << depth << ":" << idx.row() << "," << idx.column() << "=" << idx.data();
    });
}

然后使用

QModelIndex::parent()
获取项目的父项目,最后使用
QModelIndex::internalId()
获取父项目和项目本身的唯一 ID。

© www.soinside.com 2019 - 2024. All rights reserved.