QTreeView: поддержка отображения между QModelIndex и базовыми данными

У меня проблемы с миграцией QTreeWidget в QtreeView, Вещи, которые были очевидны и тривиальны с QTreeWidget кажется невозможным с точки зрения. В частности: у меня есть главное окно с видом на дерево. TreeView использует модель, которую я реализовал, но не напрямую — через QSortFilterProxyModel это устанавливается как модель дерева. Теперь пользователь активирует элемент в дереве, а главное окно получает сигнал itemActivated(QModelIndex item), Как я могу узнать, какой элемент базовых данных был активирован? Данные — это вектор, поэтому с TreeWidget я мог бы просто сохранить векторный индекс элемента в QTreeWidgetItem, но QModelIndex даже не имеет setData API.

1

Решение

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

Предполагая модель, перечисляющую контакты, со значением 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

...
}

Индекс может быть получен из самой модели контакта или любого другого прокси-сервера — код здесь не заботится.

1

Другие решения

Как я могу узнать, какой элемент базовых данных был активирован?

Путем инверсии прокси-модели:

// supposing to connect this to your itemActivated signal
void onItemActivated(const QModelIndex &index)
{
QModelIndex originalIndex = proxyModel->mapToSource(index);
originalModel->doSomething(originalIndex);
}
2

Модель для хранения ваших данных. Данные больше не принадлежат элементам /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 как только вы определили это.

0
По вопросам рекламы [email protected]