diff --git a/qmetaobject/src/qtdeclarative.rs b/qmetaobject/src/qtdeclarative.rs index 55605b40..02486d0d 100644 --- a/qmetaobject/src/qtdeclarative.rs +++ b/qmetaobject/src/qtdeclarative.rs @@ -397,9 +397,9 @@ impl QmlComponent { } } -/// Register the given type as a QML type +/// Wrapper around [`template int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)`][qt] function. /// -/// Refer to the Qt documentation for qmlRegisterType. +/// [qt]: https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterType pub fn qml_register_type( uri: &CStr, version_major: u32, @@ -502,16 +502,95 @@ pub fn qml_register_type( }) } -/// Wrapper around [`void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)`][qt] function. +/// Wrapper around [`template int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &message)`][qt] function. /// -/// [qt]: https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterModule -#[cfg(qt_5_9)] -pub fn qml_register_module( +/// [qt]: https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableType +pub fn qml_register_uncreatable_type( uri: &CStr, version_major: u32, version_minor: u32, + qml_name: &CStr, + no_creation_reason: QString, ) { let uri_ptr = uri.as_ptr(); + let qml_name_ptr = qml_name.as_ptr(); + let meta_object = T::static_meta_object(); + + let size = T::cpp_size(); + + let type_id = as PropertyType>::register_type(Default::default()); + + cpp!(unsafe [ + qml_name_ptr as "char *", + uri_ptr as "char *", + version_major as "int", + version_minor as "int", + meta_object as "const QMetaObject *", + size as "size_t", + type_id as "int", + no_creation_reason as "QString" + ] { + // BEGIN: From QML_GETTYPENAMES + // FIXME: list type? + /*const int listLen = int(strlen("QQmlListProperty<")); + QVarLengthArray listName(listLen + nameLen + 2); + memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); + memcpy(listName.data()+listLen, className, size_t(nameLen)); + listName[listLen+nameLen] = '>'; + listName[listLen+nameLen+1] = '\0';*/ + // END + + QQmlPrivate::RegisterType api = { + /*version*/ 0, + + #if QT_VERSION < QT_VERSION_CHECK(6,0,0) + /*typeId*/ type_id, + #else + /*typeId*/ QMetaType(type_id), + #endif + /*listId*/ {}, // FIXME: list type? + /*objectSize*/ int(size), + /*create*/ nullptr, + #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + /* userdata */ nullptr, + #endif + /*noCreationReason*/ no_creation_reason, + #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + /* createValueType */ nullptr, + #endif + + /*uri*/ uri_ptr, + #if QT_VERSION < QT_VERSION_CHECK(6,0,0) + /*versionMajor*/ version_major, + /*versionMinor*/ version_minor, + #else + /*version*/ QTypeRevision::fromVersion(version_major, version_minor), + #endif + /*elementName*/ qml_name_ptr, + /*metaObject*/ meta_object, + + /*attachedPropertiesFunction*/ nullptr, + /*attachedPropertiesMetaObject*/ nullptr, + + /*parserStatusCast*/ -1, + /*valueSourceCast*/ -1, + /*valueInterceptorCast*/ -1, + + /*extensionObjectCreate*/ nullptr, + /*extensionMetaObject*/ nullptr, + /*customParser*/ nullptr, + /*revision*/ {} // FIXME: support revisions? + }; + QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &api); + }) +} + +/// Wrapper around [`void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)`][qt] function. +/// +/// [qt]: https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterModule +#[cfg(qt_5_9)] +pub fn qml_register_module(uri: &CStr, version_major: u32, version_minor: u32) { + let uri_ptr = uri.as_ptr(); cpp!(unsafe [ uri_ptr as "const char *", diff --git a/qmetaobject/tests/tests.rs b/qmetaobject/tests/tests.rs index 359170b9..80e48147 100644 --- a/qmetaobject/tests/tests.rs +++ b/qmetaobject/tests/tests.rs @@ -176,8 +176,8 @@ fn call_method() { struct RegisteredObj { base: qt_base_class!(trait QObject), value: qt_property!(u32), - square: qt_method!( - fn square(&self, v: u32) -> u32 { + multiply_values: qt_method!( + fn multiply_values(&self, v: u32) -> u32 { self.value * v } ), @@ -204,7 +204,57 @@ fn register_type() { value: 55 } function doTest() { - return test.square(66) === 55 * 66; + return test.multiply_values(66) === 55 * 66; + } + } + " + )); +} + +#[derive(QObject)] +struct RegisteredObjWithNoDefault { + base: qt_base_class!(trait QObject), + value: qt_property!(u32), + multiply_values: qt_method!( + fn multiply_values(&self, v: u32) -> u32 { + self.value * self.internal_value * v + } + ), + internal_value: u32, +} + +impl RegisteredObjWithNoDefault { + fn new(internal_value: u32) -> RegisteredObjWithNoDefault { + RegisteredObjWithNoDefault { + internal_value, + base: Default::default(), + value: Default::default(), + multiply_values: Default::default(), + } + } +} + +#[test] +fn register_uncreatable_type() { + qml_register_uncreatable_type::( + CStr::from_bytes_with_nul(b"TestRegisterUncreatable\0").unwrap(), + 1, + 0, + CStr::from_bytes_with_nul(b"RegisteredObjUncreatable\0").unwrap(), + QString::from("Type has no default"), + ); + + let mut obj = RegisteredObjWithNoDefault::new(44); + obj.value = 55; + + assert!(do_test( + obj, + r" + import TestRegister 1.0 + + Item { + function doTest() { + return _obj.multiply_values(66) === 44 * 55 * 66; } } "