Skip to content

Add qobject extension trait #1226

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

Open
wants to merge 1 commit into
base: main
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
1 change: 1 addition & 0 deletions crates/cxx-qt-lib/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ fn main() {
"core/qmargins",
"core/qmarginsf",
"core/qmodelindex",
"core/qobject",
"core/qpersistentmodelindex",
"core/qpoint",
"core/qpointf",
Expand Down
9 changes: 9 additions & 0 deletions crates/cxx-qt-lib/include/core/qobject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// clang-format off
// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Ben Ford <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <QtCore/QObject>
3 changes: 3 additions & 0 deletions crates/cxx-qt-lib/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
100 changes: 100 additions & 0 deletions crates/cxx-qt-lib/src/core/qobject.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// SPDX-FileContributor: Ben Ford <[email protected]>
//
// 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);
}
}
}
2 changes: 1 addition & 1 deletion crates/cxx-qt-lib/src/core/qstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 5 additions & 3 deletions crates/cxx-qt/src/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
// TODO! Implement QObject wrapper properly
include!(<QtCore/QObject>);
/// 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);
}
}
Expand Down
Loading