0

从标题可以看出,我使用了一个 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() 但它似乎不是唯一的。

非常感谢。

4

1 回答 1

1

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

如果将idand存储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 查询上注释整个树的情况,则需要根据树的属性调整遍历顺序。

于 2018-03-06T20:16:41.703 回答