1

我想要一个 GtkAppChooserButton,它允许用户选择要运行的程序,该程序很可能希望成为诸如 pavucontrol 之类的混音器。尽管关于此事的文档含糊不清,但我收集到应用程序选择器的内容类型是 MIME 类型,但是我找不到适合混音器的 MIME 类型,或者更一般地说只是“所有应用程序”。

如果启用项目,某些类型(例如)application/将提供两个Other Application...选项Other...,它们都是相同的,并且都不包含我拥有的应用程序的一半,包括任何音频混音器。除此之外,我所做的任何事情都无法让我远离我所追求的东西。

音频混音器或所有程序是否有 MIME 类型和/或 GtkAppChooser 内容类型(它们似乎是同一件事?)?(即任何在 Gnome 应用程序启动器/xfce4-whisker-menu/等中具有图标的程序。)

4

1 回答 1

1

好的,所以我想出了一个解决方案,认为它可能不像您希望的那样干净。

该线程提到了一种GtkAppChooser“显示全部”的方法,但它实际上并没有显示您已安装的所有应用程序。但是,从中我能够弄清楚它GtkAppChooser是如何使用的Gio.AppInfo,它具有Gio.AppInfo.get_all()(这是针对 PyObject)返回我已安装的所有应用程序的 Gio.AppInfos 的完整列表,前提是它们具有 .desktop 文件。

所以,我的“解决方案”是编写我自己的应用程序选择器,它从Gio.AppInfo.get_all().

我已经清理了我以前对此的解决方案,并为 inherrit 编写了一个类 '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 中做到这一点而不必做所有这些事情,我仍然很乐意听到它。

于 2017-02-01T16:39:54.870 回答