Ваш вопрос об «удалении» индексов не имеет смысла в свете семантики С++. У вас просто нет возможности уничтожить объект, который вы вернули по значению внутри функции — по крайней мере, не прибегая к целенаправленным грязным хакам. Так что давайте забудем об этом.
Сигнал dataChanged
и время жизни индексов на самом деле не связаны. Когда ваш метод index()
возвращает индекс, вы не тот, кто может его «удалить»; тот, кто вызвал метод index()
вашей модели, несет ответственность за уничтожение индекса. Неважно, что индекс, который вы выдаете, в любом случае не размещается в свободном хранилище, поэтому понятие удаления вообще не применяется.
QModelIndex
- это то, что написано на коробке: индекс. Когда дело доходит до того, как его можно использовать, он очень похож на итератор C++. Он поставляется с несколькими предостережениями, которые предостерегает зеркальный итератор:
Он должен быть создан моделью с помощью фабричного метода index()
. Внутри вы используете фабрику createIndex()
, чтобы создать ее для себя в модели. Подумайте о возвращающих итератор методах контейнеров C++ do (begin()
, end()
и т. д.).
Его нужно использовать сразу, а затем выбросить. Он не останется действительным, если вы внесете изменения в модель. То же самое общее ограничение применяется к итераторам контейнеров C++.
Если вам нужно сохранить индекс модели с течением времени, используйте файл QPersistentModelIndex
. Стандартная библиотека C++ не предлагает этого.
Время жизни индекса не зависит от вас. Вы его создаете, вы его выдаете с расчетом, что он будет использоваться по этому протоколу. Предполагается, что пользователь (представление, например) может использовать его с учетом перечисленных выше ограничений. Если представление, например, слишком долго удерживает индекс (путем промежуточных модификаций), вполне нормально, что это приведет к неопределенному поведению (скажем, к сбою).
Когда вы испускаете (или получаете, если вы являетесь представлением или прокси-моделью) dataChanged
, вы не должны ожидать, что какие-либо индексы, выданные до этого момента, останутся пригодными для использования. Постоянные индексы, конечно, должны по-прежнему работать, но их можно сделать недействительными, если, скажем, индекс, на который указывает указатель, был удален (подумайте об удалении ячейки из электронной таблицы, не изменении данных ячейки). !).
Если вы выдали индекс, затем сгенерируйте dataChanged
, и любой метод вашей модели будет вызван с этим старым индексом, вы можете сбой, утверждение, прерывание, что угодно.
Давайте также проясним, как вы используете dataChanged
: вы должны испускать его всякий раз, когда элемент данных в заданном индексе изменяется. Вы должны быть как можно более конкретными: не вообще не рекомендуется просто сообщать о своих взглядах, что все изменилось, если на самом деле это не так. Если один индекс изменился, подайте сигнал с topLeft
и bottomRight
, установленными на один и тот же индекс. Если изменилась небольшая прямоугольная область, выделите углы этого прямоугольника. Если были изменены несколько несвязанных элементов, которые находятся слишком далеко друг от друга, чтобы их можно было осмысленно объединить в небольшой ограничивающий прямоугольник индекса, вы должны указать такие изменения отдельно для каждого измененного элемента.
Вы обязательно должны использовать modeltest, чтобы убедиться, что ваша модель ведет себя нормально.
Это можно сделать, добавив в проект modeltest.cpp
и modeltest.h
и создав экземпляр тестера для каждого экземпляра модели. Вы можете сделать это прямо в вашей модели:
#include "modeltest.h"
MyModel(QObject * parent) : ... {
new ModelTest(this, parent);
...
}
Вам также необходимо обрабатывать постоянные индексы для вашей модели, и это отдельная проблема. В документации говорится:
Модели, предоставляющие интерфейсы для структур данных с изменяемым размером, могут предоставлять реализации insertRows(), removeRows(), insertColumns() и removeColumns(). При реализации этих функций важно уведомлять любые подключенные представления об изменениях размеров модели как до, так и после их возникновения:
- Реализация insertRows() должна вызывать beginInsertRows() перед вставкой новых строк в структуру данных и endInsertRows() сразу после этого.
- Реализация insertColumns() должна вызывать beginInsertColumns() перед вставкой новых столбцов в структуру данных и endInsertColumns() сразу после этого.
- Реализация removeRows() должна вызывать beginRemoveRows() до того, как строки будут удалены из структуры данных, и endRemoveRows() сразу после этого.
- Реализация removeColumns() должна вызывать beginRemoveColumns() до того, как столбцы будут удалены из структуры данных, и endRemoveColumns() сразу после этого.
Частные сигналы, которые выдают эти функции, дают подключенным компонентам возможность предпринять действия до того, как какие-либо данные станут недоступны. Инкапсуляция операций вставки и удаления с помощью этих функций начала и конца также позволяет модели правильно управлять постоянными индексами модели. Если вы хотите, чтобы выборы обрабатывались правильно, вы должны убедиться, что вы вызываете эти функции. Если вы вставляете или удаляете элемент с дочерними элементами, вам не нужно вызывать эти функции для дочерних элементов. Другими словами, родительский элемент позаботится о своих дочерних элементах.
person
Kuba hasn't forgotten Monica
schedule
22.09.2013