diff --git a/Cargo.toml b/Cargo.toml index 585cd97..ff8c5ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,4 +20,6 @@ postage = "0.4.1" futures = "0.3.18" glib = "0.14.8" # examples/gtklauncher -once_cell = "1.8.0" \ No newline at end of file +once_cell = "1.8.0" +xdg = "2.4.0" +serde = "1.0.130" diff --git a/examples/app_library/app_group/imp.rs b/examples/app_library/app_group/imp.rs new file mode 100644 index 0000000..73b1ca3 --- /dev/null +++ b/examples/app_library/app_group/imp.rs @@ -0,0 +1,163 @@ +use glib::{FromVariant, ParamFlags, ParamSpec, ToVariant, Value, Variant, VariantTy}; +use gtk4::glib; +use gtk4::prelude::*; +use gtk4::subclass::prelude::*; +use once_cell::sync::Lazy; + +use std::cell::RefCell; +use std::rc::Rc; + +use super::AppGroupData; + +// Object holding the state +#[derive(Default)] +pub struct AppGroup { + data: Rc>, +} + +// The central trait for subclassing a GObject +#[glib::object_subclass] +impl ObjectSubclass for AppGroup { + const NAME: &'static str = "AppGroup"; + type Type = super::AppGroup; + type ParentType = glib::Object; +} + +// Trait shared by all GObjects +impl ObjectImpl for AppGroup { + fn properties() -> &'static [ParamSpec] { + static PROPERTIES: Lazy> = Lazy::new(|| { + vec![ + ParamSpec::new_uint( + // Name + "id", + // Nickname + "id", + // Short description + "Name of the application group", + 0, + u32::MAX, + // Default value + 0, + // The property can be read and written to + ParamFlags::READWRITE, + ), + ParamSpec::new_string( + // Name + "name", + // Nickname + "name", + // Short description + "Name of the application group", + // Default value + Some(""), + // The property can be read and written to + ParamFlags::READWRITE, + ), + ParamSpec::new_boolean( + // Name + "mutable", + // Nickname + "mutable", + // Short description + "Mutability of the application group", + // Default value + false, + // The property can be read and written to + ParamFlags::READWRITE, + ), + ParamSpec::new_string( + // Name + "icon", + // Nickname + "icon", + // Short description + "Icon of application Group", + // Default value + Some("folder"), + // The property can be read and written to + ParamFlags::READWRITE, + ), + ParamSpec::new_string( + // Name + "category", + // Nickname + "category", + // Short description + "Category of application Group", + // Default value + None, + // The property can be read and written to + ParamFlags::READWRITE, + ), + ParamSpec::new_variant( + // Name + "appnames", + // Nickname + "appnames", + // Short description + "Names of applications in the App Group", + VariantTy::new("as").expect("Oops invalid string for VariantTy tuple."), + // Default value + None, + // The property can be read and written to + ParamFlags::READWRITE, + ), + ] + }); + PROPERTIES.as_ref() + } + + fn set_property(&self, _obj: &Self::Type, _id: usize, value: &Value, pspec: &ParamSpec) { + match pspec.name() { + "id" => { + let id = value.get().expect("The value needs to be of type `u32`."); + self.data.borrow_mut().id = id; + } + "name" => { + let name = value + .get() + .expect("The value needs to be of type `String`."); + self.data.borrow_mut().name = name; + } + "icon" => { + let icon = value.get().expect("The icon needs to be of type `String`"); + self.data.borrow_mut().icon = icon; + } + "category" => { + let category = value + .get() + .expect("The category needs to be of type `String`"); + self.data.borrow_mut().category = category; + } + "mutable" => { + let mutable = value + .get() + .expect("The mutable property needs to be of type `bool`"); + self.data.borrow_mut().mutable = mutable; + } + "appnames" => { + let appnames = >::from_variant( + &value + .get::() + .expect("The icon needs to be a Variant"), + ) + .expect("The icon variant needs to be a Vec"); + self.data.borrow_mut().app_names = appnames; + } + _ => unimplemented!(), + } + } + + fn property(&self, _obj: &Self::Type, _id: usize, pspec: &ParamSpec) -> Value { + match pspec.name() { + "id" => self.data.borrow().id.to_value(), + "name" => self.data.borrow().name.to_value(), + "icon" => self.data.borrow().icon.to_value(), + "mutable" => self.data.borrow().mutable.to_value(), + "category" => self.data.borrow().category.to_value(), + "appnames" => self.data.borrow().app_names.to_variant().to_value(), + _ => unimplemented!(), + } + } +} diff --git a/examples/app_library/app_group/mod.rs b/examples/app_library/app_group/mod.rs new file mode 100644 index 0000000..a8f2cc7 --- /dev/null +++ b/examples/app_library/app_group/mod.rs @@ -0,0 +1,40 @@ +mod imp; + +use gdk4::glib::Object; +use glib::ObjectExt; +use glib::ToVariant; +use gtk4::glib; +use serde::{Deserialize, Serialize}; + +glib::wrapper! { + pub struct AppGroup(ObjectSubclass); +} + +impl AppGroup { + pub fn new(data: AppGroupData) -> Self { + let self_: Self = Object::new(&[ + ("id", &data.id), + ("name", &data.name), + ("mutable", &data.mutable), + ("icon", &data.icon), + ("category", &data.category), + ]) + .expect("Failed to create `ApplicationObject`."); + if let Err(e) = self_.set_property("appnames", data.app_names.to_variant()) { + println!("failed to set category icon property"); + dbg!(e); + }; + self_ + } +} + +// Object holding the state +#[derive(Default, Serialize, Deserialize, Clone)] +pub struct AppGroupData { + pub id: u32, + pub name: String, + pub icon: String, + pub mutable: bool, + pub app_names: Vec, + pub category: String, +} diff --git a/examples/app_library/app_item/mod.rs b/examples/app_library/app_item/mod.rs deleted file mode 100644 index 2a16d53..0000000 --- a/examples/app_library/app_item/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -use gtk4 as gtk; -mod imp; - -use gtk::prelude::*; -use gtk::subclass::prelude::*; -use gtk::{gio, glib}; - -glib::wrapper! { - pub struct AppItem(ObjectSubclass) - @extends gtk::Widget, gtk::Box; -} - -impl Default for AppItem { - fn default() -> Self { - Self::new() - } -} - -impl AppItem { - pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create AppItem") - } - - pub fn set_app_info(&self, app_info: &gio::AppInfo) { - let self_ = imp::AppItem::from_instance(self); - self_.name.set_text(&app_info.name()); - if let Some(icon) = app_info.icon() { - self_.image.set_from_gicon(&icon); - } - } -} diff --git a/examples/app_library/app_item/app_item.ui b/examples/app_library/grid_item/grid_item.ui similarity index 94% rename from examples/app_library/app_item/app_item.ui rename to examples/app_library/grid_item/grid_item.ui index c418e0a..6c9d582 100644 --- a/examples/app_library/app_item/app_item.ui +++ b/examples/app_library/grid_item/grid_item.ui @@ -1,6 +1,6 @@ -