--- a/qpy/QtQml/qpyqml_register_type.cpp 2017-02-23 03:32:51.000000000 +0100 +++ b/qpy/QtQml/qpyqml_register_type.cpp 2017-02-25 03:32:58.000000000 +0100 @@ -124,13 +124,13 @@ #define QPYQML_TYPE_INIT(n) \ case n##U: \ - QPyQmlObject##n::staticMetaObject = *mo; \ + QPyQmlObject##n::staticMetaObject = static_mo; \ QPyQmlObject##n::attachedPyType = attached; \ rt->typeId = qRegisterNormalizedMetaType(ptr_name); \ rt->listId = qRegisterNormalizedMetaType >(list_name); \ rt->objectSize = ctor ? sizeof(QPyQmlObject##n) : 0; \ if (ctor) rt->create = QQmlPrivate::createInto; else rt->create = 0; \ - rt->metaObject = mo; \ + rt->metaObject = &QPyQmlObject##n::staticMetaObject; \ rt->attachedPropertiesFunction = attached_mo ? QPyQmlObject##n::attachedProperties : 0; \ rt->attachedPropertiesMetaObject = attached_mo; \ rt->parserStatusCast = is_parser_status ? QQmlPrivate::StaticCastSelector::cast() : -1; \ @@ -219,7 +219,33 @@ return 0; } - const QMetaObject *mo = pyqt5_qtqml_get_qmetaobject(py_type); + const QMetaObject *orig_mo = pyqt5_qtqml_get_qmetaobject(py_type); + QMetaObject static_mo = *orig_mo; + +#if QT_VERSION >= 0x050800 + // Qt v5.8.0 changed the way properties are handled by directly calling a + // class's static meta-call (if there was one) directly. This bypasses the + // proxy and calls the static meta-call with a pointer to the proxy rather + // than a pointer to the real object. To work round this we clone the + // QMetaObject chain and remove the references to the static meta-call + // forcing the earlier behaviour. This approach may also work with earlier + // versions of Qt - but if it ain't broke... + static_mo.d.static_metacall = 0; + + QMetaObject *sub_mo = &static_mo; + + // By retaining the QObject static meta-object we don't appear to be a + // gadget. + for (const QMetaObject *mo = sub_mo->d.superdata; mo != &QObject::staticMetaObject; mo = mo->d.superdata) + { + QMetaObject *new_mo = new QMetaObject; + *new_mo = *mo; + new_mo->d.static_metacall = 0; + + sub_mo->d.superdata = new_mo; + sub_mo = new_mo; + } +#endif // See if the type is a parser status. bool is_parser_status = PyType_IsSubtype(py_type, @@ -272,7 +298,7 @@ if (qquickitem_register) { - sipErrorState estate = qquickitem_register(py_type, mo, ptr_name, + sipErrorState estate = qquickitem_register(py_type, orig_mo, ptr_name, list_name, &rt); if (estate == sipErrorFail)