Название: QAbstractItemModel + QTreeView + обновление в модели по ключу id + key [РЕШЕНО] Отправлено: vintik от Февраль 16, 2012, 19:29 Всем привет!
Проблема следующая. Есть куча данных. Их удобно представлять в виде дерева. Есть модель для дерева. Данные отображаются в QTreeView Данные отображаемые в дереве - это некие ключи. x |------y1 | |-----1 | |-----2 |------y2 | |-----1 | |-----2 Есть внешний источник, который шлёт сигналы например следующего типа. Ключ номер <y2, 2> больше не живой - его нужно удалить (т.е нужно удалить подузел 2 в узле y2) . Стандартная реализация модели предполагает при манипуляции с моделью использовать индексы ( bool QAbstractItemModel::removeRows ( int row, int count, const QModelIndex & parent = QModelIndex()) ). Вопрос в том, как правильно и грамотно установить соответствие между приходящим ключом и индексом? Первая мысль была такая: при создании нового узла в дереве (модели) - индекс (QModelIndex) сохранять в хеш используя ключ (тот самый <y2, 2>). А потом когда нужно удалить узел - получать индекс из хеша по ключу. И по индексу удалять. Но обнаружилась проблема - после удаления чего-либо из модели внутренняя индексация изменяется. Т.е. если раньше по индексу createIndex(3, 0, root) были доступны одни данные, то после removeRows(2, 0, QModelIndex()) по индексу createIndex(3, 0, root) - уже другие данные. И получается, что я ожидаю что по ключу <y2, 2> получу индекс для удаления именно этого узла из дерева - а на деле получаю индекс для удаления уже другого узла. Думаю - есть какие-то иные стандартизированные способы для решения проблемы, подскажите куда копать? Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 24, 2012, 09:37 значит вот что получилось - два способа:
1. Вообще забить на хранение соответствия между приходящим ключом и индексом. Воспользоваться методом QAbstractItemModel::match для поиска индекса листа в котором хранится y2, а потом для уже для найденного индекса тем же методом искать индекс листа, в котором хранится 2. По полученному индексу осуществлять удаление. + ничего не надо нигде хранить - если обращение к модели частое (мой случай), то на поиск конкретного листа уходит много времени. 2. Использовать QTreeWidget вместо QTreeView и самописной модели. В QTreeWidget лист представляет из себя объект класса QTreeWidgetItem. Указатель на этот объект можно сохранить в хеше по ключу (<y2, 2>). Удалять лист уже не по индексу, а по сохранённому указателю. Плюсы и минусы диаметрально противоположны первому случаю. Оба подхода достаточно поверхностны, так что если кто-то обладает опытом в решении подобных проблем, буду рад совету Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: Bepec от Февраль 24, 2012, 09:43 А что тебе мешает вообще представить это деревом в виде списка?
Тогда помоему будет вообще не проблема. Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 24, 2012, 10:26 Если честно ничего не мешает)
Дерево красивше смотрится. Если я правильно понял, то 1ый список - листья 1го уровня, 2ой список - листья 2го уровня. И так далее, сколько уровней вложений, столько и списков? list1 | list2 y1 <-- current | 1 y2 | 2 И ещё вопрос, если я буду использовать свою модель для списка, то удаление из модели тоже только через индексы? Я правильно понимаю? Если да, то снова встаёт проблема - как удалять что либо из модели по ключу? Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: andrew.k от Февраль 24, 2012, 10:41 Но обнаружилась проблема - после удаления чего-либо из модели внутренняя индексация изменяется. Ну так ты обновляй не только модель, но и хеш, где у тебя хранятся индексы. Только ту ветку, которая была затронута удалением.Т.е. если раньше по индексу createIndex(3, 0, root) были доступны одни данные, то после removeRows(2, 0, QModelIndex()) по индексу createIndex(3, 0, root) - уже другие данные. И получается, что я ожидаю что по ключу <y2, 2> получу индекс для удаления именно этого узла из дерева - а на деле получаю индекс для удаления уже другого узла. Тогда удаление будет чуть подольше, а поиск быстрее. Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 24, 2012, 11:29 Смотри, я правильно рассуждаю?
Индекс определяется 3мя параметрами (номер строки, номер колонки, родитель) Приходит сигнал, в нём ключ, по ключу я определяю, что например индекс (3, 0, root) нужно удалить. Удаляю. Потом мне нужно найти все элементы хэша, у которых в значении лежат индексы из диапазона [ (4, 0, root); (rowCount(root) - 1, 0, root) ] - номер строки нужно уменьшить на 1. hash.insert(hash.key(createIndex(4, 0, root)), createIndex(3, 0, root)) hash.insert(hash.key(createIndex(5, 0, root)), createIndex(4, 0, root)) ... hash.insert(hash.key(createIndex(rowCount(root) - 1, 0, root)), createIndex(rowCount(root) - 1 - 1, 0, root)) Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: andrew.k от Февраль 24, 2012, 14:11 что у тебя ключ в хеше? и что является твоим ключом?
я думал, что ключ в хеше это какой-то ид из бд, а значение это индекс модели.тебе надо обновить в хеше индексы всех новых, а один лишний наверное можно и не удалять. Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 24, 2012, 14:22 да, ключ в хэше. ключ представляет из себя пару чисел типа int. Он приходит в виде сигнала от стороннего модуля. По нему я получаю данные и строю элементы дерева. Ну т.е. пришёл ключ <1,4> эт значит что у корня появляется лист 1 и у листа 1 появляется лист 4. А со временем приходит сигнал для этого же ключа, о том что его нужно удалить из дерева.
попробовал вариант выше предложенный - да работает, но катастрофически долго!!! hash.key() ужасно долго отрабатывает Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: andrew.k от Февраль 24, 2012, 16:32 да, ключ в хэше. ключ представляет из себя пару чисел типа int. Он приходит в виде сигнала от стороннего модуля. По нему я получаю данные и строю элементы дерева. Ну т.е. пришёл ключ <1,4> эт значит что у корня появляется лист 1 и у листа 1 появляется лист 4. А Т.е. все листья имеют уникальный индекс?Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 26, 2012, 10:00 Т.е. все листья имеют уникальный индекс? да, именно такНазвание: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: Igors от Февраль 26, 2012, 14:02 Эта проблема (индексы "уплывают" при вставке/удалении) возникает и без всякого model-view. Мне неизвестен какой-то общий метод. В дополнение к сказанному выше (если все же хочется работать по индексу)
- если удаление сосредоточено в одном месте, то удаляющий имеет ввиду смещение индексов - то же но чуть в профиль: отложить удаление и (пока) маркировать doomed элемент (часто занося его в доп контейнер). Затем в какой-то момент удалить физически и переиндексироваться Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: Tonal от Февраль 27, 2012, 11:36 Вроде всё решается вполне просто:
После удаления узла выносишь из хеша его и его детей и обновляешь в индексы его братьев снизу. :) Я использую beginRemoveRows endRemoveRows + несколько внутренних кешей для ускорения. Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Февраль 27, 2012, 16:38 Вроде всё решается вполне просто: После удаления узла выносишь из хеша его и его детей и обновляешь в индексы его братьев снизу. :) Я использую beginRemoveRows endRemoveRows + несколько внутренних кешей для ускорения. Суть ясна, но вот немного бы пояснения про внутренние кешы для ускорения, может пример какой-нить есть)) Название: Re: QAbstractItemModel + QTreeView + обновление данных в модели по ключу + id + key Отправлено: vintik от Март 03, 2012, 10:00 Чтобы как-то завершить тему, скажу, что остановился на 2ом варианте из второго поста
|