app_chooser_button.vala 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2012-2026 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: GPL-3.0-or-later
  4. */
  5. namespace Crown
  6. {
  7. public class AppChooserButton : Gtk.Box
  8. {
  9. public const string APP_PREDEFINED = "predefined"; ///< Open with a predefined system application.
  10. public const string APP_DEFAULT = "default"; ///< Open with the default application for the file type.
  11. public const string APP_CUSTOM = "custom"; ///< Open with a custom application defined by the user.
  12. // See: https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkappchooserbutton.c
  13. public enum ModelColumn
  14. {
  15. APP_INFO,
  16. NAME
  17. }
  18. public Gtk.EventControllerScroll _controller_scroll;
  19. public Gtk.AppChooserButton _app_chooser_button;
  20. public AppChooserButton(string mime_type)
  21. {
  22. Object(orientation: Gtk.Orientation.HORIZONTAL);
  23. _app_chooser_button = new Gtk.AppChooserButton(mime_type);
  24. _app_chooser_button.append_custom_item(APP_DEFAULT, "Open by extension", null);
  25. _app_chooser_button.set_active_custom_item(APP_DEFAULT);
  26. #if CROWN_PLATFORM_LINUX
  27. _app_chooser_button.show_dialog_item = true;
  28. #endif
  29. #if CROWN_GTK3
  30. _app_chooser_button.scroll_event.connect(() => {
  31. GLib.Signal.stop_emission_by_name(_app_chooser_button, "scroll-event");
  32. return Gdk.EVENT_PROPAGATE;
  33. });
  34. #else
  35. _controller_scroll = new Gtk.EventControllerScroll(Gtk.EventControllerScrollFlags.BOTH_AXES);
  36. _controller_scroll.set_propagation_phase(Gtk.PropagationPhase.CAPTURE);
  37. _controller_scroll.scroll.connect(() => {
  38. // Do nothing, just consume the event to stop
  39. // the annoying scroll default behavior.
  40. });
  41. _app_chooser_button.add_controller(_controller_scroll);
  42. #endif
  43. this.pack_start(_app_chooser_button);
  44. }
  45. public GLib.AppInfo? get_app_info()
  46. {
  47. return _app_chooser_button.get_app_info();
  48. }
  49. /// Sets the app to @a app_name. If @a app_name is APP_PREDEFINED, it tries
  50. /// to set the predefined app based @a app_id.
  51. public void set_app(string app_name, string? app_id)
  52. {
  53. if (app_name != APP_PREDEFINED) {
  54. _app_chooser_button.set_active_custom_item(app_name);
  55. return;
  56. }
  57. if (app_id == null) {
  58. _app_chooser_button.set_active_custom_item(APP_DEFAULT);
  59. return;
  60. }
  61. _app_chooser_button.model.foreach((model, path, iter) => {
  62. Value val;
  63. model.get_value(iter, ModelColumn.APP_INFO, out val);
  64. GLib.AppInfo app_info = (GLib.AppInfo)val;
  65. if (app_info != null && app_info.get_id() == app_id) {
  66. _app_chooser_button.set_active_iter(iter);
  67. return true;
  68. }
  69. return false;
  70. });
  71. }
  72. /// Returns the item name of the selected application. If the application is predefined,
  73. /// it returns its @a app_id.
  74. public string selected_app(out string? app_id)
  75. {
  76. app_id = null;
  77. Gtk.TreeIter iter;
  78. if (_app_chooser_button.get_active_iter(out iter)) {
  79. Value val;
  80. _app_chooser_button.model.get_value(iter, ModelColumn.NAME, out val);
  81. string name = (string)val;
  82. if (name != null)
  83. return name;
  84. GLib.AppInfo app_info = _app_chooser_button.get_app_info();
  85. if (app_info != null) {
  86. app_id = app_info.get_id();
  87. return AppChooserButton.APP_PREDEFINED;
  88. }
  89. }
  90. return APP_DEFAULT;
  91. }
  92. }
  93. } /* namespace Crown */