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