QStandardItem(Model): refactor multiData support

QSI(M) allow users to override their data() functions. This
means that we can't have their data() implemented in terms of
multiData(), or otherwise a subclass that overrides data() will
fall out of sync with its multiData() implementation. We must
keep multiData() implemented in terms of data() instead.

While at it, document QSI::multiData().

Task-number: QTBUG-89423
Change-Id: If30a980d8449135b516745fec73170d53367b4b7
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
(cherry picked from commit a1e9817cec5e0dccf26040d0b0d24e974841d5b8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2020-12-13 21:37:23 +01:00 committed by Qt Cherry-pick Bot
parent 3409cda1bc
commit d0702bef50

View File

@ -968,31 +968,29 @@ void QStandardItem::clearData()
*/
QVariant QStandardItem::data(int role) const
{
QModelRoleData result(role);
multiData(result);
return result.data();
Q_D(const QStandardItem);
const int r = (role == Qt::EditRole) ? Qt::DisplayRole : role;
for (const auto &value : d->values) {
if (value.role == r)
return value.value;
}
return QVariant();
}
/*!
\since 6.0
Fills the \a roleDataSpan span with the data from this item.
The default implementation simply calls data() for each role
in the span.
\sa data()
*/
void QStandardItem::multiData(QModelRoleDataSpan roleDataSpan) const
{
Q_D(const QStandardItem);
const auto valuesBegin = d->values.begin();
const auto valuesEnd = d->values.end();
for (auto &roleData : roleDataSpan) {
const int role = (roleData.role() == Qt::EditRole) ? Qt::DisplayRole : roleData.role();
const auto hasSameRole = [role](const QStandardItemData &data)
{
return data.role == role;
};
auto dataIt = std::find_if(valuesBegin, valuesEnd, hasSameRole);
if (dataIt != valuesEnd)
roleData.setData(dataIt->value);
else
roleData.clearData();
}
for (auto &roleData : roleDataSpan)
roleData.setData(data(roleData.role()));
}
/*!
@ -2846,10 +2844,11 @@ QVariant QStandardItemModel::data(const QModelIndex &index, int role) const
*/
void QStandardItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
{
Q_D(const QStandardItemModel);
QStandardItem *item = d->itemFromIndex(index);
if (item)
item->multiData(roleDataSpan);
// Cannot offer a better implementation; users may be overriding
// data(), and thus multiData() may fall out of sync for them.
// The base class' implementation will simply call data() in a loop,
// so it's fine.
QAbstractItemModel::multiData(index, roleDataSpan);
}
/*!