У меня проблемы с миграцией QTreeWidget
в QtreeView
, Вещи, которые были очевидны и тривиальны с QTreeWidget
кажется невозможным с точки зрения. В частности: у меня есть главное окно с видом на дерево. TreeView использует модель, которую я реализовал, но не напрямую — через QSortFilterProxyModel
это устанавливается как модель дерева. Теперь пользователь активирует элемент в дереве, а главное окно получает сигнал itemActivated(QModelIndex item)
, Как я могу узнать, какой элемент базовых данных был активирован? Данные — это вектор, поэтому с TreeWidget я мог бы просто сохранить векторный индекс элемента в QTreeWidgetItem
, но QModelIndex
даже не имеет setData
API.
Вы можете определить пользовательские роли в исходной модели, возвращая базовые данные или идентификатор (если есть) в качестве варианта. Это имеет то преимущество, что работает с любым количеством промежуточных моделей, поскольку данные будут передаваться через неизмененные модели, и теперь требуется сопоставление индексов.
Предполагая модель, перечисляющую контакты, со значением struct / class Contact
хранение данных.
Это требует Contact
быть зарегистрированным через Q_DECLARE_METATYPE
,
class ContactModel ... {
...
enum Role {
ContactRole=Qt::UserRole,
ContactIdRole
};
QVariant data(...) const {
...
const Contact& contact = ...get from datastructure...
...
switch (role) {
...
case ContactRole:
return QVariant::fromValue( contact );
case ContactIdRole:
return contact.id;
}
}
...
И в коде, получающем индекс:
void SomeWidget::indexSelected(const QModelIndex& index)
{
const int id = index.data(ContactModel::ContactIdRole).toInt();
// look up Contact, do something with it
//or:
const Contact contact = index.data(ContactModel::ContactRole).value<Contact>();
// do something with the contact
...
}
Индекс может быть получен из самой модели контакта или любого другого прокси-сервера — код здесь не заботится.
Как я могу узнать, какой элемент базовых данных был активирован?
Путем инверсии прокси-модели:
// supposing to connect this to your itemActivated signal
void onItemActivated(const QModelIndex &index)
{
QModelIndex originalIndex = proxyModel->mapToSource(index);
originalModel->doSomething(originalIndex);
}
Модель для хранения ваших данных. Данные больше не принадлежат элементам /QModelIndex
в представлении. QModelIndex
только уникальный идентификатор, передаваемый между представлением и моделью (в данном случае через QSortFilterProxyModel
). Модель должна наследоваться QAbstractItemModel
который имеет некоторые чисто виртуальные функции, которые должны быть определены (вы можете скопировать шаблон из http://qt-project.org/doc/qt-4.8/itemviews-simpletreemodel.html). Вы будете, например, должен определить QAbstractItemModel::data( const QModelIndex & index, int role = Qt::DisplayRole)
который определяет, какие данные, которые соответствуют конкретному QModelIndex
,
QSortFilterProxyModel находится между представлением и моделью, но не меняет принципы для модели. Смотрите другой ответ на этот вопрос о том, как бороться с QModelIndex
преобразование.
Заключить: QAbstractItemModel::data( const QModelIndex & index)
даст вам данные для конкретного QModelIndex
как только вы определили это.