Поддержка множественного добавления / удаления (и отмены / повторения) с помощью QAbstractItemModel (C ++) - PullRequest
2 голосов
/ 12 ноября 2009

Привет,

Я писал некоторый неприятный код для поддержки отмены / повтора удаления произвольного набора объектов из моей модели. Я чувствую, что я делаю это правильно, так как все другие мутаторы (добавление / копирование-вставка) являются подмножествами этой функциональности.

Код неприятнее, чем мне нужно, в основном потому, что единственный способ изменить модель - это вызвать beginInsertRows / beginRemoveRows и удалить строки в диапазоне (просто выполняя по 1 строке за раз, не нужно оптимизировать «соседей») в один звонок еще)

Проблема с beginInsertRows / beginRemoveRows заключается в том, что удаление строки может повлиять на другой QModelIndex (скажем, один кешируется в списке). Например:

ParentObj
   ->ChildObj1
   ->ChildObj2
   ->ChildObj3

Скажем, я выбираю ChildObj1 и ChildObj3 и удаляю их, если я сначала удаляю ChildObj1, я изменил QModelIndex в ChildObj3 (строка теперь другая). Подобные проблемы возникают, если я удаляю родительский объект (но я исправил это, «обрезав» потомков из списка объектов).

Вот способы, которыми я думал обойти это ограничение интерфейса, но я подумал, что я бы попросил лучшего, прежде чем двигаться вперед:

  1. Переместить «назад», предполагая, что предоставленный список QModelIndices упорядочен сверху вниз, просто перейдите снизу вверх. Это действительно требует, чтобы сортировка была надежной, и сортировка, вероятно, будет чем-то наивным и медленным (может быть, есть разумный способ сортировки коллекции QModelIndexes? Или QItemSelectionModel предоставляет хорошие (упорядоченные) списки?)

  2. Обновлять другие QModelIndeces каждый раз, когда объект удаляется / добавляется (не могу придумать не наивное решение, выполнить поиск в списке, получить новые QModelIndeces, где это необходимо)

  3. Поскольку обновление фактических данных легко, просто обновите данные и перестройте модель. Это кажется гротескным, и я могу себе представить, что это происходит довольно медленно с большими наборами данных.

Это те идеи, которые у меня есть в настоящее время. Я сейчас работаю над вариантом 1.

С уважением, Дэн О

Ответы [ 2 ]

4 голосов
/ 19 декабря 2009

Представьте beginRemoveRows / endRemoveRows и т. Д. Как методы, чтобы попросить базовый класс QAbstractItemModel исправить ваши постоянные модельные индексы вместо того, чтобы просто обновлять представления, и стараться не путать базовый класс QAbstractItemModel в его работе над эти индексы. Проверьте http://labs.trolltech.com/page/Projects/Itemview/Modeltest, чтобы проверить вашу модель и посмотреть, насколько вы удовлетворяете базовый класс QAbstractItemModel.

Где QPersistentModelIndex не помогает, если вы хотите сохранить ваши данные отмены / повтора вне модели. Я построил модель, которая сильно отредактирована, и я не хотел пытаться сохранить все в модели. Я храню данные отмены / возврата в стеке отмены. Проблема заключается в том, что если вы редактируете столбец, сохраняя постоянный индекс этого столбца в стеке отмены, а затем удаляете строку, содержащую этот столбец, постоянный индекс столбца становится недействительным.

Что я делаю, так это сохраняю постоянный модельный индекс и "исторический" регулярный QModelIndex. Когда пришло время отменить / повторить, я проверяю, стал ли постоянный индекс недействительным. Если это так, я передаю исторический QModelIndex специальному методу моей модели, чтобы попросить его воссоздать индекс, основанный на строке, столбце и internalPointer. Так как все мои правки находятся в стеке отмены, к тому времени, когда я скопировал эти столбцы в стек отмены, строка обязательно будет в модели. Я сохраняю достаточно состояния в internalPointer, чтобы воссоздать исходный индекс.

1 голос
/ 12 ноября 2009

Я хотел бы рассмотреть возможность использования модели "все данные" и модели прокси-фильтра с моделью данных. Данные будут добавляться только в модель данных и никогда не удаляться. Таким образом, вы можете хранить информацию об отмене / восстановлении со ссылками на эту модель. (Могу ли я предложить QPersistentModelIndex?). Ваша модель данных также может как-то отслеживать то, что должно быть показано. В этом случае модель фильтра будет возвращать информацию только для элементов, которые должны отображаться в данный момент времени.

...