Russian Qt Forum

Qt => Model-View (MV) => Тема начата: 19andrew91 от Февраль 07, 2023, 17:43



Название: Не отображаются данные при вставке новой строки.
Отправлено: 19andrew91 от Февраль 07, 2023, 17:43
Мне нужно реализовать модель(Proxy) выводящую статистические расчеты в качестве дополнительных строк в таблице.

Я использовал следующую реализацию

Код:
this->beginInsertRows(QModelIndex(), idx+1, idx+1);
        this->values.append(newValues);
 endInsertRows();

idx = query.rowCount()
values - список обсчитанных данных
newValues - циклически подаваемая переменная
Данные берутся из query.data()

Но при запуске в таблицу добавляются пустые строки.

Я думал что новые строки пытаются быть извлеченными из SQL-запроса и ничего не возвращается.
Поэтому сделал тестовую модель данные для которой хранятся в разных местах

Код:
void SontekTableModel::populate(MyType newValues)
{
    this->beginInsertRows(QModelIndex(), 0, 1);
        this->values.append(newValues);
    endInsertRows();
}

void SontekTableModel::spopulate(MyType newValues)
{
    this->beginInsertRows(QModelIndex(), 0, 1); //0<->idx
        this->svalues.append(newValues);
    endInsertRows();
}

values - исходные данные
svalues - обсчитанные данные

и все работает. В чем еще может быть проблема?
И дополнительный вопрос.
Вспомогательный проект в отличии от основного не заходит в исходники по f11.
У основного проекта другие настройки для сборки, только в этом дело или есть еще какие-то настройки?


Название: Re: Не отображаются данные при вставке новой строки.
Отправлено: 19andrew91 от Февраль 09, 2023, 12:59
Пытаясь решить вопрос отлаживал все что мог.
Обнаружил что порядок вызова функций следующий
headers->flags->data
И если headers вызывается для новых индексов.
то flags и data нет.
По отладке в исходниках определил что endInsertRows отрабатывает корректно а дальше заблудился в дебрях QT.
Использование сигналов modelReset() и LayoutChanged() не помогло.
В чем может быть проблема и может ли на это влиять QAbstractProxyModel?
Упрощенный тестовый проект с QAbstractListModel отрабатывает корректно


Название: Re: Не отображаются данные при вставке новой строки.
Отправлено: kambala от Февраль 09, 2023, 19:47
честно говоря, по описанию проблемы непонятно примерно ничего. минимальный компилируемый пример, воспроизводящий проблему, бы очень помог.


Название: Re: Не отображаются данные при вставке новой
Отправлено: 19andrew91 от Февраль 11, 2023, 18:08
Тут все не очень просто.
Упрощенная версия проекта работает корректно. Могу предоставить, только как, через GitHub?
Главное отличие рабочего протекта в том, что модель наследуется от QSortFilterProxyModel и переопределяются некоторые дополнительные методы.
Скриншот же самой проблемы
https://radikal.host/i/JZLmjo


Название: Re: Не отображаются данные при вставке новой строки.
Отправлено: kambala от Февраль 11, 2023, 19:34
гитхаб подойдет, архив в крайнем случае

так в рабочем проекте QAbstractProxyModel, а в тестовом — QSortFilterProxyModel? а если сделать одинаково?


Название: Re: Не отображаются данные при вставке новой
Отправлено: 19andrew91 от Февраль 27, 2023, 16:17
Извиняюсь за задержку.
При адаптации работающего проекта под прокси-модель ошибка сохранилась.
За прошедшее время ее обнаружить не удалось.
https://github.com/SavchenkoAndreyV/ProxyModel


Название: Re: Не отображаются данные при вставке новой строки.
Отправлено: kambala от Февраль 28, 2023, 16:44
я кажется примерно понял в чем дело (прокси моделями, тем более кастомными, раньше не пользовался). прокси модель ничего не знает о новой строке т.к. для нее не существует индекса. после добавления следующих методов данные в новой строке начали отображаться когда кликаешь на чекбокс.
Код
C++ (Qt)
QModelIndex TableModel::mapFromSource(const QModelIndex& sourceIndex) const
{
return sourceIndex;
}
 
QModelIndex TableModel::mapToSource(const QModelIndex& proxyIndex) const
{
return proxyIndex.row() < 3 ? proxyIndex : QModelIndex{};
}
 
QModelIndex TableModel::index(int row, int column, const QModelIndex& parent) const
{
return row < 3 ? QSortFilterProxyModel::index(row, column, parent) : createIndex(row, column);
}

там правда дальше программа падает при клике на новую строчку (падает внутренний вызов метода parent()), я уже не стал дальше копаться.

также у тебя beginInsertRows вызывается с неправильными параметрами для вставки в конец, надо
Код
C++ (Qt)
const auto rows = QSortFilterProxyModel::rowCount();
beginInsertRows(QModelIndex(), rows, rows + newValues.size() - 1);
а beginResetModel/endResetModel там вообще не нужны.

метод setData тоже написан не совсем правильно, должно быть так:
Код
C++ (Qt)
bool TableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
   if(static_cast<headers>(index.column()) == headers::Check && role == Qt::CheckStateRole)
   {
       checkbox.setCheck(index.row(), value.toBool());
emit dataChanged(index, index, {role});
return true;
   }
return QSortFilterProxyModel::setData(index, value, role);
}

еще у тебя метод data немножко коряво написан: обрати внимание на странную фигурную скобку в конце этой строки https://github.com/SavchenkoAndreyV/ProxyModel/blob/main/ProxyModel/tablemodel.cpp#L48 Отформатируй по-человечески этот метод.

также в конструкторе MainWindow соединение с сигналом clicked не нужно — это и так происходит неявным образом за счет вызова метода connectSlotsByName. из-за этого у тебя обработчик дважды подряд срабатывает.