use std::cell::RefCell;
use std::rc::Rc;
use qtbridge_type_lib::{
QMetaType, QMetaTypeGet, QObject, QString, QVariant,
QList_bool, QList_i8, QList_u8, QList_i16, QList_u16,
QList_i32, QList_u32, QList_i64, QList_u64, QList_isize, QList_usize,
QList_f32, QList_f64, QList_QString,
};
#[cfg(feature = "serde_json")]
use qtbridge_type_lib::{QJsonArray, QJsonValue};
use crate::{QObjectHolder, QmlRegister};
pub trait QPropertyMember: Sized {
fn qmetatype() -> QMetaType;
fn to_qvariant<Owner: QObjectHolder>(&self, owner: &Owner) -> QVariant;
fn to_qvariant_view<Owner, Notify>(&self, owner: &Owner, notify: Notify) -> QVariant
where
Owner: QObjectHolder,
Notify: Fn(&mut Owner) + 'static,
{
let _ = notify;
self.to_qvariant(owner)
}
fn from_qvariant(value: &QVariant) -> Result<Self, ()>;
fn property_eq(&self, other: &Self) -> bool;
}
macro_rules! impl_primitive {
($($t:ty),*) => {
$(impl QPropertyMember for $t {
fn qmetatype() -> QMetaType { <$t as QMetaTypeGet>::get_qmetatype() }
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant { QVariant::from(self) }
fn from_qvariant(value: &QVariant) -> Result<Self, ()> { Self::try_from(value) }
fn property_eq(&self, other: &Self) -> bool { self == other }
})*
}
}
impl_primitive!(bool, i8, u8, i16, u16, i32, u32, i64, u64, isize, usize, f32, f64);
macro_rules! impl_vec {
($($t:ty => $qlist:ty),*) => {
$(impl QPropertyMember for Vec<$t> {
fn qmetatype() -> QMetaType { <$qlist as QMetaTypeGet>::get_qmetatype() }
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant { QVariant::from(self) }
fn from_qvariant(value: &QVariant) -> Result<Self, ()> { Self::try_from(value) }
fn property_eq(&self, other: &Self) -> bool { self == other }
})*
}
}
impl_vec!(
bool => QList_bool,
i8 => QList_i8,
u8 => QList_u8,
i16 => QList_i16,
u16 => QList_u16,
i32 => QList_i32,
u32 => QList_u32,
i64 => QList_i64,
u64 => QList_u64,
isize => QList_isize,
usize => QList_usize,
f32 => QList_f32,
f64 => QList_f64,
String => QList_QString
);
impl QPropertyMember for String {
fn qmetatype() -> QMetaType { <QString as QMetaTypeGet>::get_qmetatype() }
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant { QVariant::from(self) }
fn from_qvariant(value: &QVariant) -> Result<Self, ()> { Self::try_from(value) }
fn property_eq(&self, other: &Self) -> bool { self == other }
}
impl<T: QObjectHolder> QPropertyMember for Rc<RefCell<T>> {
fn qmetatype() -> QMetaType {
<*mut QObject as QMetaTypeGet>::get_qmetatype()
}
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant {
T::rc_ref_cell_to_qobject(self).cast_mut().into()
}
fn from_qvariant(value: &QVariant) -> Result<Self, ()> {
let ptr = <*mut QObject>::try_from(value)?;
Ok(unsafe { T::qobject_to_rc_ref_cell(ptr) })
}
fn property_eq(&self, other: &Self) -> bool {
Rc::ptr_eq(self, other)
}
}
impl<T: QmlRegister> QPropertyMember for Vec<Rc<RefCell<T>>> {
fn qmetatype() -> QMetaType {
T::get_list_qmetatype()
}
fn to_qvariant<Owner: QObjectHolder>(&self, owner: &Owner) -> QVariant {
T::list_to_qvariant(owner, self, |_: &mut Owner| {})
}
fn to_qvariant_view<Owner, Notify>(&self, owner: &Owner, notify: Notify) -> QVariant
where
Owner: QObjectHolder,
Notify: Fn(&mut Owner) + 'static,
{
T::list_to_qvariant(owner, self, notify)
}
fn from_qvariant(_value: &QVariant) -> Result<Self, ()> {
Err(())
}
fn property_eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| Rc::ptr_eq(a, b))
}
}
#[cfg(feature = "serde_json")]
impl QPropertyMember for serde_json::Value {
fn qmetatype() -> QMetaType { <QJsonValue as QMetaTypeGet>::get_qmetatype() }
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant {
QVariant::from(&crate::serde_tools::serde_to_qjsonvalue(self))
}
fn from_qvariant(value: &QVariant) -> Result<Self, ()> {
crate::serde_tools::qvariant_to_serde(value)
}
fn property_eq(&self, other: &Self) -> bool { self == other }
}
#[cfg(feature = "serde_json")]
impl QPropertyMember for Vec<serde_json::Value> {
fn qmetatype() -> QMetaType { <QJsonArray as QMetaTypeGet>::get_qmetatype() }
fn to_qvariant<Owner: QObjectHolder>(&self, _owner: &Owner) -> QVariant {
QVariant::from(&crate::serde_tools::serde_to_qjsonarray(self))
}
fn from_qvariant(value: &QVariant) -> Result<Self, ()> {
match crate::serde_tools::qvariant_to_serde(value)? {
serde_json::Value::Array(arr) => Ok(arr),
_ => Err(()),
}
}
fn property_eq(&self, other: &Self) -> bool { self == other }
}
#[doc(hidden)]
pub fn get_meta_type_of_fn_return_value<F, This, R>(_f: F) -> QMetaType
where
F: FnOnce(&This) -> &R,
R: QPropertyMember,
{
R::qmetatype()
}