Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlproperty.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlproperty.h"
5#include "qqmlproperty_p.h"
6
7#include "qqmlboundsignal_p.h"
8#include "qqmlcontext.h"
9#include "qqmlboundsignal_p.h"
10#include "qqmlengine.h"
11#include "qqmlengine_p.h"
12#include "qqmldata_p.h"
14
15#include "qqmlvmemetaobject_p.h"
17#include <private/qjsvalue_p.h>
18#include <private/qv4functionobject_p.h>
19#include <private/qv4qobjectwrapper_p.h>
20#include <private/qqmlbuiltinfunctions_p.h>
21#include <private/qqmlirbuilder_p.h>
22#include <QtQml/private/qqmllist_p.h>
23
24#include <QStringList>
25#include <QVector>
26#include <private/qmetaobject_p.h>
27#include <private/qqmlvaluetypewrapper_p.h>
28#include <QtCore/qdebug.h>
29#include <cmath>
30#include <QtQml/QQmlPropertyMap>
31#include <QtCore/private/qproperty_p.h>
32#include <QtCore/qsequentialiterable.h>
33
35
36DEFINE_BOOL_CONFIG_OPTION(compatResolveUrlsOnAssigment, QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT);
37
83
86{
87 if (d)
88 d->release();
89 d = nullptr;
90}
91
98{
99 d->initDefault(obj);
100}
101
110{
111 if (ctxt) {
112 d->context = QQmlContextData::get(ctxt);
113 d->engine = ctxt->engine();
114 }
115 d->initDefault(obj);
116}
117
126{
127 d->engine = engine;
128 d->initDefault(obj);
129}
130
135{
136 if (!obj)
137 return;
138
140 core.load(p);
141 if (core.isValid())
142 object = obj;
143}
144
150{
151 d->initProperty(obj, name);
152 if (!isValid()) d->object = nullptr;
153}
154
164{
165 if (ctxt) {
166 d->context = QQmlContextData::get(ctxt);
167 d->engine = ctxt->engine();
168 }
169
170 d->initProperty(obj, name);
171 if (!isValid()) {
172 d->object = nullptr;
173 d->context.reset();
174 d->engine = nullptr;
175 }
176}
177
185{
186 d->engine = engine;
187 d->initProperty(obj, name);
188 if (!isValid()) {
189 d->object = nullptr;
190 d->context.reset();
191 d->engine = nullptr;
192 }
193}
194
197 QQmlPropertyPrivate::InitFlags flags)
198{
200 auto d = new QQmlPropertyPrivate;
201 result.d = d;
202 d->context = context;
203 d->engine = context ? context->engine() : nullptr;
204 d->initProperty(target, propertyName, flags);
205 if (!result.isValid()) {
206 d->object = nullptr;
207 d->context.reset();
208 d->engine = nullptr;
209 }
210 return result;
211}
212
214{
215 return ::compatResolveUrlsOnAssigment();
216}
217
219{
220 if (context)
221 return context;
222 else if (engine)
224 else
225 return nullptr;
226}
227
228// ### Qt7: Do not accept the "onFoo" syntax for signals anymore, and change the flags accordingly.
230 QQmlPropertyPrivate::InitFlags flags)
231{
232 QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() : nullptr;
233
234 QObject *currentObject = obj;
236 QStringView terminal(name);
237
238 if (name.contains(QLatin1Char('.'))) {
240 if (path.isEmpty()) return;
241
242 // Everything up to the last property must be an "object type" property
243 for (int ii = 0; ii < path.size() - 1; ++ii) {
244 const QStringView &pathName = path.at(ii);
245
246 // Types must begin with an uppercase letter (see checkRegistration()
247 // in qqmlmetatype.cpp for the enforcement of this).
248 if (typeNameCache && !pathName.isEmpty() && pathName.at(0).isUpper()) {
249 QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
250 if (r.isValid()) {
251 if (r.type.isValid()) {
253 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
254 if (!func) return; // Not an attachable type
255
256 currentObject = qmlAttachedPropertiesObject(currentObject, func);
257 if (!currentObject) return; // Something is broken with the attachable type
258 } else if (r.importNamespace) {
259 if (++ii == path.size())
260 return; // No type following the namespace
261
262 // TODO: Do we really _not_ want to query the namespaced types here?
263 r = typeNameCache->query<QQmlTypeNameCache::QueryNamespaced::No>(
264 path.at(ii), r.importNamespace);
265
266 if (!r.type.isValid())
267 return; // Invalid type in namespace
268
270 QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
271 if (!func)
272 return; // Not an attachable type
273
274 currentObject = qmlAttachedPropertiesObject(currentObject, func);
275 if (!currentObject)
276 return; // Something is broken with the attachable type
277
278 } else if (r.scriptIndex != -1) {
279 return; // Not a type
280 } else {
281 Q_ASSERT(!"Unreachable");
282 }
283 continue;
284 }
285
286 }
287
288 QQmlPropertyData local;
289 const QQmlPropertyData *property = currentObject
290 ? QQmlPropertyCache::property(currentObject, pathName, context, &local)
291 : nullptr;
292
293 if (!property) {
294 // Not a property; Might be an ID
295 // You can't look up an ID on a non-null object, though.
296 if (currentObject || !(flags & InitFlag::AllowId))
297 return;
298
299 for (auto idContext = context; idContext; idContext = idContext->parent()) {
300 const int objectId = idContext->propertyIndex(pathName.toString());
301 if (objectId != -1 && objectId < idContext->numIdValues()) {
302 currentObject = context->idValue(objectId);
303 break;
304 }
305 }
306
307 if (!currentObject)
308 return;
309
310 continue;
311 } else if (property->isFunction()) {
312 return; // Not an object property
313 }
314
315 if (ii == (path.size() - 2) && QQmlMetaType::isValueType(property->propType())) {
316 // We're now at a value type property
317 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(property->propType());
318 if (!valueTypeMetaObject) return; // Not a value type
319
320 int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
321 if (idx == -1) return; // Value type property does not exist
322
323 QMetaProperty vtProp = valueTypeMetaObject->property(idx);
324
325 Q_ASSERT(idx <= 0x0000FFFF);
326
327 object = currentObject;
328 core = *property;
332
333 return;
334 } else {
335 if (!property->isQObject()) {
336 if (auto asPropertyMap = qobject_cast<QQmlPropertyMap*>(currentObject))
337 currentObject = asPropertyMap->value(path.at(ii).toString()).value<QObject*>();
338 else
339 return; // Not an object property, and not a property map
340 } else {
341 property->readProperty(currentObject, &currentObject);
342 }
343
344 if (!currentObject) return; // No value
345
346 }
347
348 }
349
350 terminal = path.last();
351 } else if (!currentObject) {
352 return;
353 }
354
355 auto findSignalInMetaObject = [&](const QByteArray &signalName) {
356 const QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName);
357 if (!method.isValid())
358 return false;
359
360 object = currentObject;
362 return true;
363 };
364
365 QQmlData *ddata = QQmlData::get(currentObject, false);
366 auto findChangeSignal = [&](QStringView signalName) {
367 const QString changed = QStringLiteral("Changed");
368 if (signalName.endsWith(changed)) {
369 const QStringView propName = signalName.first(signalName.size() - changed.size());
370 const QQmlPropertyData *d = ddata->propertyCache->property(propName, currentObject, context);
371 while (d && d->isFunction())
372 d = ddata->propertyCache->overrideData(d);
373
374 if (d && d->notifyIndex() != -1) {
375 object = currentObject;
376 core = *ddata->propertyCache->signal(d->notifyIndex());
377 return true;
378 }
379 }
380 return false;
381 };
382
383 const QString terminalString = terminal.toString();
384 if (QmlIR::IRBuilder::isSignalPropertyName(terminalString)) {
385 QString signalName = terminalString.mid(2);
386 int firstNon_;
387 int length = signalName.size();
388 for (firstNon_ = 0; firstNon_ < length; ++firstNon_)
389 if (signalName.at(firstNon_) != u'_')
390 break;
391 signalName[firstNon_] = signalName.at(firstNon_).toLower();
392
393 if (ddata && ddata->propertyCache) {
394 // Try method
395 const QQmlPropertyData *d = ddata->propertyCache->property(
396 signalName, currentObject, context);
397
398 // ### Qt7: This code treats methods as signals. It should use d->isSignal().
399 // That would be a change in behavior, though. Right now you can construct a
400 // QQmlProperty from such a thing.
401 while (d && !d->isFunction())
402 d = ddata->propertyCache->overrideData(d);
403
404 if (d) {
405 object = currentObject;
406 core = *d;
407 return;
408 }
409
410 if (findChangeSignal(signalName))
411 return;
412 } else if (findSignalInMetaObject(signalName.toUtf8())) {
413 return;
414 }
415 }
416
417 if (ddata && ddata->propertyCache) {
418 const QQmlPropertyData *property = ddata->propertyCache->property(
419 terminal, currentObject, context);
420
421 // Technically, we might find an override that is not a function.
422 while (property && !property->isSignal()) {
423 if (!property->isFunction()) {
424 object = currentObject;
425 core = *property;
426 nameCache = terminalString;
427 return;
428 }
429 property = ddata->propertyCache->overrideData(property);
430 }
431
433 return;
434
435 if (property) {
436 Q_ASSERT(property->isSignal());
437 object = currentObject;
438 core = *property;
439 return;
440 }
441
442 // At last: Try the change signal.
443 findChangeSignal(terminal);
444 } else {
445 // We might still find the property in the metaobject, even without property cache.
446 const QByteArray propertyName = terminal.toUtf8();
447 const QMetaProperty prop = findPropertyByName(currentObject->metaObject(), propertyName);
448
449 if (prop.isValid()) {
450 object = currentObject;
451 core.load(prop);
452 return;
453 }
454
456 findSignalInMetaObject(terminal.toUtf8());
457 }
458}
459
466{
468 QMetaMethod m = object->metaObject()->method(core.coreIndex());
470}
471
476{
477 d = other.d;
478 if (d)
479 d->addref();
480}
481
507{
508 return d ? d->propertyTypeCategory() : InvalidCategory;
509}
510
513{
514 uint type = this->type();
515
516 if (isValueType()) {
518 } else if (type & QQmlProperty::Property) {
520 if (!type.isValid())
524 else if (core.isQObject())
526 else if (core.isQList())
527 return QQmlProperty::List;
528 else
530 }
531
533}
534
540{
541 if (!d)
542 return nullptr;
543 if (d->isValueType()) {
544 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(d->core.propType());
545 Q_ASSERT(valueTypeMetaObject);
546 return valueTypeMetaObject->property(d->valueTypeData.coreIndex()).typeName();
547 } else if (d->object && type() & Property && d->core.isValid()) {
548 return d->object->metaObject()->property(d->core.coreIndex()).typeName();
549 } else {
550 return nullptr;
551 }
552}
553
559{
560 if (!d || !other.d)
561 return false;
562 // category is intentially omitted here as it is generated
563 // from the other members
564 return d->object == other.d->object &&
565 d->core.coreIndex() == other.d->core.coreIndex() &&
566 d->valueTypeData.coreIndex() == other.d->valueTypeData.coreIndex();
567}
568
576{
577 return d ? d->propertyType().id() : int(QMetaType::UnknownType);
578}
579
586{
587 return d ? d->propertyType() : QMetaType {};
588}
589
591{
592 return valueTypeData.isValid();
593}
594
596{
597 uint type = this->type();
598 if (isValueType()) {
599 return valueTypeData.propType();
600 } else if (type & QQmlProperty::Property) {
601 return core.propType();
602 } else {
603 return QMetaType();
604 }
605}
606
608{
609 if (core.isFunction())
611 else if (core.isValid())
613 else
615}
616
621{
622 return d ? d->type() : Invalid;
623}
624
629{
630 return type() & Property;
631}
632
637{
638 return type() & SignalProperty;
639}
640
645{
646 return d ? d->object : nullptr;
647}
648
653{
654 QQmlProperty copied(other);
655 qSwap(d, copied.d);
656 return *this;
657}
658
663{
664 if (!d)
665 return false;
666 if (!d->object)
667 return false;
668 if (d->core.isQList()) //list
669 return true;
670 else if (d->core.isFunction()) //signal handler
671 return false;
672 else if (d->core.isValid()) //normal property
673 return d->core.isWritable();
674 else
675 return false;
676}
677
683{
684 if (!d)
685 return false;
686 if (!d->object)
687 return false;
688 if (d->core.isValid())
689 return d->core.isBindable();
690 return false;
691}
692
697{
698 if (!d)
699 return false;
700 if (type() & Property && d->core.isValid() && d->object)
701 return d->object->metaObject()->property(d->core.coreIndex()).isDesignable();
702 else
703 return false;
704}
705
710{
711 if (!d)
712 return false;
713 if (type() & Property && d->core.isValid() && d->object)
714 return d->core.isResettable();
715 else
716 return false;
717}
718
724{
725 if (!d)
726 return false;
727 return type() != Invalid;
728}
729
734{
735 if (!d)
736 return QString();
737 if (d->nameCache.isEmpty()) {
738 if (!d->object) {
739 } else if (d->isValueType()) {
740 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(d->core.propType());
741 Q_ASSERT(valueTypeMetaObject);
742
743 const char *vtName = valueTypeMetaObject->property(d->valueTypeData.coreIndex()).name();
744 d->nameCache = d->core.name(d->object) + QLatin1Char('.') + QString::fromUtf8(vtName);
745 } else if (type() & SignalProperty) {
746 // ### Qt7: Return the original signal name here. Do not prepend "on"
747 QString name = QStringLiteral("on") + d->core.name(d->object);
748 for (int i = 2, end = name.size(); i != end; ++i) {
749 const QChar c = name.at(i);
750 if (c != u'_') {
751 name[i] = c.toUpper();
752 break;
753 }
754 }
755 d->nameCache = name;
756 } else {
757 d->nameCache = d->core.name(d->object);
758 }
759 }
760
761 return d->nameCache;
762}
763
769{
770 if (!d)
771 return QMetaProperty();
772 if (type() & Property && d->core.isValid() && d->object)
773 return d->object->metaObject()->property(d->core.coreIndex());
774 else
775 return QMetaProperty();
776}
777
783{
784 if (!d)
785 return QMetaMethod();
786 if (type() & SignalProperty && d->object)
787 return d->object->metaObject()->method(d->core.coreIndex());
788 else
789 return QMetaMethod();
790}
791
798{
799 if (!that.d || !that.isProperty() || !that.d->object)
800 return nullptr;
801
802 QQmlPropertyIndex thatIndex(that.d->core.coreIndex(), that.d->valueTypeData.coreIndex());
803 return binding(that.d->object, thatIndex);
804}
805
816void
818{
819 if (!newBinding) {
820 removeBinding(that);
821 return;
822 }
823
824 if (!that.d || !that.isProperty() || !that.d->object) {
825 if (!newBinding->ref)
826 delete newBinding;
827 return;
828 }
829 setBinding(newBinding);
830}
831
832static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
833{
834 int coreIndex = index.coreIndex();
835 int valueTypeIndex = index.valueTypeIndex();
836
837 QQmlData *data = QQmlData::get(object, false);
838
839 if (!data || !data->hasBindingBit(coreIndex))
840 return;
841
842 QQmlAbstractBinding::Ptr oldBinding;
843 oldBinding = data->bindings;
844
845 while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
846 oldBinding->targetPropertyIndex().hasValueTypeIndex()))
847 oldBinding = oldBinding->nextBinding();
848
849 if (!oldBinding)
850 return;
851
852 if (valueTypeIndex != -1 && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy)
853 oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
854
855 if (!oldBinding)
856 return;
857
859 oldBinding->setEnabled(false, {});
860 oldBinding->removeFromObject();
861}
862
864{
865 removeBinding(b->targetObject(), b->targetPropertyIndex());
866}
867
869{
870 Q_ASSERT(o);
871
872 auto [target, targetIndex] = findAliasTarget(o, index);
873 removeOldBinding(target, targetIndex);
874}
875
877{
878 if (!that.d || !that.isProperty() || !that.d->object)
879 return;
880
881 removeBinding(that.d->object, that.d->encodedIndex());
882}
883
886{
887 auto aliasTarget = findAliasTarget(object, index);
888 object = aliasTarget.targetObject;
889 index = aliasTarget.targetIndex;
890
891 QQmlData *data = QQmlData::get(object);
892 if (!data)
893 return nullptr;
894
895 const int coreIndex = index.coreIndex();
896 const int valueTypeIndex = index.valueTypeIndex();
897
898 if (coreIndex < 0 || !data->hasBindingBit(coreIndex))
899 return nullptr;
900
901 QQmlAbstractBinding *binding = data->bindings;
902 while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex ||
905
906 if (binding && valueTypeIndex != -1) {
909 }
910
911 return binding;
912}
913
915 QObject **targetObject,
916 QQmlPropertyIndex *targetBindingIndex)
917{
918 QQmlData *data = QQmlData::get(object, false);
919 if (data) {
920 int coreIndex = bindingIndex.coreIndex();
921 int valueTypeIndex = bindingIndex.valueTypeIndex();
922
923 const QQmlPropertyData *propertyData =
924 data->propertyCache?data->propertyCache->property(coreIndex):nullptr;
925 if (propertyData && propertyData->isAlias()) {
927
928 QObject *aObject = nullptr; int aCoreIndex = -1; int aValueTypeIndex = -1;
929 if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
930 // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
931 Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
932
933 QQmlPropertyIndex aBindingIndex(aCoreIndex);
934 if (aValueTypeIndex != -1) {
935 aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex);
936 } else if (valueTypeIndex != -1) {
937 aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex);
938 }
939
940 findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
941 return;
942 }
943 }
944 }
945
946 *targetObject = object;
947 *targetBindingIndex = bindingIndex;
948}
949
951{
952 ResolvedAlias resolved;
953 findAliasTarget(baseObject, baseIndex, &resolved.targetObject, &resolved.targetIndex);
954 return resolved;
955}
956
957
958
959void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, QQmlPropertyData::WriteFlags writeFlags)
960{
963
964 QObject *object = binding->targetObject();
966
967#ifndef QT_NO_DEBUG
968 int coreIndex = index.coreIndex();
969 QQmlData *data = QQmlData::get(object, true);
970 if (data->propertyCache) {
971 const QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
972 Q_ASSERT(propertyData);
973 }
974#endif
975
976 removeOldBinding(object, index, flags);
977
979 if (!(flags & DontEnable))
981
982}
983
990{
991 if (!(that.type() & QQmlProperty::SignalProperty))
992 return nullptr;
993
994 if (!that.d->object)
995 return nullptr;
996 QQmlData *data = QQmlData::get(that.d->object);
997 if (!data)
998 return nullptr;
999
1000 QQmlBoundSignal *signalHandler = data->signalHandlers;
1001
1002 while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
1003 signalHandler = signalHandler->m_nextSignal;
1004
1005 if (signalHandler)
1006 return signalHandler->expression();
1007
1008 return nullptr;
1009}
1010
1016{
1017 if (expr)
1018 expr->addref();
1020}
1021
1028{
1029 if (!(that.type() & QQmlProperty::SignalProperty)) {
1030 if (expr)
1031 expr->release();
1032 return;
1033 }
1034
1035 if (!that.d->object)
1036 return;
1037 QQmlData *data = QQmlData::get(that.d->object, nullptr != expr);
1038 if (!data)
1039 return;
1040
1041 QQmlBoundSignal *signalHandler = data->signalHandlers;
1042
1043 while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
1044 signalHandler = signalHandler->m_nextSignal;
1045
1046 if (signalHandler) {
1047 signalHandler->takeExpression(expr);
1048 return;
1049 }
1050
1051 if (expr) {
1054 expr->engine());
1055 signal->takeExpression(expr);
1056 }
1057}
1058
1063{
1064 if (!d)
1065 return QVariant();
1066 if (!d->object)
1067 return QVariant();
1068
1069 if (type() & SignalProperty) {
1070
1071 return QVariant();
1072
1073 } else if (type() & Property) {
1074
1075 return d->readValueProperty();
1076
1077 }
1078 return QVariant();
1079}
1080
1089{
1090 QQmlProperty p(const_cast<QObject *>(object), name);
1091 return p.read();
1092}
1093
1105{
1106 QQmlProperty p(const_cast<QObject *>(object), name, ctxt);
1107 return p.read();
1108}
1109
1122{
1123 QQmlProperty p(const_cast<QObject *>(object), name, engine);
1124 return p.read();
1125}
1126
1128{
1129 auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) {
1130 wrapper->read(object, core.coreIndex());
1131 return wrapper->readOnGadget(wrapper->property(valueTypeData.coreIndex()));
1132 };
1133
1134 if (isValueType()) {
1136 return doRead(wrapper);
1137 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1138 QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
1139 return doRead(&wrapper);
1140 }
1141 return QVariant();
1142 } else if (core.isQList()) {
1143
1145 core.readProperty(object, &prop);
1147
1148 } else if (core.isQObject()) {
1149
1150 QObject *rv = nullptr;
1151 core.readProperty(object, &rv);
1152 return QVariant::fromValue(rv);
1153
1154 } else {
1155
1156 if (!core.propType().isValid()) // Unregistered type
1157 return object->metaObject()->property(core.coreIndex()).read(object);
1158
1160 int status = -1;
1161 void *args[] = { nullptr, &value, &status };
1162 if (core.propType() == QMetaType::fromType<QVariant>()) {
1163 args[0] = &value;
1164 } else {
1165 value = QVariant(core.propType(), (void*)nullptr);
1166 args[0] = value.data();
1167 }
1169 if (core.propType() != QMetaType::fromType<QVariant>() && args[0] != value.data())
1170 return QVariant(QMetaType(core.propType()), args[0]);
1171
1172 return value;
1173 }
1174}
1175
1176// helper function to allow assignment / binding to QList<QUrl> properties.
1178{
1179 if (value.metaType() == QMetaType::fromType<QList<QUrl>>())
1180 return value.value<QList<QUrl> >();
1181
1182 QList<QUrl> urls;
1183 if (value.metaType() == QMetaType::fromType<QUrl>()) {
1184 urls.append(value.toUrl());
1185 } else if (value.metaType() == QMetaType::fromType<QString>()) {
1186 urls.append(QUrl(value.toString()));
1187 } else if (value.metaType() == QMetaType::fromType<QByteArray>()) {
1188 urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
1189 } else if (value.metaType() == QMetaType::fromType<QStringList>()) {
1190 QStringList urlStrings = value.value<QStringList>();
1191 const int urlStringsSize = urlStrings.size();
1192 urls.reserve(urlStringsSize);
1193 for (int i = 0; i < urlStringsSize; ++i)
1194 urls.append(QUrl(urlStrings.at(i)));
1195 } // note: QList<QByteArray> is not currently supported.
1196 return urls;
1197}
1198
1199// ### Qt7: Get rid of this
1202{
1204
1205 for (auto urlIt = urls.begin(); urlIt != urls.end(); ++urlIt)
1206 *urlIt = ctxt->resolvedUrl(*urlIt);
1207
1208 return urls;
1209}
1210
1211//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC!
1212bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
1213{
1214 if (!object || !prop.isWritable())
1215 return false;
1216
1217 QVariant v = value;
1218 if (prop.isEnumType() && v.metaType() != prop.metaType()) {
1219 QMetaEnum menum = prop.enumerator();
1220 if (v.userType() == QMetaType::QString) {
1221 bool ok;
1222 if (prop.isFlagType())
1223 v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
1224 else
1225 v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
1226 if (!ok)
1227 return false;
1228 }
1229 if (!v.convert(prop.metaType())) // ### TODO: underlyingType might be faster?
1230 return false;
1231 }
1232
1233 // the status variable is changed by qt_metacall to indicate what it did
1234 // this feature is currently only used by QtDBus and should not be depended
1235 // upon. Don't change it without looking into QDBusAbstractInterface first
1236 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
1237 // changed: result stored directly in value, return the value of status
1238 int status = -1;
1239 void *argv[] = { v.data(), &v, &status, &flags };
1241 return status;
1242}
1243
1244bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlPropertyData::WriteFlags flags)
1245{
1247}
1248
1250 QObject *object, const QQmlPropertyData &core,
1251 const QQmlPropertyData &valueTypeData, QQmlPropertyData::WriteFlags flags)
1252{
1253 // Remove any existing bindings on this property
1254 if (!(flags & QQmlPropertyData::DontRemoveBinding) && object) {
1256 object, QQmlPropertyPrivate::encodedIndex(core, valueTypeData));
1257 }
1258}
1259
1260template<typename Op>
1262 QObject *object, int coreIndex, QQmlGadgetPtrWrapper *wrapper,
1263 QQmlPropertyData::WriteFlags flags, int internalIndex, Op op)
1264{
1265 wrapper->read(object, coreIndex);
1266 const bool rv = op(wrapper);
1267 wrapper->write(object, coreIndex, flags, internalIndex);
1268 return rv;
1269}
1270
1271template<typename Op>
1273 QObject *object, const QQmlPropertyData &core,
1274 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags,
1275 int internalIndex, Op op)
1276{
1279 : nullptr) {
1281 object, core.coreIndex(), wrapper, flags, internalIndex, op);
1282 }
1283
1284 if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
1285 QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
1287 object, core.coreIndex(), &wrapper, flags, internalIndex, op);
1288 }
1289
1290 return false;
1291}
1292
1294 QObject *object, const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
1296 QQmlPropertyData::WriteFlags flags)
1297{
1299
1300 if (!valueTypeData.isValid())
1301 return write(object, core, value, context, flags);
1302
1306 return write(wrapper, valueTypeData, value, context, flags);
1307 });
1308}
1309
1311 QObject *object, const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
1312 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1313{
1315
1316 if (!valueTypeData.isValid())
1317 return reset(object, core, flags);
1318
1322 return reset(wrapper, valueTypeData, flags);
1323 });
1324}
1325
1326// We need to prevent new-style bindings from being removed.
1328{
1330
1332 QQmlPropertyData::WriteFlags flags)
1333 {
1334 if (!property.isBindable() || !(flags & QQmlPropertyData::DontRemoveBinding))
1335 return;
1336
1337 QUntypedBindable bindable;
1338 void *argv[] = {&bindable};
1340 untypedBinding = bindable.binding();
1341 if (auto priv = QPropertyBindingPrivate::get(untypedBinding))
1342 priv->setSticky(true);
1343 }
1344
1346 {
1347 if (untypedBinding.isNull())
1348 return;
1349 auto priv = QPropertyBindingPrivate::get(untypedBinding);
1350 priv->setSticky(false);
1351 }
1352
1353private:
1354 QUntypedPropertyBinding untypedBinding;
1355};
1356
1358 bool couldConvert = false;
1359 bool couldWrite = false;
1360
1361 operator bool() const { return couldConvert; }
1362};
1363
1365 QObject *object, const QQmlPropertyData &property, const QVariant &value,
1366 QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType,
1367 bool isUrl) {
1368
1369 if (isUrl
1370 || variantMetaType == QMetaType::fromType<QString>()
1371 || propertyMetaType == QMetaType::fromType<QList<QUrl>>()
1372 || property.isQList()) {
1373 return {false, false};
1374 }
1375
1376 if (variantMetaType == QMetaType::fromType<QJSValue>()) {
1377 // Handle Qt.binding bindings here to avoid mistaken conversion below
1378 const QJSValue &jsValue = get<QJSValue>(value);
1379 const QV4::FunctionObject *f
1380 = QJSValuePrivate::asManagedType<QV4::FunctionObject>(&jsValue);
1381 if (f && f->isBinding()) {
1383 f->engine(), object, &property, f->asReturnedValue());
1384 return {true, true};
1385 }
1386 }
1387
1388 // common cases:
1389 switch (propertyMetaType.id()) {
1390 case QMetaType::Bool:
1391 if (value.canConvert(propertyMetaType)) {
1392 bool b = value.toBool();
1393 return {true, property.writeProperty(object, &b, flags)};
1394 }
1395 return {false, false};
1396 case QMetaType::Int: {
1397 bool ok = false;
1398 int i = value.toInt(&ok);
1399 return {ok, ok && property.writeProperty(object, &i, flags)};
1400 }
1401 case QMetaType::UInt: {
1402 bool ok = false;
1403 uint u = value.toUInt(&ok);
1404 return {ok, ok && property.writeProperty(object, &u, flags)};
1405 }
1406 case QMetaType::Double: {
1407 bool ok = false;
1408 double d = value.toDouble(&ok);
1409 return {ok, ok && property.writeProperty(object, &d, flags)};
1410 }
1411 case QMetaType::Float: {
1412 bool ok = false;
1413 float f = value.toFloat(&ok);
1414 return {ok, ok && property.writeProperty(object, &f, flags)};
1415 }
1416 case QMetaType::QString:
1417 if (value.canConvert(propertyMetaType)) {
1418 QString s = value.toString();
1419 return {true, property.writeProperty(object, &s, flags)};
1420 }
1421 return {false, false};
1422 case QMetaType::QVariantMap:
1423 if (value.canConvert(propertyMetaType)) {
1424 QVariantMap m = value.toMap();
1425 return {true, property.writeProperty(object, &m, flags)};
1426 }
1427 return {false, false};
1428 default: {
1429 break;
1430 }
1431 }
1432
1433 QVariant converted = QQmlValueTypeProvider::createValueType(value, propertyMetaType);
1434 if (!converted.isValid()) {
1435 converted = QVariant(propertyMetaType);
1436 if (!QMetaType::convert(value.metaType(), value.constData(),
1437 propertyMetaType, converted.data())) {
1438 return {false, false};
1439 }
1440 }
1441 return {true, property.writeProperty(object, converted.data(), flags)};
1442};
1443
1444template<typename Op>
1445bool iterateQObjectContainer(QMetaType metaType, const void *data, Op op)
1446{
1447 QSequentialIterable iterable;
1448 if (!QMetaType::convert(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
1449 return false;
1450
1451 const QMetaSequence metaSequence = iterable.metaContainer();
1452
1453 if (!metaSequence.hasConstIterator()
1454 || !metaSequence.canGetValueAtConstIterator()
1455 || !iterable.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
1456 return false;
1457 }
1458
1459 const void *container = iterable.constIterable();
1460 void *it = metaSequence.constBegin(container);
1461 const void *end = metaSequence.constEnd(container);
1462 QObject *o = nullptr;
1463 while (!metaSequence.compareConstIterator(it, end)) {
1464 metaSequence.valueAtConstIterator(it, &o);
1465 op(o);
1466 metaSequence.advanceConstIterator(it, 1);
1467 }
1468 metaSequence.destroyConstIterator(it);
1469 metaSequence.destroyConstIterator(end);
1470 return true;
1471}
1472
1474 QObject *object, const QQmlPropertyData &property, const QVariant &value,
1475 const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
1476{
1477 const QMetaType propertyMetaType = property.propType();
1478 const QMetaType variantMetaType = value.metaType();
1479
1480 const BindingFixer bindingFixer(object, property, flags);
1481
1482 if (property.isEnum()) {
1483 QMetaProperty prop = object->metaObject()->property(property.coreIndex());
1484 QVariant v = value;
1485 // Enum values come through the script engine as doubles
1486 if (variantMetaType == QMetaType::fromType<double>()) {
1487 double integral;
1488 double fractional = std::modf(value.toDouble(), &integral);
1489 if (qFuzzyIsNull(fractional))
1490 v.convert(QMetaType::fromType<qint32>());
1491 }
1492 return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
1493 }
1494
1496 const bool isUrl = propertyMetaType == QMetaType::fromType<QUrl>(); // handled separately
1497
1498 // The cases below are in approximate order of likelyhood:
1499 if (propertyMetaType == variantMetaType && !isUrl
1500 && propertyMetaType != QMetaType::fromType<QList<QUrl>>() && !property.isQList()) {
1501 return property.writeProperty(object, const_cast<void *>(value.constData()), flags);
1502 } else if (property.isQObject()) {
1503 QVariant val = value;
1504 QMetaType varType;
1505 if (variantMetaType == QMetaType::fromType<std::nullptr_t>()) {
1506 // This reflects the fact that you can assign a nullptr to a QObject pointer
1507 // Without the change to QObjectStar, rawMetaObjectForType would not give us a QQmlMetaObject
1508 varType = QMetaType::fromType<QObject*>();
1509 val = QVariant(varType, nullptr);
1510 } else {
1511 varType = variantMetaType;
1512 }
1513 QQmlMetaObject valMo = rawMetaObjectForType(varType);
1514 if (valMo.isNull() || !varType.flags().testFlag(QMetaType::PointerToQObject))
1515 return false;
1516 QObject *o = *static_cast<QObject *const *>(val.constData());
1517 QQmlMetaObject propMo = rawMetaObjectForType(propertyMetaType);
1518
1519 if (o)
1520 valMo = o;
1521
1522 if (QQmlMetaObject::canConvert(valMo, propMo)) {
1523 return property.writeProperty(object, &o, flags);
1524 } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
1525 // In the case of a null QObject, we assign the null if there is
1526 // any change that the null variant type could be up or down cast to
1527 // the property type.
1528 return property.writeProperty(object, &o, flags);
1529 } else {
1530 return false;
1531 }
1533 object, property, value, flags, propertyMetaType, variantMetaType, isUrl)) {
1534 return result.couldWrite;
1535 } else if (propertyMetaType == QMetaType::fromType<QVariant>()) {
1536 return property.writeProperty(object, const_cast<QVariant *>(&value), flags);
1537 } else if (isUrl) {
1538 QUrl u;
1539 if (variantMetaType == QMetaType::fromType<QUrl>()) {
1540 u = value.toUrl();
1541 if (compatResolveUrlsOnAssigment() && context && u.isRelative() && !u.isEmpty())
1542 u = context->resolvedUrl(u);
1543 }
1544 else if (variantMetaType == QMetaType::fromType<QByteArray>())
1545 u = QUrl(QString::fromUtf8(value.toByteArray()));
1546 else if (variantMetaType == QMetaType::fromType<QString>())
1547 u = QUrl(value.toString());
1548 else
1549 return false;
1550
1551 return property.writeProperty(object, &u, flags);
1552 } else if (propertyMetaType == QMetaType::fromType<QList<QUrl>>()) {
1553 QList<QUrl> urlSeq = compatResolveUrlsOnAssigment()
1555 : urlSequence(value);
1556 return property.writeProperty(object, &urlSeq, flags);
1557 } else if (property.isQList()) {
1558 if (propertyMetaType.flags() & QMetaType::IsQmlList) {
1559 QMetaType listValueType = QQmlMetaType::listValueType(propertyMetaType);
1560 QQmlMetaObject valueMetaObject = QQmlMetaType::rawMetaObjectForType(listValueType);
1561 if (valueMetaObject.isNull())
1562 return false;
1563
1565 property.readProperty(object, &prop);
1566
1567 if (!prop.clear || !prop.append)
1568 return false;
1569
1570 const bool useNonsignalingListOps = prop.clear == &QQmlVMEMetaObject::list_clear
1572
1573 auto propClear =
1574 useNonsignalingListOps ? &QQmlVMEMetaObject::list_clear_nosignal : prop.clear;
1575 auto propAppend =
1576 useNonsignalingListOps ? &QQmlVMEMetaObject::list_append_nosignal : prop.append;
1577
1578 propClear(&prop);
1579
1580 const auto doAppend = [&](QObject *o) {
1581 if (o && !QQmlMetaObject::canConvert(o, valueMetaObject))
1582 o = nullptr;
1583 propAppend(&prop, o);
1584 };
1585
1586 if (variantMetaType == QMetaType::fromType<QQmlListReference>()) {
1588 for (qsizetype ii = 0; ii < qdlr.count(); ++ii)
1589 doAppend(qdlr.at(ii));
1590 } else if (variantMetaType == QMetaType::fromType<QList<QObject *>>()) {
1591 const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value);
1592 for (qsizetype ii = 0; ii < list.size(); ++ii)
1593 doAppend(list.at(ii));
1594 } else if (variantMetaType == QMetaType::fromType<QList<QVariant>>()) {
1595 const QList<QVariant> &list
1596 = *static_cast<const QList<QVariant> *>(value.constData());
1597 for (const QVariant &entry : list)
1598 doAppend(QQmlMetaType::toQObject(entry));
1599 } else if (!iterateQObjectContainer(variantMetaType, value.data(), doAppend)) {
1600 doAppend(QQmlMetaType::toQObject(value));
1601 }
1602 if (useNonsignalingListOps) {
1605 }
1606 } else if (variantMetaType == propertyMetaType) {
1607 QVariant v = value;
1608 property.writeProperty(object, v.data(), flags);
1609 } else {
1610 QVariant list(propertyMetaType);
1611 const QQmlType type = QQmlMetaType::qmlType(propertyMetaType);
1612 const QMetaSequence sequence = type.listMetaSequence();
1613 if (sequence.canAddValue())
1614 sequence.addValue(list.data(), value.data());
1615 property.writeProperty(object, list.data(), flags);
1616 }
1617 } else if (enginePriv && propertyMetaType == QMetaType::fromType<QJSValue>()) {
1618 // We can convert everything into a QJSValue if we have an engine.
1620 enginePriv->v4engine()->metaTypeToJS(variantMetaType, value.constData()));
1621 return property.writeProperty(object, &jsValue, flags);
1622 } else {
1623 Q_ASSERT(variantMetaType != propertyMetaType);
1624
1625 bool ok = false;
1626 QVariant v;
1627 if (variantMetaType == QMetaType::fromType<QString>())
1628 v = QQmlStringConverters::variantFromString(value.toString(), propertyMetaType, &ok);
1629
1630 if (!ok) {
1631 v = value;
1632 if (v.convert(propertyMetaType)) {
1633 ok = true;
1634 }
1635 }
1636 if (!ok) {
1637 // the only other options are that they are assigning a single value
1638 // or a QVariantList to a sequence type property (eg, an int to a
1639 // QList<int> property) or that we encountered an interface type.
1640 // Note that we've already handled single-value assignment to QList<QUrl> properties.
1641 QSequentialIterable iterable;
1642 v = QVariant(propertyMetaType);
1643 if (QMetaType::view(
1644 propertyMetaType, v.data(),
1645 QMetaType::fromType<QSequentialIterable>(),
1646 &iterable)) {
1647 const QMetaSequence propertyMetaSequence = iterable.metaContainer();
1648 if (propertyMetaSequence.canAddValueAtEnd()) {
1649 const QMetaType elementMetaType = iterable.valueMetaType();
1650 void *propertyContainer = iterable.mutableIterable();
1651
1652 if (variantMetaType == elementMetaType) {
1653 propertyMetaSequence.addValueAtEnd(propertyContainer, value.constData());
1654 ok = true;
1655 } else if (variantMetaType == QMetaType::fromType<QVariantList>()) {
1657 for (const QVariant &valueElement : list) {
1658 if (valueElement.metaType() == elementMetaType) {
1659 propertyMetaSequence.addValueAtEnd(
1660 propertyContainer, valueElement.constData());
1661 } else {
1662 QVariant converted(elementMetaType);
1664 valueElement.metaType(), valueElement.constData(),
1665 elementMetaType, converted.data());
1666 propertyMetaSequence.addValueAtEnd(
1667 propertyContainer, converted.constData());
1668 }
1669 }
1670 ok = true;
1671 } else if (elementMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1672 const QMetaObject *elementMetaObject = elementMetaType.metaObject();
1673 Q_ASSERT(elementMetaObject);
1674
1675 const auto doAppend = [&](QObject *o) {
1676 QObject *casted = elementMetaObject->cast(o);
1677 propertyMetaSequence.addValueAtEnd(propertyContainer, &casted);
1678 };
1679
1680 if (variantMetaType.flags().testFlag(QMetaType::PointerToQObject)) {
1681 doAppend(*static_cast<QObject *const *>(value.data()));
1682 ok = true;
1683 } else if (variantMetaType == QMetaType::fromType<QQmlListReference>()) {
1685 = static_cast<const QQmlListReference *>(value.constData());
1686 Q_ASSERT(elementMetaObject);
1687 for (int i = 0, end = reference->size(); i < end; ++i)
1688 doAppend(reference->at(i));
1689 ok = true;
1690 } else if (!iterateQObjectContainer(
1691 variantMetaType, value.data(), doAppend)) {
1692 doAppend(QQmlMetaType::toQObject(value));
1693 }
1694 } else {
1695 QVariant converted = value;
1696 if (converted.convert(elementMetaType)) {
1697 propertyMetaSequence.addValueAtEnd(propertyContainer, converted.constData());
1698 ok = true;
1699 }
1700 }
1701 }
1702 }
1703 }
1704
1705 if (!ok && QQmlMetaType::isInterface(propertyMetaType)) {
1706 auto valueAsQObject = qvariant_cast<QObject *>(value);
1707
1708 if (void *iface = valueAsQObject
1709 ? valueAsQObject->qt_metacast(QQmlMetaType::interfaceIId(propertyMetaType))
1710 : nullptr;
1711 iface) {
1712 // this case can occur when object has an interface type
1713 // and the variant contains a type implementing the interface
1714 return property.writeProperty(object, &iface, flags);
1715 }
1716 }
1717
1718 if (ok) {
1719 return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
1720 } else {
1721 return false;
1722 }
1723 }
1724
1725 return true;
1726}
1727
1729 QObject *object, const QQmlPropertyData &property,
1730 QQmlPropertyData::WriteFlags flags)
1731{
1732 const BindingFixer bindingFixer(object, property, flags);
1733 property.resetProperty(object, flags);
1734 return true;
1735}
1736
1738{
1739 if (metaType.flags() & QMetaType::PointerToQObject) {
1740 if (const QMetaObject *metaObject = metaType.metaObject())
1741 return metaObject;
1742 }
1743 return QQmlMetaType::rawMetaObjectForType(metaType);
1744}
1745
1752{
1753 return QQmlPropertyPrivate::write(*this, value, {});
1754}
1755
1768{
1769 QQmlProperty p(object, name);
1770 return p.write(value);
1771}
1772
1786 const QString &name,
1787 const QVariant &value,
1788 QQmlContext *ctxt)
1789{
1790 QQmlProperty p(object, name, ctxt);
1791 return p.write(value);
1792}
1793
1809{
1810 QQmlProperty p(object, name, engine);
1811 return p.write(value);
1812}
1813
1820{
1821 if (isResettable()) {
1822 void *args[] = { nullptr };
1824 return true;
1825 } else {
1826 return false;
1827 }
1828}
1829
1831 const QVariant &value, QQmlPropertyData::WriteFlags flags)
1832{
1833 if (!that.d)
1834 return false;
1835 if (that.d->object && that.type() & QQmlProperty::Property &&
1836 that.d->core.isValid() && that.isWritable())
1837 return that.d->writeValueProperty(value, flags);
1838 else
1839 return false;
1840}
1841
1846{
1847 if (type() & Property && d->object) {
1848 return d->object->metaObject()->property(d->core.coreIndex()).hasNotifySignal();
1849 }
1850 return false;
1851}
1852
1861{
1862 return type() & Property && !property().isConstant();
1863}
1864
1874{
1875 if (!(type() & Property) || !d->object)
1876 return false;
1877
1878 QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
1879 if (prop.hasNotifySignal()) {
1881 } else {
1882 return false;
1883 }
1884}
1885
1897bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
1898{
1899 if (!(type() & Property) || !d->object)
1900 return false;
1901
1902 QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
1903 if (prop.hasNotifySignal()) {
1905 return QObject::connect(d->object, signal.constData(), dest, slot);
1906 } else {
1907 return false;
1908 }
1909}
1910
1915{
1916 return d ? d->core.coreIndex() : -1;
1917}
1918
1920{
1921 return that.d ? that.d->encodedIndex() : QQmlPropertyIndex();
1922}
1923
1926 const QQmlPropertyData *valueTypeData,
1928{
1929 QQmlProperty prop;
1930
1931 prop.d = new QQmlPropertyPrivate;
1932 prop.d->object = object;
1933 prop.d->context = ctxt;
1934 prop.d->engine = ctxt ? ctxt->engine() : nullptr;
1935
1936 prop.d->core = data;
1937 if (valueTypeData)
1938 prop.d->valueTypeData = *valueTypeData;
1939
1940 return prop;
1941}
1942
1947{
1948 Q_ASSERT(mo);
1949 int methods = mo->methodCount();
1950 for (int ii = methods - 1; ii >= 2; --ii) { // >= 2 to block the destroyed signal
1951 QMetaMethod method = mo->method(ii);
1952
1953 if (method.name() == name && (method.methodType() & QMetaMethod::Signal))
1954 return method;
1955 }
1956
1957 // If no signal is found, but the signal is of the form "onBlahChanged",
1958 // return the notify signal for the property "Blah"
1959 if (name.endsWith("Changed")) {
1960 QByteArray propName = name.mid(0, name.size() - 7);
1961 int propIdx = mo->indexOfProperty(propName.constData());
1962 if (propIdx >= 0) {
1963 QMetaProperty prop = mo->property(propIdx);
1964 if (prop.hasNotifySignal())
1965 return prop.notifySignal();
1966 }
1967 }
1968
1969 return QMetaMethod();
1970}
1971
1976{
1977 Q_ASSERT(mo);
1978 const int i = mo->indexOfProperty(name);
1979 return i < 0 ? QMetaProperty() : mo->property(i);
1980}
1981
1987static inline void flush_vme_signal(const QObject *object, int index, bool indexInSignalRange)
1988{
1989 QQmlData *data = QQmlData::get(object);
1990 if (data && data->propertyCache) {
1991 const QQmlPropertyData *property = indexInSignalRange ? data->propertyCache->signal(index)
1992 : data->propertyCache->method(index);
1993
1994 if (property && property->isVMESignal()) {
1995 QQmlVMEMetaObject *vme;
1996 if (indexInSignalRange)
1997 vme = QQmlVMEMetaObject::getForSignal(const_cast<QObject *>(object), index);
1998 else
1999 vme = QQmlVMEMetaObject::getForMethod(const_cast<QObject *>(object), index);
2000 vme->connectAliasSignal(index, indexInSignalRange);
2001 }
2002 }
2003}
2004
2012bool QQmlPropertyPrivate::connect(const QObject *sender, int signal_index,
2013 const QObject *receiver, int method_index,
2014 int type, int *types)
2015{
2016 static const bool indexInSignalRange = false;
2017 flush_vme_signal(sender, signal_index, indexInSignalRange);
2018 flush_vme_signal(receiver, method_index, indexInSignalRange);
2019
2020 return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
2021}
2022
2027void QQmlPropertyPrivate::flushSignal(const QObject *sender, int signal_index)
2028{
2029 static const bool indexInSignalRange = true;
2030 flush_vme_signal(sender, signal_index, indexInSignalRange);
2031}
2032
2034
2035#include "moc_qqmlproperty.cpp"
static JNINativeMethod methods[]
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
\inmodule QtCore
Definition qchar.h:48
QChar toLower() const noexcept
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition qchar.h:448
constexpr bool isUpper() const noexcept
Returns true if the character is an uppercase letter, for example category() is Letter_Uppercase.
Definition qchar.h:475
QChar toUpper() const noexcept
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
Definition qchar.h:449
T * data() const noexcept
Returns a pointer to the shared data object.
const void * constIterable() const
Definition qiterable.h:465
void * mutableIterable()
Definition qiterable.h:466
Container metaContainer() const
Definition qiterable.h:504
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
Definition qjsvalue_p.h:189
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
T value(qsizetype i) const
Definition qlist.h:661
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
pointer data()
Definition qlist.h:414
void append(parameter_type t)
Definition qlist.h:441
void advanceConstIterator(void *iterator, qsizetype step) const
Advances the const iterator by step steps.
void * constEnd(const void *container) const
Creates and returns a const iterator pointing to the end of container.
bool compareConstIterator(const void *i, const void *j) const
Returns true if the const iterators i and j point to the same value in the container they are iterati...
void destroyConstIterator(const void *iterator) const
Destroys a const iterator previously created using \l constBegin() or \l constEnd().
void * constBegin(const void *container) const
Creates and returns a const iterator pointing to the beginning of container.
bool hasConstIterator() const
Returns true if the underlying container offers a const iterator, false otherwise.
\inmodule QtCore
int keysToValue(const char *keys, bool *ok=nullptr) const
Returns the value derived from combining together the values of the keys using the OR operator,...
int keyToValue(const char *key, bool *ok=nullptr) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
\inmodule QtCore
Definition qmetaobject.h:18
QByteArray methodSignature() const
\inmodule QtCore
const char * typeName() const
Returns the name of this property's type.
QMetaType metaType() const
QMetaMethod notifySignal() const
bool isWritable() const
Returns true if this property is writable; otherwise returns false.
bool isConstant() const
QMetaEnum enumerator() const
Returns the enumerator if this property's type is an enumerator type; otherwise the returned value is...
int notifySignalIndex() const
bool isEnumType() const
Returns true if the property's type is an enumeration value; otherwise returns false.
const char * name() const
Returns this property's name.
bool isValid() const
Returns true if this property is valid (readable); otherwise returns false.
bool isFlagType() const
Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns...
bool hasNotifySignal() const
Returns true if this property has a corresponding change notify signal; otherwise returns false.
\inmodule QtCore
bool canAddValueAtEnd() const
Returns true if values added using \l addValue() can be placed at the end of the container,...
void valueAtConstIterator(const void *iterator, void *result) const
Retrieves the value pointed to by the const iterator and stores it in the memory location pointed to ...
void addValueAtEnd(void *container, const void *value) const
Adds value to the end of container if possible.
void addValue(void *container, const void *value) const
Adds value to the container if possible.
bool canGetValueAtConstIterator() const
Returns true if the underlying container can retrieve the value pointed to by a const iterator,...
bool canAddValue() const
Returns true if values can be added to the container, false otherwise.
\inmodule QtCore
Definition qmetatype.h:320
static constexpr QMetaType fromType()
Definition qmetatype.h:2612
constexpr TypeFlags flags() const
Definition qmetatype.h:2628
static bool view(QMetaType fromType, void *from, QMetaType toType, void *to)
Creates a mutable view on the object at from of fromType in the preallocated space at to typed toType...
bool isValid() const
int id(int=0) const
Definition qmetatype.h:454
@ PointerToQObject
Definition qmetatype.h:385
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2633
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4187
static QPropertyBindingPrivate * get(const QUntypedPropertyBinding &binding)
QQmlPropertyIndex targetPropertyIndex() const
QQmlAbstractBinding * nextBinding() const
QObject * targetObject() const
virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f=QQmlPropertyData::DontRemoveBinding)=0
void addToObject()
Add this binding to object.
virtual Kind kind() const =0
void takeExpression(QQmlBoundSignalExpression *)
Sets the signal expression to e.
QQmlBoundSignalExpression * expression() const
Returns the signal expression.
QObject * idValue(int index) const
QQmlRefPointer< QQmlTypeNameCache > imports() const
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
QUrl resolvedUrl(const QUrl &) const
QQmlRefPointer< QQmlContextData > parent() const
QQmlEngine * engine() const
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
QQmlEngine * engine() const
Return the context's QQmlEngine, or \nullptr if the context has no QQmlEngine or the QQmlEngine was d...
QQmlPropertyCache::ConstPtr propertyCache
Definition qqmldata_p.h:195
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
static QQmlEnginePrivate * get(QQmlEngine *e)
QV4::ExecutionEngine * v4engine() const
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QQmlContext * rootContext() const
Returns the engine's root context.
static QQmlGadgetPtrWrapper * instance(QQmlEngine *engine, QMetaType type)
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
ClearFunction clear
Definition qqmllist.h:87
AppendFunction append
Definition qqmllist.h:84
static QQmlListReference init(const QQmlListProperty< QObject > &, QMetaType)
Definition qqmllist.cpp:25
The QQmlListReference class allows the manipulation of QQmlListProperty properties.
Definition qqmllist.h:183
qsizetype count() const
Returns the number of objects in the list, or 0 if the operation failed.
Definition qqmllist.cpp:367
QObject * at(qsizetype) const
Returns the list element at index, or 0 if the operation failed.
Definition qqmllist.cpp:343
bool isNull() const
static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to)
static QMetaType listValueType(QMetaType type)
static const char * interfaceIId(QMetaType type)
static const QMetaObject * metaObjectForValueType(QMetaType type)
static QObject * toQObject(const QVariant &, bool *ok=nullptr)
static bool isInterface(QMetaType type)
See qmlRegisterInterface() for information about when this will return true.
static QQmlMetaObject rawMetaObjectForType(QMetaType metaType)
static QQmlValueType * valueType(QMetaType metaType)
static QMetaProperty defaultProperty(const QMetaObject *)
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
static bool isValueType(QMetaType type)
const QQmlPropertyData * property(const K &key, QObject *object, const QQmlRefPointer< QQmlContextData > &context) const
void readProperty(QObject *target, void *property) const
bool isResettable() const
void readPropertyWithArgs(QObject *target, void *args[]) const
QMetaType propType() const
void setCoreIndex(int idx)
void setPropType(QMetaType pt)
static Flags flagsForProperty(const QMetaProperty &)
void load(const QMetaProperty &)
QString name(QObject *) const
bool hasValueTypeIndex() const
static QQmlBoundSignalExpression * signalExpression(const QQmlProperty &that)
Returns the expression associated with this signal property, or 0 if no signal expression exists.
static void takeSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *)
Set the signal expression associated with this signal property to expr.
static bool resolveUrlsOnAssignment()
QMetaType propertyType() const
QQmlPropertyData core
static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags=None, QQmlPropertyData::WriteFlags writeFlags=QQmlPropertyData::DontRemoveBinding)
static void findAliasTarget(QObject *, QQmlPropertyIndex, QObject **, QQmlPropertyIndex *)
static QQmlMetaObject rawMetaObjectForType(QMetaType metaType)
static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *, const QQmlRefPointer< QQmlContextData > &)
QQmlProperty::PropertyTypeCategory propertyTypeCategory() const
static QQmlProperty create(QObject *target, const QString &propertyName, const QQmlRefPointer< QQmlContextData > &context, QQmlPropertyPrivate::InitFlags flags)
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
QQmlPropertyIndex encodedIndex() const
static void removeBinding(const QQmlProperty &that)
static bool write(QObject *, const QQmlPropertyData &, const QVariant &, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
static QQmlPropertyIndex propertyIndex(const QQmlProperty &that)
static bool reset(QObject *, const QQmlPropertyData &, QQmlPropertyData::WriteFlags flags={})
static QMetaProperty findPropertyByName(const QMetaObject *mo, const QByteArray &)
Return the property corresponding to name.
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Connect sender signal_index to receiver method_index with the specified type and types.
QQmlProperty::Type type() const
static void setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *)
Set the signal expression associated with this signal property to expr.
QQmlPropertyData valueTypeData
static QQmlPropertyPrivate * get(const QQmlProperty &p)
static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &)
Return the signal corresponding to name.
void initDefault(QObject *obj)
Initialize from the default property of obj.
static void flushSignal(const QObject *sender, int signal_index)
QQmlRefPointer< QQmlContextData > effectiveContext() const
static QQmlAbstractBinding * binding(QObject *, QQmlPropertyIndex index)
static QList< QUrl > urlSequence(const QVariant &value)
bool writeValueProperty(const QVariant &, QQmlPropertyData::WriteFlags)
void initProperty(QObject *obj, const QString &name, InitFlags flags=InitFlag::None)
QQmlRefPointer< QQmlContextData > context
static bool resetValueProperty(QObject *, const QQmlPropertyData &, const QQmlPropertyData &valueTypeData, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
QPointer< QQmlEngine > engine
QPointer< QObject > object
bool isValueType() const
The QQmlProperty class abstracts accessing properties on objects created from QML.
bool isDesignable() const
Returns true if the property is designable, otherwise false.
bool isBindable() const
QMetaType propertyMetaType() const
Returns the metatype of the property.
bool isValid() const
Returns true if the QQmlProperty refers to a valid property, otherwise false.
QMetaMethod method() const
Return the QMetaMethod for this property if it is a SignalProperty, otherwise returns an invalid QMet...
bool hasNotifySignal() const
Returns true if the property has a change notifier signal, otherwise false.
const char * propertyTypeName() const
Returns the type name of the property, or 0 if the property has no type name.
PropertyTypeCategory propertyTypeCategory() const
Returns the property category.
int index() const
Return the Qt metaobject index of the property.
QQmlProperty & operator=(const QQmlProperty &)
Assign other to this QQmlProperty.
QVariant read() const
Returns the property value.
bool operator==(const QQmlProperty &) const
Returns true if other and this QQmlProperty represent the same property.
QQmlProperty()
Create an invalid QQmlProperty.
bool isProperty() const
Returns true if this QQmlProperty represents a regular Qt property.
Type
This enum specifies a type of QML property.
Type type() const
Returns the type of the property.
QMetaProperty property() const
Returns the \l{QMetaProperty} {Qt property} associated with this QML property.
PropertyTypeCategory
This enum specifies a category of QML property.
QML_ANONYMOUSQObject * object
bool write(const QVariant &) const
Sets the property value to value.
bool needsNotifySignal() const
Returns true if the property needs a change notifier signal for bindings to remain upto date,...
bool isSignalProperty() const
Returns true if this QQmlProperty represents a QML signal property.
bool isWritable() const
Returns true if the property is writable, otherwise false.
bool connectNotifySignal(QObject *dest, const char *slot) const
Connects the property's change notifier signal to the specified slot of the dest object and returns t...
bool isResettable() const
Returns true if the property is resettable, otherwise false.
int propertyType() const
Returns the metatype id of the property, or QMetaType::UnknownType if the property has no metatype.
bool reset() const
Resets the property and returns true if the property is resettable.
void addref() const
void release() const
void reset(T *t=nullptr)
static void list_append(QQmlListProperty< QObject > *prop, QObject *o)
static void list_clear_nosignal(QQmlListProperty< QObject > *prop)
static QQmlVMEMetaObject * getForSignal(QObject *o, int coreIndex)
static void list_clear(QQmlListProperty< QObject > *prop)
static void list_append_nosignal(QQmlListProperty< QObject > *prop, QObject *o)
static QQmlVMEMetaObject * get(QObject *o)
static QQmlVMEMetaObject * getForProperty(QObject *o, int coreIndex)
static QQmlVMEMetaObject * getForMethod(QObject *o, int coreIndex)
void connectAliasSignal(int index, bool indexInSignalRange)
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
static QVariant createValueType(const QJSValue &, QMetaType)
The QSequentialIterable class is an iterable interface for a container in a QVariant.
QMetaType valueMetaType() const
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
constexpr QStringView first(qsizetype n) const noexcept
QByteArray toUtf8() const
Returns a UTF-8 representation of the string view as a QByteArray.
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:7987
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1014
constexpr QStringView last(qsizetype n) const noexcept
constexpr QChar at(qsizetype n) const noexcept
Returns the character at position n in this string view.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QByteArray toUtf8() const &
Definition qstring.h:563
\inmodule QtCore
Definition qproperty.h:677
QUntypedPropertyBinding binding() const
Returns the underlying property's binding if there is any, or a default constructed QUntypedPropertyB...
Definition qproperty.h:755
bool isNull() const
Returns true if the QUntypedPropertyBinding is null.
\inmodule QtCore
Definition qurl.h:94
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition qurl.cpp:2797
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
\inmodule QtCore
Definition qvariant.h:64
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
bool convert(QMetaType type)
Casts the variant to the requested type, targetType.
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
const char * typeName() const
Returns the name of the type stored in the variant.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
const void * constData() const
Definition qvariant.h:446
static void writeFlags(QTextStream &stream, const Provider &provider)
Definition ctf.cpp:269
qSwap(pi, e)
QSet< QString >::iterator it
auto signal
auto mo
[7]
Q_QML_PRIVATE_EXPORT QVariant variantFromString(const QString &, QMetaType preferredType, bool *ok=nullptr)
Combined button and popup list for selecting options.
@ DirectConnection
static void * context
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
static const QMetaObjectPrivate * priv(const uint *data)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLfloat GLfloat f
GLint reference
GLenum type
GLenum target
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLuint bindingIndex
GLhandleARB obj
[2]
GLboolean reset
GLenum func
Definition qopenglext.h:663
const GLubyte * c
GLuint GLfloat * val
GLuint entry
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
QObject * qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc func, bool create)
Definition qqml.cpp:110
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
QQmlPrivate::QQmlAttachedPropertiesFunc< QObject > QQmlAttachedPropertiesFunc
Definition qqmlprivate.h:62
bool changeThroughGadgetPtrWrapper(QObject *object, const QQmlPropertyData &core, const QQmlRefPointer< QQmlContextData > &context, QQmlPropertyData::WriteFlags flags, int internalIndex, Op op)
static ConvertAndAssignResult tryConvertAndAssign(QObject *object, const QQmlPropertyData &property, const QVariant &value, QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType, bool isUrl)
static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPropertyPrivate::BindingFlags flags=QQmlPropertyPrivate::None)
static void flush_vme_signal(const QObject *object, int index, bool indexInSignalRange)
static void removeValuePropertyBinding(QObject *object, const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData, QQmlPropertyData::WriteFlags flags)
bool changePropertyAndWriteBack(QObject *object, int coreIndex, QQmlGadgetPtrWrapper *wrapper, QQmlPropertyData::WriteFlags flags, int internalIndex, Op op)
bool iterateQObjectContainer(QMetaType metaType, const void *data, Op op)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
obj metaObject() -> className()
QSharedPointer< T > other(t)
[5]
QJSValueList args
QJSEngine engine
[0]
Q_DISABLE_COPY_MOVE(BindingFixer)
BindingFixer(QObject *object, const QQmlPropertyData &property, QQmlPropertyData::WriteFlags flags)
\inmodule QtCore \reentrant
Definition qchar.h:17
static Q_CORE_EXPORT int signalIndex(const QMetaMethod &m)
\inmodule QtCore
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.
static int metacall(QObject *, Call, int, void **)
QObject * cast(QObject *obj) const
static Connection connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Definition qobject.cpp:3419
int indexOfProperty(const char *name) const
Finds property name and returns its index; otherwise returns -1.
QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data)
static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
static bool isSignalPropertyName(const QString &name)
void wrapper()