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 QVariant QStandardItem::data(int role) const
{ {
QModelRoleData result(role); Q_D(const QStandardItem);
multiData(result); const int r = (role == Qt::EditRole) ? Qt::DisplayRole : role;
return result.data(); 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 void QStandardItem::multiData(QModelRoleDataSpan roleDataSpan) const
{ {
Q_D(const QStandardItem); for (auto &roleData : roleDataSpan)
roleData.setData(data(roleData.role()));
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();
}
} }
/*! /*!
@ -2846,10 +2844,11 @@ QVariant QStandardItemModel::data(const QModelIndex &index, int role) const
*/ */
void QStandardItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const void QStandardItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
{ {
Q_D(const QStandardItemModel); // Cannot offer a better implementation; users may be overriding
QStandardItem *item = d->itemFromIndex(index); // data(), and thus multiData() may fall out of sync for them.
if (item) // The base class' implementation will simply call data() in a loop,
item->multiData(roleDataSpan); // so it's fine.
QAbstractItemModel::multiData(index, roleDataSpan);
} }
/*! /*!