use std::{ffi::c_char, ptr};
use ffi::{ClepsydreCalendar, ClepsydreTimeframe};
use gio::ffi::{
GAsyncReadyCallback, GAsyncResult, GCancellable, g_task_new, g_task_propagate_boolean,
g_task_return_boolean, g_task_return_error,
};
use glib::{
ffi::{GError, GFALSE, GTRUE, gboolean, gpointer},
gobject_ffi::g_object_unref,
prelude::*,
subclass::prelude::*,
translate::*,
};
use crate::{
Calendar, Event, PinnedFutureResult, Timeframe,
ffi::{ClepsydreEvent, ClepsydreEventClass},
};
pub trait EventImpl: ObjectImpl + ObjectSubclass<Type: IsA<Event>> {
fn try_update(
&self,
calendar: Option<&impl IsA<Calendar>>,
name: Option<&str>,
description: Option<&str>,
location: Option<&str>,
conference: Option<&str>,
timeframe: Option<&Timeframe>,
) -> Result<(), glib::Error> {
self.parent_try_update(calendar, name, description, location, conference, timeframe)
}
fn try_update_future(
&self,
calendar: Option<&impl IsA<Calendar>>,
name: Option<&str>,
description: Option<&str>,
location: Option<&str>,
conference: Option<&str>,
timeframe: Option<&Timeframe>,
) -> PinnedFutureResult<()> {
self.parent_try_update_future(calendar, name, description, location, conference, timeframe)
}
fn try_remove(&self) -> Result<(), glib::Error> {
self.parent_try_remove()
}
fn try_remove_future(&self) -> PinnedFutureResult<()> {
self.parent_try_remove_future()
}
}
pub trait EventImplExt: EventImpl {
fn parent_try_update(
&self,
calendar: Option<&impl IsA<Calendar>>,
name: Option<&str>,
description: Option<&str>,
location: Option<&str>,
conference: Option<&str>,
timeframe: Option<&Timeframe>,
) -> Result<(), glib::Error> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ClepsydreEventClass;
let mut error = ptr::null_mut();
if let Some(f) = (*parent_class).try_update {
if f(
self.obj().unsafe_cast_ref::<Event>().to_glib_none().0,
if let Some(calendar) = calendar {
calendar.unsafe_cast_ref::<Calendar>().to_glib_none().0
} else {
ptr::null_mut()
},
name.to_glib_none().0,
description.to_glib_none().0,
location.to_glib_none().0,
conference.to_glib_none().0,
timeframe.to_glib_none().0,
&mut error,
) == GTRUE
{
Ok(())
} else {
Err(from_glib_full(error))
}
} else {
Err(glib::Error::new(
crate::Error::NotImplemented,
"The method Event::try_remove is not implemented",
))
}
}
}
fn parent_try_update_future(
&self,
_calendar: Option<&impl IsA<Calendar>>,
_name: Option<&str>,
_description: Option<&str>,
_location: Option<&str>,
_conference: Option<&str>,
_timeframe: Option<&Timeframe>,
) -> PinnedFutureResult<()> {
unimplemented!()
}
fn parent_try_remove(&self) -> Result<(), glib::Error> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ClepsydreEventClass;
let mut error = ptr::null_mut();
if let Some(f) = (*parent_class).try_remove {
if f(
self.obj().unsafe_cast_ref::<Event>().to_glib_none().0,
&mut error,
) == GTRUE
{
Ok(())
} else {
Err(from_glib_full(error))
}
} else {
Err(glib::Error::new(
crate::Error::NotImplemented,
"The method Event::try_remove is not implemented",
))
}
}
}
fn parent_try_remove_future(&self) -> PinnedFutureResult<()> {
unimplemented!()
}
}
impl<T: EventImpl> EventImplExt for T {}
unsafe impl<T: EventImpl> IsSubclassable<T> for Event {
fn class_init(class: &mut ::glib::Class<Self>) {
Self::parent_class_init::<T>(class);
let klass = class.as_mut();
klass.try_update = Some(event_try_update::<T>);
klass.try_update_async = Some(event_try_update_async::<T>);
klass.try_update_finish = Some(event_try_update_finish);
klass.try_remove = Some(event_try_remove::<T>);
klass.try_remove_async = Some(event_try_remove_async::<T>);
klass.try_remove_finish = Some(event_try_remove_finish);
}
}
unsafe extern "C" fn event_try_update<T: EventImpl>(
event_ptr: *mut ClepsydreEvent,
calendar_ptr: *mut ClepsydreCalendar,
name_ptr: *const c_char,
description_ptr: *const c_char,
location_ptr: *const c_char,
conference_ptr: *const c_char,
timeframe_ptr: *mut ClepsydreTimeframe,
error_ptr: *mut *mut GError,
) -> gboolean {
unsafe {
let instance = &*(event_ptr as *mut T::Instance);
let imp = instance.imp();
let calendar = if !calendar_ptr.is_null() {
Some(&*Calendar::from_glib_borrow(calendar_ptr))
} else {
None
};
let name = if !name_ptr.is_null() {
Some(glib::GStr::from_ptr(name_ptr).to_string().leak() as &str)
} else {
None
};
let description = if !description_ptr.is_null() {
Some(glib::GStr::from_ptr(description_ptr).to_string().leak() as &str)
} else {
None
};
let location = if !location_ptr.is_null() {
Some(glib::GStr::from_ptr(location_ptr).to_string().leak() as &str)
} else {
None
};
let conference = if !conference_ptr.is_null() {
Some(glib::GStr::from_ptr(conference_ptr).to_string().leak() as &str)
} else {
None
};
let timeframe = if !timeframe_ptr.is_null() {
Some(&*Timeframe::from_glib_borrow(timeframe_ptr))
} else {
None
};
match imp.try_update(calendar, name, description, location, conference, timeframe) {
Ok(()) => GTRUE,
Err(error) => {
if !error_ptr.is_null() {
*error_ptr = error.to_glib_full();
}
GFALSE
}
}
}
}
unsafe extern "C" fn event_try_update_async<T: EventImpl>(
event_ptr: *mut ClepsydreEvent,
calendar_ptr: *mut ClepsydreCalendar,
name_ptr: *const c_char,
description_ptr: *const c_char,
location_ptr: *const c_char,
conference_ptr: *const c_char,
timeframe_ptr: *mut ClepsydreTimeframe,
cancellable: *mut GCancellable,
callback: GAsyncReadyCallback,
user_data: gpointer,
) {
unsafe {
let task = g_task_new(event_ptr as *mut _, cancellable, callback, user_data);
let instance = &*(event_ptr as *mut T::Instance);
let imp = instance.imp();
let calendar = if !calendar_ptr.is_null() {
Some(&*Calendar::from_glib_borrow(calendar_ptr))
} else {
None
};
let name = if !name_ptr.is_null() {
Some(glib::GStr::from_ptr(name_ptr).as_str())
} else {
None
};
let description = if !description_ptr.is_null() {
Some(glib::GStr::from_ptr(description_ptr).as_str())
} else {
None
};
let location = if !location_ptr.is_null() {
Some(glib::GStr::from_ptr(location_ptr).as_str())
} else {
None
};
let conference = if !conference_ptr.is_null() {
Some(glib::GStr::from_ptr(conference_ptr).as_str())
} else {
None
};
let timeframe = if !timeframe_ptr.is_null() {
Some(&*Timeframe::from_glib_borrow(timeframe_ptr))
} else {
None
};
let future =
imp.try_update_future(calendar, name, description, location, conference, timeframe);
glib::MainContext::ref_thread_default().spawn_local(async move {
match future.await {
Ok(()) => g_task_return_boolean(task, GTRUE),
Err(error) => g_task_return_error(task, error.into_glib_ptr()),
}
g_object_unref(task as *mut _);
});
}
}
unsafe extern "C" fn event_try_update_finish(
_event_ptr: *mut ClepsydreEvent,
async_result: *mut GAsyncResult,
error_ptr: *mut *mut GError,
) -> gboolean {
unsafe { g_task_propagate_boolean(async_result as *mut _, error_ptr) }
}
unsafe extern "C" fn event_try_remove<T: EventImpl>(
event_ptr: *mut ClepsydreEvent,
error_ptr: *mut *mut GError,
) -> gboolean {
let instance = unsafe { &*(event_ptr as *mut T::Instance) };
let imp = instance.imp();
match imp.try_remove() {
Ok(()) => GTRUE,
Err(error) => {
if !error_ptr.is_null() {
unsafe { *error_ptr = error.to_glib_full() };
}
GFALSE
}
}
}
unsafe extern "C" fn event_try_remove_async<T: EventImpl>(
event_ptr: *mut ClepsydreEvent,
cancellable: *mut GCancellable,
callback: GAsyncReadyCallback,
user_data: gpointer,
) {
unsafe {
let task = g_task_new(event_ptr as *mut _, cancellable, callback, user_data);
let instance = &*(event_ptr as *mut T::Instance);
let imp = instance.imp();
let future = imp.try_remove_future();
glib::MainContext::ref_thread_default().spawn_local(async move {
match future.await {
Ok(()) => g_task_return_boolean(task, GTRUE),
Err(error) => g_task_return_error(task, error.into_glib_ptr()),
}
g_object_unref(task as *mut _);
});
}
}
unsafe extern "C" fn event_try_remove_finish(
_event_ptr: *mut ClepsydreEvent,
async_result: *mut GAsyncResult,
error_ptr: *mut *mut GError,
) -> gboolean {
unsafe { g_task_propagate_boolean(async_result as *mut _, error_ptr) }
}
#[allow(clippy::missing_safety_doc)]
pub unsafe trait EventClassExt: ClassStruct {}
unsafe impl<T: ClassStruct> EventClassExt for T where T::Type: EventImpl {}