#[macro_export]
macro_rules! qvarlist{
(__ $v:ident, [$($inside:tt)*], $($rest:tt)*) => {
$v.push(qvarlist!($($inside)*).into());
qvarlist!(__ $v, $($rest)*);
};
(__ $v:ident, [$($inside:tt)*]) => {
$v.push(qvarlist!($($inside)*).into());
};
(__ $v:ident, $varname:expr, $($rest:tt)*) => {
$v.push($varname.into());
qvarlist!(__ $v, $($rest)*);
};
(__ $v:ident, $varname:expr) => {
$v.push($varname.into());
};
($($rest:tt)*) => {{
let mut v: Vec<QVariant> = Vec::new();
qvarlist!(__ v, $($rest)*);
v
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __gen_signals{
(fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* ); $($rest:tt)*) =>{
#[allow(unused_mut)]
#[allow(dead_code)]
pub fn $signalname(&self, $( $signalvar: $signalqtype ),*){
let mut vec: Vec<QVariant> = Vec::new();
$(
let $signalvar: $signalqtype = $signalvar;
vec.push($signalvar.into());
)*
emit_signal(self, stringify!($signalname), vec);
}
__gen_signals!($($rest)*);
};
() => ();
}
#[macro_export]
macro_rules! Q_OBJECT{
(
pub $obj:ident as $wrapper:ident{
signals:
$(fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* );)*
slots:
$(fn $slotname:ident ( $( $slotvar:ident : $slotqtype:ident ),* );)*
properties:
$($propname:ident : $proptype:ident; read: $read_slot:ident, write: $write_slot:ident,
notify: $notify_sig:ident;)*
}) =>{
#[allow(dead_code)]
pub struct $wrapper{
origin: Box<$obj>,
ptr: QObject,
properties: ::std::collections::HashMap<&'static str, (QVariant, QMetaType)>,
}
impl ::std::ops::Deref for $wrapper {
type Target = $obj;
fn deref(&self) -> &$obj {
let ref b: Box<$obj> = self.origin;
b.as_ref()
}
}
impl ::std::ops::DerefMut for $wrapper {
fn deref_mut<'a>(&'a mut self) -> &'a mut $obj {
self.origin.as_mut()
}
}
impl $wrapper{
__gen_signals!($(fn $signalname ( $( $signalvar : $signalqtype ),* );)*
$(fn $notify_sig ();)*);
#[allow(unused_mut)]
#[allow(dead_code)]
pub fn with_no_props(origin: $obj)-> Box<Self> {
unsafe{
let mut local = $wrapper{
origin: Box::new(origin),
ptr: ::std::mem::uninitialized(),
properties: ::std::collections::HashMap::new(),
};
$(local.properties.insert(stringify!($propname), ($proptype::default().into(), $proptype::metatype()));)*
let mut local = Box::new(local);
let qobj = QObject::new(&mut *local);
::std::ptr::write(&mut local.ptr, qobj);
local
}
}
#[allow(unused_mut)]
#[allow(dead_code)]
pub fn new(origin: $obj, $($propname: $proptype),*) -> Box<Self>{
let mut local = Self::with_no_props(origin);
$(local.properties.insert(stringify!($propname), ($propname.into(), $proptype::metatype()));)*
local
}
$(
#[allow(dead_code)]
pub fn $read_slot(&self) -> &QVariant {
&self.properties.get(stringify!($propname)).unwrap().0
}
#[allow(dead_code)]
pub fn $write_slot(&mut self, input: $proptype) {
self.properties.insert(stringify!($propname), (input.into(), $proptype::metatype()));
})*
#[allow(dead_code)]
fn threaded<F: FnOnce(&mut $wrapper) + Send + 'static>(&mut self, f: F){
let ptr = ::std::sync::atomic::AtomicPtr::new(self);
::std::thread::spawn(move || {
f(unsafe { &mut *ptr.load(::std::sync::atomic::Ordering::Relaxed) });
});
}
}
impl QObjectMacro for $wrapper{
#[allow(unused_variables)]
#[allow(unused_mut)]
#[allow(dead_code)]
fn qslot_call(&mut self, name: &str, args: Vec<QVariant>) -> Option<&QVariant>{
fn next_or_panic(qt: Option<QVariant>) -> QVariant{
if let Some(o) = qt {
o
}else {
panic!("Not enough parameters to call a slot")
}
}
match name {
$(stringify!($slotname) => {
let mut iter = args.into_iter();
$(
let next = next_or_panic (iter.next());
let $slotvar: $slotqtype = next.into();
)*
self.$slotname ($($slotvar),*)
},)*
$(stringify!($read_slot) => {
Some(self.$read_slot ())
},
stringify!($write_slot) => {
let mut iter = args.into_iter();
let next = next_or_panic (iter.next());
let property: $proptype = next.into();
self.$write_slot (property);
None
},)*
_ => panic!("Unrecognized slot call: {}", name)
}
}
#[allow(unused_mut)]
fn qmeta(&self) -> (Vec<(&'static str, i32, Vec<i32>)>,
Vec<(&'static str, i32, i32, Vec<i32>)>,
Vec<(&'static str, i32, &'static str, &'static str, &'static str)>,
&'static str){
let mut signals = Vec::new();
$(
let mut argc = 0;
let mut mttypes = Vec::new();
$(
argc += 1;
mttypes.push($signalqtype::metatype() as i32);
)*
signals.push((stringify!($signalname), argc, mttypes));
)*
$(
signals.push((stringify!($notify_sig), 0, Vec::new()));
)*
let mut slots = Vec::new();
$(
let mut argc = 0;
let mut mttypes = Vec::new();
$(
argc += 1;
mttypes.push($slotqtype::metatype() as i32);
)*
slots.push((stringify!($slotname), 43, argc, mttypes));
)*
$(
slots.push((stringify!($read_slot), $proptype::metatype() as i32, 0, Vec::new()));
slots.push((stringify!($write_slot), QMetaType::Void as i32, 1, vec![$proptype::metatype() as i32]));
)*
let mut props: Vec<(&'static str, i32, &'static str, &'static str, &'static str)> = Vec::new();
$(
props.push((stringify!($propname), $proptype::metatype() as i32, stringify!($read_slot),
stringify!($write_slot), stringify!($notify_sig)));
)*
(signals, slots, props, stringify!($obj))
}
fn get_qobj(&self) -> &QObject{
&self.ptr
}
fn get_qobj_mut(&mut self) -> &mut QObject{
&mut self.ptr
}
}
};
}
#[macro_export]
macro_rules! Q_LISTMODEL_ITEM{
(pub $wrapper:ident <$wrapper_item:ident> {
$($rolename:ident : $roletype:ty,)*
}) => {
pub struct $wrapper_item {
$( $rolename : $roletype, )*
}
Q_LISTMODEL!{
pub $wrapper {
$($rolename : $roletype),*
}
}
impl $wrapper {
#[allow(unused_mut)]
pub fn append_item<T>(&mut self, obj :T ) where T: Into<$wrapper_item> {
let item: $wrapper_item = obj.into();
let mut vec = Vec::new();
$(
vec.push(item.$rolename.into());
)*
self.qalm.append_row(vec.into_iter());
}
#[allow(unused_mut)]
pub fn insert_item<T>(&mut self, index: usize, obj :T ) where T: Into<$wrapper_item> {
let item: $wrapper_item = obj.into();
let mut vec = Vec::new();
$(
vec.push(item.$rolename.into());
)*
self.qalm.insert_row(index, vec.into_iter());
}
}
}
}
#[macro_export]
macro_rules! Q_LISTMODEL{
(pub $wrapper:ident{
$($rolename:ident : $roletype:ty),*
}) => {
pub struct $wrapper {
qalm: Box<QListModel<'static>>,
}
impl $wrapper {
pub fn new() -> Self{
$wrapper{ qalm: QListModel::new(&[$(stringify!($rolename)),*])}
}
#[allow(unused_mut)]
pub fn append_row(&mut self, $($rolename : $roletype),*) {
let mut vec = Vec::new();
$(
vec.push($rolename.into());
)*
self.qalm.append_row(vec.into_iter());
}
#[allow(unused_mut)]
pub fn insert_row(&mut self, index: usize, $($rolename : $roletype),*) {
let mut vec = Vec::new();
$(
vec.push($rolename.into());
)*
self.qalm.insert_row(index, vec.into_iter());
}
#[allow(unused_mut)]
pub fn remove_row(&mut self, index: usize) {
self.qalm.remove_row(index);
}
pub fn get_qvar(&self) -> QVariant{
self.qalm.get_qvar()
}
#[allow(unused_mut)]
pub fn set_data(&mut self, vec: Vec<($($roletype,)*)>) {
self.qalm.set_data(vec.into_iter()
.map(|($($rolename,)*)| {
let mut vec = Vec::new();
$(
vec.push($rolename.into());
)*
vec
}).collect::<Vec<Vec<QVariant>>>())
}
pub fn view_raw_data(&self) -> &[Vec<QVariant>]{
self.qalm.view_data()
}
pub fn view_data(&self) -> Vec<($($roletype),*)>{
let view = self.qalm.view_data();
view.into_iter().map(|v| {
let mut v = v.iter();
$(
let $rolename = v.next().unwrap().into();
)*
($($rolename),*)
}).collect()
}
pub fn change_line(&mut self, index: usize, $($rolename : $roletype),*) {
let mut vec = Vec::new();
$(
vec.push($rolename.into());
)*
self.qalm.change_line(index, vec);
}
#[allow(unused_mut)]
pub fn clear(&mut self) {
self.qalm.clear();
}
}
impl<'a, 'b> From<&'a $wrapper> for QVariant {
fn from(i: &$wrapper) -> QVariant {
i.get_qvar()
}
}
}
}
#[macro_export]
macro_rules! Q_REGISTERABLE_QML(
($wrapper:ident : $origin:ident as $qml:ident $major:expr=>$minor:expr, from $uri:ident) => {
impl QMLRegisterable for $wrapper{
fn qualify_to_register(&self) -> (i32, i32, &'static str, &'static str) {
($major, $minor, stringify!($uri), stringify!($qml))
}
fn get_new(&self) -> *mut c_void {
let obj = $wrapper::with_no_props($origin::default());
let res = Box::into_raw(obj) as *mut c_void;
res
}
fn get_qobj_from_ptr(&self, ptr: *mut c_void) -> *mut QObject {
unsafe {
let mut obj: Box<$wrapper> = Box::from_raw(ptr as *mut $wrapper);
let res = obj.get_qobj_mut() as *mut QObject;
::std::mem::forget(obj);
res
}
}
}
impl $wrapper {
pub fn get_shallow() -> Self {
unsafe {
::std::mem::uninitialized()
}
}
}
}
);
#[macro_export]
macro_rules! Q_REGISTER_QML(
($wrapper:ident) => {
register_qml_type($wrapper::get_shallow());
}
);
#[macro_export]
macro_rules! Q_REGISTER_SINGLETON_QML(
($wrapper:ident) => {
register_qml_singleton_type($wrapper::get_shallow());
}
);