Уведомить QAbstractTableModel об изменении data sourse

128
26 декабря 2020, 16:30

Возможно, данная тема обсуждалась большое количество раз, но я не смог найти однозначного ответа и рабочей реализации задачи.

Имеется модель, унаследованная от QAbstractTableModel. Модель редактируемая. Пользователь может изменять некоторые данные в ней, так же добавлять/удалять строки.

Источником данных выступает класс Scanner для каждой строки. Данные в объекте изменяются внутри. Вообще это отображение данных api запросов, но для примера написал некий счетчик, который обновляется по таймеру.

Scanner::Scanner(QObject * parent)
    : QObject (parent)
{
    auto timer = new QTimer();
    connect(timer, &QTimer::timeout, this, [this] {
        this->setDifference(getDifference() + 1);
        emit dataChanged();
    });
    timer->start(1000);
}

Для каждой строки в view создается отдельный объект Scanner.

bool ScanningModel::insertRows(int position, int rows, const QModelIndex &parent)
{
    beginInsertRows(parent, position, position + rows - 1);
    for (int row = 0; row < rows; row++) {
        auto scanner = new Scanner();
        connect(scanner, &Scanner::dataChanged, this, [this] {
            emit beginResetModel();
            emit endResetModel();
        }, Qt::QueuedConnection);
        m_scanners.insert(position, scanner);
    }
    endInsertRows();
    return true;
}

Собственно вопрос: как уведомить модель о том, что данные в Scanner изменились и нужно их отобразить в view?

Вариант с beginResetModel и endResetModel работает. Но при этом модель сбрасывается и выделенная строка в view тоже. Т.е, чтобы внести изменения в строку через интерфейс, пользователю нужно успеть это сделать.

Для данной задачи предназначен сигнал в модели dataChanged. Но для него нужно передавать QModelIndex, которого нет в Scanner и сам index может изменится в любой момент (когда пользователь удалил/добавил новые строки).

Answer 1

В вашем коде вы уведомили модель о том, что данные изменились: вы соединили сигнал Scanner::dataChanged с лямбда-слотом модели. Тут всё правильно. Стало быть, ваш вопрос в том, как уведомить представление о том, что данные изменились. И опять вы сами же ответили: сигналом dataChanged модели. Осталось понять, как сформировать левый верхний и правый нижний индексы.

Сигнал dataChanged имеет следующие параметры:

void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = ...)

Одним из способов решения (не буду утверждать, что самым оптимальным) будет добавить в класс Scanner числовое поле, показывающее номер строки. Например, так:

class Scanner : public QObject {
    Q_OBJECT
    int m_rowNumber;
public:
    int rowNumber();
    void setRowNumber();
};

В модели при добавлении и удалении строк вам нужно будет правильно заполнять номер строк у созданных объектов, а также обновлять номера существующих объектов при их изменении. Когда вы это сделаете, у вас будут все необходимые данные для создания индекса. Тогда вы можете переписать ваш слот следующим образом:

connect(scanner, &Scanner::dataChanged, this, [this] {
    Scanner *scanner = sender();//Возвращает объект, который отправил сигнал
    dataChanged(index(scanner->rowNumber(), 0), index(scanner->rowNumber(), columnCount()));
}, Qt::QueuedConnection);

Я не проверял, будет ли работать метод sender в лямбда-функции. Но если не будет, вы можете вынести её в отдельный слот.

READ ALSO
Не могу вызвать перегрузку

Не могу вызвать перегрузку

Продолжаю пробовать перегружать операторы, и вновь не могу вызвать перегрузкуНапример, есть класс List:

136
Линия которую я не понимаю

Линия которую я не понимаю

Вызываю функцию которая рисует круги и почему то дорисовывает одну точку из центра и не как избавиться от этого "явления" не могу

136
Не учитывать клик по элементам родителя

Не учитывать клик по элементам родителя

Нужно получить клик только по контейнеруЕсли я произвожу клик по элементам внутри контейнера, то они тоже засчитываются

99
вложенные категории django+jquaery

вложенные категории django+jquaery

Подскажите пожалуйста как реализовать подобную структуру на django+jquery? modelspy

123