1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use glib_ffi::{GList, g_list_append, gpointer};
use gtk_ffi::GtkWidget;
use info_provider::FileInfo;
use libc::c_void;
use nautilus_ffi::{NautilusPropertyPageProvider, nautilus_property_page_new};
use std::borrow::Cow;
use std::ffi::CString;
use std::ptr;
use std::sync::Mutex;
use std::sync::atomic::{AtomicUsize, Ordering};
use translate::file_info_vec_from_g_list;
pub struct PropertyPage {
pub name: Cow<'static, str>,
pub raw_label: *mut GtkWidget,
pub raw_page: *mut GtkWidget,
}
impl PropertyPage {
pub fn new<S: Into<Cow<'static, str>>>(name: S, raw_label: *mut GtkWidget, raw_page: *mut GtkWidget) -> PropertyPage {
PropertyPage {
name: name.into(),
raw_label,
raw_page,
}
}
}
pub trait PropertyPageProvider : Send {
fn get_pages(&self, files: &[FileInfo]) -> Vec<PropertyPage>;
}
macro_rules! property_page_provider_iface {
($iface_init_fn:ident, $get_pages_fn:ident, $rust_provider:ident, $set_rust_provider:ident) => {
#[no_mangle]
pub unsafe extern "C" fn $iface_init_fn(iface: gpointer, _: gpointer) {
use nautilus_ffi::NautilusPropertyPageProviderIface;
let iface_struct = iface as *mut NautilusPropertyPageProviderIface;
(*iface_struct).get_pages = Some($get_pages_fn);
}
#[no_mangle]
pub extern "C" fn $get_pages_fn(_provider: *mut NautilusPropertyPageProvider, raw_files: *mut GList) -> *mut GList {
let mut pages_g_list = ptr::null_mut();
let pages = match *$rust_provider.lock().unwrap() {
Some(ref p) => p.get_pages(&file_info_vec_from_g_list(raw_files)),
None => Vec::new(),
};
for page in pages {
let name = CString::new(&page.name as &str).unwrap().into_raw();
let label = page.raw_label;
let page_widget = page.raw_page;
unsafe {
let page_c = nautilus_property_page_new(name, label, page_widget);
pages_g_list = g_list_append(pages_g_list, page_c as *mut c_void);
let _ = CString::from_raw(name);
}
}
pages_g_list
}
pub fn $set_rust_provider(page_provider: Box<dyn PropertyPageProvider>) {
*$rust_provider.lock().unwrap() = Some(page_provider);
}
lazy_static! {
static ref $rust_provider: Mutex<Option<Box<dyn PropertyPageProvider>>> = Mutex::new(None);
}
}
}
property_page_provider_iface!(property_page_provider_iface_init_0, property_page_provider_get_pages_0, PROPERTY_PAGE_PROVIDER_0, set_property_page_provider_0);
property_page_provider_iface!(property_page_provider_iface_init_1, property_page_provider_get_pages_1, PROPERTY_PAGE_PROVIDER_1, set_property_page_provider_1);
property_page_provider_iface!(property_page_provider_iface_init_2, property_page_provider_get_pages_2, PROPERTY_PAGE_PROVIDER_2, set_property_page_provider_2);
property_page_provider_iface!(property_page_provider_iface_init_3, property_page_provider_get_pages_3, PROPERTY_PAGE_PROVIDER_3, set_property_page_provider_3);
property_page_provider_iface!(property_page_provider_iface_init_4, property_page_provider_get_pages_4, PROPERTY_PAGE_PROVIDER_4, set_property_page_provider_4);
property_page_provider_iface!(property_page_provider_iface_init_5, property_page_provider_get_pages_5, PROPERTY_PAGE_PROVIDER_5, set_property_page_provider_5);
property_page_provider_iface!(property_page_provider_iface_init_6, property_page_provider_get_pages_6, PROPERTY_PAGE_PROVIDER_6, set_property_page_provider_6);
property_page_provider_iface!(property_page_provider_iface_init_7, property_page_provider_get_pages_7, PROPERTY_PAGE_PROVIDER_7, set_property_page_provider_7);
property_page_provider_iface!(property_page_provider_iface_init_8, property_page_provider_get_pages_8, PROPERTY_PAGE_PROVIDER_8, set_property_page_provider_8);
property_page_provider_iface!(property_page_provider_iface_init_9, property_page_provider_get_pages_9, PROPERTY_PAGE_PROVIDER_9, set_property_page_provider_9);
pub fn property_page_provider_iface_externs() -> Vec<unsafe extern "C" fn(gpointer, gpointer)> {
vec![
property_page_provider_iface_init_0,
property_page_provider_iface_init_1,
property_page_provider_iface_init_2,
property_page_provider_iface_init_3,
property_page_provider_iface_init_4,
property_page_provider_iface_init_5,
property_page_provider_iface_init_6,
property_page_provider_iface_init_7,
property_page_provider_iface_init_8,
property_page_provider_iface_init_9,
]
}
pub fn rust_property_page_provider_setters() -> Vec<fn(Box<dyn PropertyPageProvider>)> {
vec![
set_property_page_provider_0,
set_property_page_provider_1,
set_property_page_provider_2,
set_property_page_provider_3,
set_property_page_provider_4,
set_property_page_provider_5,
set_property_page_provider_6,
set_property_page_provider_7,
set_property_page_provider_8,
set_property_page_provider_9,
]
}
static NEXT_PROPERTY_PAGE_PROVIDER_IFACE_INDEX: AtomicUsize = AtomicUsize::new(0);
pub fn take_next_property_page_provider_iface_index() -> usize {
NEXT_PROPERTY_PAGE_PROVIDER_IFACE_INDEX.fetch_add(1, Ordering::SeqCst)
}