В Qt у меня есть подкласс модели QAbstractItemModel
- это дерево, отображаемое в QTreeView.
Модель поддерживает различные формы изменений, и все они работают нормально. Два релевантных:
1) Некоторые данные в небольшом количестве связанных строк изменяются
2) Изменение визуализации означает, что у большинства строк должно измениться их форматирование, в частности у них изменена подсветка фона. Их DisplayRole
данные не меняются.
Текущий дизайн работает с обоими одинаково: для каждой строки, в которой есть какие-либо изменения, модель выдает dataChanged(start_of_row_index,end_of_row_index)
. Я испускаю сигнал для обеих родительских строк, которые изменились, и для всех их дочерних строк, которые изменились.
Однако это плохо работает в случае 2, поскольку модель становится большой: испускается очень большое количество сигналов dataChanged
.
Я изменил код так, что в случае 2 модель выдает dataChanged
только для (одной) строки, которая является родительской для всего дерева.
Это по-прежнему работает правильно, но не соответствует моему пониманию обязанностей модели. Но я подозреваю, что могу ошибаться.
Возможно, я неправильно понимаю сигнал dataChanged
? Действительно ли это приводит к тому, что представление обновляет все дочерние элементы, а также указанный диапазон? Или я могу избежать испускания dataChanged
, когда изменяется не DisplayRole
?
Отредактировано с моим прогрессом до сих пор
Как указывает Ян, в случае 2 я должен выдать dataChanged
либо для большинства, либо для всех строк.
Мой код изначально делал это, выдавая dataChanged
для каждой измененной строки, но это слишком дорого — представление слишком долго обрабатывает все эти сигналы.
Возможным решением может быть агрегирование сигнала dataChanged
для любых смежных блоков измененных строк, но это все равно не будет работать хорошо, когда, например, изменилась каждая вторая строка - все равно будет выдаваться слишком много сигналов.
В идеале я хотел бы просто указать представлению, что все данные должны рассматриваться как потенциально измененные (но все индексы все еще действительны - макет не изменился). Это не представляется возможным с одним сигналом.
Из-за причуды класса QTreeView
возможно (хотя и неправильно согласно спецификации) испускать только один dataChanged(tl,br
) до tl != br
. У меня это работало, и оно прошло наше тестирование, но заставило меня нервничать.
На данный момент я остановился на версии, которая проходит по дереву и выдает один dataChanged(tl,br)
для каждого родителя (с tl,br, охватывающими всех дочерних элементов этого родителя). Это соответствует протоколу модель/представление и для наших моделей обычно уменьшает количество сигналов примерно в 10 раз.
Однако он не кажется идеальным. Любые другие предложения кто-нибудь?