SIGNAL: QStandarditemmodel :: datachanged (...) не испускает роли при использовании QStandarditemmodel :: setData (...)) - PullRequest
0 голосов
/ 12 июня 2018

Моя проблема в том, что при использовании

QStandarditemmodel::setData(const QModelIndex &index, const QVariant &value, int role)

создается впечатление, что роль никогда не испускается.

Пример:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{

QStandardItemModel *model = new QStandardItemModel();

QList<QStandardItem*> itemList;
itemList.append(new QStandardItem());

model->appendRow(itemList);

connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(myslot_dataChanged(QModelIndex,QModelIndex,QVector<int>)));

model->item(0,0)->setData("supercool value", Qt::DisplayRole); // // should emit 1 role, but 0 are arriving
model->item(0,0)->setData("another supercool value", Qt::UserRole); //  // should emit 1 role, but 0 are arriving

QVector<int> roles;
roles.append(Qt::DisplayRole); 
roles.append(Qt::UserRole);
emit model->dataChanged(model->index(0,0), model->index(0,0), roles); // works. roles.count() == 2
}

MainWindow::myslot_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    qDebug() << roles.count();
}

учитывая Вывод:

0
0
2

Ожидаемый результат:

1
1
2

Я знаю, что роли QVector в сигнале необязательны.Может ли быть так, что Qt опускает роли и просто использует роли по умолчанию?Может быть, я должен использовать правильный сигнал (НЕ те, где вы можете опустить роли ...) явно, но я не знаю, как.

Извините за плохой английский, и спасибо за помощь!;)

Редактировать 1: Дальнейшие исследования:

Я пролистал источники Qt и нашел это в qstandarditemmodel.cpp

void QStandardItem::setData(const QVariant &value, int role)
{
    Q_D(QStandardItem);
    role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
    QVector<QStandardItemData>::iterator it;
    for (it = d->values.begin(); it != d->values.end(); ++it) {
        if ((*it).role == role) {
            if (value.isValid()) {
                if ((*it).value.type() == value.type() && (*it).value == value)
                    return;
                (*it).value = value;
            } else {
                d->values.erase(it);
            }
            if (d->model)
                d->model->d_func()->itemChanged(this);
            return;
        }
    }
    d->values.append(QStandardItemData(role, value));
    if (d->model)
        d->model->d_func()->itemChanged(this);
}

При использовании setData функция itemChangedиспользуется который не заботится о ролях.Кажется, что параметр role в dataChanged является для вас необязательным и никогда не используется нативными функциями Qt.

Редактировать 2: еще больше исследований ...

Я прошел через функцию setData.Вот фрагмент кода, когда setData вызывает itemChanged ():

void QStandardItemModelPrivate::itemChanged(QStandardItem *item)
{
    Q_Q(QStandardItemModel);
    Q_ASSERT(item);
    if (item->d_func()->parent == 0) {
        // Header item
        int idx = columnHeaderItems.indexOf(item);
        if (idx != -1) {
            emit q->headerDataChanged(Qt::Horizontal, idx, idx);
        } else {
            idx = rowHeaderItems.indexOf(item);
            if (idx != -1)
                emit q->headerDataChanged(Qt::Vertical, idx, idx);
        }
    } else {
        // Normal item
        QModelIndex index = q->indexFromItem(item);
        emit q->dataChanged(index, index);
    }
}

Как упоминалось в предыдущих исследованиях, setData вызывает itemChanged, что, в свою очередь, вызывает emit q->dataChanged(index, index); Там мы видим, что dataChanged пропускает параметр роли.Это означает, что мое предыдущее предположение о том, что нативные функции Qt не используют роли, похоже, подтвердилось.

1 Ответ

0 голосов
/ 18 июня 2018

Из документов по сигналу QAbstractItemModel::dataChanged() (выделено мной):

void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = ...)
[...]
Необязательный аргумент role может использоваться для указания того, какие роли данных были фактически изменены. пустой вектор в аргументе role означает, что все роли следует считать измененными.

Как вы сказали, реализация Qt QStandardItemModel не заботится о том, для каких ролей были изменены данные, но вместо этого указывает, что все данные должны быть обновлены.

Ответ на вопрос (который вы не задавали):

Если ваш слот вызывается с определенным набором roles, вы можете оптимизировать его.Если roles пусто, вам нужно получить данные для всех ролей, которые имеют отношение к вашему представлению.

...