From a47540de944b4ca4a334a557d4ad4840b7e98510 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Fri, 7 Mar 2025 10:02:20 +0000 Subject: [PATCH] Add qobject extension trait - cxx-qt-lib trait for additional qobject wrappers - adds blockSignals - adds signalsBlocked - adds setObjectName - adds objectName - adds parent - adds setParent --- crates/cxx-qt-lib/build.rs | 1 + crates/cxx-qt-lib/include/core/qobject.h | 9 ++ crates/cxx-qt-lib/src/core/mod.rs | 3 + crates/cxx-qt-lib/src/core/qobject.rs | 100 +++++++++++++++++++++++ crates/cxx-qt-lib/src/core/qstring.rs | 2 +- crates/cxx-qt/src/qobject.rs | 8 +- 6 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 crates/cxx-qt-lib/include/core/qobject.h create mode 100644 crates/cxx-qt-lib/src/core/qobject.rs diff --git a/crates/cxx-qt-lib/build.rs b/crates/cxx-qt-lib/build.rs index 99932b43c..e132c51fc 100644 --- a/crates/cxx-qt-lib/build.rs +++ b/crates/cxx-qt-lib/build.rs @@ -150,6 +150,7 @@ fn main() { "core/qmargins", "core/qmarginsf", "core/qmodelindex", + "core/qobject", "core/qpersistentmodelindex", "core/qpoint", "core/qpointf", diff --git a/crates/cxx-qt-lib/include/core/qobject.h b/crates/cxx-qt-lib/include/core/qobject.h new file mode 100644 index 000000000..5cc0867c6 --- /dev/null +++ b/crates/cxx-qt-lib/include/core/qobject.h @@ -0,0 +1,9 @@ +// clang-format off +// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company +// clang-format on +// SPDX-FileContributor: Ben Ford +// +// SPDX-License-Identifier: MIT OR Apache-2.0 +#pragma once + +#include \ No newline at end of file diff --git a/crates/cxx-qt-lib/src/core/mod.rs b/crates/cxx-qt-lib/src/core/mod.rs index 51e9acb5d..cd5b08753 100644 --- a/crates/cxx-qt-lib/src/core/mod.rs +++ b/crates/cxx-qt-lib/src/core/mod.rs @@ -47,6 +47,9 @@ pub use cxx_qt::{QMetaObjectConnection, QMetaObjectConnectionGuard}; mod qmodelindex; pub use qmodelindex::QModelIndex; +mod qobject; +pub use qobject::QObjectExt; + mod qpersistentmodelindex; pub use qpersistentmodelindex::QPersistentModelIndex; diff --git a/crates/cxx-qt-lib/src/core/qobject.rs b/crates/cxx-qt-lib/src/core/qobject.rs new file mode 100644 index 000000000..0f818865d --- /dev/null +++ b/crates/cxx-qt-lib/src/core/qobject.rs @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company +// SPDX-FileContributor: Ben Ford +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +pub use cxx_qt::QObject; +use std::pin::Pin; + +#[cxx::bridge] +pub mod ffi { + unsafe extern "C++" { + include!("cxx-qt-lib/qstring.h"); + type QString = crate::QString; + } + + unsafe extern "C++" { + include!("cxx-qt-lib/qobject.h"); + #[rust_name = "QObjectExternal"] + type QObject; + #[rust_name = "block_signals"] + pub fn blockSignals(self: Pin<&mut Self>, block: bool) -> bool; + + #[rust_name = "signals_blocked"] + pub fn signalsBlocked(&self) -> bool; + + #[rust_name = "set_object_name"] + pub fn setObjectName(self: Pin<&mut Self>, name: &QString); + + #[rust_name = "object_name"] + pub fn objectName(&self) -> QString; + + pub fn parent(&self) -> *mut QObjectExternal; + + #[rust_name = "set_parent"] + pub unsafe fn setParent(self: Pin<&mut Self>, parent: *mut QObjectExternal); + } +} + +use ffi::{QObjectExternal, QString}; + +/// Trait which exposes methods available on a `QObject`. +/// Exposes some basic signals and methods for now, more to be added. +pub trait QObjectExt { + fn block_signals(self: Pin<&mut Self>, block: bool) -> bool; + + fn signals_blocked(&self) -> bool; + + fn set_object_name(self: Pin<&mut Self>, name: &QString); + + fn object_name(&self) -> QString; + + fn parent(&self) -> *mut Self; + + fn set_parent(self: Pin<&mut Self>, parent: &Self); +} + +/// Used to convert the QObject type from the library type to the C++ type, as a pin +fn cast_pin(obj: Pin<&mut QObject>) -> Pin<&mut QObjectExternal> { + unsafe { + let mut_ptr = obj.get_unchecked_mut() as *mut QObject as *mut QObjectExternal; + Pin::new_unchecked(&mut *mut_ptr) + } +} + +/// Used to convert the QObject type from the library type to the C++ type +fn cast(obj: &QObject) -> &QObjectExternal { + unsafe { + let ptr = obj as *const QObject as *const QObjectExternal; + &*ptr + } +} + +impl QObjectExt for QObject { + fn block_signals(self: Pin<&mut Self>, block: bool) -> bool { + cast_pin(self).block_signals(block) + } + + fn signals_blocked(&self) -> bool { + cast(self).signals_blocked() + } + + fn set_object_name(self: Pin<&mut Self>, name: &QString) { + cast_pin(self).set_object_name(name) + } + + fn object_name(&self) -> QString { + cast(self).object_name() + } + + fn parent(&self) -> *mut Self { + cast(self).parent() as *mut Self + } + + fn set_parent(self: Pin<&mut Self>, parent: &Self) { + unsafe { + cast_pin(self) + .set_parent(cast(parent) as *const QObjectExternal as *mut QObjectExternal); + } + } +} diff --git a/crates/cxx-qt-lib/src/core/qstring.rs b/crates/cxx-qt-lib/src/core/qstring.rs index 9bcff0100..8b0fc47f4 100644 --- a/crates/cxx-qt-lib/src/core/qstring.rs +++ b/crates/cxx-qt-lib/src/core/qstring.rs @@ -434,7 +434,7 @@ impl<'de> serde::Deserialize<'de> for QString { struct StringVisitor; - impl<'de> Visitor<'de> for StringVisitor { + impl Visitor<'_> for StringVisitor { type Value = QString; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { diff --git a/crates/cxx-qt/src/qobject.rs b/crates/cxx-qt/src/qobject.rs index a1e0b6610..f1f02edf9 100644 --- a/crates/cxx-qt/src/qobject.rs +++ b/crates/cxx-qt/src/qobject.rs @@ -8,13 +8,15 @@ #[cxx::bridge] mod ffi { unsafe extern "C++" { - // TODO! Implement QObject wrapper properly include!(); - /// QObject type + /// QObject type. + /// + /// Most methods available on this type are within the [cxx_qt_lib::core::QObjectExt] trait, + /// which needs to be imported in order to access these. type QObject; #[cxx_name = "dumpObjectInfo"] - /// Dump Object info method, added so that upcast methods can be tested. + /// Dump information about this QObjects name and signals fn dump_object_info(&self); } }