Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add qml_register_uncreatable_type #227

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 85 additions & 6 deletions qmetaobject/src/qtdeclarative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@ impl QmlComponent {
}
}

/// Register the given type as a QML type
/// Wrapper around [`template <typename T> 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<T: QObject + Default + Sized>(
uri: &CStr,
version_major: u32,
Expand Down Expand Up @@ -502,16 +502,95 @@ pub fn qml_register_type<T: QObject + Default + Sized>(
})
}

/// Wrapper around [`void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)`][qt] function.
ratijas marked this conversation as resolved.
Show resolved Hide resolved
/// Wrapper around [`template <typename T> 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<T: QObject + Sized>(
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 = <RefCell<T> 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<char,64> 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 *",
Expand Down
56 changes: 53 additions & 3 deletions qmetaobject/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
),
Expand All @@ -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
ratijas marked this conversation as resolved.
Show resolved Hide resolved
}
),
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::<RegisteredObjWithNoDefault>(
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;
}
}
"
Expand Down