Название: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 26, 2011, 23:01 Доброй ночи. qt 4.4.2. postgres 8.
На форме живет QTreeView, используется пользовательская модель QAbstractItemModel, в которой живет дерево, произростающее из rootItem. В дереве одна колонка. Дерево строится по данным из БД, но в данном случае это не важно. Соответственно данные организованы древовидно. Интерфейс должен позволять пользователю вести дерево, добавлять, удалять итемы и т.д. По умолчанию итемы дерева отсортированы. RItem * rootItem - указатель на корневой итем QList<RItem *> childs - список указателей (детки каждого итема) Функция добавления нового итема в дерево реализована через beginInsertRows() и endInsertRows(). Итем добавляется в конец childs выбранного родителя, потом срабатывает функция сортировки. После сортировки итемы сбиваются, причем QModelIndex после сортировки распологаются верно, но такое чувство что QTreeView не понял что произошла сортировка ветки с новым итемом в модели. При клике на итемы QTreeView после сортировки, выводя наименования итемов в консоль, становится понятно что итемы сбиты. Проблема решается после открытия и закрытия битой ветки, когда модель сама переиндексирует ветку. Так же проблема решается через reset() всей модели. Но после reset() приходится разворачивать все ветки дерева, выделять нужный итем (который был добавлен), а это лишнее время. Если открывать и закрыть ветку программно после сортитровки, то теряется выделение правильного итема после добавления нового итема через beginInsertRows. Приходится выделять нужный итем, используя доп функцию. Теряется скорость, а это критично. Подскажите, как решить проблему без всякой черезжопности. Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: twp от Май 27, 2011, 12:32 перед сортировкой лучше сделать beginResetModel() а после нее endResetModel() и сконнектить сигнал QAbstractItemModel::modelReset() со слотом QTreeView::expandAll()
Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 12:52 Вы предлагаете использовать begin/endResetModel. Это резетнет модель, что затратно по времени и на экране будет видно перерисовку, мерцание. Сконектить сигнал с expandAll... ммм это откроет/закроет все узлы, это тоже долго. Вы предлагаете при каждом добавлении нового итема в дерево резетить модель и закрывать/открывать все узлы. Это не подходит.
Да и к тому же уже написаны функции которые могут expand-ить нужный мне узел, а не все узлы. Это тоже не подходит, потому что это сбивает выделение итема после добавления нового в дерево. Вопрос остается. Но все равно спасибо за совет. Интересует как решить проблему не теряя выделение нового итема после добавления. Где знатоки qt) Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: twp от Май 27, 2011, 13:16 мерцания по идее не должно быть видно, ведь в этом случае перерисовка вью блокируется через setUpdatesEnabled(false). Если не подходит раскрытие всех узлов, то придется делать вручную, запоминать открытые узлы, а также выделенный индекс и восстанавливать после сортировки. Но в вашем случае лучше вообще не сортировать, а сразу определить правильное место для новой строки. Зачем все пересортировывать?
Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 13:27 Потому что реализован drag/drop и добавляться может несколько итемов сразу. Используется qSort(). Childs() это QList и удобно сортировать используя итератор.
Я с вами согласен, если самому вставлять итемы в нужные места, то данный вопрос решится, но зачем, неужели нельзя нормально подружить модель с представлением в данном случае? Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 13:33 Кстати функция expandAll() у представления работает медленно. Если руками написать функцию, которая будет открывать только узлы (итемы у которых есть детки), можно неплохо выиграть времени.
Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: GreatSnake от Май 27, 2011, 13:48 Цитировать Итем добавляется в конец childs выбранного родителя, потом срабатывает функция сортировки. Цитировать Используется qSort(). Так как именно делается сортировка?Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 13:58 Итем (кратко):
class RItem; { RItem * parent; - родитель QList<RItem *> childs; - дети } Добавление итема Childs << newItem; Сортировка qSort(childs.begin; childs.end, функтор); Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: GreatSnake от Май 27, 2011, 14:06 Цитировать Сортировка qSort(childs.begin; childs.end, функтор); Мде...И как MVC узнает, что вы отсортировали детей элемента ??? Используйте QStandardItemModel и делайте сортировку через QStandardItem::sortChildren(). Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 14:23 В том-то и дело, что никак.
sortChildren() мммм... Мне необходима сортировка итемов по типу. А не по алфавиту. Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: GreatSnake от Май 27, 2011, 14:31 Использовать
Код либо перегружать Код либо вообще навесить на уже используемую модель QSortFilterProxyModel и перегрузить Код либо перейти на QTreeWidget, где всё это уже есть ) Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 15:20 QTreeWidget медленный.
Переход на QStandardItemModel возможен, но долгий, потому что написано уже много. А вот использование QSortFilterProxyModel интересно. Спасибо за советы. Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 16:33 Построил дерево через QStandardItemModel пока что без сортировки веток по типу.
Моя модель строилась намного шустрее. Так что оставлю свой вариант. Если время найду, попробую привинтить QSortFilterProxyModel к своей модели. Вопрос не решен. Но людям, которым скорость работы не критична, вариант с QStandardItemModel подойдет. Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: twp от Май 27, 2011, 16:36 если QTreeWidget медленный, то после навешивания прокси модели скорее будет еще медленней. Все таки я придерживаюсь мнения что нужно изначально вставить строки в нужные позиции. В данном случае можно поступить так:
1. Берем копию чайлдов и добавляем новые строки 2. Сортируем 3. Пробегаемся по этой копии и ищем вставленные строки, тем самым находя строку (индекс в списке) для вставки. 4. Вставляем уже в настоящий список чайлдов через beginInsertRows/endInsertRows новые строки Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 27, 2011, 16:41 Ну если ничего не поможет, то придется добавлять итемы в нужные позиции и не сортировать ветку.
Потом сравню с сортировкой qSort + открытие/закрытие ветки + выделение нужного итема. Замерю тайминги и обязательно напишу тут что шустрее. Спасибо за предложения. Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Авварон от Май 28, 2011, 14:05 а теперь приду я и расскажу про сигнал dataChanged, к-ый не для таких случаев нужен, ибо тс извращенец - сразу найти место для вставки видимо слабо. qLowerBound да поможет вам в этом.
Название: Re: QTreeView + QAbstractItemModel после сортировки сбиваются индексы Отправлено: Polt от Май 30, 2011, 12:20 не слабо, искал альтернативные шустро работающие варианты, не нашел, вопрос решен вставкой на нужную позицию.
|