SIGNAL:QStandarditemmodel :: datachanged(...)在使用QStandarditemmodel :: setData(...)时不会发出角色

时间:2018-06-12 13:16:45

标签: c++ qt qt-signals slot

我的问题是,在使用时

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不关心角色。似乎dataChanged中的roles参数对您来说是可选的,并且从未被本机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省略了role参数。这意味着我之前的猜测,即Qt原生函数不使用角色,似乎已经确认。

1 个答案:

答案 0 :(得分:1)

来自信号QAbstractItemModel::dataChanged()的文件(我强调):

  

<强> void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = ...)
  [...]
  可选的 roles 参数可用于指定实际修改了哪些数据角色。 roles 参数中的空向量表示应将所有角色视为已修改。

如您所述,Qt的QStandardItemModel实施并不关心指定数据更改的角色,而是指定应更新所有数据。

问题的答案(你没有问过)是:

如果使用特定的roles集调用您的广告位,则可以对其进行优化。如果roles为空,则需要获取与您的视图相关的所有角色的数据。