Qt: сохранить дерево (QTreeView + QStandardItemModel) в таблице базы данных

Как видно из названия, я использую 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» является ссылкой на родительский узел. Корневой узел — это пустое поле.

Мой вопрос: как получить уникальный идентификатор (в формате int) из QStandardItemModel? Я пробовал с QModelIndex::row() и QPersistentModelIndex::row(), но, похоже, он не уникален.

Огромное спасибо.


person Axel    schedule 06.03.2018    source источник
comment
Вы могли бы объясниться лучше, ваш вопрос меня смущает, ваш вопрос заключается в том, чтобы сохранить QStandardItemModel в базе данных с этой структурой?   -  person eyllanesc    schedule 06.03.2018
comment
в вашем примере, где QModelIndex::row() и QPersistentModelIndex::row() не уникальны?   -  person eyllanesc    schedule 06.03.2018
comment
Спасибо за интерес к моему вопросу, я нашел решение с предложениями Кубы Обера. И извините за неясность. В любом случае, мой вопрос был связан со способом экспорта древовидной структуры из QStandardItemModel в таблицу базы данных, где идентификатор поля идентифицирует узел, а родительское поле является ссылкой на родительский узел. Моей первой попыткой было получить уникальный идентификатор из QModelIndex::row(), но он уникален только для строк одного родителя.   -  person Axel    schedule 07.03.2018


Ответы (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. Порядок обхода должен быть адаптирован к свойствам вашего дерева, если вы хотите избежать потенциальной необходимости аннотировать все дерево в одном запросе идентификатора.

person Kuba hasn't forgotten Monica    schedule 06.03.2018
comment
Спасибо! Я не знал роли Qt. Я новичок в Qt. - person Axel; 07.03.2018