1use crate::{ffi, AppInfoCreateFlags, AppLaunchContext, AsyncResult, Cancellable, File, Icon};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10 #[doc(alias = "GAppInfo")]
11 pub struct AppInfo(Interface<ffi::GAppInfo, ffi::GAppInfoIface>);
12
13 match fn {
14 type_ => || ffi::g_app_info_get_type(),
15 }
16}
17
18impl AppInfo {
19 pub const NONE: Option<&'static AppInfo> = None;
20
21 #[doc(alias = "g_app_info_create_from_commandline")]
22 pub fn create_from_commandline(
23 commandline: impl AsRef<std::ffi::OsStr>,
24 application_name: Option<&str>,
25 flags: AppInfoCreateFlags,
26 ) -> Result<AppInfo, glib::Error> {
27 unsafe {
28 let mut error = std::ptr::null_mut();
29 let ret = ffi::g_app_info_create_from_commandline(
30 commandline.as_ref().to_glib_none().0,
31 application_name.to_glib_none().0,
32 flags.into_glib(),
33 &mut error,
34 );
35 if error.is_null() {
36 Ok(from_glib_full(ret))
37 } else {
38 Err(from_glib_full(error))
39 }
40 }
41 }
42
43 #[doc(alias = "g_app_info_get_all")]
44 #[doc(alias = "get_all")]
45 pub fn all() -> Vec<AppInfo> {
46 unsafe { FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_all()) }
47 }
48
49 #[doc(alias = "g_app_info_get_all_for_type")]
50 #[doc(alias = "get_all_for_type")]
51 pub fn all_for_type(content_type: &str) -> Vec<AppInfo> {
52 unsafe {
53 FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_all_for_type(
54 content_type.to_glib_none().0,
55 ))
56 }
57 }
58
59 #[doc(alias = "g_app_info_get_default_for_type")]
60 #[doc(alias = "get_default_for_type")]
61 pub fn default_for_type(content_type: &str, must_support_uris: bool) -> Option<AppInfo> {
62 unsafe {
63 from_glib_full(ffi::g_app_info_get_default_for_type(
64 content_type.to_glib_none().0,
65 must_support_uris.into_glib(),
66 ))
67 }
68 }
69
70 #[cfg(feature = "v2_74")]
71 #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
72 #[doc(alias = "g_app_info_get_default_for_type_async")]
73 #[doc(alias = "get_default_for_type_async")]
74 pub fn default_for_type_async<P: FnOnce(Result<AppInfo, glib::Error>) + 'static>(
75 content_type: &str,
76 must_support_uris: bool,
77 cancellable: Option<&impl IsA<Cancellable>>,
78 callback: P,
79 ) {
80 let main_context = glib::MainContext::ref_thread_default();
81 let is_main_context_owner = main_context.is_owner();
82 let has_acquired_main_context = (!is_main_context_owner)
83 .then(|| main_context.acquire().ok())
84 .flatten();
85 assert!(
86 is_main_context_owner || has_acquired_main_context.is_some(),
87 "Async operations only allowed if the thread is owning the MainContext"
88 );
89
90 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
91 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
92 unsafe extern "C" fn default_for_type_async_trampoline<
93 P: FnOnce(Result<AppInfo, glib::Error>) + 'static,
94 >(
95 _source_object: *mut glib::gobject_ffi::GObject,
96 res: *mut crate::ffi::GAsyncResult,
97 user_data: glib::ffi::gpointer,
98 ) {
99 let mut error = std::ptr::null_mut();
100 let ret = ffi::g_app_info_get_default_for_type_finish(res, &mut error);
101 let result = if error.is_null() {
102 Ok(from_glib_full(ret))
103 } else {
104 Err(from_glib_full(error))
105 };
106 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
107 Box_::from_raw(user_data as *mut _);
108 let callback: P = callback.into_inner();
109 callback(result);
110 }
111 let callback = default_for_type_async_trampoline::<P>;
112 unsafe {
113 ffi::g_app_info_get_default_for_type_async(
114 content_type.to_glib_none().0,
115 must_support_uris.into_glib(),
116 cancellable.map(|p| p.as_ref()).to_glib_none().0,
117 Some(callback),
118 Box_::into_raw(user_data) as *mut _,
119 );
120 }
121 }
122
123 #[cfg(feature = "v2_74")]
124 #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
125 pub fn default_for_type_future(
126 content_type: &str,
127 must_support_uris: bool,
128 ) -> Pin<Box_<dyn std::future::Future<Output = Result<AppInfo, glib::Error>> + 'static>> {
129 let content_type = String::from(content_type);
130 Box_::pin(crate::GioFuture::new(
131 &(),
132 move |_obj, cancellable, send| {
133 Self::default_for_type_async(
134 &content_type,
135 must_support_uris,
136 Some(cancellable),
137 move |res| {
138 send.resolve(res);
139 },
140 );
141 },
142 ))
143 }
144
145 #[doc(alias = "g_app_info_get_default_for_uri_scheme")]
146 #[doc(alias = "get_default_for_uri_scheme")]
147 pub fn default_for_uri_scheme(uri_scheme: &str) -> Option<AppInfo> {
148 unsafe {
149 from_glib_full(ffi::g_app_info_get_default_for_uri_scheme(
150 uri_scheme.to_glib_none().0,
151 ))
152 }
153 }
154
155 #[cfg(feature = "v2_74")]
156 #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
157 #[doc(alias = "g_app_info_get_default_for_uri_scheme_async")]
158 #[doc(alias = "get_default_for_uri_scheme_async")]
159 pub fn default_for_uri_scheme_async<P: FnOnce(Result<AppInfo, glib::Error>) + 'static>(
160 uri_scheme: &str,
161 cancellable: Option<&impl IsA<Cancellable>>,
162 callback: P,
163 ) {
164 let main_context = glib::MainContext::ref_thread_default();
165 let is_main_context_owner = main_context.is_owner();
166 let has_acquired_main_context = (!is_main_context_owner)
167 .then(|| main_context.acquire().ok())
168 .flatten();
169 assert!(
170 is_main_context_owner || has_acquired_main_context.is_some(),
171 "Async operations only allowed if the thread is owning the MainContext"
172 );
173
174 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
175 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
176 unsafe extern "C" fn default_for_uri_scheme_async_trampoline<
177 P: FnOnce(Result<AppInfo, glib::Error>) + 'static,
178 >(
179 _source_object: *mut glib::gobject_ffi::GObject,
180 res: *mut crate::ffi::GAsyncResult,
181 user_data: glib::ffi::gpointer,
182 ) {
183 let mut error = std::ptr::null_mut();
184 let ret = ffi::g_app_info_get_default_for_uri_scheme_finish(res, &mut error);
185 let result = if error.is_null() {
186 Ok(from_glib_full(ret))
187 } else {
188 Err(from_glib_full(error))
189 };
190 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
191 Box_::from_raw(user_data as *mut _);
192 let callback: P = callback.into_inner();
193 callback(result);
194 }
195 let callback = default_for_uri_scheme_async_trampoline::<P>;
196 unsafe {
197 ffi::g_app_info_get_default_for_uri_scheme_async(
198 uri_scheme.to_glib_none().0,
199 cancellable.map(|p| p.as_ref()).to_glib_none().0,
200 Some(callback),
201 Box_::into_raw(user_data) as *mut _,
202 );
203 }
204 }
205
206 #[cfg(feature = "v2_74")]
207 #[cfg_attr(docsrs, doc(cfg(feature = "v2_74")))]
208 pub fn default_for_uri_scheme_future(
209 uri_scheme: &str,
210 ) -> Pin<Box_<dyn std::future::Future<Output = Result<AppInfo, glib::Error>> + 'static>> {
211 let uri_scheme = String::from(uri_scheme);
212 Box_::pin(crate::GioFuture::new(
213 &(),
214 move |_obj, cancellable, send| {
215 Self::default_for_uri_scheme_async(&uri_scheme, Some(cancellable), move |res| {
216 send.resolve(res);
217 });
218 },
219 ))
220 }
221
222 #[doc(alias = "g_app_info_get_fallback_for_type")]
223 #[doc(alias = "get_fallback_for_type")]
224 pub fn fallback_for_type(content_type: &str) -> Vec<AppInfo> {
225 unsafe {
226 FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_fallback_for_type(
227 content_type.to_glib_none().0,
228 ))
229 }
230 }
231
232 #[doc(alias = "g_app_info_get_recommended_for_type")]
233 #[doc(alias = "get_recommended_for_type")]
234 pub fn recommended_for_type(content_type: &str) -> Vec<AppInfo> {
235 unsafe {
236 FromGlibPtrContainer::from_glib_full(ffi::g_app_info_get_recommended_for_type(
237 content_type.to_glib_none().0,
238 ))
239 }
240 }
241
242 #[doc(alias = "g_app_info_launch_default_for_uri")]
243 pub fn launch_default_for_uri(
244 uri: &str,
245 context: Option<&impl IsA<AppLaunchContext>>,
246 ) -> Result<(), glib::Error> {
247 unsafe {
248 let mut error = std::ptr::null_mut();
249 let is_ok = ffi::g_app_info_launch_default_for_uri(
250 uri.to_glib_none().0,
251 context.map(|p| p.as_ref()).to_glib_none().0,
252 &mut error,
253 );
254 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
255 if error.is_null() {
256 Ok(())
257 } else {
258 Err(from_glib_full(error))
259 }
260 }
261 }
262
263 #[doc(alias = "g_app_info_launch_default_for_uri_async")]
264 pub fn launch_default_for_uri_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
265 uri: &str,
266 context: Option<&impl IsA<AppLaunchContext>>,
267 cancellable: Option<&impl IsA<Cancellable>>,
268 callback: P,
269 ) {
270 let main_context = glib::MainContext::ref_thread_default();
271 let is_main_context_owner = main_context.is_owner();
272 let has_acquired_main_context = (!is_main_context_owner)
273 .then(|| main_context.acquire().ok())
274 .flatten();
275 assert!(
276 is_main_context_owner || has_acquired_main_context.is_some(),
277 "Async operations only allowed if the thread is owning the MainContext"
278 );
279
280 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
281 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
282 unsafe extern "C" fn launch_default_for_uri_async_trampoline<
283 P: FnOnce(Result<(), glib::Error>) + 'static,
284 >(
285 _source_object: *mut glib::gobject_ffi::GObject,
286 res: *mut crate::ffi::GAsyncResult,
287 user_data: glib::ffi::gpointer,
288 ) {
289 let mut error = std::ptr::null_mut();
290 ffi::g_app_info_launch_default_for_uri_finish(res, &mut error);
291 let result = if error.is_null() {
292 Ok(())
293 } else {
294 Err(from_glib_full(error))
295 };
296 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
297 Box_::from_raw(user_data as *mut _);
298 let callback: P = callback.into_inner();
299 callback(result);
300 }
301 let callback = launch_default_for_uri_async_trampoline::<P>;
302 unsafe {
303 ffi::g_app_info_launch_default_for_uri_async(
304 uri.to_glib_none().0,
305 context.map(|p| p.as_ref()).to_glib_none().0,
306 cancellable.map(|p| p.as_ref()).to_glib_none().0,
307 Some(callback),
308 Box_::into_raw(user_data) as *mut _,
309 );
310 }
311 }
312
313 pub fn launch_default_for_uri_future(
314 uri: &str,
315 context: Option<&(impl IsA<AppLaunchContext> + Clone + 'static)>,
316 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
317 let uri = String::from(uri);
318 let context = context.map(ToOwned::to_owned);
319 Box_::pin(crate::GioFuture::new(
320 &(),
321 move |_obj, cancellable, send| {
322 Self::launch_default_for_uri_async(
323 &uri,
324 context.as_ref().map(::std::borrow::Borrow::borrow),
325 Some(cancellable),
326 move |res| {
327 send.resolve(res);
328 },
329 );
330 },
331 ))
332 }
333
334 #[doc(alias = "g_app_info_reset_type_associations")]
335 pub fn reset_type_associations(content_type: &str) {
336 unsafe {
337 ffi::g_app_info_reset_type_associations(content_type.to_glib_none().0);
338 }
339 }
340}
341
342pub trait AppInfoExt: IsA<AppInfo> + 'static {
343 #[doc(alias = "g_app_info_add_supports_type")]
344 fn add_supports_type(&self, content_type: &str) -> Result<(), glib::Error> {
345 unsafe {
346 let mut error = std::ptr::null_mut();
347 let is_ok = ffi::g_app_info_add_supports_type(
348 self.as_ref().to_glib_none().0,
349 content_type.to_glib_none().0,
350 &mut error,
351 );
352 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
353 if error.is_null() {
354 Ok(())
355 } else {
356 Err(from_glib_full(error))
357 }
358 }
359 }
360
361 #[doc(alias = "g_app_info_can_delete")]
362 fn can_delete(&self) -> bool {
363 unsafe { from_glib(ffi::g_app_info_can_delete(self.as_ref().to_glib_none().0)) }
364 }
365
366 #[doc(alias = "g_app_info_can_remove_supports_type")]
367 fn can_remove_supports_type(&self) -> bool {
368 unsafe {
369 from_glib(ffi::g_app_info_can_remove_supports_type(
370 self.as_ref().to_glib_none().0,
371 ))
372 }
373 }
374
375 #[doc(alias = "g_app_info_delete")]
376 fn delete(&self) -> bool {
377 unsafe { from_glib(ffi::g_app_info_delete(self.as_ref().to_glib_none().0)) }
378 }
379
380 #[doc(alias = "g_app_info_dup")]
381 #[must_use]
382 fn dup(&self) -> AppInfo {
383 unsafe { from_glib_full(ffi::g_app_info_dup(self.as_ref().to_glib_none().0)) }
384 }
385
386 #[doc(alias = "g_app_info_equal")]
387 fn equal(&self, appinfo2: &impl IsA<AppInfo>) -> bool {
388 unsafe {
389 from_glib(ffi::g_app_info_equal(
390 self.as_ref().to_glib_none().0,
391 appinfo2.as_ref().to_glib_none().0,
392 ))
393 }
394 }
395
396 #[doc(alias = "g_app_info_get_commandline")]
397 #[doc(alias = "get_commandline")]
398 fn commandline(&self) -> Option<std::path::PathBuf> {
399 unsafe {
400 from_glib_none(ffi::g_app_info_get_commandline(
401 self.as_ref().to_glib_none().0,
402 ))
403 }
404 }
405
406 #[doc(alias = "g_app_info_get_description")]
407 #[doc(alias = "get_description")]
408 fn description(&self) -> Option<glib::GString> {
409 unsafe {
410 from_glib_none(ffi::g_app_info_get_description(
411 self.as_ref().to_glib_none().0,
412 ))
413 }
414 }
415
416 #[doc(alias = "g_app_info_get_display_name")]
417 #[doc(alias = "get_display_name")]
418 fn display_name(&self) -> glib::GString {
419 unsafe {
420 from_glib_none(ffi::g_app_info_get_display_name(
421 self.as_ref().to_glib_none().0,
422 ))
423 }
424 }
425
426 #[doc(alias = "g_app_info_get_executable")]
427 #[doc(alias = "get_executable")]
428 fn executable(&self) -> std::path::PathBuf {
429 unsafe {
430 from_glib_none(ffi::g_app_info_get_executable(
431 self.as_ref().to_glib_none().0,
432 ))
433 }
434 }
435
436 #[doc(alias = "g_app_info_get_icon")]
437 #[doc(alias = "get_icon")]
438 fn icon(&self) -> Option<Icon> {
439 unsafe { from_glib_none(ffi::g_app_info_get_icon(self.as_ref().to_glib_none().0)) }
440 }
441
442 #[doc(alias = "g_app_info_get_id")]
443 #[doc(alias = "get_id")]
444 fn id(&self) -> Option<glib::GString> {
445 unsafe { from_glib_none(ffi::g_app_info_get_id(self.as_ref().to_glib_none().0)) }
446 }
447
448 #[doc(alias = "g_app_info_get_name")]
449 #[doc(alias = "get_name")]
450 fn name(&self) -> glib::GString {
451 unsafe { from_glib_none(ffi::g_app_info_get_name(self.as_ref().to_glib_none().0)) }
452 }
453
454 #[doc(alias = "g_app_info_get_supported_types")]
455 #[doc(alias = "get_supported_types")]
456 fn supported_types(&self) -> Vec<glib::GString> {
457 unsafe {
458 FromGlibPtrContainer::from_glib_none(ffi::g_app_info_get_supported_types(
459 self.as_ref().to_glib_none().0,
460 ))
461 }
462 }
463
464 #[doc(alias = "g_app_info_launch")]
465 fn launch(
466 &self,
467 files: &[File],
468 context: Option<&impl IsA<AppLaunchContext>>,
469 ) -> Result<(), glib::Error> {
470 unsafe {
471 let mut error = std::ptr::null_mut();
472 let is_ok = ffi::g_app_info_launch(
473 self.as_ref().to_glib_none().0,
474 files.to_glib_none().0,
475 context.map(|p| p.as_ref()).to_glib_none().0,
476 &mut error,
477 );
478 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
479 if error.is_null() {
480 Ok(())
481 } else {
482 Err(from_glib_full(error))
483 }
484 }
485 }
486
487 #[doc(alias = "g_app_info_launch_uris")]
488 fn launch_uris(
489 &self,
490 uris: &[&str],
491 context: Option<&impl IsA<AppLaunchContext>>,
492 ) -> Result<(), glib::Error> {
493 unsafe {
494 let mut error = std::ptr::null_mut();
495 let is_ok = ffi::g_app_info_launch_uris(
496 self.as_ref().to_glib_none().0,
497 uris.to_glib_none().0,
498 context.map(|p| p.as_ref()).to_glib_none().0,
499 &mut error,
500 );
501 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
502 if error.is_null() {
503 Ok(())
504 } else {
505 Err(from_glib_full(error))
506 }
507 }
508 }
509
510 #[doc(alias = "g_app_info_remove_supports_type")]
511 fn remove_supports_type(&self, content_type: &str) -> Result<(), glib::Error> {
512 unsafe {
513 let mut error = std::ptr::null_mut();
514 let is_ok = ffi::g_app_info_remove_supports_type(
515 self.as_ref().to_glib_none().0,
516 content_type.to_glib_none().0,
517 &mut error,
518 );
519 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
520 if error.is_null() {
521 Ok(())
522 } else {
523 Err(from_glib_full(error))
524 }
525 }
526 }
527
528 #[doc(alias = "g_app_info_set_as_default_for_extension")]
529 fn set_as_default_for_extension(
530 &self,
531 extension: impl AsRef<std::path::Path>,
532 ) -> Result<(), glib::Error> {
533 unsafe {
534 let mut error = std::ptr::null_mut();
535 let is_ok = ffi::g_app_info_set_as_default_for_extension(
536 self.as_ref().to_glib_none().0,
537 extension.as_ref().to_glib_none().0,
538 &mut error,
539 );
540 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
541 if error.is_null() {
542 Ok(())
543 } else {
544 Err(from_glib_full(error))
545 }
546 }
547 }
548
549 #[doc(alias = "g_app_info_set_as_default_for_type")]
550 fn set_as_default_for_type(&self, content_type: &str) -> Result<(), glib::Error> {
551 unsafe {
552 let mut error = std::ptr::null_mut();
553 let is_ok = ffi::g_app_info_set_as_default_for_type(
554 self.as_ref().to_glib_none().0,
555 content_type.to_glib_none().0,
556 &mut error,
557 );
558 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
559 if error.is_null() {
560 Ok(())
561 } else {
562 Err(from_glib_full(error))
563 }
564 }
565 }
566
567 #[doc(alias = "g_app_info_set_as_last_used_for_type")]
568 fn set_as_last_used_for_type(&self, content_type: &str) -> Result<(), glib::Error> {
569 unsafe {
570 let mut error = std::ptr::null_mut();
571 let is_ok = ffi::g_app_info_set_as_last_used_for_type(
572 self.as_ref().to_glib_none().0,
573 content_type.to_glib_none().0,
574 &mut error,
575 );
576 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
577 if error.is_null() {
578 Ok(())
579 } else {
580 Err(from_glib_full(error))
581 }
582 }
583 }
584
585 #[doc(alias = "g_app_info_should_show")]
586 fn should_show(&self) -> bool {
587 unsafe { from_glib(ffi::g_app_info_should_show(self.as_ref().to_glib_none().0)) }
588 }
589
590 #[doc(alias = "g_app_info_supports_files")]
591 fn supports_files(&self) -> bool {
592 unsafe {
593 from_glib(ffi::g_app_info_supports_files(
594 self.as_ref().to_glib_none().0,
595 ))
596 }
597 }
598
599 #[doc(alias = "g_app_info_supports_uris")]
600 fn supports_uris(&self) -> bool {
601 unsafe {
602 from_glib(ffi::g_app_info_supports_uris(
603 self.as_ref().to_glib_none().0,
604 ))
605 }
606 }
607}
608
609impl<O: IsA<AppInfo>> AppInfoExt for O {}