571void QQmlBind::setObject(QObject *obj)
575 case QQmlBindPrivate::GeneralizedGroup:
577 warnIgnoredProperties(
this);
579 case QQmlBindPrivate::ObjectPropertyValue:
580 if (d->objectPropertyValueData.obj == obj)
583 case QQmlBindPrivate::Unknown:
586 new (&d->objectPropertyValueData) ObjectPropertyValueData;
587 d->mode = QQmlBindPrivate::ObjectPropertyValue;
593
599
600
601
602 const QQmlProperty whenProp(
this, QLatin1StringView(
"when"));
603 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
604 if (
auto abstractBinding = potentialWhenBinding.asAbstractBinding()) {
605 QQmlBinding *binding =
static_cast<QQmlBinding *>(abstractBinding);
606 if (binding->hasValidContext()) {
607 const auto boolType = QMetaType::fromType<
bool>();
609 binding->evaluate(&when, boolType);
610 if (when != d->when) {
618 case QQmlBindPrivate::GeneralizedGroup:
619 case QQmlBindPrivate::Unknown:
622 case QQmlBindPrivate::ObjectPropertyValue:
623 d->objectPropertyValueData.obj = obj;
624 if (d->componentComplete) {
625 setTarget(QQmlProperty(
626 d->objectPropertyValueData.obj, d->objectPropertyValueData.propName,
632 if (d->componentComplete && d->when)
636 emit objectChanged();
918 const QQmlProperty &prop,
const QV4::CompiledData::Binding *binding,
919 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
920 const QQmlRefPointer<QQmlContextData> &contextData,
921 QObject *scopeObject)
923 switch (binding->type()) {
924 case QV4::CompiledData::Binding::Type_Translation:
925 case QV4::CompiledData::Binding::Type_TranslationById:
926 return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject);
927 case QV4::CompiledData::Binding::Type_Script: {
928 const QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
929 if (id == QQmlBinding::Invalid) {
930 return QQmlAnyBinding::createFromCodeString(
931 prop, compilationUnit->bindingValueAsString(binding), scopeObject,
932 contextData, compilationUnit->finalUrlString(), binding->location.line());
934 QV4::Scope scope(contextData->engine()->handle());
935 QV4::Scoped<QV4::QmlContext> qmlCtxt(
936 scope, QV4::QmlContext::create(
937 scope.engine->rootContext(), contextData, scopeObject));
938 return QQmlAnyBinding::createFromFunction(
939 prop, compilationUnit->runtimeFunctions.at(id), scopeObject, contextData,
945 return QQmlAnyBinding();
963 QQmlBind *q,
const QString &propertyPrefix,
964 QQmlData::DeferredData *deferredData,
965 const QV4::CompiledData::Binding *binding,
966 QQmlComponentPrivate::ConstructionState *immediateState)
968 const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
969 = deferredData->compilationUnit;
970 const QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
971 const QString propertyName = propertyPrefix + propertySuffix;
973 switch (binding->type()) {
974 case QV4::CompiledData::Binding::Type_AttachedProperty:
975 if (propertyPrefix.isEmpty()) {
982 Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
983 ->inheritedTypeNameIndex).isEmpty());
985 const QV4::ResolvedTypeReference *typeReference
986 = compilationUnit->resolvedType(binding->propertyNameIndex);
987 Q_ASSERT(typeReference);
988 QQmlType attachedType = typeReference->type();
989 if (!attachedType.isValid()) {
990 if (QQmlTypeLoader *typeLoader = compilationUnit->engine->typeLoader()) {
991 const QQmlTypeNameCache::Result result
992 = deferredData->context->imports()->query(propertySuffix, typeLoader);
993 if (!result.isValid()) {
994 qmlWarning(q).nospace()
995 <<
"Unknown name " << propertySuffix <<
". The binding is ignored.";
998 attachedType = result.type;
1002 QQmlContext *context = qmlContext(q);
1003 QObject *attachedObject = qmlAttachedPropertiesObject(
1004 q, attachedType.attachedPropertiesFunction(QQmlTypeLoader::get(context->engine())));
1005 if (!attachedObject) {
1006 qmlWarning(q).nospace() <<
"Could not create attached properties object '"
1007 << attachedType.typeName() <<
"'";
1011 initCreator(deferredData, QQmlContextData::get(context), immediateState);
1012 immediateState->creator()->populateDeferredInstance(
1013 q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
1014 attachedObject,
nullptr, binding);
1018 case QV4::CompiledData::Binding::Type_GroupProperty: {
1019 const QString pre = propertyName + u'.';
1020 const QV4::CompiledData::Object *subObj
1021 = compilationUnit->objectAt(binding->value.objectIndex);
1022 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
1023 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
1024 decodeBinding(q, pre, deferredData, subBinding, immediateState);
1031 QQmlBindEntry entry;
1032 QQmlContext *context = qmlContext(q);
1033 const QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1034 entry.prop = QQmlPropertyPrivate::create(
nullptr, propertyName, contextData,
1035 QQmlPropertyPrivate::InitFlag::AllowId);
1036 if (!entry.prop.isValid()) {
1039 if (!immediateState)
1042 QQmlProperty property = QQmlPropertyPrivate::create(
1043 q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
1044 if (property.isValid()) {
1045 initCreator(deferredData, contextData, immediateState);
1046 immediateState->creator()->populateDeferredBinding(
1047 property, deferredData->deferredIdx, binding);
1049 qmlWarning(q).nospace() <<
"Unknown name " << propertyName
1050 <<
". The binding is ignored.";
1056 case GeneralizedGroup:
1058 case ObjectPropertyValue:
1059 warnIgnoredProperties(q);
1060 objectPropertyValueData.~ObjectPropertyValueData();
1063 new (&generalizedGroupData) GeneralizedGroupData;
1064 mode = GeneralizedGroup;
1068 const auto setVariant = [&entry](QV4::PersistentValue value) {
1069 entry.currentKind = entry.current.setVariant(value, entry.currentKind);
1072 const auto setBinding = [&entry](QQmlAnyBinding binding) {
1073 entry.currentKind = entry.current.set(binding, entry.currentKind);
1076 switch (binding->type()) {
1077 case QV4::CompiledData::Binding::Type_AttachedProperty:
1078 case QV4::CompiledData::Binding::Type_GroupProperty:
1081 case QV4::CompiledData::Binding::Type_Translation:
1082 case QV4::CompiledData::Binding::Type_TranslationById:
1083 case QV4::CompiledData::Binding::Type_Script:
1085 if (!generalizedGroupData.delayedValues)
1086 createDelayedValues();
1087 const QString delayedName = QString::number(generalizedGroupData.entries.size());
1088 generalizedGroupData.delayedValues->insert(delayedName, QVariant());
1089 QQmlProperty bindingTarget
1090 = QQmlProperty(generalizedGroupData.delayedValues.get(), delayedName);
1091 Q_ASSERT(bindingTarget.isValid());
1092 QQmlAnyBinding anyBinding = createBinding(
1093 bindingTarget, binding, compilationUnit, contextData, q);
1094 anyBinding.installOn(bindingTarget);
1096 setBinding(createBinding(entry.prop, binding, compilationUnit, contextData, q));
1099 case QV4::CompiledData::Binding::Type_String:
1100 setVariant(QV4::PersistentValue(
1101 compilationUnit->engine,
1102 compilationUnit->runtimeStrings[binding->stringIndex]->asReturnedValue()));
1104 case QV4::CompiledData::Binding::Type_Number:
1105 setVariant(QV4::PersistentValue(
1106 compilationUnit->engine,
1107 compilationUnit->constants[binding->value.constantValueIndex].asReturnedValue()));
1109 case QV4::CompiledData::Binding::Type_Boolean:
1110 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode(binding->value.b)));
1112 case QV4::CompiledData::Binding::Type_Null:
1113 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode::null()));
1115 case QV4::CompiledData::Binding::Type_Object:
1116 case QV4::CompiledData::Binding::Type_Invalid:
1120 generalizedGroupData.entries.append(std::move(entry));
1172void QQmlBindPrivate::buildBindEntries(QQmlBind *q, QQmlComponentPrivate::DeferredState *deferredState)
1174 QQmlData *data = QQmlData::get(q);
1175 if (data && !data->deferredData.isEmpty()) {
1176 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
1177 for (QQmlData::DeferredData *deferredData : data->deferredData) {
1178 QMultiHash<
int,
const QV4::CompiledData::Binding *> *bindings = &deferredData->bindings;
1179 if (deferredState) {
1180 QQmlComponentPrivate::ConstructionState constructionState;
1181 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1182 decodeBinding(q, QString(), deferredData, *it, &constructionState);
1185 if (constructionState.hasCreator()) {
1186 ++ep->inProgressCreations;
1187 constructionState.creator()->finalizePopulateDeferred();
1188 constructionState.appendCreatorErrors();
1189 deferredState->push_back(std::move(constructionState));
1192 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1193 decodeBinding(q, QString(), deferredData, *it,
nullptr);
1197 if (deferredState) {
1198 data->releaseDeferredData();
1199 if (!deferredState->empty())
1200 QQmlComponentPrivate::completeDeferred(ep, deferredState);
1270 if (!entry->prop.isValid() || (entry->currentKind == QQmlBindEntryKind::None))
1272 if (!entry->prop.object())
1282 switch (entry->previousKind) {
1283 case QQmlBindEntryKind::Binding:
1285 QQmlAnyBinding p = std::move(entry->previous.binding);
1287 p.installOn(entry->prop);
1290 case QQmlBindEntryKind::V4Value:
1292 QQmlAnyBinding::takeFrom(entry->prop);
1293 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1294 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1296 vmemo->setVMEProperty(propPriv->core.coreIndex(),
1297 *entry->previous.v4Value.valueRef());
1301 case QQmlBindEntryKind::Variant:
1303 QQmlAnyBinding::takeFrom(entry->prop);
1304 const QV4::PersistentValue &v4Value = entry->previous.v4Value;
1305 entry->prop.write(v4Value.engine()->toVariant(
1306 *v4Value.valueRef(), entry->prop.propertyMetaType()));
1310 case QQmlBindEntryKind::None:
1317 if (entry->previousKind == QQmlBindEntryKind::None) {
1319 QQmlAnyBinding prevBind = QQmlAnyBinding::takeFrom(entry->prop);
1321 entry->previousKind = entry->previous.set(std::move(prevBind), entry->previousKind);
1324 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1325 auto propData = propPriv->core;
1326 if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
1327 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1329 auto retVal = vmemo->vmeProperty(propData.coreIndex());
1330 entry->previousKind = entry->previous.set(
1331 QV4::PersistentValue(vmemo->engine, retVal), entry->previousKind);
1334 entry->previousKind = entry->previous.set(
1335 propPriv->engine->handle(), entry->prop.read(), entry->previousKind);
1342 QQmlPropertyPrivate::removeBinding(entry->prop, QQmlPropertyPrivate::OverrideSticky);