Множественное чередование QAbstractItemModel::beginInsertRows()/beginRemoveRows(), за которым следует один вызов endInsertRow()/endRemoveRow()?

Я разрабатываю клон top/htop в Qt, который должен отображать процессы на удаленном устройстве. Свежий список процессов передается каждую секунду и вызывает обновление внутренней производной модели QAbstractItemModel, представляющей состояния в клиенте. Это происходит в цикле, который использует два итератора (один для старого списка и один для нового списка), которые я одновременно перебираю, чтобы сравнить записи и применить изменения (т.е. удалить/вставить/обновить записи), если это необходимо.

Я хотел бы знать, должен ли за каждым вызовом beginInsertRows/beginRemoveRows немедленно следовать закрывающий вызов endInsertRows/endRemoveRows после соответствующего изменения или можно ли иметь логические флаги, указывающие, что действительно вставка/удаление имела место, а затем продолжить применение больше вставок/удалений и только в конце вызывать endInsertRows/endRemoveRows один раз в зависимости от ранее упомянутых флагов.

Поскольку потенциально большое количество записей в модели могло измениться (что, в свою очередь, вызвало большое количество вставок/удалений), я обеспокоен производительностью и не хотел бы, чтобы модель уведомляла представления об обновлении, пока я не закончу все вставки/удаления.

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

Редактировать 1: Пустые строки, за которыми следует сбой, по-видимому, ответили на вопрос, как видно из это изображение.


person momesana    schedule 25.03.2016    source источник


Ответы (1)


Всякий раз, когда вы вставляете строку в середину, вы делаете недействительными как минимум индексы следующих строк.

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

Вызов endInsertRow() сообщает представлению, что теперь внутреннее состояние модели допустимо и может быть запрошено.

Вложение этих вызовов не поддерживается.

Возможно, вам следует использовать begin/endResetModel() вместо этого.

person Martin Hennings    schedule 06.05.2019