From 55647b9920177521fa034489050e3286825c3be4 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Sun, 8 Dec 2024 10:36:52 -0500 Subject: [PATCH] cxx-qt-lib: Add binding for QQmlApplicationEngine::singletonInstance This allows accessing QObject singleton instances registered in the QML engine (using #[qml_singleton]) from the Rust side. --- CHANGELOG.md | 1 + .../include/qml/qqmlapplicationengine.h | 7 ++++ .../src/qml/qqmlapplicationengine.cpp | 11 +++++ .../src/qml/qqmlapplicationengine.rs | 40 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c066438..a7df86375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - QObject subclasses can now inherit from other CXX-Qt generated QObject classes - `BUILD_WASM` CMake option to support WebAssembly builds and a book page for building for WASM - Add support for cxx_name and rust_name on qproperty attributes which applies to the QProperty generated as well as functions +- Add binding for `singletonInstance` of `QQmlApplicationEngine`, allowing access to singleton instances registered in the QML engine. ### Changed diff --git a/crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h b/crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h index cf561a4d4..826432f26 100644 --- a/crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h +++ b/crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h @@ -22,6 +22,13 @@ qqmlapplicationengineNew(); QQmlEngine& qqmlapplicationengineAsQQmlEngine(QQmlApplicationEngine&); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) +void* +qqmlapplicationengineSingletonInstance(QQmlApplicationEngine& engine, + QAnyStringView uri, + QAnyStringView typeName); +#endif + } } diff --git a/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.cpp b/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.cpp index 1e858de98..880242344 100644 --- a/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.cpp +++ b/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.cpp @@ -22,5 +22,16 @@ qqmlapplicationengineAsQQmlEngine(QQmlApplicationEngine& engine) return static_cast(engine); } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) +void* +qqmlapplicationengineSingletonInstance(QQmlApplicationEngine& engine, + QAnyStringView uri, + QAnyStringView typeName) +{ + return reinterpret_cast( + engine.singletonInstance(uri, typeName)); +} +#endif + } } diff --git a/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.rs b/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.rs index 9e7b848a2..f4cdd0e50 100644 --- a/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.rs +++ b/crates/cxx-qt-lib/src/qml/qqmlapplicationengine.rs @@ -68,6 +68,9 @@ mod ffi { #[namespace = "rust::cxxqtlib1"] unsafe extern "C++" { + include!("cxx-qt-lib/common.h"); + type c_void = crate::c_void; + #[doc(hidden)] #[rust_name = "qqmlapplicationengine_new"] fn qqmlapplicationengineNew() -> UniquePtr; @@ -79,6 +82,24 @@ mod ffi { ) -> Pin<&mut QQmlEngine>; } + #[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))] + unsafe extern "C++" { + include!("cxx-qt-lib/qanystringview.h"); + type QAnyStringView<'a> = crate::QAnyStringView<'a>; + } + + #[namespace = "rust::cxxqtlib1"] + #[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))] + unsafe extern "C++" { + #[doc(hidden)] + #[rust_name = "qqmlapplicationengine_singleton_instance"] + fn qqmlapplicationengineSingletonInstance( + ptr: Pin<&mut QQmlApplicationEngine>, + uri: QAnyStringView, + typeName: QAnyStringView, + ) -> *mut c_void; + } + // QQmlApplicationEngine is not a trivial to CXX and is not relocatable in Qt // as the following fails in C++. So we cannot mark it as a trivial type // and need to use references or pointers. @@ -86,6 +107,8 @@ mod ffi { impl UniquePtr {} } +#[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))] +use crate::QAnyStringView; use crate::QQmlEngine; use core::pin::Pin; @@ -101,4 +124,21 @@ impl QQmlApplicationEngine { pub fn new() -> cxx::UniquePtr { ffi::qqmlapplicationengine_new() } + + /// Returns the instance of a singleton type named typeName from the module specified by uri. + /// This function was introduced in Qt 6.5. + #[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))] + pub fn singleton_instance( + self: Pin<&mut Self>, + uri: QAnyStringView, + type_name: QAnyStringView, + ) -> Option<&mut T> { + unsafe { + let ptr = ffi::qqmlapplicationengine_singleton_instance(self, uri, type_name); + if ptr.is_null() { + return None; + } + Some(&mut *(ptr as *mut T)) + } + } }