QSortFIlterProxyModel не отображаются данные вставленной строки
у меня есть следующая задача.
Для столбцов строк отмеченных чекбоксами нужно посчитать среднее арифметическое и добавить в таблицу. Для QAbstractListModel все работает корректно. Но при переходе на QSortFilterProxyModel получается следующий результат

Привожу часть кода
int TableModel::rowCount(const QModelIndex &) const
{
return QSortFilterProxyModel::rowCount() + values.count();
}
void TableModel::populate(QList<TableData> newValues)
{
this->beginInsertRows(QModelIndex(), 0, 0);
this->values= newValues;
endInsertRows();
}
QVariant TableModel::data( const QModelIndex &index, int role ) const
{
...
value = QSortFilterProxyModel::data(index, role);
if (index.row()>2) value = this->values.at(index.row()-3).getValueByIndex(index.column());
return value;
...
}
Чего я не учитываю или в чем ошибаюсь?
Ответы (2 шт):
Проблема тут QVariant TableModel::data( const QModelIndex &index, int role ) const, поскольку передаваемый здесь QModelIndex принадлежит модели таблицы, а используя QSortFilterProxyModel вы уже перемешали все индексы изначальной модели.
Что у вас делает эта штука value = QSortFilterProxyModel::data(index, role); честно говоря непонятно
Если я правильно помню, вам надо получить исходный индекс из индекса прокси модели и работать с ним: QModelIndex sourceIndex = yourProxyModel->mapToSource(index);
https://doc.qt.io/qt-6/qsortfilterproxymodel.html#mapToSource
PS: Это не точно(ц), но в любом случае дебаг решает
Прокси-модели используют индексы модели источника для получения своих индексов с помощью метода QAbstractProxyModel::mapToSource. В итоге если в прокси-модели индексов больше чем в модели источнике, то индексы не присутствующие в модели-источнике будут вести себя некорректно.
Для корректной работы Вам нужно переопределить методы:
QModelIndex TableModel::mapToSource(const QModelIndex& proxyIndex) const
{
if (proxyIndex.row() >= sourceModel()->rowCount()) {
return createIndex(proxyIndex.row(), proxyIndex.column());
}
return QSortFilterProxyModel::mapToSource(proxyIndex);
}
QModelIndex TableModel::index(int row, int column, const QModelIndex& parent) const
{
if (row >= sourceModel()->rowCount()) {
return createIndex(row, column);
}
return QSortFilterProxyModel::index(row, column, parent);
}
Qt::ItemFlags TableModel::flags(const QModelIndex& index) const
{
if (index.row() >= sourceModel()->rowCount()) {
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren;
}
return QSortFilterProxyModel::flags(index);
}
Помимо этого нужно заметить, что помимо mapToSource QSortFilterProxyModel использует скрытую от пользователя функцию index_to_iterator для ускорения многих операций. Она работает на основе internalPointer-а индекса, который у нас для row >= sourceModel()->rowCount() равен nullptr. (Мы использовали QAbstractItemModel::createIndex). По этой причине нам нужно переопределить методы, которые могут использовать данную функцию на наших добавочных индексах (Как правило в других прокси-моделях их тоже необходимо переопределять, но по другим причинам):
QModelIndex TableModel::parent(const QModelIndex& child) const
{
return QModelIndex(); //Мы знаем, что работаем с таблицей
}
QModelIndex TableModel::sibling(int row, int column, const QModelIndex& idx) const
{
if (row >= sourceModel()->rowCount()) {
return createIndex(row, column);
}
return QSortFilterProxyModel::sibling(row, column, idx);
}
Замечу, что помимо этих мест, index_to_iterator неявно вызывается в приватном методе QSortFilterProxyModelPrivate::needsReorder, на который мы повлиять не можем, а потому я не могу предсказать насколько корректно будет работать сортировка модели (это я не тестировал). Однако, я бы в любом случае порекомендовал вам использовать QSortFilterProxyModel исключительно для вопросов фильтрации и сортировки, а дополнительные строки добавлять через ещё одну прокси-модель наследуемую от QIdentityProxyModel.
Обратите внимание, что я предполагал использование таблиц. Для деревьев всё немного сложнее.