группировка по прокси-модели

У меня есть модель дерева с теоретически бесконечной глубиной и некоторым свойством «Группа».

исходный вид

В дополнение к стандартному представлению мне нужно показать эту модель (и синхронизировать ее) таким образом, чтобы каждая группа становилась виртуальным родителем для всех элементов с одинаковым значением свойства.

введите здесь описание изображения

Каков наилучший способ добиться этого с архитектурой модели/представления Qt?

Не так давно я решил аналогичную проблему, вставив дополнительные виртуальные «группы» при добавлении/удалении элементов в/из модели, но этот метод оказался не очень гибким, поэтому я ищу лучшее решение.

В идеале я вижу это реализованным через модель QSortProxyFilter на данный момент.


person rsht    schedule 10.04.2018    source источник
comment
Вам придется реализовать собственную прокси-модель. Просто реализуйте QAbstractProxyModel. Задача не тривиальная, но выполнимая. Самая важная часть - правильно получить преобразование индекса.   -  person Felix    schedule 11.04.2018
comment
Как хранятся данные вашей модели? Какова его структура?   -  person vahancho    schedule 11.04.2018
comment
@ Феликс, да, это определенно так. Будем разбираться, спасибо.   -  person rsht    schedule 11.04.2018
comment
@vahancho данные иногда заполняются вручную или могут динамически добавляться пользователем (или обоими), и это в основном неупорядоченный массив некоторых структур, который примерно можно представить как Item { id: string; name: string; group: int; etc... }.   -  person rsht    schedule 11.04.2018
comment
@rsht, я вижу. Я бы решил это следующим образом: 1) Напишите процедуру, которая будет искать все элементы, чтобы получить все существующие группы 2) Список групп будет представлять узлы верхнего уровня вашей модели (не прокси) 3) Модель будет индексировать дочерние узлы путем поиска элементов, принадлежащих данной группе (родителю).   -  person vahancho    schedule 11.04.2018
comment
Одна важная вещь: является ли группа принадлежащей изменчивой или нет? (в другом мире вы можете редактировать группу предметов?)   -  person sandwood    schedule 23.04.2018
comment
@sandwood да, это изменчиво. Кроме того, отображаемые свойства группы (например, имя) также могут быть изменены.   -  person rsht    schedule 23.04.2018
comment
Будьте осторожны, если ваша исходная модель переопределяет hasChildren, fetchMore, так как это по необходимости должно будет посетить каждый узел.   -  person Caleth    schedule 23.04.2018


Ответы (1)


В зависимости от того, что вы хотите получить в результате:

  • вы можете добиться фильтрации без необходимости реализации QAbstractProxyModel.

    QSortFilterProxyModel может сортировать по роли Item, по умолчанию это Qt::DisplayRole. Но если вы поместите свое групповое свойство в настраиваемую роль своего элемента, вы можете сортировать по этой пользовательской роли: cf: https://doc.qt.io/qt-5/qsortfilterproxymodel.html#sortRole-prop

    Это должно выполнять основную работу по сортировке для конкретного представления, заказанного группой.

    Но у вас не будет узла "сворачиваемая группа". трудно сказать, сможете ли вы справиться с эквивалентной функцией с помощью специального средства визуализации.

  • В противном случае, сложный путь, предложенный Феликсом, реализовать свою пользовательскую модель QAbstractProxyModel, которая будет создавать индексы группы узлов.

  • Последнее решение: создайте свою собственную (базовую) модель (что-то вроде MyTree и Map<Group,Node> и две модели Qt (по одной для каждого представления)). Обновите обе модели с помощью механизма сигнала/слота Qt при обновлении вашей базовой модели и наоборот.

person sandwood    schedule 23.04.2018
comment
QSortFilterProxyModel не подходит для изменения формы, как это было бы. Обратите внимание, что исходная модель древовидная. - person Caleth; 23.04.2018
comment
отредактируйте его через QAbstractProxyModel. Спасибо! - person rsht; 11.05.2018
comment
@rsht, не могли бы вы поделиться своим решением. Я пытаюсь сделать то же самое прямо сейчас - person JokerMartini; 05.10.2019
comment
@JokerMartini Да, но я не могу из-за моего соглашения с компанией, в которой я работал, внедряя это. По сути, вам нужно будет реализовать свою собственную QAbstractProxyModel, которая добавит виртуальных родителей для каждого элемента из исходной модели. Добавьте этих виртуальных родителей, если они не существуют, в rowsInserted и удалите их в rowsRemoved (вам нужно будет поместить их в очередь удаления на rowsAboutToBeRemoved, а затем выполнить фактическое удаление на rowsRemoved). Трудной частью для меня было выяснить, как сопоставить исходный индекс с вашим индексом (см. QModelIndex::internalId). - person rsht; 24.07.2020
comment
@JokerMartini все остальное должно быть тривиальным (реализуйте любой другой чисто виртуальный метод, преобразовав индекс с помощью mapFromSource() и перенаправив его). Дайте мне знать, если вам нужны какие-либо другие подсказки по этому поводу, я был бы рад помочь. - person rsht; 24.07.2020
comment
@JokerMartini Другая важная вещь заключается в том, что я реализовал это только для списков и преобразовываю модели деревьев в списки с помощью KDescendantsProxyModel (с открытым исходным кодом, поищите). Итак, если вам нужно, чтобы он работал с древовидными моделями без использования упомянутой прокси-модели, вы можете столкнуться с некоторыми проблемами, о которых я не знаю. - person rsht; 24.07.2020