Моделирование самоизменяющихся моделей данных/оболочек в Qt

В Qt я пишу свою собственную древовидную модель (путем создания подкласса QAbstractItemModel), которая охватывает существующую структуру данных. Должна быть возможность обновлять структуру данных как внутри (не через модель), так и через модель (чтобы представления могли ее изменить). Чтобы представить это лучше: это граф сцены, который можно редактировать с помощью представления сцены (без использования модели Qt), а также с помощью планировщика (QTreeView, который использует модель Qt в качестве прокси вокруг графа сцены).

Чтобы избежать путаницы, мы должны рассмотреть два разных сценария (далее я использую операцию «удалить» в качестве примера):

  1. Пользователь использует представление Qt для удаления узла. Представление хочет удалить строку из модели, используя QAbstractItemModel::removeRow. Это, в свою очередь, должно удалить соответствующий узел из базовой структуры данных, графа сцены. Вызовы в сценарии 1

  2. Пользователь использует представление сцены для удаления узла. Представление сцены хочет удалить узел из графа сцены. Модель, которая окружает граф сцены, получает уведомление и, в свою очередь, хочет уведомить подключенные представления о том, что строка была только что удалена. Вызовы в сценарии 2

Хотя я думаю, что знаю, как реализовать 1., я не знаю, как реализовать уведомляющую часть в 2. Есть сигнал QAbstractItemModel::rowsAboutToBeRemoved(), а также rowsRemoved(), которые звучат так, будто они мои друзья. Но это приватные сигналы (в исходном коде шапки написано: "может быть испущен только QAbstractItemModel"). Также есть beginRemoveRows() и endRemoveRows(), но, согласно их документации, их следует вызывать при обновлении из представления, т. е. при вызове removeRow. Кроме того, когда я пытался их использовать, вид был полностью испорчен.

Согласно документации, кажется, что класс модели не может моделировать самоизменяющиеся данные. Возьмем файловую систему в качестве другого примера. При использовании наблюдения за файловой системой, которое может обнаруживать изменения в каталогах, модель должна уведомлять представление, чтобы изменения в каталоге могли отображаться в реальном времени, даже если представление не использовалось для изменения файловой системы. Возможны ли такие модели в Qt?


person leemes    schedule 05.10.2013    source источник


Ответы (1)


Вы неправильно читаете. Модель должна сигнализировать своим пользователям, когда она собирается начать изменять свою «геометрию». Таким образом, независимо от того, что удаляет строки из модели, это должно сообщить внешнему миру, что это произошло. Последовательность событий, когда представление удаляет строки из модели, такова:

  1. Представление вызывает model->removeRows().

  2. Модель вызывает beginRemoveRows()

  3. Модель фактически удаляет строки из внутренних данных.

  4. Модель вызывает endRemoveRows().

Если вы реализуете какой-то другой интерфейс, который будет удалять строки без вызова model->removeRows(), вы должны сделать то же самое. Неважно, представление это или какой-то другой код, удаляющий строки из модели, поведение модели должно быть одинаковым, иначе ничего не будет работать.

Вы можете спроектировать класс адаптера, который вставляется между вашим SceneGraph и Model. Он должен содержать указатель на граф сцены и модель и переводить операции между ними.

person Kuba hasn't forgotten Monica    schedule 05.10.2013
comment
Извините за поздний ответ. Спасибо за ваши разъяснения. Мое текущее решение запрещает изменять базовый SG напрямую, поэтому все представления должны изменять его через модель. Так что единственное направление модификации это вид -> модель -> SG, что вообще не проблема. Кажется, это самый чистый дизайн. - person leemes; 24.10.2013
comment
То, что вы описываете, это именно то, что я написал выше, и на самом деле это то, как нужно действовать. SG — это деталь реализации. Модель, производная от QAbstractItemModel (или его подклассов), — это то, с чем взаимодействуют представления. - person Kuba hasn't forgotten Monica; 24.10.2013