239void QQmlPropertyPrivate::initProperty(QObject *obj,
const QString &name,
240 QQmlPropertyPrivate::InitFlags flags)
242 QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() :
nullptr;
244 QObject *currentObject = obj;
245 QList<QStringView> path;
246 QStringView terminal(name);
248 if (name.contains(QLatin1Char(
'.'))) {
249 path = QStringView{name}.split(QLatin1Char(
'.'));
250 if (path.isEmpty())
return;
253 for (
int ii = 0; ii < path.size() - 1; ++ii) {
254 const QStringView &pathName = path.at(ii);
258 if (typeNameCache && !pathName.isEmpty() && pathName.at(0).isUpper()) {
259 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine.data());
260 QQmlTypeNameCache::Result r = typeNameCache->query(pathName, typeLoader);
262 if (r.type.isValid()) {
263 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
266 currentObject = qmlAttachedPropertiesObject(currentObject, func);
267 if (!currentObject)
return;
268 }
else if (r.importNamespace) {
269 if (++ii == path.size())
273 r = typeNameCache->query<QQmlTypeNameCache::QueryNamespaced::No>(
274 path.at(ii), r.importNamespace, typeLoader);
276 if (!r.type.isValid())
279 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
283 currentObject = qmlAttachedPropertiesObject(currentObject, func);
287 }
else if (r.scriptIndex != -1) {
290 Q_ASSERT(!
"Unreachable");
297 QQmlPropertyData local;
298 const QQmlPropertyData *property = currentObject
299 ? QQmlPropertyCache::property(currentObject, pathName, context, &local)
305 if (currentObject || !(flags & InitFlag::AllowId))
308 for (
auto idContext = context; idContext; idContext = idContext->parent()) {
309 const int objectId = idContext->propertyIndex(pathName.toString());
310 if (objectId != -1 && objectId < idContext->numIdValues()) {
311 currentObject = idContext->idValue(objectId);
320 }
else if (property->isFunction()) {
324 if (ii == (path.size() - 2) && QQmlMetaType::isValueType(property->propType())) {
326 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(property->propType());
327 if (!valueTypeMetaObject)
return;
329 int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
330 if (idx == -1)
return;
332 QMetaProperty vtProp = valueTypeMetaObject->property(idx);
334 Q_ASSERT(idx <= 0x0000FFFF);
336 object = currentObject;
338 valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
339 valueTypeData.setPropType(vtProp.metaType());
340 valueTypeData.setCoreIndex(idx);
344 if (!property->isQObject()) {
345 if (
auto asPropertyMap = qobject_cast<QQmlPropertyMap*>(currentObject))
346 currentObject = asPropertyMap->value(path.at(ii).toString()).value<QObject*>();
350 property->readProperty(currentObject, ¤tObject);
353 if (!currentObject)
return;
359 terminal = path.last();
360 }
else if (!currentObject) {
364 auto findSignalInMetaObject = [&](
const QByteArray &signalName) {
365 const QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName);
366 if (!method.isValid())
369 object = currentObject;
374 QQmlData *ddata = QQmlData::get(currentObject,
false);
375 auto findChangeSignal = [&](QStringView signalName) {
376 if (
auto propName = QQmlSignalNames::changedSignalNameToPropertyName(signalName)) {
377 const QQmlPropertyData *d =
378 ddata->propertyCache->property(*propName, currentObject, context);
379 while (d && d->isFunction())
380 d = ddata->propertyCache->overrideData(d);
382 if (d && d->notifyIndex() != -1) {
383 object = currentObject;
384 core = *ddata->propertyCache->signal(d->notifyIndex());
391 const auto findSignal = [&](
const QString &signalName) {
392 if (ddata && ddata->propertyCache) {
394 const QQmlPropertyData *d
395 = ddata->propertyCache->property(signalName, currentObject, context);
400 while (d && !d->isFunction())
401 d = ddata->propertyCache->overrideData(d);
404 object = currentObject;
409 return findChangeSignal(signalName);
412 return findSignalInMetaObject(signalName.toUtf8());
415 auto signalName = QQmlSignalNames::handlerNameToSignalName(terminal);
417 if (findSignal(*signalName))
420 signalName = QQmlSignalNames::badHandlerNameToSignalName(terminal);
422 if (findSignal(*signalName)) {
425 <<
"is not a properly capitalized signal handler name."
426 << QQmlSignalNames::signalNameToHandlerName(*signalName)
427 <<
"would be correct.";
433 if (ddata && ddata->propertyCache) {
434 const QQmlPropertyData *property = ddata->propertyCache->property(
435 terminal, currentObject, context);
438 while (property && !property->isSignal()) {
439 if (!property->isFunction()) {
440 object = currentObject;
442 nameCache = terminal.toString();
445 property = ddata->propertyCache->overrideData(property);
448 if (!(flags & InitFlag::AllowSignal))
452 Q_ASSERT(property->isSignal());
453 object = currentObject;
459 findChangeSignal(terminal);
462 const QByteArray propertyName = terminal.toUtf8();
463 const QMetaProperty prop = findPropertyByName(currentObject->metaObject(), propertyName);
465 if (prop.isValid()) {
466 object = currentObject;
471 if (flags & InitFlag::AllowSignal)
472 findSignalInMetaObject(terminal.toUtf8());
853 QObject *object, QQmlPropertyIndex index,
856 int coreIndex = index.coreIndex();
857 int valueTypeIndex = index.valueTypeIndex();
859 QQmlData *data = QQmlData::get(object,
false);
861 if (!data || !data->hasBindingBit(coreIndex))
864 QQmlAbstractBinding::Ptr oldBinding;
865 oldBinding = data->bindings;
867 while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
868 oldBinding->targetPropertyIndex().hasValueTypeIndex())) {
869 oldBinding = oldBinding->nextBinding();
874 data->clearBindingBit(coreIndex);
878 if (valueTypeIndex != -1 && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy) {
879 oldBinding =
static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
884 if (oldBinding->isSticky() && !(flags & QQmlPropertyPrivate::OverrideSticky))
887 if (!(flags & QQmlPropertyPrivate::DontEnable))
888 oldBinding->setEnabled(
false, {});
889 oldBinding->removeFromObject();
921QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index)
923 auto aliasTarget = findAliasTarget(object, index);
924 object = aliasTarget.targetObject;
925 index = aliasTarget.targetIndex;
927 QQmlData *data = QQmlData::get(object);
931 const int coreIndex = index.coreIndex();
932 const int valueTypeIndex = index.valueTypeIndex();
934 if (coreIndex < 0 || !data->hasBindingBit(coreIndex))
937 QQmlAbstractBinding *binding = data->bindings;
938 while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex ||
939 binding->targetPropertyIndex().hasValueTypeIndex()))
940 binding = binding->nextBinding();
942 if (binding && valueTypeIndex != -1) {
943 if (binding->kind() == QQmlAbstractBinding::ValueTypeProxy)
944 binding =
static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
950void QQmlPropertyPrivate::findAliasTarget(QObject *object, QQmlPropertyIndex bindingIndex,
951 QObject **targetObject,
952 QQmlPropertyIndex *targetBindingIndex)
954 QQmlData *data = QQmlData::get(object,
false);
956 int coreIndex = bindingIndex.coreIndex();
957 int valueTypeIndex = bindingIndex.valueTypeIndex();
959 const QQmlPropertyData *propertyData =
960 data->propertyCache?data->propertyCache->property(coreIndex):
nullptr;
961 if (propertyData && propertyData->isAlias()) {
962 QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
964 QObject *aObject =
nullptr;
int aCoreIndex = -1;
int aValueTypeIndex = -1;
965 if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
967 Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
969 QQmlPropertyIndex aBindingIndex(aCoreIndex);
970 if (aValueTypeIndex != -1) {
971 aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex);
972 }
else if (valueTypeIndex != -1) {
973 aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex);
976 findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
982 *targetObject = object;
983 *targetBindingIndex = bindingIndex;
1061void QQmlPropertyPrivate::takeSignalExpression(
const QQmlProperty &that,
1062 QQmlBoundSignalExpression *expr)
1064 if (!(that.type() & QQmlProperty::SignalProperty)) {
1070 if (!that.d->object)
1072 QQmlData *data = QQmlData::get(that.d->object,
nullptr != expr);
1076 QQmlBoundSignal *signalHandler = data->signalHandlers;
1078 while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
1079 signalHandler = signalHandler->m_nextSignal;
1081 if (signalHandler) {
1082 signalHandler->takeExpression(expr);
1087 int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
1088 QQmlBoundSignal *signal =
new QQmlBoundSignal(that.d->object, signalIndex, that.d->object,
1090 signal->takeExpression(expr);
1162QVariant QQmlPropertyPrivate::readValueProperty()
1164 auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) {
1165 wrapper->read(object, core.coreIndex());
1166 return wrapper->readOnGadget(wrapper->property(valueTypeData.coreIndex()));
1169 if (isValueType()) {
1170 if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType()))
1171 return doRead(wrapper);
1172 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1173 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1174 return doRead(&wrapper);
1177 }
else if (core.isQList()) {
1178 auto coreMetaType = core.propType();
1181 if (coreMetaType.flags() & QMetaType::IsQmlList) {
1182 QQmlListProperty<QObject> prop;
1183 core.readProperty(object, &prop);
1184 return QVariant::fromValue(QQmlListReferencePrivate::init(prop, coreMetaType));
1187 QVariant result(coreMetaType);
1190 coreMetaType.construct(result.data());
1191 core.readProperty(object, result.data());
1195 }
else if (core.isQObject()) {
1197 QObject *rv =
nullptr;
1198 core.readProperty(object, &rv);
1199 return QVariant::fromValue(rv);
1203 if (!core.propType().isValid())
1204 return object->metaObject()->property(core.coreIndex()).read(object);
1208 void *args[] = {
nullptr, &value, &status };
1209 if (core.propType() == QMetaType::fromType<QVariant>()) {
1212 value = QVariant(core.propType(), (
void*)
nullptr);
1213 args[0] = value.data();
1215 core.readPropertyWithArgs(object, args);
1216 if (core.propType() != QMetaType::fromType<QVariant>() && args[0] != value.data())
1217 return QVariant(QMetaType(core.propType()), args[0]);
1224QList<QUrl> QQmlPropertyPrivate::urlSequence(
const QVariant &value)
1226 if (value.metaType() == QMetaType::fromType<QList<QUrl>>())
1227 return value.value<QList<QUrl> >();
1230 if (value.metaType() == QMetaType::fromType<QUrl>()) {
1231 urls.append(value.toUrl());
1232 }
else if (value.metaType() == QMetaType::fromType<QString>()) {
1233 urls.append(QUrl(value.toString()));
1234 }
else if (value.metaType() == QMetaType::fromType<QByteArray>()) {
1235 urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
1236 }
else if (value.metaType() == QMetaType::fromType<QStringList>()) {
1237 QStringList urlStrings = value.value<QStringList>();
1238 const int urlStringsSize = urlStrings.size();
1239 urls.reserve(urlStringsSize);
1240 for (
int i = 0; i < urlStringsSize; ++i)
1241 urls.append(QUrl(urlStrings.at(i)));
1259bool QQmlPropertyPrivate::writeEnumProperty(
const QMetaProperty &prop,
int idx, QObject *object,
const QVariant &value,
int flags)
1261 if (!object || !prop.isWritable())
1265 if (prop.isEnumType() && v.metaType() != prop.metaType()) {
1266 QMetaEnum menum = prop.enumerator();
1267 if (v.userType() == QMetaType::QString) {
1269 if (prop.isFlagType())
1270 v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
1272 v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
1276 if (!v.convert(prop.metaType()))
1286 void *argv[] = { v.data(), &v, &status, &flags };
1287 QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
1321 QObject *object,
const QQmlPropertyData &core,
1322 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags,
1323 int internalIndex, Op op)
1325 if (QQmlGadgetPtrWrapper *wrapper = context
1326 ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
1328 return changePropertyAndWriteBack(
1329 object, core.coreIndex(), wrapper, flags, internalIndex, op);
1332 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1333 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1334 return changePropertyAndWriteBack(
1335 object, core.coreIndex(), &wrapper, flags, internalIndex, op);
1341bool QQmlPropertyPrivate::writeValueProperty(
1342 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1343 const QVariant &value,
const QQmlRefPointer<QQmlContextData> &context,
1344 QQmlPropertyData::WriteFlags flags)
1346 removeValuePropertyBinding(object, core, valueTypeData, flags);
1348 if (!valueTypeData.isValid())
1349 return write(object, core, value, context, flags);
1351 return changeThroughGadgetPtrWrapper(
1352 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1353 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1354 return write(wrapper, valueTypeData, value, context, flags);
1358bool QQmlPropertyPrivate::resetValueProperty(
1359 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1360 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1362 removeValuePropertyBinding(object, core, valueTypeData, flags);
1364 if (!valueTypeData.isValid())
1365 return reset(object, core, flags);
1367 return changeThroughGadgetPtrWrapper(
1368 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1369 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1370 return reset(wrapper, valueTypeData, flags);
1418 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1419 QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType,
1420 bool isUrl, QQmlEnginePrivate *enginePriv) {
1423 || variantMetaType == QMetaType::fromType<QString>()
1424 || propertyMetaType == QMetaType::fromType<QList<QUrl>>()
1425 || property.isQList()) {
1426 return {
false,
false};
1430 switch (propertyMetaType.id()) {
1431 case QMetaType::Bool:
1432 if (value.canConvert(propertyMetaType)) {
1433 bool b = value.toBool();
1434 return {
true, property.writeProperty(object, &b, flags)};
1436 return {
false,
false};
1437 case QMetaType::Int: {
1439 int i = value.toInt(&ok);
1440 return {ok, ok && property.writeProperty(object, &i, flags)};
1442 case QMetaType::UInt: {
1444 uint u = value.toUInt(&ok);
1445 return {ok, ok && property.writeProperty(object, &u, flags)};
1447 case QMetaType::Double: {
1449 double d = value.toDouble(&ok);
1450 return {ok, ok && property.writeProperty(object, &d, flags)};
1452 case QMetaType::Float: {
1454 float f = value.toFloat(&ok);
1455 return {ok, ok && property.writeProperty(object, &f, flags)};
1457 case QMetaType::QString:
1458 if (value.canConvert(propertyMetaType)) {
1459 QString s = value.toString();
1460 return {
true, property.writeProperty(object, &s, flags)};
1462 return {
false,
false};
1463 case QMetaType::QVariantMap:
1464 if (value.canConvert(propertyMetaType)) {
1465 QVariantMap m = value.toMap();
1466 return {
true, property.writeProperty(object, &m, flags)};
1468 return {
false,
false};
1474 QVariant converted = QQmlValueTypeProvider::createValueType(
1475 value, propertyMetaType, enginePriv ? enginePriv->v4Engine.get() :
nullptr);
1476 if (!converted.isValid()) {
1477 converted = QVariant(propertyMetaType);
1478 if (!QMetaType::convert(value.metaType(), value.constData(),
1479 propertyMetaType, converted.data())) {
1480 return {
false,
false};
1483 return {
true, property.writeProperty(object, converted.data(), flags)};
1489 QMetaSequence::Iterable iterable;
1490 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QMetaSequence::Iterable>(), &iterable))
1493 const QMetaSequence metaSequence = iterable.metaContainer();
1495 if (!metaSequence.hasConstIterator()
1496 || !metaSequence.canGetValueAtConstIterator()
1497 || !metaSequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1501 const void *container = iterable.constIterable();
1502 void *it = metaSequence.constBegin(container);
1503 const void *end = metaSequence.constEnd(container);
1504 QObject *o =
nullptr;
1505 while (!metaSequence.compareConstIterator(it, end)) {
1506 metaSequence.valueAtConstIterator(it, &o);
1508 metaSequence.advanceConstIterator(it, 1);
1510 metaSequence.destroyConstIterator(it);
1511 metaSequence.destroyConstIterator(end);
1590 QQmlListProperty<QObject> *prop, QMetaType metaType,
const void *data, DoAppend &&doAppend)
1592 QMetaSequence::Iterable iterable;
1593 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QMetaSequence::Iterable>(), &iterable))
1594 return AssignResult::TypeMismatch;
1596 const QMetaSequence metaSequence = iterable.metaContainer();
1597 if (!metaSequence.hasConstIterator()
1598 || !metaSequence.canGetValueAtConstIterator()
1599 || !metaSequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1600 return AssignResult::TypeMismatch;
1603 const void *container = iterable.constIterable();
1604 const void *end = metaSequence.constEnd(container);
1606 QObject *o =
nullptr;
1608 if (prop->at && prop->count && metaSequence.hasSize()
1609 && metaSequence.size(container) == prop->count(prop)) {
1610 void *it = metaSequence.constBegin(container);
1613 while (!metaSequence.compareConstIterator(it, end)) {
1614 metaSequence.valueAtConstIterator(it, &o);
1615 if (o != prop->at(prop, ++i)) {
1619 metaSequence.advanceConstIterator(it, 1);
1621 metaSequence.destroyConstIterator(it);
1626 void *it = metaSequence.constBegin(container);
1627 while (!metaSequence.compareConstIterator(it, end)) {
1628 metaSequence.valueAtConstIterator(it, &o);
1630 metaSequence.advanceConstIterator(it, 1);
1632 metaSequence.destroyConstIterator(it);
1635 metaSequence.destroyConstIterator(end);
1636 return same ? AssignResult::WasEqual : AssignResult::Copied;
1647QQmlPropertyPrivate::ListCopyResult QQmlPropertyPrivate::convertToQQmlListProperty(QQmlListProperty<QObject> *listProperty, QMetaType actualListType,
const QVariant &value) {
1648 QQmlListProperty<QObject> &prop = *listProperty;
1649 QMetaType listValueType = QQmlMetaType::listValueType(actualListType);
1652 QQmlMetaObject elementMetaObject = QQmlMetaType::rawMetaObjectForType(listValueType);
1654 auto doAppend = [&](QQmlListProperty<QObject> *propPtr, QObject *o) {
1655 if (Q_UNLIKELY(o && (elementMetaObject.isNull()
1656 || !QQmlMetaObject::canConvert(o, elementMetaObject)))) {
1657 qCWarning(lcIncompatibleElement)
1658 <<
"Cannot append" << o <<
"to a QML list of" << listValueType.name();
1661 propPtr->append(propPtr, o);
1665 AssignResult result = AssignResult::TypeMismatch;
1666 QMetaType variantMetaType = value.metaType();
1667 if (variantMetaType == QMetaType::fromType<QQmlListReference>()) {
1668 result = assignListToListProperty(
1669 &prop,
static_cast<
const QQmlListReference *>(value.constData()),
1670 std::move(doAppend));
1671 }
else if (variantMetaType == QMetaType::fromType<QObjectList>()) {
1672 result = assignListToListProperty(
1673 &prop,
static_cast<
const QObjectList *>(value.constData()),
1674 std::move(doAppend));
1675 }
else if (variantMetaType == QMetaType::fromType<QVariantList>()) {
1676 result = assignListToListProperty(
1677 &prop,
static_cast<
const QVariantList *>(value.constData()),
1678 std::move(doAppend));
1680 result = assignMetaContainerToListProperty(
1681 &prop, variantMetaType, value.data(), doAppend);
1682 if (result == AssignResult::TypeMismatch) {
1684 doAppend(&prop, QQmlMetaType::toQObject(value));
1685 result = AssignResult::Copied;
1695 const QQmlPropertyData &property,
1696 const QMetaType propertyMetaType,
const QVariant &value)
1698 Q_ASSERT(propertyMetaType.flags() & QMetaType::IsQmlList);
1699 QQmlListProperty<QObject> prop;
1700 property.readProperty(object, &prop);
1703 if (!prop.clear || !prop.append)
1706 const bool useNonsignalingListOps = prop.clear == &QQmlVMEMetaObject::list_clear
1707 && prop.append == &QQmlVMEMetaObject::list_append;
1708 if (useNonsignalingListOps) {
1709 prop.clear = &QQmlVMEMetaObject::list_clear_nosignal;
1710 prop.append = &QQmlVMEMetaObject::list_append_nosignal;
1713 auto result = QQmlPropertyPrivate::convertToQQmlListProperty(&prop, propertyMetaType, value);
1715 if (useNonsignalingListOps && result == QQmlPropertyPrivate::ListCopyResult::Copied) {
1716 Q_ASSERT(QQmlVMEMetaObject::get(object));
1717 QQmlVMEResolvedList(&prop).activateSignal();
1720 return result != QQmlPropertyPrivate::ListCopyResult::TypeMismatch;
1726 const QQmlPropertyData &property, QQmlPropertyData::WriteFlags flags,
1727 const QMetaType propertyMetaType,
const QMetaType variantMetaType,
const QVariant &value,
1730 Q_ASSERT(!(propertyMetaType.flags() & QMetaType::IsQmlList));
1731 if (variantMetaType == propertyMetaType) {
1733 return property.writeProperty(object, v.data(), flags);
1735 QVariant outputList(propertyMetaType);
1736 const QQmlType type = QQmlMetaType::qmlListType(propertyMetaType);
1737 const QMetaSequence outputSequence = type.listMetaSequence();
1738 if (!outputSequence.canAddValue())
1739 return property.writeProperty(object, outputList.data(), flags);
1741 const QMetaType outputElementMetaType = outputSequence.valueMetaType();
1742 const bool outputIsQVariant = (outputElementMetaType == QMetaType::fromType<QVariant>());
1744 QMetaSequence::Iterable inputIterable;
1745 QVariant inputList = value;
1746 if (QMetaType::view(
1747 inputList.metaType(), inputList.data(),
1748 QMetaType::fromType<QMetaSequence::Iterable>(), &inputIterable)) {
1750 const QMetaSequence inputSequence = inputIterable.metaContainer();
1751 const QMetaType inputElementMetaType = inputSequence.valueMetaType();
1752 const bool inputIsQVariant = (inputElementMetaType == QMetaType::fromType<QVariant>());
1754 QVariant outputElement
1755 = outputIsQVariant ? QVariant() : QVariant(outputElementMetaType);
1756 QVariant inputElement
1757 = inputIsQVariant ? QVariant() : QVariant(inputElementMetaType);
1759 void *it = inputSequence.constBegin(inputList.constData());
1760 void *end = inputSequence.constEnd(inputList.constData());
1762 for (; !inputSequence.compareConstIterator(it, end);
1763 inputSequence.advanceConstIterator(it, 1)) {
1765 if (inputIsQVariant)
1766 inputSequence.valueAtIterator(it, &inputElement);
1768 inputSequence.valueAtIterator(it, inputElement.data());
1770 if (outputIsQVariant) {
1771 outputSequence.addValue(outputList.data(), &inputElement);
1772 }
else if (inputElement.metaType() == outputElement.metaType()) {
1773 outputSequence.addValue(outputList.data(), inputElement.constData());
1776 inputElement.metaType(), inputElement.constData(),
1777 outputElementMetaType, outputElement.data());
1778 outputSequence.addValue(outputList.data(), outputElement.constData());
1782 inputSequence.destroyConstIterator(it);
1783 inputSequence.destroyConstIterator(end);
1784 }
else if (outputIsQVariant) {
1785 outputSequence.addValue(outputList.data(), &value);
1786 }
else if (outputElementMetaType == value.metaType()){
1787 outputSequence.addValue(outputList.data(), value.constData());
1789 QVariant output(outputElementMetaType);
1791 value.metaType(), value.constData(), outputElementMetaType, output.data());
1792 outputSequence.addValue(outputList.data(), output.constData());
1795 return property.writeProperty(object, outputList.data(), flags);
1799QVariant QQmlPropertyPrivate::convertToWriteTargetType(
const QVariant &value, QMetaType targetMetaType){
1800 QMetaType sourceMetaType = value.metaType();
1801 Q_ASSERT(sourceMetaType != targetMetaType);
1804 if (sourceMetaType == QMetaType::fromType<QString>()) {
1806 QVariant converted = QQmlStringConverters::variantFromString(value.toString(), targetMetaType, &ok);
1813 if (QMetaType::canConvert(sourceMetaType, targetMetaType))
1814 if (QVariant copy = value; copy.convert(targetMetaType))
1822
1823
1824 QMetaSequence::Iterable iterable;
1825 QVariant sequenceVariant = QVariant(targetMetaType);
1826 if (QMetaType::view(
1827 targetMetaType, sequenceVariant.data(),
1828 QMetaType::fromType<QMetaSequence::Iterable>(),
1830 const QMetaSequence propertyMetaSequence = iterable.metaContainer();
1831 if (propertyMetaSequence.canAddValueAtEnd()) {
1832 const QMetaType elementMetaType = propertyMetaSequence.valueMetaType();
1833 void *propertyContainer = iterable.mutableIterable();
1835 if (sourceMetaType == elementMetaType) {
1836 propertyMetaSequence.addValueAtEnd(propertyContainer, value.constData());
1837 return sequenceVariant;
1838 }
else if (sourceMetaType == QMetaType::fromType<QVariantList>()) {
1839 const QVariantList list = value.value<QVariantList>();
1840 for (
const QVariant &valueElement : list) {
1841 if (valueElement.metaType() == elementMetaType) {
1842 propertyMetaSequence.addValueAtEnd(
1843 propertyContainer, valueElement.constData());
1845 QVariant converted(elementMetaType);
1847 valueElement.metaType(), valueElement.constData(),
1848 elementMetaType, converted.data());
1849 propertyMetaSequence.addValueAtEnd(
1850 propertyContainer, converted.constData());
1853 return sequenceVariant;
1854 }
else if (elementMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1855 const QMetaObject *elementMetaObject = elementMetaType.metaObject();
1856 Q_ASSERT(elementMetaObject);
1858 const auto doAppend = [&](QObject *o) {
1859 QObject *casted = elementMetaObject->cast(o);
1860 propertyMetaSequence.addValueAtEnd(propertyContainer, &casted);
1863 if (sourceMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1864 doAppend(*
static_cast<QObject *
const *>(value.data()));
1865 return sequenceVariant;
1866 }
else if (sourceMetaType == QMetaType::fromType<QQmlListReference>()) {
1867 const QQmlListReference *reference
1868 =
static_cast<
const QQmlListReference *>(value.constData());
1869 Q_ASSERT(elementMetaObject);
1870 for (
int i = 0, end = reference->size(); i < end; ++i)
1871 doAppend(reference->at(i));
1872 return sequenceVariant;
1873 }
else if (!iterateQObjectContainer(
1874 sourceMetaType, value.data(), doAppend)) {
1875 doAppend(QQmlMetaType::toQObject(value));
1878 QVariant converted = value;
1879 if (converted.convert(elementMetaType)) {
1880 propertyMetaSequence.addValueAtEnd(propertyContainer, converted.constData());
1881 return sequenceVariant;
1888 if (QQmlMetaType::isInterface(targetMetaType)) {
1889 auto valueAsQObject = qvariant_cast<QObject *>(value);
1891 if (
void *iface = valueAsQObject
1892 ? valueAsQObject->qt_metacast(QQmlMetaType::interfaceIId(targetMetaType))
1897 return QVariant(targetMetaType, &iface);
1903bool QQmlPropertyPrivate::write(
1904 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1905 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1907 const QMetaType propertyMetaType = property.propType();
1908 const QMetaType variantMetaType = value.metaType();
1910 const BindingFixer bindingFixer(object, property, flags);
1913 if (property.isResettable() && !value.isValid()) {
1914 property.resetProperty(object, flags);
1918 if (property.isEnum()) {
1919 QMetaProperty prop = object->metaObject()->property(property.coreIndex());
1922 if (variantMetaType == QMetaType::fromType<
double>()) {
1924 double fractional = std::modf(value.toDouble(), &integral);
1925 if (qFuzzyIsNull(fractional))
1926 v.convert(QMetaType::fromType<qint32>());
1928 return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
1931 QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
1932 const bool isUrl = propertyMetaType == QMetaType::fromType<QUrl>();
1935 if (tryAssignBinding(object, property, value, variantMetaType))
1939 if (propertyMetaType == variantMetaType && !isUrl
1940 && propertyMetaType != QMetaType::fromType<QList<QUrl>>() && !property.isQList()) {
1941 return property.writeProperty(object,
const_cast<
void *>(value.constData()), flags);
1942 }
else if (property.isQObject()) {
1943 QVariant val = value;
1945 if (variantMetaType == QMetaType::fromType<std::nullptr_t>()) {
1948 varType = QMetaType::fromType<QObject*>();
1949 val = QVariant(varType,
nullptr);
1951 varType = variantMetaType;
1954 if (!varType.flags().testFlag(QMetaType::PointerToQObject))
1957 QObject *o = *
static_cast<QObject *
const *>(val.constData());
1961 return QQmlMetaType::canConvert(o, propertyMetaType)
1962 && property.writeProperty(object, &o, flags);
1968 const QQmlMetaObject valMo = rawMetaObjectForType(varType);
1969 const QQmlMetaObject propMo = rawMetaObjectForType(propertyMetaType);
1970 if (QQmlMetaObject::canConvert(valMo, propMo) || QQmlMetaObject::canConvert(propMo, valMo))
1971 return property.writeProperty(object, &o, flags);
1973 }
else if (ConvertAndAssignResult result = tryConvertAndAssign(
1974 object, property, value, flags, propertyMetaType, variantMetaType, isUrl,
1976 return result.couldWrite;
1977 }
else if (propertyMetaType == QMetaType::fromType<QVariant>()) {
1978 return property.writeProperty(object,
const_cast<QVariant *>(&value), flags);
1981 if (variantMetaType == QMetaType::fromType<QUrl>()) {
1983 if (compatResolveUrlsOnAssigment() && context && u.isRelative() && !u.isEmpty())
1984 u = context->resolvedUrl(u);
1986 else if (variantMetaType == QMetaType::fromType<QByteArray>())
1987 u = QUrl(QString::fromUtf8(value.toByteArray()));
1988 else if (variantMetaType == QMetaType::fromType<QString>())
1989 u = QUrl(value.toString());
1993 return property.writeProperty(object, &u, flags);
1994 }
else if (propertyMetaType == QMetaType::fromType<QList<QUrl>>()) {
1995 QList<QUrl> urlSeq = compatResolveUrlsOnAssigment()
1996 ? urlSequence(value, context)
1997 : urlSequence(value);
1998 return property.writeProperty(object, &urlSeq, flags);
1999 }
else if (property.isQList()) {
2000 if (propertyMetaType.flags() & QMetaType::IsQmlList) {
2001 return assignToQQmlListProperty(object, property, propertyMetaType, value);
2003 return assignToListProperty(property, flags, propertyMetaType, variantMetaType, value, object);
2005 }
else if (enginePriv && propertyMetaType == QMetaType::fromType<QJSValue>()) {
2007 QJSValue jsValue = QJSValuePrivate::fromReturnedValue(
2008 enginePriv->v4Engine->metaTypeToJS(variantMetaType, value.constData()));
2009 return property.writeProperty(object, &jsValue, flags);
2011 Q_ASSERT(variantMetaType != propertyMetaType);
2013 QVariant converted = convertToWriteTargetType(value, propertyMetaType);
2014 if (converted.isValid()) {
2015 return property.writeProperty(object,
const_cast<
void *>(converted.constData()), flags);