238void QQmlPropertyPrivate::initProperty(QObject *obj,
const QString &name,
239 QQmlPropertyPrivate::InitFlags flags)
241 QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() :
nullptr;
243 QObject *currentObject = obj;
244 QList<QStringView> path;
245 QStringView terminal(name);
247 if (name.contains(QLatin1Char(
'.'))) {
248 path = QStringView{name}.split(QLatin1Char(
'.'));
249 if (path.isEmpty())
return;
252 for (
int ii = 0; ii < path.size() - 1; ++ii) {
253 const QStringView &pathName = path.at(ii);
257 if (typeNameCache && !pathName.isEmpty() && pathName.at(0).isUpper()) {
258 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine.data());
259 QQmlTypeNameCache::Result r = typeNameCache->query(pathName, typeLoader);
261 if (r.type.isValid()) {
262 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
265 currentObject = qmlAttachedPropertiesObject(currentObject, func);
266 if (!currentObject)
return;
267 }
else if (r.importNamespace) {
268 if (++ii == path.size())
272 r = typeNameCache->query<QQmlTypeNameCache::QueryNamespaced::No>(
273 path.at(ii), r.importNamespace, typeLoader);
275 if (!r.type.isValid())
278 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader);
282 currentObject = qmlAttachedPropertiesObject(currentObject, func);
286 }
else if (r.scriptIndex != -1) {
289 Q_ASSERT(!
"Unreachable");
296 QQmlPropertyData local;
297 const QQmlPropertyData *property = currentObject
298 ? QQmlPropertyCache::property(currentObject, pathName, context, &local)
304 if (currentObject || !(flags & InitFlag::AllowId))
307 for (
auto idContext = context; idContext; idContext = idContext->parent()) {
308 const int objectId = idContext->propertyIndex(pathName.toString());
309 if (objectId != -1 && objectId < idContext->numIdValues()) {
310 currentObject = idContext->idValue(objectId);
319 }
else if (property->isFunction()) {
323 if (ii == (path.size() - 2) && QQmlMetaType::isValueType(property->propType())) {
325 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(property->propType());
326 if (!valueTypeMetaObject)
return;
328 int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
329 if (idx == -1)
return;
331 QMetaProperty vtProp = valueTypeMetaObject->property(idx);
333 Q_ASSERT(idx <= 0x0000FFFF);
335 object = currentObject;
337 valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
338 valueTypeData.setPropType(vtProp.metaType());
339 valueTypeData.setCoreIndex(idx);
343 if (!property->isQObject()) {
344 if (
auto asPropertyMap = qobject_cast<QQmlPropertyMap*>(currentObject))
345 currentObject = asPropertyMap->value(path.at(ii).toString()).value<QObject*>();
349 property->readProperty(currentObject, ¤tObject);
352 if (!currentObject)
return;
358 terminal = path.last();
359 }
else if (!currentObject) {
363 auto findSignalInMetaObject = [&](
const QByteArray &signalName) {
364 const QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName);
365 if (!method.isValid())
368 object = currentObject;
373 QQmlData *ddata = QQmlData::get(currentObject,
false);
374 auto findChangeSignal = [&](QStringView signalName) {
375 if (
auto propName = QQmlSignalNames::changedSignalNameToPropertyName(signalName)) {
376 const QQmlPropertyData *d =
377 ddata->propertyCache->property(*propName, currentObject, context);
378 while (d && d->isFunction())
379 d = ddata->propertyCache->overrideData(d);
381 if (d && d->notifyIndex() != -1) {
382 object = currentObject;
383 core = *ddata->propertyCache->signal(d->notifyIndex());
390 const auto findSignal = [&](
const QString &signalName) {
391 if (ddata && ddata->propertyCache) {
393 const QQmlPropertyData *d
394 = ddata->propertyCache->property(signalName, currentObject, context);
399 while (d && !d->isFunction())
400 d = ddata->propertyCache->overrideData(d);
403 object = currentObject;
408 return findChangeSignal(signalName);
411 return findSignalInMetaObject(signalName.toUtf8());
414 auto signalName = QQmlSignalNames::handlerNameToSignalName(terminal);
416 if (findSignal(*signalName))
419 signalName = QQmlSignalNames::badHandlerNameToSignalName(terminal);
421 if (findSignal(*signalName)) {
424 <<
"is not a properly capitalized signal handler name."
425 << QQmlSignalNames::signalNameToHandlerName(*signalName)
426 <<
"would be correct.";
432 if (ddata && ddata->propertyCache) {
433 const QQmlPropertyData *property = ddata->propertyCache->property(
434 terminal, currentObject, context);
437 while (property && !property->isSignal()) {
438 if (!property->isFunction()) {
439 object = currentObject;
441 nameCache = terminal.toString();
444 property = ddata->propertyCache->overrideData(property);
447 if (!(flags & InitFlag::AllowSignal))
451 Q_ASSERT(property->isSignal());
452 object = currentObject;
458 findChangeSignal(terminal);
461 const QByteArray propertyName = terminal.toUtf8();
462 const QMetaProperty prop = findPropertyByName(currentObject->metaObject(), propertyName);
464 if (prop.isValid()) {
465 object = currentObject;
470 if (flags & InitFlag::AllowSignal)
471 findSignalInMetaObject(terminal.toUtf8());
852 QObject *object, QQmlPropertyIndex index,
855 int coreIndex = index.coreIndex();
856 int valueTypeIndex = index.valueTypeIndex();
858 QQmlData *data = QQmlData::get(object,
false);
860 if (!data || !data->hasBindingBit(coreIndex))
863 QQmlAbstractBinding::Ptr oldBinding;
864 oldBinding = data->bindings;
866 while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
867 oldBinding->targetPropertyIndex().hasValueTypeIndex())) {
868 oldBinding = oldBinding->nextBinding();
873 data->clearBindingBit(coreIndex);
877 if (valueTypeIndex != -1 && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy) {
878 oldBinding =
static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
883 if (oldBinding->isSticky() && !(flags & QQmlPropertyPrivate::OverrideSticky))
886 if (!(flags & QQmlPropertyPrivate::DontEnable))
887 oldBinding->setEnabled(
false, {});
888 oldBinding->removeFromObject();
917QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index)
919 auto aliasTarget = findAliasTarget(object, index);
920 object = aliasTarget.targetObject;
921 index = aliasTarget.targetIndex;
923 QQmlData *data = QQmlData::get(object);
927 const int coreIndex = index.coreIndex();
928 const int valueTypeIndex = index.valueTypeIndex();
930 if (coreIndex < 0 || !data->hasBindingBit(coreIndex))
933 QQmlAbstractBinding *binding = data->bindings;
934 while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex ||
935 binding->targetPropertyIndex().hasValueTypeIndex()))
936 binding = binding->nextBinding();
938 if (binding && valueTypeIndex != -1) {
939 if (binding->kind() == QQmlAbstractBinding::ValueTypeProxy)
940 binding =
static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
946void QQmlPropertyPrivate::findAliasTarget(QObject *object, QQmlPropertyIndex bindingIndex,
947 QObject **targetObject,
948 QQmlPropertyIndex *targetBindingIndex)
950 QQmlData *data = QQmlData::get(object,
false);
952 int coreIndex = bindingIndex.coreIndex();
953 int valueTypeIndex = bindingIndex.valueTypeIndex();
955 const QQmlPropertyData *propertyData =
956 data->propertyCache?data->propertyCache->property(coreIndex):
nullptr;
957 if (propertyData && propertyData->isAlias()) {
958 QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
960 QObject *aObject =
nullptr;
int aCoreIndex = -1;
int aValueTypeIndex = -1;
961 if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
963 Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
965 QQmlPropertyIndex aBindingIndex(aCoreIndex);
966 if (aValueTypeIndex != -1) {
967 aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex);
968 }
else if (valueTypeIndex != -1) {
969 aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex);
972 findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
978 *targetObject = object;
979 *targetBindingIndex = bindingIndex;
1057void QQmlPropertyPrivate::takeSignalExpression(
const QQmlProperty &that,
1058 QQmlBoundSignalExpression *expr)
1060 if (!(that.type() & QQmlProperty::SignalProperty)) {
1066 if (!that.d->object)
1068 QQmlData *data = QQmlData::get(that.d->object,
nullptr != expr);
1072 QQmlBoundSignal *signalHandler = data->signalHandlers;
1074 while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
1075 signalHandler = signalHandler->m_nextSignal;
1077 if (signalHandler) {
1078 signalHandler->takeExpression(expr);
1083 int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
1084 QQmlBoundSignal *signal =
new QQmlBoundSignal(that.d->object, signalIndex, that.d->object,
1086 signal->takeExpression(expr);
1158QVariant QQmlPropertyPrivate::readValueProperty()
1160 auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) {
1161 wrapper->read(object, core.coreIndex());
1162 return wrapper->readOnGadget(wrapper->property(valueTypeData.coreIndex()));
1165 if (isValueType()) {
1166 if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType()))
1167 return doRead(wrapper);
1168 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1169 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1170 return doRead(&wrapper);
1173 }
else if (core.isQList()) {
1174 auto coreMetaType = core.propType();
1177 if (coreMetaType.flags() & QMetaType::IsQmlList) {
1178 QQmlListProperty<QObject> prop;
1179 core.readProperty(object, &prop);
1180 return QVariant::fromValue(QQmlListReferencePrivate::init(prop, coreMetaType));
1183 QVariant result(coreMetaType);
1186 coreMetaType.construct(result.data());
1187 core.readProperty(object, result.data());
1191 }
else if (core.isQObject()) {
1193 QObject *rv =
nullptr;
1194 core.readProperty(object, &rv);
1195 return QVariant::fromValue(rv);
1199 if (!core.propType().isValid())
1200 return object->metaObject()->property(core.coreIndex()).read(object);
1204 void *args[] = {
nullptr, &value, &status };
1205 if (core.propType() == QMetaType::fromType<QVariant>()) {
1208 value = QVariant(core.propType(), (
void*)
nullptr);
1209 args[0] = value.data();
1211 core.readPropertyWithArgs(object, args);
1212 if (core.propType() != QMetaType::fromType<QVariant>() && args[0] != value.data())
1213 return QVariant(QMetaType(core.propType()), args[0]);
1220QList<QUrl> QQmlPropertyPrivate::urlSequence(
const QVariant &value)
1222 if (value.metaType() == QMetaType::fromType<QList<QUrl>>())
1223 return value.value<QList<QUrl> >();
1226 if (value.metaType() == QMetaType::fromType<QUrl>()) {
1227 urls.append(value.toUrl());
1228 }
else if (value.metaType() == QMetaType::fromType<QString>()) {
1229 urls.append(QUrl(value.toString()));
1230 }
else if (value.metaType() == QMetaType::fromType<QByteArray>()) {
1231 urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
1232 }
else if (value.metaType() == QMetaType::fromType<QStringList>()) {
1233 QStringList urlStrings = value.value<QStringList>();
1234 const int urlStringsSize = urlStrings.size();
1235 urls.reserve(urlStringsSize);
1236 for (
int i = 0; i < urlStringsSize; ++i)
1237 urls.append(QUrl(urlStrings.at(i)));
1255bool QQmlPropertyPrivate::writeEnumProperty(
const QMetaProperty &prop,
int idx, QObject *object,
const QVariant &value,
int flags)
1257 if (!object || !prop.isWritable())
1261 if (prop.isEnumType() && v.metaType() != prop.metaType()) {
1262 QMetaEnum menum = prop.enumerator();
1263 if (v.userType() == QMetaType::QString) {
1265 if (prop.isFlagType())
1266 v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
1268 v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
1272 if (!v.convert(prop.metaType()))
1282 void *argv[] = { v.data(), &v, &status, &flags };
1283 QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
1317 QObject *object,
const QQmlPropertyData &core,
1318 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags,
1319 int internalIndex, Op op)
1321 if (QQmlGadgetPtrWrapper *wrapper = context
1322 ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
1324 return changePropertyAndWriteBack(
1325 object, core.coreIndex(), wrapper, flags, internalIndex, op);
1328 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1329 QQmlGadgetPtrWrapper wrapper(valueType,
nullptr);
1330 return changePropertyAndWriteBack(
1331 object, core.coreIndex(), &wrapper, flags, internalIndex, op);
1337bool QQmlPropertyPrivate::writeValueProperty(
1338 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1339 const QVariant &value,
const QQmlRefPointer<QQmlContextData> &context,
1340 QQmlPropertyData::WriteFlags flags)
1342 removeValuePropertyBinding(object, core, valueTypeData, flags);
1344 if (!valueTypeData.isValid())
1345 return write(object, core, value, context, flags);
1347 return changeThroughGadgetPtrWrapper(
1348 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1349 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1350 return write(wrapper, valueTypeData, value, context, flags);
1354bool QQmlPropertyPrivate::resetValueProperty(
1355 QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
1356 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1358 removeValuePropertyBinding(object, core, valueTypeData, flags);
1360 if (!valueTypeData.isValid())
1361 return reset(object, core, flags);
1363 return changeThroughGadgetPtrWrapper(
1364 object, core, context, flags | QQmlPropertyData::HasInternalIndex,
1365 valueTypeData.coreIndex(), [&](QQmlGadgetPtrWrapper *wrapper) {
1366 return reset(wrapper, valueTypeData, flags);
1414 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1415 QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType,
1416 bool isUrl, QQmlEnginePrivate *enginePriv) {
1419 || variantMetaType == QMetaType::fromType<QString>()
1420 || propertyMetaType == QMetaType::fromType<QList<QUrl>>()
1421 || property.isQList()) {
1422 return {
false,
false};
1426 switch (propertyMetaType.id()) {
1427 case QMetaType::Bool:
1428 if (value.canConvert(propertyMetaType)) {
1429 bool b = value.toBool();
1430 return {
true, property.writeProperty(object, &b, flags)};
1432 return {
false,
false};
1433 case QMetaType::Int: {
1435 int i = value.toInt(&ok);
1436 return {ok, ok && property.writeProperty(object, &i, flags)};
1438 case QMetaType::UInt: {
1440 uint u = value.toUInt(&ok);
1441 return {ok, ok && property.writeProperty(object, &u, flags)};
1443 case QMetaType::Double: {
1445 double d = value.toDouble(&ok);
1446 return {ok, ok && property.writeProperty(object, &d, flags)};
1448 case QMetaType::Float: {
1450 float f = value.toFloat(&ok);
1451 return {ok, ok && property.writeProperty(object, &f, flags)};
1453 case QMetaType::QString:
1454 if (value.canConvert(propertyMetaType)) {
1455 QString s = value.toString();
1456 return {
true, property.writeProperty(object, &s, flags)};
1458 return {
false,
false};
1459 case QMetaType::QVariantMap:
1460 if (value.canConvert(propertyMetaType)) {
1461 QVariantMap m = value.toMap();
1462 return {
true, property.writeProperty(object, &m, flags)};
1464 return {
false,
false};
1470 QVariant converted = QQmlValueTypeProvider::createValueType(
1471 value, propertyMetaType, enginePriv ? enginePriv->v4Engine.get() :
nullptr);
1472 if (!converted.isValid()) {
1473 converted = QVariant(propertyMetaType);
1474 if (!QMetaType::convert(value.metaType(), value.constData(),
1475 propertyMetaType, converted.data())) {
1476 return {
false,
false};
1479 return {
true, property.writeProperty(object, converted.data(), flags)};
1485 QSequentialIterable iterable;
1486 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
1489 const QMetaSequence metaSequence = iterable.metaContainer();
1491 if (!metaSequence.hasConstIterator()
1492 || !metaSequence.canGetValueAtConstIterator()
1493 || !iterable.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1497 const void *container = iterable.constIterable();
1498 void *it = metaSequence.constBegin(container);
1499 const void *end = metaSequence.constEnd(container);
1500 QObject *o =
nullptr;
1501 while (!metaSequence.compareConstIterator(it, end)) {
1502 metaSequence.valueAtConstIterator(it, &o);
1504 metaSequence.advanceConstIterator(it, 1);
1506 metaSequence.destroyConstIterator(it);
1507 metaSequence.destroyConstIterator(end);
1586 QQmlListProperty<QObject> *prop, QMetaType metaType,
const void *data, DoAppend &&doAppend)
1588 QSequentialIterable iterable;
1589 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
1590 return AssignResult::TypeMismatch;
1592 const QMetaSequence metaSequence = iterable.metaContainer();
1593 if (!metaSequence.hasConstIterator()
1594 || !metaSequence.canGetValueAtConstIterator()
1595 || !iterable.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1596 return AssignResult::TypeMismatch;
1599 const void *container = iterable.constIterable();
1600 const void *end = metaSequence.constEnd(container);
1602 QObject *o =
nullptr;
1604 if (prop->at && prop->count && metaSequence.hasSize()
1605 && metaSequence.size(container) == prop->count(prop)) {
1606 void *it = metaSequence.constBegin(container);
1609 while (!metaSequence.compareConstIterator(it, end)) {
1610 metaSequence.valueAtConstIterator(it, &o);
1611 if (o != prop->at(prop, ++i)) {
1615 metaSequence.advanceConstIterator(it, 1);
1617 metaSequence.destroyConstIterator(it);
1622 void *it = metaSequence.constBegin(container);
1623 while (!metaSequence.compareConstIterator(it, end)) {
1624 metaSequence.valueAtConstIterator(it, &o);
1626 metaSequence.advanceConstIterator(it, 1);
1628 metaSequence.destroyConstIterator(it);
1631 metaSequence.destroyConstIterator(end);
1632 return same ? AssignResult::WasEqual : AssignResult::Copied;
1643QQmlPropertyPrivate::ListCopyResult QQmlPropertyPrivate::convertToQQmlListProperty(QQmlListProperty<QObject> *listProperty, QMetaType actualListType,
const QVariant &value) {
1644 QQmlListProperty<QObject> &prop = *listProperty;
1645 QMetaType listValueType = QQmlMetaType::listValueType(actualListType);
1648 QQmlMetaObject elementMetaObject = QQmlMetaType::rawMetaObjectForType(listValueType);
1650 auto doAppend = [&](QQmlListProperty<QObject> *propPtr, QObject *o) {
1651 if (Q_UNLIKELY(o && (elementMetaObject.isNull()
1652 || !QQmlMetaObject::canConvert(o, elementMetaObject)))) {
1653 qCWarning(lcIncompatibleElement)
1654 <<
"Cannot append" << o <<
"to a QML list of" << listValueType.name();
1657 propPtr->append(propPtr, o);
1661 AssignResult result = AssignResult::TypeMismatch;
1662 QMetaType variantMetaType = value.metaType();
1663 if (variantMetaType == QMetaType::fromType<QQmlListReference>()) {
1664 result = assignListToListProperty(
1665 &prop,
static_cast<
const QQmlListReference *>(value.constData()),
1666 std::move(doAppend));
1667 }
else if (variantMetaType == QMetaType::fromType<QObjectList>()) {
1668 result = assignListToListProperty(
1669 &prop,
static_cast<
const QObjectList *>(value.constData()),
1670 std::move(doAppend));
1671 }
else if (variantMetaType == QMetaType::fromType<QVariantList>()) {
1672 result = assignListToListProperty(
1673 &prop,
static_cast<
const QVariantList *>(value.constData()),
1674 std::move(doAppend));
1676 result = assignMetaContainerToListProperty(
1677 &prop, variantMetaType, value.data(), doAppend);
1678 if (result == AssignResult::TypeMismatch) {
1680 doAppend(&prop, QQmlMetaType::toQObject(value));
1681 result = AssignResult::Copied;
1691 const QQmlPropertyData &property,
1692 const QMetaType propertyMetaType,
const QVariant &value)
1694 Q_ASSERT(propertyMetaType.flags() & QMetaType::IsQmlList);
1695 QQmlListProperty<QObject> prop;
1696 property.readProperty(object, &prop);
1699 if (!prop.clear || !prop.append)
1702 const bool useNonsignalingListOps = prop.clear == &QQmlVMEMetaObject::list_clear
1703 && prop.append == &QQmlVMEMetaObject::list_append;
1704 if (useNonsignalingListOps) {
1705 prop.clear = &QQmlVMEMetaObject::list_clear_nosignal;
1706 prop.append = &QQmlVMEMetaObject::list_append_nosignal;
1709 auto result = QQmlPropertyPrivate::convertToQQmlListProperty(&prop, propertyMetaType, value);
1711 if (useNonsignalingListOps && result == QQmlPropertyPrivate::ListCopyResult::Copied) {
1712 Q_ASSERT(QQmlVMEMetaObject::get(object));
1713 QQmlVMEResolvedList(&prop).activateSignal();
1716 return result != QQmlPropertyPrivate::ListCopyResult::TypeMismatch;
1722 const QQmlPropertyData &property, QQmlPropertyData::WriteFlags flags,
1723 const QMetaType propertyMetaType,
const QMetaType variantMetaType,
const QVariant &value,
1726 Q_ASSERT(!(propertyMetaType.flags() & QMetaType::IsQmlList));
1727 if (variantMetaType == propertyMetaType) {
1729 return property.writeProperty(object, v.data(), flags);
1731 QVariant outputList(propertyMetaType);
1732 const QQmlType type = QQmlMetaType::qmlListType(propertyMetaType);
1733 const QMetaSequence outputSequence = type.listMetaSequence();
1734 if (!outputSequence.canAddValue())
1735 return property.writeProperty(object, outputList.data(), flags);
1737 const QMetaType outputElementMetaType = outputSequence.valueMetaType();
1738 const bool outputIsQVariant = (outputElementMetaType == QMetaType::fromType<QVariant>());
1740 QSequentialIterable inputIterable;
1741 QVariant inputList = value;
1742 if (QMetaType::view(
1743 inputList.metaType(), inputList.data(),
1744 QMetaType::fromType<QSequentialIterable>(), &inputIterable)) {
1746 const QMetaSequence inputSequence = inputIterable.metaContainer();
1747 const QMetaType inputElementMetaType = inputSequence.valueMetaType();
1748 const bool inputIsQVariant = (inputElementMetaType == QMetaType::fromType<QVariant>());
1750 QVariant outputElement
1751 = outputIsQVariant ? QVariant() : QVariant(outputElementMetaType);
1752 QVariant inputElement
1753 = inputIsQVariant ? QVariant() : QVariant(inputElementMetaType);
1755 void *it = inputSequence.constBegin(inputList.constData());
1756 void *end = inputSequence.constEnd(inputList.constData());
1758 for (; !inputSequence.compareConstIterator(it, end);
1759 inputSequence.advanceConstIterator(it, 1)) {
1761 if (inputIsQVariant)
1762 inputSequence.valueAtIterator(it, &inputElement);
1764 inputSequence.valueAtIterator(it, inputElement.data());
1766 if (outputIsQVariant) {
1767 outputSequence.addValue(outputList.data(), &inputElement);
1768 }
else if (inputElement.metaType() == outputElement.metaType()) {
1769 outputSequence.addValue(outputList.data(), inputElement.constData());
1772 inputElement.metaType(), inputElement.constData(),
1773 outputElementMetaType, outputElement.data());
1774 outputSequence.addValue(outputList.data(), outputElement.constData());
1778 inputSequence.destroyConstIterator(it);
1779 inputSequence.destroyConstIterator(end);
1780 }
else if (outputIsQVariant) {
1781 outputSequence.addValue(outputList.data(), &value);
1782 }
else if (outputElementMetaType == value.metaType()){
1783 outputSequence.addValue(outputList.data(), value.constData());
1785 QVariant output(outputElementMetaType);
1787 value.metaType(), value.constData(), outputElementMetaType, output.data());
1788 outputSequence.addValue(outputList.data(), output.constData());
1791 return property.writeProperty(object, outputList.data(), flags);
1795QVariant QQmlPropertyPrivate::convertToWriteTargetType(
const QVariant &value, QMetaType targetMetaType){
1796 QMetaType sourceMetaType = value.metaType();
1797 Q_ASSERT(sourceMetaType != targetMetaType);
1800 if (sourceMetaType == QMetaType::fromType<QString>()) {
1802 QVariant converted = QQmlStringConverters::variantFromString(value.toString(), targetMetaType, &ok);
1809 if (QMetaType::canConvert(sourceMetaType, targetMetaType))
1810 if (QVariant copy = value; copy.convert(targetMetaType))
1818
1819
1820 QSequentialIterable iterable;
1821 QVariant sequenceVariant = QVariant(targetMetaType);
1822 if (QMetaType::view(
1823 targetMetaType, sequenceVariant.data(),
1824 QMetaType::fromType<QSequentialIterable>(),
1826 const QMetaSequence propertyMetaSequence = iterable.metaContainer();
1827 if (propertyMetaSequence.canAddValueAtEnd()) {
1828 const QMetaType elementMetaType = iterable.valueMetaType();
1829 void *propertyContainer = iterable.mutableIterable();
1831 if (sourceMetaType == elementMetaType) {
1832 propertyMetaSequence.addValueAtEnd(propertyContainer, value.constData());
1833 return sequenceVariant;
1834 }
else if (sourceMetaType == QMetaType::fromType<QVariantList>()) {
1835 const QVariantList list = value.value<QVariantList>();
1836 for (
const QVariant &valueElement : list) {
1837 if (valueElement.metaType() == elementMetaType) {
1838 propertyMetaSequence.addValueAtEnd(
1839 propertyContainer, valueElement.constData());
1841 QVariant converted(elementMetaType);
1843 valueElement.metaType(), valueElement.constData(),
1844 elementMetaType, converted.data());
1845 propertyMetaSequence.addValueAtEnd(
1846 propertyContainer, converted.constData());
1849 return sequenceVariant;
1850 }
else if (elementMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1851 const QMetaObject *elementMetaObject = elementMetaType.metaObject();
1852 Q_ASSERT(elementMetaObject);
1854 const auto doAppend = [&](QObject *o) {
1855 QObject *casted = elementMetaObject->cast(o);
1856 propertyMetaSequence.addValueAtEnd(propertyContainer, &casted);
1859 if (sourceMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1860 doAppend(*
static_cast<QObject *
const *>(value.data()));
1861 return sequenceVariant;
1862 }
else if (sourceMetaType == QMetaType::fromType<QQmlListReference>()) {
1863 const QQmlListReference *reference
1864 =
static_cast<
const QQmlListReference *>(value.constData());
1865 Q_ASSERT(elementMetaObject);
1866 for (
int i = 0, end = reference->size(); i < end; ++i)
1867 doAppend(reference->at(i));
1868 return sequenceVariant;
1869 }
else if (!iterateQObjectContainer(
1870 sourceMetaType, value.data(), doAppend)) {
1871 doAppend(QQmlMetaType::toQObject(value));
1874 QVariant converted = value;
1875 if (converted.convert(elementMetaType)) {
1876 propertyMetaSequence.addValueAtEnd(propertyContainer, converted.constData());
1877 return sequenceVariant;
1884 if (QQmlMetaType::isInterface(targetMetaType)) {
1885 auto valueAsQObject = qvariant_cast<QObject *>(value);
1887 if (
void *iface = valueAsQObject
1888 ? valueAsQObject->qt_metacast(QQmlMetaType::interfaceIId(targetMetaType))
1893 return QVariant(targetMetaType, &iface);
1899bool QQmlPropertyPrivate::write(
1900 QObject *object,
const QQmlPropertyData &property,
const QVariant &value,
1901 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1903 const QMetaType propertyMetaType = property.propType();
1904 const QMetaType variantMetaType = value.metaType();
1906 const BindingFixer bindingFixer(object, property, flags);
1909 if (property.isResettable() && !value.isValid()) {
1910 property.resetProperty(object, flags);
1914 if (property.isEnum()) {
1915 QMetaProperty prop = object->metaObject()->property(property.coreIndex());
1918 if (variantMetaType == QMetaType::fromType<
double>()) {
1920 double fractional = std::modf(value.toDouble(), &integral);
1921 if (qFuzzyIsNull(fractional))
1922 v.convert(QMetaType::fromType<qint32>());
1924 return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
1927 QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
1928 const bool isUrl = propertyMetaType == QMetaType::fromType<QUrl>();
1931 if (tryAssignBinding(object, property, value, variantMetaType))
1935 if (propertyMetaType == variantMetaType && !isUrl
1936 && propertyMetaType != QMetaType::fromType<QList<QUrl>>() && !property.isQList()) {
1937 return property.writeProperty(object,
const_cast<
void *>(value.constData()), flags);
1938 }
else if (property.isQObject()) {
1939 QVariant val = value;
1941 if (variantMetaType == QMetaType::fromType<std::nullptr_t>()) {
1944 varType = QMetaType::fromType<QObject*>();
1945 val = QVariant(varType,
nullptr);
1947 varType = variantMetaType;
1949 QQmlMetaObject valMo = rawMetaObjectForType(varType);
1950 if (valMo.isNull() || !varType.flags().testFlag(QMetaType::PointerToQObject))
1952 QObject *o = *
static_cast<QObject *
const *>(val.constData());
1953 QQmlMetaObject propMo = rawMetaObjectForType(propertyMetaType);
1958 if (QQmlMetaObject::canConvert(valMo, propMo)) {
1959 return property.writeProperty(object, &o, flags);
1960 }
else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
1964 return property.writeProperty(object, &o, flags);
1968 }
else if (ConvertAndAssignResult result = tryConvertAndAssign(
1969 object, property, value, flags, propertyMetaType, variantMetaType, isUrl,
1971 return result.couldWrite;
1972 }
else if (propertyMetaType == QMetaType::fromType<QVariant>()) {
1973 return property.writeProperty(object,
const_cast<QVariant *>(&value), flags);
1976 if (variantMetaType == QMetaType::fromType<QUrl>()) {
1978 if (compatResolveUrlsOnAssigment() && context && u.isRelative() && !u.isEmpty())
1979 u = context->resolvedUrl(u);
1981 else if (variantMetaType == QMetaType::fromType<QByteArray>())
1982 u = QUrl(QString::fromUtf8(value.toByteArray()));
1983 else if (variantMetaType == QMetaType::fromType<QString>())
1984 u = QUrl(value.toString());
1988 return property.writeProperty(object, &u, flags);
1989 }
else if (propertyMetaType == QMetaType::fromType<QList<QUrl>>()) {
1990 QList<QUrl> urlSeq = compatResolveUrlsOnAssigment()
1991 ? urlSequence(value, context)
1992 : urlSequence(value);
1993 return property.writeProperty(object, &urlSeq, flags);
1994 }
else if (property.isQList()) {
1995 if (propertyMetaType.flags() & QMetaType::IsQmlList) {
1996 return assignToQQmlListProperty(object, property, propertyMetaType, value);
1998 return assignToListProperty(property, flags, propertyMetaType, variantMetaType, value, object);
2000 }
else if (enginePriv && propertyMetaType == QMetaType::fromType<QJSValue>()) {
2002 QJSValue jsValue = QJSValuePrivate::fromReturnedValue(
2003 enginePriv->v4Engine->metaTypeToJS(variantMetaType, value.constData()));
2004 return property.writeProperty(object, &jsValue, flags);
2006 Q_ASSERT(variantMetaType != propertyMetaType);
2008 QVariant converted = convertToWriteTargetType(value, propertyMetaType);
2009 if (converted.isValid()) {
2010 return property.writeProperty(object,
const_cast<
void *>(converted.constData()), flags);