Хорошо, поэтому я придумал решение, подумал, что это может быть не так чисто, как вы надеялись.
This thread упомянул способ получения GtkAppChooser
«показать все», но на самом деле не показывает все приложения, которые вы установили. Однако из этого я смог выяснить, как GtkAppChooser
использует Gio.AppInfo
, который имеет Gio.AppInfo.get_all()
(это для PyObject), который возвращает полный список Gio.AppInfos для всех приложений, которые я установил, при условии, что они имеют файл .desktop.
Итак, мое «решение» должно написать мой собственный выбор приложений, который получает список приложений от Gio.AppInfo.get_all()
.
Я очистил свое предыдущее решение и написал класс «AllAppChooser» для наследования Gtk.Dialog
, что дает гораздо большую настройку. Заполненный диалог выглядит так:
И код, используемый:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio
class AllAppChooser(Gtk.Dialog):
"""Provide a dialog to select an app from all those installed.
The regular Gtk.AppChooserDialog does not seem to provide any way to allow
selection from all installed apps, so this dialog serves as a replacement.
"""
def __init__(self, parent=None):
super().__init__(self)
self.set_default_size(350, 400)
self.set_icon_name('gtk-search')
self.set_title('App Chooser')
if parent:
self.set_parent(parent)
self.content_box = self.get_content_area()
self.content_box.set_margin_left(8)
self.content_box.set_margin_right(8)
self.content_box.set_margin_top(8)
self.content_box.set_margin_bottom(8)
self.content_box.set_spacing(8)
self.button_box = self.get_action_area()
self.button_box.set_margin_left(4)
self.button_box.set_margin_right(4)
self.button_box.set_margin_top(4)
self.button_box.set_margin_bottom(4)
self.label = Gtk.Label('Choose An Application')
self.content_box.pack_start(self.label, False, False, 0)
self.list_store = Gtk.ListStore(str, str, int)
pixbuf_renderer = Gtk.CellRendererPixbuf()
text_renderer = Gtk.CellRendererText()
icon_column = Gtk.TreeViewColumn('icon', pixbuf_renderer, icon_name=1)
text_column = Gtk.TreeViewColumn('text', text_renderer, text=0)
self.tree_view = Gtk.TreeView()
self.tree_view.set_model(self.list_store)
self.tree_view.set_headers_visible(False)
self.tree_view.append_column(icon_column)
self.tree_view.append_column(text_column)
self.view_port = Gtk.Viewport()
self.view_port.add(self.tree_view)
self.scroll_window = Gtk.ScrolledWindow()
self.scroll_window.add(self.view_port)
self.content_box.pack_start(self.scroll_window, True, True, 0)
self.ok_button = self.add_button(Gtk.STOCK_OK, 1)
self.ok_button.connect('clicked', self.on_ok)
self.cancel_button = self.add_button(Gtk.STOCK_CANCEL, 0)
self.selected_app = None
self.app_list = []
def populate_app_list(self):
"""Populate the list of apps with all installed apps.
Icons are provided by icon-name, however some apps may return a full
path to a custom icon rather than a themed-icon name, or even no name
at all. In these cases the generic 'gtk-missing-icon' icon is used.
"""
self.app_list = Gio.AppInfo.get_all()
for i in range(len(self.app_list)):
gio_icon = self.app_list[i].get_icon()
app_icon = 'gtk-missing-icon'
if gio_icon:
app_icon = gio_icon.to_string()
app_name = self.app_list[i].get_display_name()
self.list_store.append([app_name, app_icon, i])
self.list_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
def run(self):
"""Run the dialog to get a selected app."""
self.populate_app_list()
self.show_all()
super().run()
self.destroy()
return self.selected_app
def set_label(self, text):
"""Set the label text, \"Choose An App\" by default."""
self.label.set_text(text)
def on_ok(self, button):
"""Get Gio.AppInfo of selected app when user presses OK."""
selection = self.tree_view.get_selection()
tree_model, tree_iter = selection.get_selected()
app_index = tree_model.get_value(tree_iter, 2)
self.selected_app = self.app_list[app_index]
Это затем запустить похож на обычный диалог:
app_chooser = AllAppChooser()
application = app_chooser.run()
Если пользователь выходит из диалоговое окно или нажмите «Отмена», тогда результат будет «Нет», но если они выбрали приложение, то run()
вернет Gio.AppInfo
для приложения, которое вы можете делать, когда захотите. Например, для запуска нового выбранного приложения:
application.launch()
Я считаю, что это теперь относительно твердый раствор, но я до сих пор приветствовать дополнительные предложения. Кроме того, если есть способ сделать это в Gtk без необходимости делать все это, я все равно буду любить его слушать.