Skip to content

Commit

Permalink
cxx-qt-lib: Add binding for QQmlApplicationEngine::singletonInstance
Browse files Browse the repository at this point in the history
This allows accessing QObject singleton instances registered in the QML
engine (using #[qml_singleton]) from the Rust side.
  • Loading branch information
redstrate committed Dec 31, 2024
1 parent f5afefe commit 892f14f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/KDAB/cxx-qt/compare/v0.7.0...HEAD)

### Added

- Add binding for `singletonInstance` of `QQmlApplicationEngine`, allowing access to singleton instances registered in the QML engine.

### Fixed

- Build warnings due to unused unsafe blocks since CXX 1.0.130
Expand Down
7 changes: 7 additions & 0 deletions crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
}

Expand Down
11 changes: 11 additions & 0 deletions crates/cxx-qt-lib/src/qml/qqmlapplicationengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,16 @@ qqmlapplicationengineAsQQmlEngine(QQmlApplicationEngine& engine)
return static_cast<QQmlEngine&>(engine);
}

#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
void*
qqmlapplicationengineSingletonInstance(QQmlApplicationEngine& engine,
QAnyStringView uri,
QAnyStringView typeName)
{
return reinterpret_cast<void*>(
engine.singletonInstance<QObject*>(uri, typeName));
}
#endif

}
}
39 changes: 39 additions & 0 deletions crates/cxx-qt-lib/src/qml/qqmlapplicationengine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<QQmlApplicationEngine>;
Expand All @@ -79,13 +82,33 @@ 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"]
unsafe extern "C++" {
#[doc(hidden)]
#[rust_name = "qqmlapplicationengine_singleton_instance"]
#[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))]
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.
// static_assert(QTypeInfo<QQmlApplicationEngine>::isRelocatable);
impl UniquePtr<QQmlApplicationEngine> {}
}

#[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;

Expand All @@ -101,4 +124,20 @@ impl QQmlApplicationEngine {
pub fn new() -> cxx::UniquePtr<Self> {
ffi::qqmlapplicationengine_new()
}

/// Returns the instance of a singleton type named typeName from the module specified by uri.
/// This is inherently unsafe as it does not perform any type checks.
/// This function was introduced in Qt 6.5.
#[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))]
pub unsafe fn singleton_instance<'a, T>(
self: Pin<&'a mut Self>,
uri: QAnyStringView,
type_name: QAnyStringView,
) -> Option<Pin<&'a mut T>> {
let ptr = ffi::qqmlapplicationengine_singleton_instance(self, uri, type_name);
if ptr.is_null() {
return None;
}
Some(Pin::new_unchecked(&mut *(ptr as *mut T)))
}
}

0 comments on commit 892f14f

Please sign in to comment.