QMetaProperty: add write() overload taking rvalue QVariant

The existing overload unconditionally copies the QVariant, causing it
to unconditional detach in most cases (when calling data() later).

The rvalue overload need not preserve the source object, so doesn't
need to copy.

Implement the lvalue overload in terms of the rvalue one, but keep the
sanity check in both to avoid copying the QVariant just to find that
there's nothing to do.

Following the copy, there were some references to the source object,
but they can all be replaced by references to the target object
instead, which hasn't been touched by then, yet.

[ChangeLog][QtCore][QMetaProperty] Added write() overload taking an
rvalue QVariant.

Fixes: QTBUG-112762
Change-Id: I0a8a91aa32143f071ebc8dae8f1f64b07fad9764
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2023-04-27 13:50:08 +02:00
parent 5fc53f58e9
commit 968250ee14
2 changed files with 17 additions and 4 deletions

View File

@ -3681,26 +3681,38 @@ QVariant QMetaProperty::read(const QObject *object) const
if this property is resettable, or setting a default-constructed object
otherwise.
\note This function internally makes a copy of \a value. Prefer to use the
rvalue overload when possible.
\sa read(), reset(), isWritable()
*/
bool QMetaProperty::write(QObject *object, const QVariant &value) const
{
if (!object || !isWritable())
return false;
return write(object, QVariant(value));
}
QVariant v = value;
/*!
\overload
\since 6.6
*/
bool QMetaProperty::write(QObject *object, QVariant &&v) const
{
if (!object || !isWritable())
return false;
QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
if (isEnumType() && !t.metaObject() && v.metaType().id() == QMetaType::QString) {
// Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
bool ok;
if (isFlagType())
v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
v = QVariant(menum.keysToValue(v.toByteArray(), &ok));
else
v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
v = QVariant(menum.keyToValue(v.toByteArray(), &ok));
if (!ok)
return false;
} else if (!value.isValid()) {
} else if (!v.isValid()) {
if (isResettable())
return reset(object);
v = QVariant(t, nullptr);

View File

@ -363,6 +363,7 @@ public:
QVariant read(const QObject *obj) const;
bool write(QObject *obj, const QVariant &value) const;
bool write(QObject *obj, QVariant &&value) const;
bool reset(QObject *obj) const;
QUntypedBindable bindable(QObject *object) const;