I am basically following the gtk-rs book to create a simple app. I have the following rust struct, which I want to display in a ListView. This struct is basically read-only and should not be edited, so I do not want to expose it's members as properties and I also do not want to create it from GTK itself (it's created inside the rust-only business logic). I would like to expose the entire struct as one property.
pub struct Video {
pub number: u32,
pub encoding: Encoding,
pub chapters: Vec<Chapter>,
}
pub struct Chapter {
pub number: u32,
pub filename: String,
pub thumbnail_filename: Option<String>,
pub preview_video_filename: Option<String>,
}
How can I wrap this inside a GObject? I'm trying to create the following wrapper:
mod imp {
#[derive(Default)]
pub struct VideoObject {
pub data: Rc<RefCell<Video>>,
}
#[glib::object_subclass]
impl ObjectSubclass for VideoObject {
const NAME: &'static str = "VideoObject";
type Type = super::VideoObject;
}
impl ObjectImpl for VideoObject {}
}
pub const VIDEO_PROPERTY: &str = "video";
glib::wrapper! {
pub struct VideoObject(ObjectSubclass<imp::VideoObject>);
}
impl VideoObject {
pub fn new(video: Video) -> Self {
Object::new(&[]).expect("Could not create VideoObject")
}
}
This fails because Video does not implement Default. I thought about wrapping it inside an Option
like data: Rc<RefCell<Option<Video>>>
, which compiles. Unfortunately, then I'm stuck on how to set it as a property.
I guess one way would be to use a ParamSpecPointer
, box and leak Video
and then pass it before, but this strucks me as unsafe and ugly...
Is there a better way to do it?
You can directly access the "imp" object and set fields manually. No need to transform everything into GObject properties:
impl VideoObject {
pub fn new(video: Video) -> Self {
let object = Object::new(&[]).unwrap();
let imp = imp::VideoObject::from_instance(&object);
imp.data.replace(Some(video));
object
}
}