gtk4/
recent_data.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ffi::CStr;
4
5use crate::ffi;
6use glib::{collections::StrV, translate::*, GStringPtr};
7
8glib::wrapper! {
9    /// Meta-data to be passed to gtk_recent_manager_add_full() when
10    /// registering a recently used resource.
11    #[doc(alias = "GtkRecentData")]
12    pub struct RecentData(BoxedInline<ffi::GtkRecentData>);
13
14    match fn {
15        init => |ptr| init_recent_data(ptr),
16        copy_into => |dest, src| copy_into_recent_data(dest, src),
17        clear => |ptr| clear_recent_data(ptr),
18    }
19}
20
21impl RecentData {
22    #[inline]
23    pub fn new(
24        display_name: Option<&str>,
25        description: Option<&str>,
26        mime_type: &str,
27        app_name: &str,
28        app_exec: &str,
29        groups: &[&str],
30        is_private: bool,
31    ) -> Self {
32        assert_initialized_main_thread!();
33        unsafe {
34            Self::unsafe_from(ffi::GtkRecentData {
35                display_name: display_name.to_glib_full(),
36                description: description.to_glib_full(),
37                mime_type: mime_type.to_glib_full(),
38                app_name: app_name.to_glib_full(),
39                app_exec: app_exec.to_glib_full(),
40                groups: groups.to_glib_full(),
41                is_private: is_private.into_glib(),
42            })
43        }
44    }
45
46    #[inline]
47    pub fn display_name(&self) -> Option<&str> {
48        unsafe {
49            if self.inner.display_name.is_null() {
50                None
51            } else {
52                CStr::from_ptr(self.inner.display_name).to_str().ok()
53            }
54        }
55    }
56
57    #[inline]
58    pub fn description(&self) -> Option<&str> {
59        unsafe {
60            if self.inner.description.is_null() {
61                None
62            } else {
63                CStr::from_ptr(self.inner.description).to_str().ok()
64            }
65        }
66    }
67
68    #[inline]
69    pub fn mime_type(&self) -> &str {
70        unsafe { CStr::from_ptr(self.inner.mime_type).to_str().unwrap() }
71    }
72
73    #[inline]
74    pub fn app_name(&self) -> &str {
75        unsafe { CStr::from_ptr(self.inner.app_name).to_str().unwrap() }
76    }
77
78    #[inline]
79    pub fn app_exec(&self) -> &str {
80        unsafe { CStr::from_ptr(self.inner.app_exec).to_str().unwrap() }
81    }
82
83    #[inline]
84    pub fn groups<'a>(&self) -> &'a [GStringPtr] {
85        unsafe { StrV::from_glib_borrow(self.inner.groups as *const _) }
86    }
87
88    #[inline]
89    pub fn is_private(&self) -> bool {
90        unsafe { from_glib(self.inner.is_private) }
91    }
92}
93
94unsafe fn init_recent_data(recent_data: *mut ffi::GtkRecentData) {
95    std::ptr::write(recent_data, std::mem::zeroed());
96}
97
98unsafe fn copy_into_recent_data(dest: *mut ffi::GtkRecentData, src: *const ffi::GtkRecentData) {
99    init_recent_data(dest);
100    (*dest).display_name = glib::ffi::g_strdup((*src).display_name);
101    (*dest).description = glib::ffi::g_strdup((*src).description);
102    (*dest).mime_type = glib::ffi::g_strdup((*src).mime_type);
103    (*dest).app_name = glib::ffi::g_strdup((*src).app_name);
104    (*dest).app_exec = glib::ffi::g_strdup((*src).app_exec);
105    (*dest).groups = glib::ffi::g_strdupv((*src).groups);
106    (*dest).is_private = (*src).is_private;
107}
108
109unsafe fn clear_recent_data(recent_data: *mut ffi::GtkRecentData) {
110    glib::ffi::g_free((*recent_data).display_name as *mut _);
111    glib::ffi::g_free((*recent_data).description as *mut _);
112    glib::ffi::g_free((*recent_data).mime_type as *mut _);
113    glib::ffi::g_free((*recent_data).app_name as *mut _);
114    glib::ffi::g_free((*recent_data).app_exec as *mut _);
115    glib::ffi::g_strfreev((*recent_data).groups as *mut _);
116}