2017-01-31 17 views
1

Я хотел бы иметь GtkAppChooserButton, который позволяет пользователю выбирать программу для запуска, которая, скорее всего, будет использоваться для микшера аудио, такого как pavucontrol. Несмотря на туманную документацию по этому вопросу, я понимаю, что тип контента для выбранного приложения является типом MIME, однако я не могу найти подходящий тип MIME для аудиомикшера или, в более общем смысле, просто «все приложения».GtkAppChooser Тип контента для всех приложений и/или аудиомикшеров

Некоторые типы, такие как application/, предоставят два варианта Other Application..., если включены Other... элементов, оба из которых идентичны, и ни одна из них не содержит половины приложений, которые у меня есть, включая любые аудиомикшеры. Кроме того, ничто другое, что я делаю, не дает мне удаленно близко к тому, что мне нужно.

Существует ли тип MIME и/или тип содержимого GtkAppChooser (они, похоже, одно и то же?) Для аудиомикшеров или только для всех программ в целом? (Т.е. любая программа, которая имела бы значок в подобных приложениях запуска Gnome/xfce4-whisker-menu/etc.)

ответ

1

Хорошо, поэтому я придумал решение, подумал, что это может быть не так чисто, как вы надеялись.

This thread упомянул способ получения GtkAppChooser «показать все», но на самом деле не показывает все приложения, которые вы установили. Однако из этого я смог выяснить, как GtkAppChooser использует Gio.AppInfo, который имеет Gio.AppInfo.get_all() (это для PyObject), который возвращает полный список Gio.AppInfos для всех приложений, которые я установил, при условии, что они имеют файл .desktop.

Итак, мое «решение» должно написать мой собственный выбор приложений, который получает список приложений от Gio.AppInfo.get_all().

Я очистил свое предыдущее решение и написал класс «AllAppChooser» для наследования Gtk.Dialog, что дает гораздо большую настройку. Заполненный диалог выглядит так:

enter image description here

И код, используемый:

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 без необходимости делать все это, я все равно буду любить его слушать.