qtbridge_runtime/
qobjectholder.rs1use std::cell::RefCell;
5use std::rc::Rc;
6
7use qtbridge_type_lib::{QObject, QVariant, QMetaType, QMetaObject};
8use crate::qrustproxy::{QRustProxy, ConstructionMode};
9use crate::{DispatchMetaCall, QMetaInfo};
10use std::collections::HashMap;
11
12
13pub trait QObjectHolder : DispatchMetaCall + QMetaInfo + Default {
14 #[doc(hidden)]
19 type ProxyRust : QRustProxy;
20
21 #[doc(hidden)]
22 fn try_borrow_mut_proxies_map<F, R>(f: F) -> R
23 where
24 F: FnOnce( &mut HashMap<*const u8, *const u8>) -> R
25 {
26 thread_local! { static INSTANCES: RefCell<HashMap<*const u8, *const u8>> =
27 RefCell::new(HashMap::new());
28 }
29 INSTANCES.with_borrow_mut(f)
30 }
31
32 #[doc(hidden)]
34 fn get_rust_proxy(&self) -> &Self::ProxyRust
35 {
36 Self::get_rust_proxy_mut(self)
37 }
38
39 #[doc(hidden)]
41 fn get_rust_proxy_mut(&self) -> &mut Self::ProxyRust
42 {
43 Self::try_get_rust_proxy_mut(self)
44 .expect("No proxy registered for given rust object")
45 }
46
47 #[doc(hidden)]
49 fn try_get_rust_proxy_mut(&self) -> Option<&mut Self::ProxyRust>
50 {
51 let rust_obj_ptr = std::ptr::from_ref(self).cast::<u8>();
52 let proxy_ptr = Self::try_borrow_mut_proxies_map(|map| {
53 map.get(&rust_obj_ptr).copied().unwrap_or_default()
54 });
55
56 unsafe {
57 (proxy_ptr as *mut Self::ProxyRust).as_mut()
58 }
59 }
60
61 #[doc(hidden)]
62 fn get_qobject_ptr(&self) -> *mut QObject {
63 let Some(rust_proxy) = Self::try_get_rust_proxy_mut(&self) else {
64 return std::ptr::null_mut()
65 };
66 let cpp_proxy = rust_proxy.get_cpp_proxy();
67 cpp_proxy as *mut QObject
68 }
69
70 #[doc(hidden)]
72 fn try_get_qobject(&self) -> Option<&mut QObject> {
73 let ptr = self.get_qobject_ptr();
74 unsafe { ptr.as_mut() }
75 }
76
77 #[doc(hidden)]
80 fn get_qobject(&self) -> &mut QObject
81 {
82 self.try_get_qobject()
83 .expect("QObject is not attached")
84 }
85
86 #[doc(hidden)]
93 fn as_adaptor_trait(rust_obj_rc: Rc<RefCell<Self>>) -> Rc<RefCell<<Self::ProxyRust as QRustProxy>::AdapterType>>;
94
95 #[doc(hidden)]
100 fn register_instance_in_map(rust_obj_rc: Rc<RefCell<Self>>, construction: ConstructionMode) {
101 let key = (*rust_obj_rc).as_ptr() as *const u8;
102 let dyn_rc = Self::as_adaptor_trait(rust_obj_rc);
103 let proxy = Self::ProxyRust::new(&dyn_rc, construction, move || Self::unregister_instance_in_map(key));
104 Self::try_borrow_mut_proxies_map(|proxies| {
105 proxies.insert(key, proxy as *const u8);
106 })
107 }
108
109 #[doc(hidden)]
111 fn unregister_instance_in_map(rust_obj_ptr: *const u8) {
112 Self::try_borrow_mut_proxies_map(|proxies| proxies.remove(&rust_obj_ptr))
113 .expect("Proxy object for rust object is not registered")
114 .cast_mut();
115 }
116
117 #[doc(hidden)]
120 fn set_dynamic_meta(instance: &Rc<RefCell<Self>>)
121 {
122 let dynamic_meta = Self::get_shared_dynamic_meta_object_data();
123 let instance_ref = &instance.borrow();
124 let qobject_ref = instance_ref.get_qobject();
125 dynamic_meta.set_to_qobject(qobject_ref);
126 }
127
128 fn default_with_attached_qobject() -> std::rc::Rc<std::cell::RefCell<Self>> {
133 let instance = std::rc::Rc::new(std::cell::RefCell::new(Self::default()));
134 Self::attach_qobject(&instance);
135 instance
136 }
137 fn attach_qobject(instance: &std::rc::Rc<std::cell::RefCell<Self>>) {
141 Self::register_instance_in_map(
142 instance.clone(),
143 ConstructionMode::Weak
144 );
145 Self::set_dynamic_meta(instance);
146 }
147
148 fn detach_qobject(&self) {
152 if let Some(qobj) = Self::try_get_qobject(self) {
153 QObject::delete(std::ptr::from_mut(qobj));
154 }
155 }
156
157 fn as_qvariant(&self) -> QVariant {
159 let qobj_ref = self.get_qobject();
160 let qobj_ptr = std::ptr::from_mut(qobj_ref);
161 qobj_ptr.into()
162 }
163
164 #[doc(hidden)]
165 fn get_static_meta_object() -> &'static QMetaObject {
166 <Self::ProxyRust as QRustProxy>::get_static_meta_object()
167 }
168
169 #[doc(hidden)]
170 fn get_size_of_cpp_proxy() -> usize {
171 <Self::ProxyRust as QRustProxy>::get_size_of_cpp_proxy()
172 }
173
174 #[doc(hidden)]
175 fn get_align_of_cpp_proxy() -> usize {
176 <Self::ProxyRust as QRustProxy>::get_align_of_cpp_proxy()
177 }
178
179 #[doc(hidden)]
180 fn get_qmetatype_list_of_cpp_proxy() -> QMetaType {
181 <Self::ProxyRust as QRustProxy>::get_qmetatype_list_of_cpp_proxy()
182 }
183}