242void QQmlPropertyPrivate::initProperty(QObject *obj,
const QString &name,
243 QQmlPropertyPrivate::InitFlags flags)
245 QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() :
nullptr;
247 QObject *currentObject = obj;
248 QList<QStringView> path;
249 QStringView terminal(name);
251 if (name.contains(QLatin1Char(
'.'))) {
252 path = QStringView{name}.split(QLatin1Char(
'.'));
253 if (path.isEmpty())
return;
256 for (
int ii = 0; ii < path.size() - 1; ++ii) {
257 const QStringView &pathName = path.at(ii);
261 if (typeNameCache && !pathName.isEmpty() && pathName.at(0).isUpper()) {
262 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine.data());
263 QQmlTypeNameCache::Result r = typeNameCache->query(pathName, typeLoader);
265 if (r.type.isValid()) {
266 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
269 currentObject = qmlAttachedPropertiesObject(currentObject, func);
270 if (!currentObject)
return;
271 }
else if (r.importNamespace) {
272 if (++ii == path.size())
276 r = typeNameCache->query<QQmlTypeNameCache::QueryNamespaced::No>(
277 path.at(ii), r.importNamespace, typeLoader);
279 if (!r.type.isValid())
282 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
286 currentObject = qmlAttachedPropertiesObject(currentObject, func);
290 }
else if (r.scriptIndex != -1) {
293 Q_ASSERT(!
"Unreachable");
300 QQmlPropertyData local;
301 const QQmlPropertyData *property = currentObject
302 ? QQmlPropertyCache::property(currentObject, pathName, context, &local)
308 if (currentObject || !(flags & InitFlag::AllowId))
311 for (
auto idContext = context; idContext; idContext = idContext->parent()) {
312 const int objectId = idContext->propertyIndex(pathName.toString());
313 if (objectId != -1 && objectId < idContext->numIdValues()) {
314 currentObject = idContext->idValue(objectId);
323 }
else if (property->isFunction()) {
327 if (ii == (path.size() - 2) && QQmlMetaType::isValueType(property->propType())) {
329 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(property->propType());
330 if (!valueTypeMetaObject)
return;
332 int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
333 if (idx == -1)
return;
335 QMetaProperty vtProp = valueTypeMetaObject->property(idx);
337 Q_ASSERT(idx <= 0x0000FFFF);
339 object = currentObject;
341 valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
342 valueTypeData.setPropType(vtProp.metaType());
343 valueTypeData.setCoreIndex(idx);
347 if (!property->isQObject()) {
348 if (
auto asPropertyMap = qobject_cast<QQmlPropertyMap*>(currentObject))
349 currentObject = asPropertyMap->value(path.at(ii).toString()).value<QObject*>();
353 property->readProperty(currentObject, ¤tObject);
356 if (!currentObject)
return;
362 terminal = path.last();
363 }
else if (!currentObject) {
367 auto findSignalInMetaObject = [&](
const QByteArray &signalName) {
368 const QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName);
369 if (!method.isValid())
372 object = currentObject;
377 QQmlData *ddata = QQmlData::get(currentObject,
false);
378 auto findChangeSignal = [&](QStringView signalName) {
379 if (
auto propName = QQmlSignalNames::changedSignalNameToPropertyName(signalName)) {
380 const QQmlPropertyData *d =
381 ddata->propertyCache->property(*propName, currentObject, context);
382 while (d && d->isFunction())
383 d = ddata->propertyCache->overrideData(d);
385 if (d && d->notifyIndex() != -1) {
386 object = currentObject;
387 core = *ddata->propertyCache->signal(d->notifyIndex());
394 const auto findSignal = [&](
const QString &signalName) {
395 if (ddata && ddata->propertyCache) {
397 const QQmlPropertyData *d
398 = ddata->propertyCache->property(signalName, currentObject, context);
403 while (d && !d->isFunction())
404 d = ddata->propertyCache->overrideData(d);
407 object = currentObject;
412 return findChangeSignal(signalName);
415 return findSignalInMetaObject(signalName.toUtf8());
418 auto signalName = QQmlSignalNames::handlerNameToSignalName(terminal);
420 if (findSignal(*signalName))
423 signalName = QQmlSignalNames::badHandlerNameToSignalName(terminal);
425 if (findSignal(*signalName)) {
428 <<
"is not a properly capitalized signal handler name."
429 << QQmlSignalNames::signalNameToHandlerName(*signalName)
430 <<
"would be correct.";
436 if (ddata && ddata->propertyCache) {
437 const QQmlPropertyData *property = ddata->propertyCache->property(
438 terminal, currentObject, context);
441 while (property && !property->isSignal()) {
442 if (!property->isFunction()) {
443 object = currentObject;
445 nameCache = terminal.toString();
448 property = ddata->propertyCache->overrideData(property);
451 if (!(flags & InitFlag::AllowSignal))
455 Q_ASSERT(property->isSignal());
456 object = currentObject;
462 findChangeSignal(terminal);
465 const QByteArray propertyName = terminal.toUtf8();
466 const QMetaProperty prop = findPropertyByName(currentObject->metaObject(), propertyName);
468 if (prop.isValid()) {
469 object = currentObject;
474 if (flags & InitFlag::AllowSignal)
475 findSignalInMetaObject(terminal.toUtf8());
856 QObject *object, QQmlPropertyIndex index,
859 int coreIndex = index.coreIndex();
860 int valueTypeIndex = index.valueTypeIndex();
862 QQmlData *data = QQmlData::get(object,
false);
864 if (!data || !data->hasBindingBit(coreIndex))
867 QQmlAbstractBinding::Ptr oldBinding;
868 oldBinding = data->bindings;
870 while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
871 oldBinding->targetPropertyIndex().hasValueTypeIndex())) {
872 oldBinding = oldBinding->nextBinding();
877 data->clearBindingBit(coreIndex);
881 if (valueTypeIndex != -1 && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy) {
882 oldBinding =
static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
887 if (oldBinding->isSticky() && !(flags & QQmlPropertyPrivate::OverrideSticky))
890 if (!(flags & QQmlPropertyPrivate::DontEnable))
891 oldBinding->setEnabled(
false, {});
892 oldBinding->removeFromObject();
924QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index)
926 auto aliasTarget = findAliasTarget(object, index);
927 object = aliasTarget.targetObject;
928 index = aliasTarget.targetIndex;
930 QQmlData *data = QQmlData::get(object);
934 const int coreIndex = index.coreIndex();
935 const int valueTypeIndex = index.valueTypeIndex();
937 if (coreIndex < 0 || !data->hasBindingBit(coreIndex))
940 QQmlAbstractBinding *binding = data->bindings;
941 while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex ||
942 binding->targetPropertyIndex().hasValueTypeIndex()))
943 binding = binding->nextBinding();
945 if (binding && valueTypeIndex != -1) {
946 if (binding->kind() == QQmlAbstractBinding::ValueTypeProxy)
947 binding =
static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
953void QQmlPropertyPrivate::findAliasTarget(QObject *object, QQmlPropertyIndex bindingIndex,
954 QObject **targetObject,
955 QQmlPropertyIndex *targetBindingIndex)
957 QQmlData *data = QQmlData::get(object,
false);
959 int coreIndex = bindingIndex.coreIndex();
960 int valueTypeIndex = bindingIndex.valueTypeIndex();
962 const QQmlPropertyData *propertyData =
963 data->propertyCache?data->propertyCache->property(coreIndex):
nullptr;
964 if (propertyData && propertyData->isAlias()) {
966 QObject *aObject =
nullptr;
int aCoreIndex = -1;
int aValueTypeIndex = -1;
967 if (QQmlVMEMetaObject::aliasTarget(object, coreIndex, &aObject, &aCoreIndex,
971 Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
973 QQmlPropertyIndex aBindingIndex(aCoreIndex);
974 if (aValueTypeIndex != -1) {
975 aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex);
976 }
else if (valueTypeIndex != -1) {
977 aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex);
980 findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
986 *targetObject = object;
987 *targetBindingIndex = bindingIndex;
1065void QQmlPropertyPrivate::takeSignalExpression(
const QQmlProperty &that,
1066 QQmlBoundSignalExpression *expr)
1068 if (!(that.type() & QQmlProperty::SignalProperty)) {
1074 if (!that.d->object)
1076 QQmlData *data = QQmlData::get(that.d->object,
nullptr != expr);
1080 QQmlBoundSignal *signalHandler = data->signalHandlers;
1082 while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
1083 signalHandler = signalHandler->m_nextSignal;
1085 if (signalHandler) {
1086 signalHandler->takeExpression(expr);
1091 int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
1092 QQmlBoundSignal *signal =
new QQmlBoundSignal(that.d->object, signalIndex, that.d->object,
1094 signal->takeExpression(expr);
1166QVariant QQmlPropertyPrivate::readValueProperty()
1168 auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) {
1169 wrapper->read(object, core.coreIndex());
1170 return wrapper->readOnGadget(wrapper->property(valueTypeData.coreIndex()));
1173 if (isValueType()) {
1174 if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType()))
1175 return doRead(wrapper);
1176 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1177 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1178 return doRead(&wrapper);
1181 }
else if (core.isQList()) {
1182 auto coreMetaType = core.propType();
1185 if (coreMetaType.flags() & QMetaType::IsQmlList) {
1186 QQmlListProperty<QObject> prop;
1187 core.readProperty(object, &prop);
1188 return QVariant::fromValue(QQmlListReferencePrivate::init(prop, coreMetaType));
1191 QVariant result(coreMetaType);
1194 coreMetaType.construct(result.data());
1195 core.readProperty(object, result.data());
1199 }
else if (core.isQObject()) {
1201 QObject *rv =
nullptr;
1202 core.readProperty(object, &rv);
1203 return QVariant::fromValue(rv);
1207 if (!core.propType().isValid())
1208 return object->metaObject()->property(core.coreIndex()).read(object);
1212 void *args[] = {
nullptr, &value, &status };
1213 if (core.propType() == QMetaType::fromType<QVariant>()) {
1216 value = QVariant(core.propType(), (
void*)
nullptr);
1217 args[0] = value.data();
1219 core.readPropertyWithArgs(object, args);
1220 if (core.propType() != QMetaType::fromType<QVariant>() && args[0] != value.data())
1221 return QVariant(QMetaType(core.propType()), args[0]);
1228QList<QUrl> QQmlPropertyPrivate::urlSequence(
const QVariant &value)
1230 if (value.metaType() == QMetaType::fromType<QList<QUrl>>())
1231 return value.value<QList<QUrl> >();
1234 if (value.metaType() == QMetaType::fromType<QUrl>()) {
1235 urls.append(value.toUrl());
1236 }
else if (value.metaType() == QMetaType::fromType<QString>()) {
1237 urls.append(QUrl(value.toString()));
1238 }
else if (value.metaType() == QMetaType::fromType<QByteArray>()) {
1239 urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
1240 }
else if (value.metaType() == QMetaType::fromType<QStringList>()) {
1241 QStringList urlStrings = value.value<QStringList>();
1242 const int urlStringsSize = urlStrings.size();
1243 urls.reserve(urlStringsSize);
1244 for (
int i = 0; i < urlStringsSize; ++i)
1245 urls.append(QUrl(urlStrings.at(i)));
1263bool QQmlPropertyPrivate::writeEnumProperty(
const QMetaProperty &prop,
int idx, QObject *object,
const QVariant &value,
int flags)
1265 if (!object || !prop.isWritable())
1269 if (prop.isEnumType() && v.metaType() != prop.metaType()) {
1270 QMetaEnum menum = prop.enumerator();
1271 if (v.userType() == QMetaType::QString) {
1273 if (prop.isFlagType())
1274 v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
1276 v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
1280 if (!v.convert(prop.metaType()))
1290 void *argv[] = { v.data(), &v, &status, &flags };
1291 QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
1325 QObject *object,
const QQmlPropertyData &core,
1326 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags,
1327 int internalIndex, Op op)
1329 if (QQmlGadgetPtrWrapper *wrapper = context
1330 ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
1332 return changePropertyAndWriteBack(
1333 object, core.coreIndex(), wrapper, flags, internalIndex, op);
1336 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1337 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1338 return changePropertyAndWriteBack(
1339 object, core.coreIndex(), &wrapper, flags, internalIndex, op);
1345bool QQmlPropertyPrivate::writeValueProperty(
1346 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1347 const QVariant &value,
const QQmlRefPointer<QQmlContextData> &context,
1348 QQmlPropertyData::WriteFlags flags)
1350 removeValuePropertyBinding(object, core, valueTypeData, flags);
1352 if (!valueTypeData.isValid())
1353 return write(object, core, value, context, flags);
1355 return changeThroughGadgetPtrWrapper(
1356 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1357 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1358 return write(wrapper, valueTypeData, value, context, flags);
1362bool QQmlPropertyPrivate::resetValueProperty(
1363 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1364 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1366 removeValuePropertyBinding(object, core, valueTypeData, flags);
1368 if (!valueTypeData.isValid())
1369 return reset(object, core, flags);
1371 return changeThroughGadgetPtrWrapper(
1372 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1373 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1374 return reset(wrapper, valueTypeData, flags);
1422 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1423 QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType,
1424 bool isUrl, QQmlEnginePrivate *enginePriv) {
1427 || variantMetaType == QMetaType::fromType<QString>()
1428 || propertyMetaType == QMetaType::fromType<QList<QUrl>>()
1429 || property.isQList()) {
1430 return {
false,
false};
1434 switch (propertyMetaType.id()) {
1435 case QMetaType::Bool:
1436 if (value.canConvert(propertyMetaType)) {
1437 bool b = value.toBool();
1438 return {
true, property.writeProperty(object, &b, flags)};
1440 return {
false,
false};
1441 case QMetaType::Int: {
1443 int i = value.toInt(&ok);
1444 return {ok, ok && property.writeProperty(object, &i, flags)};
1446 case QMetaType::UInt: {
1448 uint u = value.toUInt(&ok);
1449 return {ok, ok && property.writeProperty(object, &u, flags)};
1451 case QMetaType::Double: {
1453 double d = value.toDouble(&ok);
1454 return {ok, ok && property.writeProperty(object, &d, flags)};
1456 case QMetaType::Float: {
1458 float f = value.toFloat(&ok);
1459 return {ok, ok && property.writeProperty(object, &f, flags)};
1461 case QMetaType::QString:
1462 if (value.canConvert(propertyMetaType)) {
1463 QString s = value.toString();
1464 return {
true, property.writeProperty(object, &s, flags)};
1466 return {
false,
false};
1467 case QMetaType::QVariantMap:
1468 if (value.canConvert(propertyMetaType)) {
1469 QVariantMap m = value.toMap();
1470 return {
true, property.writeProperty(object, &m, flags)};
1472 return {
false,
false};
1478 QVariant converted = QQmlValueTypeProvider::createValueType(
1479 value, propertyMetaType, enginePriv ? enginePriv->v4Engine.get() :
nullptr);
1480 if (!converted.isValid()) {
1481 converted = QVariant(propertyMetaType);
1482 if (!QMetaType::convert(value.metaType(), value.constData(),
1483 propertyMetaType, converted.data())) {
1484 return {
false,
false};
1487 return {
true, property.writeProperty(object, converted.data(), flags)};
1493 QMetaSequence::Iterable iterable;
1494 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QMetaSequence::Iterable>(), &iterable))
1497 const QMetaSequence metaSequence = iterable.metaContainer();
1499 if (!metaSequence.hasConstIterator()
1500 || !metaSequence.canGetValueAtConstIterator()
1501 || !metaSequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1505 const void *container = iterable.constIterable();
1506 void *it = metaSequence.constBegin(container);
1507 const void *end = metaSequence.constEnd(container);
1508 QObject *o =
nullptr;
1509 while (!metaSequence.compareConstIterator(it, end)) {
1510 metaSequence.valueAtConstIterator(it, &o);
1512 metaSequence.advanceConstIterator(it, 1);
1514 metaSequence.destroyConstIterator(it);
1515 metaSequence.destroyConstIterator(end);
1594 QQmlListProperty<QObject> *prop, QMetaType metaType,
const void *data, DoAppend &&doAppend)
1596 QMetaSequence::Iterable iterable;
1597 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QMetaSequence::Iterable>(), &iterable))
1598 return AssignResult::TypeMismatch;
1600 const QMetaSequence metaSequence = iterable.metaContainer();
1601 if (!metaSequence.hasConstIterator()
1602 || !metaSequence.canGetValueAtConstIterator()
1603 || !metaSequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1604 return AssignResult::TypeMismatch;
1607 const void *container = iterable.constIterable();
1608 const void *end = metaSequence.constEnd(container);
1610 QObject *o =
nullptr;
1612 if (prop->at && prop->count && metaSequence.hasSize()
1613 && metaSequence.size(container) == prop->count(prop)) {
1614 void *it = metaSequence.constBegin(container);
1617 while (!metaSequence.compareConstIterator(it, end)) {
1618 metaSequence.valueAtConstIterator(it, &o);
1619 if (o != prop->at(prop, ++i)) {
1623 metaSequence.advanceConstIterator(it, 1);
1625 metaSequence.destroyConstIterator(it);
1630 void *it = metaSequence.constBegin(container);
1631 while (!metaSequence.compareConstIterator(it, end)) {
1632 metaSequence.valueAtConstIterator(it, &o);
1634 metaSequence.advanceConstIterator(it, 1);
1636 metaSequence.destroyConstIterator(it);
1639 metaSequence.destroyConstIterator(end);
1640 return same ? AssignResult::WasEqual : AssignResult::Copied;
1651QQmlPropertyPrivate::ListCopyResult QQmlPropertyPrivate::convertToQQmlListProperty(QQmlListProperty<QObject> *listProperty, QMetaType actualListType,
const QVariant &value) {
1652 QQmlListProperty<QObject> &prop = *listProperty;
1653 QMetaType listValueType = QQmlMetaType::listValueType(actualListType);
1656 QQmlMetaObject elementMetaObject = QQmlMetaType::rawMetaObjectForType(listValueType);
1658 auto doAppend = [&](QQmlListProperty<QObject> *propPtr, QObject *o) {
1659 if (Q_UNLIKELY(o && (elementMetaObject.isNull()
1660 || !QQmlMetaObject::canConvert(o, elementMetaObject)))) {
1661 qCWarning(lcIncompatibleElement)
1662 <<
"Cannot append" << o <<
"to a QML list of" << listValueType.name();
1665 propPtr->append(propPtr, o);
1669 AssignResult result = AssignResult::TypeMismatch;
1670 QMetaType variantMetaType = value.metaType();
1671 if (variantMetaType == QMetaType::fromType<QQmlListReference>()) {
1672 result = assignListToListProperty(
1673 &prop,
static_cast<
const QQmlListReference *>(value.constData()),
1674 std::move(doAppend));
1675 }
else if (variantMetaType == QMetaType::fromType<QObjectList>()) {
1676 result = assignListToListProperty(
1677 &prop,
static_cast<
const QObjectList *>(value.constData()),
1678 std::move(doAppend));
1679 }
else if (variantMetaType == QMetaType::fromType<QVariantList>()) {
1680 result = assignListToListProperty(
1681 &prop,
static_cast<
const QVariantList *>(value.constData()),
1682 std::move(doAppend));
1684 result = assignMetaContainerToListProperty(
1685 &prop, variantMetaType, value.data(), doAppend);
1686 if (result == AssignResult::TypeMismatch) {
1688 doAppend(&prop, QQmlMetaType::toQObject(value));
1689 result = AssignResult::Copied;
1699 const QQmlPropertyData &property,
1700 const QMetaType propertyMetaType,
const QVariant &value)
1702 Q_ASSERT(propertyMetaType.flags() & QMetaType::IsQmlList);
1703 QQmlListProperty<QObject> prop;
1704 property.readProperty(object, &prop);
1707 if (!prop.clear || !prop.append)
1710 const bool useNonsignalingListOps = prop.clear == &QQmlVMEMetaObject::list_clear
1711 && prop.append == &QQmlVMEMetaObject::list_append;
1712 if (useNonsignalingListOps) {
1713 prop.clear = &QQmlVMEMetaObject::list_clear_nosignal;
1714 prop.append = &QQmlVMEMetaObject::list_append_nosignal;
1717 auto result = QQmlPropertyPrivate::convertToQQmlListProperty(&prop, propertyMetaType, value);
1719 if (useNonsignalingListOps && result == QQmlPropertyPrivate::ListCopyResult::Copied) {
1720 Q_ASSERT(QQmlData::get(object)->hasVMEMetaObject);
1721 QQmlVMEResolvedList(&prop).activateSignal();
1724 return result != QQmlPropertyPrivate::ListCopyResult::TypeMismatch;
1730 const QQmlPropertyData &property, QQmlPropertyData::WriteFlags flags,
1731 const QMetaType propertyMetaType,
const QMetaType variantMetaType,
const QVariant &value,
1734 Q_ASSERT(!(propertyMetaType.flags() & QMetaType::IsQmlList));
1735 if (variantMetaType == propertyMetaType) {
1737 return property.writeProperty(object, v.data(), flags);
1739 QVariant outputList(propertyMetaType);
1740 const QQmlType type = QQmlMetaType::qmlListType(propertyMetaType);
1741 const QMetaSequence outputSequence = type.listMetaSequence();
1742 if (!outputSequence.canAddValue())
1743 return property.writeProperty(object, outputList.data(), flags);
1745 const QMetaType outputElementMetaType = outputSequence.valueMetaType();
1746 const bool outputIsQVariant = (outputElementMetaType == QMetaType::fromType<QVariant>());
1748 QMetaSequence::Iterable inputIterable;
1749 QVariant inputList = value;
1750 if (QMetaType::view(
1751 inputList.metaType(), inputList.data(),
1752 QMetaType::fromType<QMetaSequence::Iterable>(), &inputIterable)) {
1754 const QMetaSequence inputSequence = inputIterable.metaContainer();
1755 const QMetaType inputElementMetaType = inputSequence.valueMetaType();
1756 const bool inputIsQVariant = (inputElementMetaType == QMetaType::fromType<QVariant>());
1758 QVariant outputElement
1759 = outputIsQVariant ? QVariant() : QVariant(outputElementMetaType);
1760 QVariant inputElement
1761 = inputIsQVariant ? QVariant() : QVariant(inputElementMetaType);
1763 void *it = inputSequence.constBegin(inputList.constData());
1764 void *end = inputSequence.constEnd(inputList.constData());
1766 for (; !inputSequence.compareConstIterator(it, end);
1767 inputSequence.advanceConstIterator(it, 1)) {
1769 if (inputIsQVariant)
1770 inputSequence.valueAtIterator(it, &inputElement);
1772 inputSequence.valueAtIterator(it, inputElement.data());
1774 if (outputIsQVariant) {
1775 outputSequence.addValue(outputList.data(), &inputElement);
1776 }
else if (inputElement.metaType() == outputElement.metaType()) {
1777 outputSequence.addValue(outputList.data(), inputElement.constData());
1780 inputElement.metaType(), inputElement.constData(),
1781 outputElementMetaType, outputElement.data());
1782 outputSequence.addValue(outputList.data(), outputElement.constData());
1786 inputSequence.destroyConstIterator(it);
1787 inputSequence.destroyConstIterator(end);
1788 }
else if (outputIsQVariant) {
1789 outputSequence.addValue(outputList.data(), &value);
1790 }
else if (outputElementMetaType == value.metaType()){
1791 outputSequence.addValue(outputList.data(), value.constData());
1793 QVariant output(outputElementMetaType);
1795 value.metaType(), value.constData(), outputElementMetaType, output.data());
1796 outputSequence.addValue(outputList.data(), output.constData());
1799 return property.writeProperty(object, outputList.data(), flags);
1803QVariant QQmlPropertyPrivate::convertToWriteTargetType(
const QVariant &value, QMetaType targetMetaType){
1804 QMetaType sourceMetaType = value.metaType();
1805 Q_ASSERT(sourceMetaType != targetMetaType);
1808 if (sourceMetaType == QMetaType::fromType<QString>()) {
1810 QVariant converted = QQmlStringConverters::variantFromString(value.toString(), targetMetaType, &ok);
1817 if (QMetaType::canConvert(sourceMetaType, targetMetaType))
1818 if (QVariant copy = value; copy.convert(targetMetaType))
1826
1827
1828 QMetaSequence::Iterable iterable;
1829 QVariant sequenceVariant = QVariant(targetMetaType);
1830 if (QMetaType::view(
1831 targetMetaType, sequenceVariant.data(),
1832 QMetaType::fromType<QMetaSequence::Iterable>(),
1834 const QMetaSequence propertyMetaSequence = iterable.metaContainer();
1835 if (propertyMetaSequence.canAddValueAtEnd()) {
1836 const QMetaType elementMetaType = propertyMetaSequence.valueMetaType();
1837 void *propertyContainer = iterable.mutableIterable();
1839 if (sourceMetaType == elementMetaType) {
1840 propertyMetaSequence.addValueAtEnd(propertyContainer, value.constData());
1841 return sequenceVariant;
1842 }
else if (sourceMetaType == QMetaType::fromType<QVariantList>()) {
1843 const QVariantList list = value.value<QVariantList>();
1844 for (
const QVariant &valueElement : list) {
1845 if (valueElement.metaType() == elementMetaType) {
1846 propertyMetaSequence.addValueAtEnd(
1847 propertyContainer, valueElement.constData());
1849 QVariant converted(elementMetaType);
1851 valueElement.metaType(), valueElement.constData(),
1852 elementMetaType, converted.data());
1853 propertyMetaSequence.addValueAtEnd(
1854 propertyContainer, converted.constData());
1857 return sequenceVariant;
1858 }
else if (elementMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1859 const QMetaObject *elementMetaObject = elementMetaType.metaObject();
1860 Q_ASSERT(elementMetaObject);
1862 const auto doAppend = [&](QObject *o) {
1863 QObject *casted = elementMetaObject->cast(o);
1864 propertyMetaSequence.addValueAtEnd(propertyContainer, &casted);
1867 if (sourceMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1868 doAppend(*
static_cast<QObject *
const *>(value.data()));
1869 return sequenceVariant;
1870 }
else if (sourceMetaType == QMetaType::fromType<QQmlListReference>()) {
1871 const QQmlListReference *reference
1872 =
static_cast<
const QQmlListReference *>(value.constData());
1873 Q_ASSERT(elementMetaObject);
1874 for (
int i = 0, end = reference->size(); i < end; ++i)
1875 doAppend(reference->at(i));
1876 return sequenceVariant;
1877 }
else if (!iterateQObjectContainer(
1878 sourceMetaType, value.data(), doAppend)) {
1879 doAppend(QQmlMetaType::toQObject(value));
1882 QVariant converted = value;
1883 if (converted.convert(elementMetaType)) {
1884 propertyMetaSequence.addValueAtEnd(propertyContainer, converted.constData());
1885 return sequenceVariant;
1892 if (QQmlMetaType::isInterface(targetMetaType)) {
1893 auto valueAsQObject = qvariant_cast<QObject *>(value);
1895 if (
void *iface = valueAsQObject
1896 ? valueAsQObject->qt_metacast(QQmlMetaType::interfaceIId(targetMetaType))
1901 return QVariant(targetMetaType, &iface);
1907bool QQmlPropertyPrivate::write(
1908 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1909 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1911 const QMetaType propertyMetaType = property.propType();
1912 const QMetaType variantMetaType = value.metaType();
1914 const BindingFixer bindingFixer(object, property, flags);
1917 if (property.isResettable() && !value.isValid()) {
1918 property.resetProperty(object, flags);
1922 if (property.isEnum()) {
1923 QMetaProperty prop = object->metaObject()->property(property.coreIndex());
1926 if (variantMetaType == QMetaType::fromType<
double>()) {
1928 double fractional = std::modf(value.toDouble(), &integral);
1929 if (qFuzzyIsNull(fractional))
1930 v.convert(QMetaType::fromType<qint32>());
1932 return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
1935 QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
1936 const bool isUrl = propertyMetaType == QMetaType::fromType<QUrl>();
1939 if (tryAssignBinding(object, property, value, variantMetaType))
1943 if (propertyMetaType == variantMetaType && !isUrl
1944 && propertyMetaType != QMetaType::fromType<QList<QUrl>>() && !property.isQList()) {
1945 return property.writeProperty(object,
const_cast<
void *>(value.constData()), flags);
1946 }
else if (property.isQObject()) {
1947 QVariant val = value;
1949 if (variantMetaType == QMetaType::fromType<std::nullptr_t>()) {
1952 varType = QMetaType::fromType<QObject*>();
1953 val = QVariant(varType,
nullptr);
1955 varType = variantMetaType;
1958 if (!varType.flags().testFlag(QMetaType::PointerToQObject))
1961 QObject *o = *
static_cast<QObject *
const *>(val.constData());
1965 return QQmlMetaType::canConvert(o, propertyMetaType)
1966 && property.writeProperty(object, &o, flags);
1972 const QQmlMetaObject valMo = rawMetaObjectForType(varType);
1973 const QQmlMetaObject propMo = rawMetaObjectForType(propertyMetaType);
1974 if (QQmlMetaObject::canConvert(valMo, propMo) || QQmlMetaObject::canConvert(propMo, valMo))
1975 return property.writeProperty(object, &o, flags);
1977 }
else if (ConvertAndAssignResult result = tryConvertAndAssign(
1978 object, property, value, flags, propertyMetaType, variantMetaType, isUrl,
1980 return result.couldWrite;
1981 }
else if (propertyMetaType == QMetaType::fromType<QVariant>()) {
1982 return property.writeProperty(object,
const_cast<QVariant *>(&value), flags);
1985 if (variantMetaType == QMetaType::fromType<QUrl>()) {
1987 if (compatResolveUrlsOnAssigment() && context && u.isRelative() && !u.isEmpty())
1988 u = context->resolvedUrl(u);
1990 else if (variantMetaType == QMetaType::fromType<QByteArray>())
1991 u = QUrl(QString::fromUtf8(value.toByteArray()));
1992 else if (variantMetaType == QMetaType::fromType<QString>())
1993 u = QUrl(value.toString());
1997 return property.writeProperty(object, &u, flags);
1998 }
else if (propertyMetaType == QMetaType::fromType<QList<QUrl>>()) {
1999 QList<QUrl> urlSeq = compatResolveUrlsOnAssigment()
2000 ? urlSequence(value, context)
2001 : urlSequence(value);
2002 return property.writeProperty(object, &urlSeq, flags);
2003 }
else if (property.isQList()) {
2004 if (propertyMetaType.flags() & QMetaType::IsQmlList) {
2005 return assignToQQmlListProperty(object, property, propertyMetaType, value);
2007 return assignToListProperty(property, flags, propertyMetaType, variantMetaType, value, object);
2009 }
else if (enginePriv && propertyMetaType == QMetaType::fromType<QJSValue>()) {
2011 QJSValue jsValue = QJSValuePrivate::fromReturnedValue(
2012 enginePriv->v4Engine->metaTypeToJS(variantMetaType, value.constData()));
2013 return property.writeProperty(object, &jsValue, flags);
2015 Q_ASSERT(variantMetaType != propertyMetaType);
2017 QVariant converted = convertToWriteTargetType(value, propertyMetaType);
2018 if (converted.isValid()) {
2019 return property.writeProperty(object,
const_cast<
void *>(converted.constData()), flags);