Как лучше всего получать уведомления об изменениях в QAbstractItemView

У меня есть QListView, модель которого (производная от QAbstractItemModel) регулярно меняется на основе некоторых критериев в пользовательском интерфейсе. Я хотел бы получать уведомления, когда само представление считает, что новая строка была добавлена/удалена либо при обновлении текущей модели, либо при изменении модели. Мне нужно это уведомление, чтобы я мог вызвать setIndexWidget и добавить настраиваемый элемент управления в определенный столбец. Я бы предпочел не вызывать setIndexWidget повторно, потому что заполнение виджета дорого. Так что один раз в строке было бы идеально.

Я пробовал rowsInserted/rowsAboutToBeRemoved и dataChanged, но они не вызываются, если в модели, устанавливаемой в представлении, уже есть элементы.

Мы будем очень признательны за любые мысли.


person cppguy    schedule 20.09.2013    source источник
comment
Вы уверены, что при заполнении модели вы не заменяете ее (другим объектом QAbstractItemModel), что приводит к потере ваших первоначальных подключений к QListView?   -  person drescherjm    schedule 21.09.2013
comment
Разве setModel не должен обрабатывать все эти соединения?   -  person cppguy    schedule 24.09.2013
comment
SetModel обработает это правильно, если вы подключитесь к сигналам для QListView. Я пытался выяснить причину проблемы, и я думал, что вы напрямую подключаетесь к сигналам для своей модели, а затем меняете модель. В этом случае ваши сигналы больше не будут отправляться, если вы не обновите свои соединения после изменения модели.   -  person drescherjm    schedule 24.09.2013


Ответы (1)


Вы ошибаетесь насчет dataChanged. Если содержимое любого элемента данных изменяется, то сигнализируется dataChanged. Следующий инвариант сохраняется, предполагая, что слот dataChanged подключен к одному и тому же сигналу в модели.

class ... : public QObject {
  QModelIndex m_index;
  bool m_changed;
  Q_SLOT void dataChanged(const QModelIndex & tl) {
    m_changed = m_changed || tl == m_index;
  }
  ...
};  

m_index = QModelIndex(...);
QVariant before, after;
m_changed = false;
before = model->data(index);
after = model->data(index);
Q_ASSERT(before == after || m_changed);

То, что вы описываете, скорее всего, вызвано неправильным поведением вашей модели. Существует набор тестов модели, который вы можете использовать для проверки соответствия вашей модели требуемым инвариантам.

Конкретно отвечая на ваши вопросы:

  1. Я хотел бы получать уведомления, когда само представление считает, что новая строка была добавлена/удалена либо при обновлении текущей модели...

    Взгляду не нужно ни во что верить. Ваша модель должна излучать соответствующие сигналы на этот счет. Просто подключитесь к этим сигналам с какого-нибудь QObject. Это все, что делает представление. Если сигналы не срабатывают, представление не будет уведомлено. Конец истории.

  2. ... или при смене модели.

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

person Kuba hasn't forgotten Monica    schedule 21.09.2013
comment
Но моя модель не меняется. Почему вызывается dataChanged, если я просто назначаю статическую модель представлению? Я имею в виду, что это то поведение, которое я хочу, но, похоже, это не так. - person cppguy; 24.09.2013
comment
Вы говорите, что модель меняется. Вы буквально меняете всю модель? - person Kuba hasn't forgotten Monica; 24.09.2013
comment
Иногда я меняю модель на другую вызывающую setModel. Но те модели, которые установлены в представлении, могут изменяться, будучи установленными в представлении и не заданными в представлении. У них также есть потенциал вообще не меняться. - person cppguy; 24.09.2013