#![recursion_limit = "10240"]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::needless_pass_by_value))] #![cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]
#[doc(hidden)]
pub use qmetaobject_impl::{qrc_internal, SimpleListItem};
#[doc(hidden)]
#[cfg(not(qt_6_0))]
pub use qmetaobject_impl::{QEnum, QGadget, QObject};
#[doc(hidden)]
#[cfg(qt_6_0)]
pub use qmetaobject_impl::{QEnum6 as QEnum, QGadget6 as QGadget, QObject6 as QObject};
#[allow(unused_imports)]
#[doc(hidden)]
pub use lazy_static::lazy_static;
#[doc(hidden)]
#[macro_export]
macro_rules! qmetaobject_lazy_static { ($($t:tt)*) => { $crate::lazy_static!($($t)*) } }
use std::cell::{RefCell, RefMut};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};
use cpp::{cpp, cpp_class};
pub use qttypes;
pub use crate::log::*;
pub use connections::RustSignal;
pub use connections::{connect, Signal, SignalInner};
pub use future::*;
pub use itemmodel::*;
pub use listmodel::*;
pub use qmetatype::*;
pub use qtdeclarative::*;
#[cfg(qt_5_7)]
pub use qtquickcontrols2::*;
pub use qttypes::*;
pub use tablemodel::*;
pub mod connections;
pub mod future;
pub mod itemmodel;
pub mod listmodel;
pub mod log;
pub mod qmetatype;
pub mod qrc;
pub mod qtcore;
pub mod qtdeclarative;
#[cfg(qt_5_7)]
pub mod qtquickcontrols2;
pub mod scenegraph;
pub mod tablemodel;
#[cfg(feature = "webengine")]
#[cfg(not(all(qt_6_0, not(qt_6_2))))]
#[cfg(not(all(target_os = "windows", not(target_env = "msvc"))))]
pub mod webengine;
pub mod prelude {
#[cfg(qt_5_8)]
pub use crate::qtdeclarative::qml_register_enum;
#[cfg(qt_5_9)]
pub use crate::qtdeclarative::qml_register_module;
pub use crate::{
qml_register_type, qrc, qt_base_class, qt_method, qt_plugin, qt_property, qt_signal,
QAbstractListModel, QByteArray, QColor, QDate, QDateTime, QEnum, QModelIndex, QObject,
QObjectBox, QPointer, QQmlExtensionPlugin, QQuickItem, QQuickView, QRectF, QString, QTime,
QVariant, QmlEngine,
};
}
cpp! {{
#include <qmetaobject_rust.hpp>
}}
#[doc(hidden)]
pub struct QObjectCppWrapper {
ptr: *mut c_void,
}
impl Drop for QObjectCppWrapper {
fn drop(&mut self) {
let ptr = self.ptr;
cpp!(unsafe [ptr as "QObject *"] {
QEvent e = QEvent(QEvent::Type(QtJambi_EventType_DeleteOnMainThread));
if (ptr) {
ptr->event(&e);
}
});
}
}
impl Default for QObjectCppWrapper {
fn default() -> QObjectCppWrapper {
QObjectCppWrapper { ptr: std::ptr::null_mut() }
}
}
impl QObjectCppWrapper {
pub fn get(&self) -> *mut c_void {
self.ptr
}
pub fn set(&mut self, val: *mut c_void) {
self.ptr = val;
}
}
#[doc(hidden)]
#[deprecated]
pub type QObjectDescription = QObjectDescriptor;
#[doc(hidden)]
#[repr(C)]
pub struct QObjectDescriptor {
pub size: usize,
pub meta_object: *const QMetaObject,
pub create: unsafe extern "C" fn(
pinned_object: *const c_void,
trait_object_ptr: *const c_void,
) -> *mut c_void,
pub qml_construct: unsafe extern "C" fn(
mem: *mut c_void,
pinned_object: *const c_void,
trait_object_ptr: *const c_void,
extra_destruct: extern "C" fn(*mut c_void),
),
pub get_rust_refcell: unsafe extern "C" fn(*mut c_void) -> *const RefCell<dyn QObject>,
}
pub trait QObject {
fn meta_object(&self) -> *const QMetaObject;
fn static_meta_object() -> *const QMetaObject
where
Self: Sized;
fn get_cpp_object(&self) -> *mut c_void;
unsafe fn cpp_construct(pined: &RefCell<Self>) -> *mut c_void
where
Self: Sized;
unsafe fn qml_construct(
pined: &RefCell<Self>,
mem: *mut c_void,
extra_destruct: extern "C" fn(*mut c_void),
) where
Self: Sized;
fn cpp_size() -> usize
where
Self: Sized;
unsafe fn get_from_cpp<'a>(p: *mut c_void) -> QObjectPinned<'a, Self>
where
Self: Sized;
fn get_object_description() -> &'static QObjectDescriptor
where
Self: Sized,
{
unsafe {
&*cpp!([]-> *const QObjectDescriptor as "RustQObjectDescriptor const*" {
return RustQObjectDescriptor::instance<RustObject<QObject>>();
})
}
}
}
impl dyn QObject {
pub unsafe fn as_qvariant(&self) -> QVariant {
let self_ = self.get_cpp_object();
cpp!([self_ as "QObject*"] -> QVariant as "QVariant" {
return QVariant::fromValue(self_);
})
}
pub fn destroyed_signal() -> Signal<fn()> {
unsafe {
Signal::new(cpp!([] -> SignalInner as "SignalInner" {
return &QObject::destroyed;
}))
}
}
pub fn set_object_name(&self, name: QString) {
let self_ = self.get_cpp_object();
unsafe {
cpp!([self_ as "QObject*", name as "QString"] {
if (self_) self_->setObjectName(std::move(name));
})
}
}
pub fn object_name_changed_signal() -> Signal<fn(QString)> {
unsafe {
Signal::new(cpp!([] -> SignalInner as "SignalInner" {
return &QObject::objectNameChanged;
}))
}
}
}
cpp_class!(unsafe struct QPointerImpl as "QPointer<QObject>");
pub struct QPointer<T: QObject + ?Sized>(QPointerImpl, *const T);
impl<T: QObject + ?Sized> QPointer<T> {
pub fn cpp_ptr(&self) -> *mut c_void {
let x = &self.0;
cpp!(unsafe [x as "QPointer<QObject> *"] -> *mut c_void as "QObject *" {
return x->data();
})
}
pub fn as_ref(&self) -> Option<&T> {
let x = self.cpp_ptr();
if x.is_null() {
None
} else {
unsafe { Some(&*self.1) }
}
}
pub fn is_null(&self) -> bool {
self.cpp_ptr().is_null()
}
}
impl<T: QObject> QPointer<T> {
pub fn as_pinned(&self) -> Option<QObjectPinned<T>> {
let x = self.cpp_ptr();
if x.is_null() {
None
} else {
Some(unsafe { T::get_from_cpp(x) })
}
}
}
impl<'a, T: QObject + ?Sized> From<&'a T> for QPointer<T> {
fn from(obj: &'a T) -> Self {
let cpp_obj = obj.get_cpp_object();
QPointer(
cpp!(unsafe [cpp_obj as "QObject *"] -> QPointerImpl as "QPointer<QObject>" {
return cpp_obj; }),
obj as *const T,
)
}
}
impl<T: QObject> Default for QPointer<T> {
fn default() -> Self {
QPointer(Default::default(), std::ptr::null())
}
}
impl<T: QObject + ?Sized> Clone for QPointer<T> {
fn clone(&self) -> Self {
QPointer(self.0.clone(), self.1)
}
}
pub struct QObjectRefMut<'b, T: QObject + ?Sized + 'b> {
old_value: *mut c_void,
inner: RefMut<'b, T>,
}
impl<'b, T: QObject + ?Sized> std::ops::Deref for QObjectRefMut<'b, T> {
type Target = RefMut<'b, T>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'b, T: QObject + ?Sized> std::ops::DerefMut for QObjectRefMut<'b, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<'b, T: QObject + ?Sized + 'b> Drop for QObjectRefMut<'b, T> {
#[inline]
fn drop(&mut self) {
assert_eq!(
self.old_value,
self.get_cpp_object(),
"Internal pointer changed while borrowed"
);
}
}
#[repr(transparent)]
pub struct QObjectPinned<'pin, T: QObject + ?Sized + 'pin>(&'pin RefCell<T>);
impl<'pin, T: QObject + ?Sized + 'pin> Clone for QObjectPinned<'pin, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'pin, T: QObject + ?Sized + 'pin> Copy for QObjectPinned<'pin, T> {}
impl<'pin, T: QObject + ?Sized + 'pin> QObjectPinned<'pin, T> {
#[cfg_attr(feature = "cargo-clippy", allow(clippy::should_implement_trait))]
pub fn borrow(&self) -> &T {
unsafe { &*self.0.as_ptr() }
}
pub fn borrow_mut(&self) -> QObjectRefMut<T> {
let x = self.0.borrow_mut();
QObjectRefMut { old_value: x.get_cpp_object(), inner: x }
}
pub fn as_ptr(&self) -> *mut T {
self.0.as_ptr()
}
}
impl<'pin, T: QObject + ?Sized + 'pin> QObjectPinned<'pin, T> {
pub unsafe fn new(inner: &'pin RefCell<T>) -> Self {
QObjectPinned(inner)
}
}
impl<'pin, T: QObject + 'pin> QObjectPinned<'pin, T> {
pub fn get_or_create_cpp_object(self) -> *mut c_void {
let r = unsafe { &*self.0.as_ptr() }.get_cpp_object();
if r.is_null() {
unsafe { QObject::cpp_construct(self.0) }
} else {
r
}
}
}
impl<'pin, T: QObject + 'pin> From<QObjectPinned<'pin, T>> for QVariant {
fn from(obj: QObjectPinned<'pin, T>) -> Self {
let x = obj.get_or_create_cpp_object();
cpp!(unsafe [x as "QObject *"] -> QVariant as "QVariant" {
return QVariant::fromValue(x);
})
}
}
pub struct QObjectBox<T: QObject + ?Sized>(Box<RefCell<T>>);
impl<T: QObject> QObjectBox<T> {
pub fn new(obj: T) -> Self {
QObjectBox(Box::new(RefCell::new(obj)))
}
}
impl<T: QObject + Default> Default for QObjectBox<T> {
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T: QObject + ?Sized> QObjectBox<T> {
pub fn pinned(&self) -> QObjectPinned<T> {
unsafe { QObjectPinned::new(&self.0) }
}
}
pub fn into_leaked_cpp_ptr<T: QObject>(obj: T) -> *mut c_void {
let b = Box::new(RefCell::new(obj));
let obj_ptr = unsafe { QObject::cpp_construct(&b) };
Box::into_raw(b);
obj_ptr
}
pub trait QGadget {
fn meta_object(&self) -> *const QMetaObject;
fn static_meta_object() -> *const QMetaObject
where
Self: Sized;
}
pub trait QEnum {
fn static_meta_object() -> *const QMetaObject
where
Self: Sized;
}
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn RustObject_metaObject(p: *mut RefCell<dyn QObject>) -> *const QMetaObject {
(*(*p).as_ptr()).meta_object()
}
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn RustObject_destruct(p: *mut RefCell<dyn QObject>) {
let _b = Box::from_raw(p);
}
#[doc(hidden)]
pub unsafe fn invoke_signal(
object: *mut c_void,
meta: *const QMetaObject,
id: u32,
a: &[*mut c_void],
) {
let a = a.as_ptr();
cpp!([
object as "QObject *",
meta as "const QMetaObject *",
id as "int",
a as "void **"
] {
if (!object) {
return;
}
QMetaObject::activate(object, meta, id, a);
})
}
type StaticMetacallFunction = Option<
extern "C" fn(
o: *mut c_void, // FIXME: should be QObject or something
c: u32,
idx: u32,
a: *const *mut c_void,
),
>;
#[doc(hidden)]
#[repr(C)]
pub struct QMetaObject {
pub super_data: *const QMetaObject,
#[cfg(all(qt_6_0, target_os = "windows"))] pub super_data_getter: Option<extern "C" fn() -> *const QMetaObject>,
pub string_data: *const u8,
pub data: *const u32,
pub static_metacall: StaticMetacallFunction,
pub related_meta_objects: *const c_void,
pub meta_types: *const c_void,
pub extra_data: *const c_void,
}
unsafe impl Sync for QMetaObject {}
unsafe impl Send for QMetaObject {}
#[macro_export]
macro_rules! qt_base_class {
($($t:tt)*) => {
$crate::QObjectCppWrapper
};
}
#[macro_export]
macro_rules! qt_property {
($t:ty $(; $($rest:tt)*)*) => {
$t
};
}
#[macro_export]
macro_rules! qt_method {
($($t:tt)*) => { ::std::marker::PhantomData<()> };
}
#[macro_export]
macro_rules! qt_signal {
($( $name:ident : $ty:ty ),*) => { $crate::RustSignal<fn( $( $ty ),* )> };
}
#[macro_export]
macro_rules! qt_plugin {
($($t:tt)*) => { std::marker::PhantomData<()> };
}
cpp! {{
struct FnBoxWrapper {
TraitObject fnbox;
~FnBoxWrapper() {
if (fnbox.isValid()) {
rust!(FnBoxWrapper_destructor [fnbox: *mut dyn FnMut() as "TraitObject"] {
unsafe { let _ = Box::from_raw(fnbox); }
});
}
}
FnBoxWrapper &operator=(const FnBoxWrapper&) = delete;
#if false && QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
FnBoxWrapper(const FnBoxWrapper&) = delete;
#else
FnBoxWrapper(const FnBoxWrapper &o) : fnbox(o.fnbox) {
const_cast<FnBoxWrapper &>(o).fnbox = {};
}
#endif
FnBoxWrapper(FnBoxWrapper &&o) : fnbox(o.fnbox) {
o.fnbox = {};
}
FnBoxWrapper &operator=(FnBoxWrapper &&o) {
std::swap(o.fnbox, fnbox);
return *this;
}
void operator()() {
rust!(FnBoxWrapper_operator [fnbox : *mut dyn FnMut() as "TraitObject"] {
unsafe { (*fnbox)(); }
});
}
};
template<typename T>
static void invokeMethod(QObject *reciever, T &&func) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
QMetaObject::invokeMethod(reciever, std::forward<T>(func), Qt::QueuedConnection); #else
QObject o;
QObject::connect(&o, &QObject::destroyed, reciever, std::forward<T>(func), Qt::QueuedConnection);
#endif
}
}}
pub fn single_shot<F>(interval: std::time::Duration, func: F)
where
F: FnMut() + 'static,
{
let func_box: Box<dyn FnMut()> = Box::new(func);
let mut func_raw = Box::into_raw(func_box);
let interval_ms: u32 = interval.as_secs() as u32 * 1000 + interval.subsec_nanos() * 1e-6 as u32;
cpp!(unsafe [interval_ms as "int", mut func_raw as "FnBoxWrapper"] {
QTimer::singleShot(interval_ms, std::move(func_raw));
});
}
pub fn queued_callback<T: Send, F: FnMut(T) + 'static>(
func: F,
) -> impl Fn(T) + Send + Sync + Clone {
let current_thread = cpp!(unsafe [] -> QPointerImpl as "QPointer<QThread>" {
return QThread::currentThread();
});
struct UnsafeSendFn<T>(RefCell<T>);
unsafe impl<T> Send for UnsafeSendFn<T> {}
unsafe impl<T> Sync for UnsafeSendFn<T> {}
let func = std::sync::Arc::new(UnsafeSendFn(RefCell::new(func)));
move |x| {
let mut x = Some(x); let func = func.clone();
let func: Box<dyn FnMut()> = Box::new(move || {
let f = &mut (*(func.0).borrow_mut());
if let Some(x) = x.take() {
f(x);
};
});
let mut func_raw = Box::into_raw(func);
cpp!(unsafe [mut func_raw as "FnBoxWrapper", current_thread as "QPointer<QThread>"] {
if (!current_thread) {
return;
}
if (!qApp || current_thread != qApp->thread()) {
QObject *reciever = new QObject();
reciever->moveToThread(current_thread);
invokeMethod(reciever, std::move(func_raw));
reciever->deleteLater();
} else {
invokeMethod(qApp, std::move(func_raw));
}
});
}
}
fn add_to_hash(hash: *mut c_void, key: i32, value: QByteArray) {
cpp!(unsafe [
hash as "QHash<int, QByteArray> *",
key as "int",
value as "QByteArray"
] {
(*hash)[key] = std::move(value);
});
}
pub const USER_ROLE: i32 = 0x0100;
pub use qmetaobject_impl::qrc_internal as qrc;