532void QQmlBind::setObject(QObject *obj)
536 case QQmlBindPrivate::GeneralizedGroup:
538 warnIgnoredProperties(
this);
540 case QQmlBindPrivate::ObjectPropertyValue:
541 if (d->objectPropertyValueData.obj == obj)
544 case QQmlBindPrivate::Unknown:
547 new (&d->objectPropertyValueData) ObjectPropertyValueData;
548 d->mode = QQmlBindPrivate::ObjectPropertyValue;
554
560
561
562
563 const QQmlProperty whenProp(
this, QLatin1StringView(
"when"));
564 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
565 if (
auto abstractBinding = potentialWhenBinding.asAbstractBinding()) {
566 QQmlBinding *binding =
static_cast<QQmlBinding *>(abstractBinding);
567 if (binding->hasValidContext()) {
568 const auto boolType = QMetaType::fromType<
bool>();
570 binding->evaluate(&when, boolType);
571 if (when != d->when) {
579 case QQmlBindPrivate::GeneralizedGroup:
580 case QQmlBindPrivate::Unknown:
583 case QQmlBindPrivate::ObjectPropertyValue:
584 d->objectPropertyValueData.obj = obj;
585 if (d->componentComplete) {
586 setTarget(QQmlProperty(
587 d->objectPropertyValueData.obj, d->objectPropertyValueData.propName,
593 if (d->componentComplete && d->when)
597 emit objectChanged();
870 const QQmlProperty &prop,
const QV4::CompiledData::Binding *binding,
871 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
872 const QQmlRefPointer<QQmlContextData> &contextData,
873 QObject *scopeObject)
875 switch (binding->type()) {
876 case QV4::CompiledData::Binding::Type_Translation:
877 case QV4::CompiledData::Binding::Type_TranslationById:
878 return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject);
879 case QV4::CompiledData::Binding::Type_Script: {
880 const QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
881 if (id == QQmlBinding::Invalid) {
882 return QQmlAnyBinding::createFromCodeString(
883 prop, compilationUnit->bindingValueAsString(binding), scopeObject,
884 contextData, compilationUnit->finalUrlString(), binding->location.line());
886 QV4::Scope scope(contextData->engine()->handle());
887 QV4::Scoped<QV4::QmlContext> qmlCtxt(
888 scope, QV4::QmlContext::create(
889 scope.engine->rootContext(), contextData, scopeObject));
890 return QQmlAnyBinding::createFromFunction(
891 prop, compilationUnit->runtimeFunctions.at(id), scopeObject, contextData,
897 return QQmlAnyBinding();
915 QQmlBind *q,
const QString &propertyPrefix,
916 QQmlData::DeferredData *deferredData,
917 const QV4::CompiledData::Binding *binding,
918 QQmlComponentPrivate::ConstructionState *immediateState)
920 const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
921 = deferredData->compilationUnit;
922 const QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
923 const QString propertyName = propertyPrefix + propertySuffix;
925 switch (binding->type()) {
926 case QV4::CompiledData::Binding::Type_AttachedProperty:
927 if (propertyPrefix.isEmpty()) {
934 Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
935 ->inheritedTypeNameIndex).isEmpty());
937 const QV4::ResolvedTypeReference *typeReference
938 = compilationUnit->resolvedType(binding->propertyNameIndex);
939 Q_ASSERT(typeReference);
940 QQmlType attachedType = typeReference->type();
941 if (!attachedType.isValid()) {
942 if (QQmlTypeLoader *typeLoader = compilationUnit->engine->typeLoader()) {
943 const QQmlTypeNameCache::Result result
944 = deferredData->context->imports()->query(propertySuffix, typeLoader);
945 if (!result.isValid()) {
946 qmlWarning(q).nospace()
947 <<
"Unknown name " << propertySuffix <<
". The binding is ignored.";
950 attachedType = result.type;
954 QQmlContext *context = qmlContext(q);
955 QObject *attachedObject = qmlAttachedPropertiesObject(
956 q, attachedType.attachedPropertiesFunction(
957 QQmlEnginePrivate::get(context->engine())));
958 if (!attachedObject) {
959 qmlWarning(q).nospace() <<
"Could not create attached properties object '"
960 << attachedType.typeName() <<
"'";
964 initCreator(deferredData, QQmlContextData::get(context), immediateState);
965 immediateState->creator()->populateDeferredInstance(
966 q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
967 attachedObject,
nullptr, binding);
971 case QV4::CompiledData::Binding::Type_GroupProperty: {
972 const QString pre = propertyName + u'.';
973 const QV4::CompiledData::Object *subObj
974 = compilationUnit->objectAt(binding->value.objectIndex);
975 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
976 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
977 decodeBinding(q, pre, deferredData, subBinding, immediateState);
985 QQmlContext *context = qmlContext(q);
986 const QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
987 entry.prop = QQmlPropertyPrivate::create(
nullptr, propertyName, contextData,
988 QQmlPropertyPrivate::InitFlag::AllowId);
989 if (!entry.prop.isValid()) {
995 QQmlProperty property = QQmlPropertyPrivate::create(
996 q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
997 if (property.isValid()) {
998 initCreator(deferredData, contextData, immediateState);
999 immediateState->creator()->populateDeferredBinding(
1000 property, deferredData->deferredIdx, binding);
1002 qmlWarning(q).nospace() <<
"Unknown name " << propertyName
1003 <<
". The binding is ignored.";
1009 case GeneralizedGroup:
1011 case ObjectPropertyValue:
1012 warnIgnoredProperties(q);
1013 objectPropertyValueData.~ObjectPropertyValueData();
1016 new (&generalizedGroupData) GeneralizedGroupData;
1017 mode = GeneralizedGroup;
1021 const auto setVariant = [&entry](QVariant var) {
1022 entry.currentKind = entry.current.set(std::move(var), entry.currentKind);
1025 const auto setBinding = [&entry](QQmlAnyBinding binding) {
1026 entry.currentKind = entry.current.set(binding, entry.currentKind);
1029 switch (binding->type()) {
1030 case QV4::CompiledData::Binding::Type_AttachedProperty:
1031 case QV4::CompiledData::Binding::Type_GroupProperty:
1034 case QV4::CompiledData::Binding::Type_Translation:
1035 case QV4::CompiledData::Binding::Type_TranslationById:
1036 case QV4::CompiledData::Binding::Type_Script:
1038 if (!generalizedGroupData.delayedValues)
1039 createDelayedValues();
1040 const QString delayedName = QString::number(generalizedGroupData.entries.size());
1041 generalizedGroupData.delayedValues->insert(delayedName, QVariant());
1042 QQmlProperty bindingTarget
1043 = QQmlProperty(generalizedGroupData.delayedValues.get(), delayedName);
1044 Q_ASSERT(bindingTarget.isValid());
1045 QQmlAnyBinding anyBinding = createBinding(
1046 bindingTarget, binding, compilationUnit, contextData, q);
1047 anyBinding.installOn(bindingTarget);
1049 setBinding(createBinding(entry.prop, binding, compilationUnit, contextData, q));
1052 case QV4::CompiledData::Binding::Type_String:
1053 setVariant(compilationUnit->bindingValueAsString(binding));
1055 case QV4::CompiledData::Binding::Type_Number:
1056 setVariant(compilationUnit->bindingValueAsNumber(binding));
1058 case QV4::CompiledData::Binding::Type_Boolean:
1059 setVariant(binding->valueAsBoolean());
1061 case QV4::CompiledData::Binding::Type_Null:
1062 setVariant(QVariant::fromValue(
nullptr));
1064 case QV4::CompiledData::Binding::Type_Object:
1065 case QV4::CompiledData::Binding::Type_Invalid:
1069 generalizedGroupData.entries.append(std::move(entry));
1121void QQmlBindPrivate::buildBindEntries(QQmlBind *q, QQmlComponentPrivate::DeferredState *deferredState)
1123 QQmlData *data = QQmlData::get(q);
1124 if (data && !data->deferredData.isEmpty()) {
1125 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
1126 for (QQmlData::DeferredData *deferredData : data->deferredData) {
1127 QMultiHash<
int,
const QV4::CompiledData::Binding *> *bindings = &deferredData->bindings;
1128 if (deferredState) {
1129 QQmlComponentPrivate::ConstructionState constructionState;
1130 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1131 decodeBinding(q, QString(), deferredData, *it, &constructionState);
1134 if (constructionState.hasCreator()) {
1135 ++ep->inProgressCreations;
1136 constructionState.creator()->finalizePopulateDeferred();
1137 constructionState.appendCreatorErrors();
1138 deferredState->push_back(std::move(constructionState));
1141 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1142 decodeBinding(q, QString(), deferredData, *it,
nullptr);
1146 if (deferredState) {
1147 data->releaseDeferredData();
1148 if (!deferredState->empty())
1149 QQmlComponentPrivate::completeDeferred(ep, deferredState);
1193 if (!entry->prop.isValid() || (entry->currentKind == QQmlBindEntryKind::None))
1195 if (!entry->prop.object())
1200 switch (entry->previousKind) {
1201 case QQmlBindEntryKind::Binding:
1203 QQmlAnyBinding p = std::move(entry->previous.binding);
1205 p.installOn(entry->prop);
1208 case QQmlBindEntryKind::V4Value:
1210 QQmlAnyBinding::takeFrom(entry->prop);
1211 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1212 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1214 vmemo->setVMEProperty(propPriv->core.coreIndex(),
1215 *entry->previous.v4Value.valueRef());
1219 case QQmlBindEntryKind::Variant:
1221 QQmlAnyBinding::takeFrom(entry->prop);
1222 entry->prop.write(entry->previous.variant);
1226 case QQmlBindEntryKind::None:
1233 if (entry->previousKind == QQmlBindEntryKind::None) {
1235 QQmlAnyBinding prevBind = QQmlAnyBinding::takeFrom(entry->prop);
1237 entry->previousKind = entry->previous.set(std::move(prevBind), entry->previousKind);
1240 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1241 auto propData = propPriv->core;
1242 if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
1243 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1245 auto retVal = vmemo->vmeProperty(propData.coreIndex());
1246 entry->previousKind = entry->previous.set(
1247 QV4::PersistentValue(vmemo->engine, retVal), entry->previousKind);
1250 entry->previousKind = entry->previous.set(entry->prop.read(), entry->previousKind);
1257 QQmlPropertyPrivate::removeBinding(entry->prop);