1use crate::{ffi, Window};
6use glib::{
7 prelude::*,
8 signal::{connect_raw, SignalHandlerId},
9 translate::*,
10};
11use std::{boxed::Box as Box_, pin::Pin};
12
13glib::wrapper! {
14 #[doc(alias = "GtkFileLauncher")]
51 pub struct FileLauncher(Object<ffi::GtkFileLauncher, ffi::GtkFileLauncherClass>);
52
53 match fn {
54 type_ => || ffi::gtk_file_launcher_get_type(),
55 }
56}
57
58impl FileLauncher {
59 #[doc(alias = "gtk_file_launcher_new")]
67 pub fn new(file: Option<&impl IsA<gio::File>>) -> FileLauncher {
68 assert_initialized_main_thread!();
69 unsafe {
70 from_glib_full(ffi::gtk_file_launcher_new(
71 file.map(|p| p.as_ref()).to_glib_none().0,
72 ))
73 }
74 }
75
76 #[cfg(feature = "v4_12")]
82 #[cfg_attr(docsrs, doc(cfg(feature = "v4_12")))]
83 #[doc(alias = "gtk_file_launcher_get_always_ask")]
84 #[doc(alias = "get_always_ask")]
85 #[doc(alias = "always-ask")]
86 pub fn must_always_ask(&self) -> bool {
87 unsafe { from_glib(ffi::gtk_file_launcher_get_always_ask(self.to_glib_none().0)) }
88 }
89
90 #[doc(alias = "gtk_file_launcher_get_file")]
96 #[doc(alias = "get_file")]
97 pub fn file(&self) -> Option<gio::File> {
98 unsafe { from_glib_none(ffi::gtk_file_launcher_get_file(self.to_glib_none().0)) }
99 }
100
101 #[cfg(feature = "v4_14")]
107 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
108 #[doc(alias = "gtk_file_launcher_get_writable")]
109 #[doc(alias = "get_writable")]
110 #[doc(alias = "writable")]
111 pub fn is_writable(&self) -> bool {
112 unsafe { from_glib(ffi::gtk_file_launcher_get_writable(self.to_glib_none().0)) }
113 }
114
115 #[doc(alias = "gtk_file_launcher_launch")]
126 pub fn launch<P: FnOnce(Result<(), glib::Error>) + 'static>(
127 &self,
128 parent: Option<&impl IsA<Window>>,
129 cancellable: Option<&impl IsA<gio::Cancellable>>,
130 callback: P,
131 ) {
132 let main_context = glib::MainContext::ref_thread_default();
133 let is_main_context_owner = main_context.is_owner();
134 let has_acquired_main_context = (!is_main_context_owner)
135 .then(|| main_context.acquire().ok())
136 .flatten();
137 assert!(
138 is_main_context_owner || has_acquired_main_context.is_some(),
139 "Async operations only allowed if the thread is owning the MainContext"
140 );
141
142 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
143 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
144 unsafe extern "C" fn launch_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
145 _source_object: *mut glib::gobject_ffi::GObject,
146 res: *mut gio::ffi::GAsyncResult,
147 user_data: glib::ffi::gpointer,
148 ) {
149 let mut error = std::ptr::null_mut();
150 ffi::gtk_file_launcher_launch_finish(_source_object as *mut _, res, &mut error);
151 let result = if error.is_null() {
152 Ok(())
153 } else {
154 Err(from_glib_full(error))
155 };
156 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
157 Box_::from_raw(user_data as *mut _);
158 let callback: P = callback.into_inner();
159 callback(result);
160 }
161 let callback = launch_trampoline::<P>;
162 unsafe {
163 ffi::gtk_file_launcher_launch(
164 self.to_glib_none().0,
165 parent.map(|p| p.as_ref()).to_glib_none().0,
166 cancellable.map(|p| p.as_ref()).to_glib_none().0,
167 Some(callback),
168 Box_::into_raw(user_data) as *mut _,
169 );
170 }
171 }
172
173 pub fn launch_future(
174 &self,
175 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
176 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
177 let parent = parent.map(ToOwned::to_owned);
178 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
179 obj.launch(
180 parent.as_ref().map(::std::borrow::Borrow::borrow),
181 Some(cancellable),
182 move |res| {
183 send.resolve(res);
184 },
185 );
186 }))
187 }
188
189 #[doc(alias = "gtk_file_launcher_open_containing_folder")]
201 pub fn open_containing_folder<P: FnOnce(Result<(), glib::Error>) + 'static>(
202 &self,
203 parent: Option<&impl IsA<Window>>,
204 cancellable: Option<&impl IsA<gio::Cancellable>>,
205 callback: P,
206 ) {
207 let main_context = glib::MainContext::ref_thread_default();
208 let is_main_context_owner = main_context.is_owner();
209 let has_acquired_main_context = (!is_main_context_owner)
210 .then(|| main_context.acquire().ok())
211 .flatten();
212 assert!(
213 is_main_context_owner || has_acquired_main_context.is_some(),
214 "Async operations only allowed if the thread is owning the MainContext"
215 );
216
217 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
218 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
219 unsafe extern "C" fn open_containing_folder_trampoline<
220 P: FnOnce(Result<(), glib::Error>) + 'static,
221 >(
222 _source_object: *mut glib::gobject_ffi::GObject,
223 res: *mut gio::ffi::GAsyncResult,
224 user_data: glib::ffi::gpointer,
225 ) {
226 let mut error = std::ptr::null_mut();
227 ffi::gtk_file_launcher_open_containing_folder_finish(
228 _source_object as *mut _,
229 res,
230 &mut error,
231 );
232 let result = if error.is_null() {
233 Ok(())
234 } else {
235 Err(from_glib_full(error))
236 };
237 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
238 Box_::from_raw(user_data as *mut _);
239 let callback: P = callback.into_inner();
240 callback(result);
241 }
242 let callback = open_containing_folder_trampoline::<P>;
243 unsafe {
244 ffi::gtk_file_launcher_open_containing_folder(
245 self.to_glib_none().0,
246 parent.map(|p| p.as_ref()).to_glib_none().0,
247 cancellable.map(|p| p.as_ref()).to_glib_none().0,
248 Some(callback),
249 Box_::into_raw(user_data) as *mut _,
250 );
251 }
252 }
253
254 pub fn open_containing_folder_future(
255 &self,
256 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
257 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
258 let parent = parent.map(ToOwned::to_owned);
259 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
260 obj.open_containing_folder(
261 parent.as_ref().map(::std::borrow::Borrow::borrow),
262 Some(cancellable),
263 move |res| {
264 send.resolve(res);
265 },
266 );
267 }))
268 }
269
270 #[cfg(feature = "v4_12")]
277 #[cfg_attr(docsrs, doc(cfg(feature = "v4_12")))]
278 #[doc(alias = "gtk_file_launcher_set_always_ask")]
279 #[doc(alias = "always-ask")]
280 pub fn set_always_ask(&self, always_ask: bool) {
281 unsafe {
282 ffi::gtk_file_launcher_set_always_ask(self.to_glib_none().0, always_ask.into_glib());
283 }
284 }
285
286 #[doc(alias = "gtk_file_launcher_set_file")]
290 #[doc(alias = "file")]
291 pub fn set_file(&self, file: Option<&impl IsA<gio::File>>) {
292 unsafe {
293 ffi::gtk_file_launcher_set_file(
294 self.to_glib_none().0,
295 file.map(|p| p.as_ref()).to_glib_none().0,
296 );
297 }
298 }
299
300 #[cfg(feature = "v4_14")]
304 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
305 #[doc(alias = "gtk_file_launcher_set_writable")]
306 #[doc(alias = "writable")]
307 pub fn set_writable(&self, writable: bool) {
308 unsafe {
309 ffi::gtk_file_launcher_set_writable(self.to_glib_none().0, writable.into_glib());
310 }
311 }
312
313 #[cfg(feature = "v4_12")]
314 #[cfg_attr(docsrs, doc(cfg(feature = "v4_12")))]
315 #[doc(alias = "always-ask")]
316 pub fn connect_always_ask_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
317 unsafe extern "C" fn notify_always_ask_trampoline<F: Fn(&FileLauncher) + 'static>(
318 this: *mut ffi::GtkFileLauncher,
319 _param_spec: glib::ffi::gpointer,
320 f: glib::ffi::gpointer,
321 ) {
322 let f: &F = &*(f as *const F);
323 f(&from_glib_borrow(this))
324 }
325 unsafe {
326 let f: Box_<F> = Box_::new(f);
327 connect_raw(
328 self.as_ptr() as *mut _,
329 c"notify::always-ask".as_ptr() as *const _,
330 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
331 notify_always_ask_trampoline::<F> as *const (),
332 )),
333 Box_::into_raw(f),
334 )
335 }
336 }
337
338 #[cfg(feature = "v4_10")]
339 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
340 #[doc(alias = "file")]
341 pub fn connect_file_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
342 unsafe extern "C" fn notify_file_trampoline<F: Fn(&FileLauncher) + 'static>(
343 this: *mut ffi::GtkFileLauncher,
344 _param_spec: glib::ffi::gpointer,
345 f: glib::ffi::gpointer,
346 ) {
347 let f: &F = &*(f as *const F);
348 f(&from_glib_borrow(this))
349 }
350 unsafe {
351 let f: Box_<F> = Box_::new(f);
352 connect_raw(
353 self.as_ptr() as *mut _,
354 c"notify::file".as_ptr() as *const _,
355 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
356 notify_file_trampoline::<F> as *const (),
357 )),
358 Box_::into_raw(f),
359 )
360 }
361 }
362
363 #[cfg(feature = "v4_14")]
364 #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))]
365 #[doc(alias = "writable")]
366 pub fn connect_writable_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
367 unsafe extern "C" fn notify_writable_trampoline<F: Fn(&FileLauncher) + 'static>(
368 this: *mut ffi::GtkFileLauncher,
369 _param_spec: glib::ffi::gpointer,
370 f: glib::ffi::gpointer,
371 ) {
372 let f: &F = &*(f as *const F);
373 f(&from_glib_borrow(this))
374 }
375 unsafe {
376 let f: Box_<F> = Box_::new(f);
377 connect_raw(
378 self.as_ptr() as *mut _,
379 c"notify::writable".as_ptr() as *const _,
380 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
381 notify_writable_trampoline::<F> as *const (),
382 )),
383 Box_::into_raw(f),
384 )
385 }
386 }
387}