Как Наутилус решает который значок использовать?

Это - боковая панель моего окна наутилуса. Вы видите два различных значка - один для карт с интерфейсом USB и один для дисков.

Как наутилус определяет, который получает значок жесткого диска и который получает флеш-накопитель один?

6
задан 4 January 2017 в 09:49

1 ответ

TL; DR : Наутилус использует интерфейсы Gio GDrive, GVolume и GVolumeMonitor для получения значков, соответствующих конкретному устройству.

API, диски и значки Gio

В Gio есть набор классов, которые позволяют приложениям читать доступные диски и тома и какие значки с ними связаны (и это то, что API уже обрабатывает). Значки возвращаются в виде Gio Icon, поэтому приложениям не обязательно знать, где находится значок, однако всегда возможен запрос значка по имени или по полному пути. Вы увидите два типа значков: «символические» и пользовательские, и «символические» значки являются стандартными. Если вы посмотрите /usr/share/icons, то обнаружите, что есть много значков, которые заканчиваются на -symbolic в их названии и хранятся в нескольких папках тем (например, стандартные Adwaita, Humanity и Oxygen), обычно файлы .svg. На скриншоте в вопросе значок жесткого диска обозначен drive-harddisk-symbolic и drive-removable-media-usb. Когда пользователь переключает тему рабочего стола, приложению не нужно искать полный путь к значку - если в папке темы есть значок drive-harddisk-symbolic, Gio найдет его и вернется в приложение. Откуда я все это знаю? Я использовал те же значки для моего собственного индикатора UDisks (хотя мой подход отличается от того, что делает Наутилус).

Как Наутилус использует API Джио

Из чтения исходного кода Наутилуса, в частности, кода nautilusgtkplacesview.c , важными являются следующие:

  1. Наутилус добавляет диски и тома (думаю, разделы). Есть функция add_drive , которая использует функцию Gio g_drive_get_volumes (drive) для получения томов на конкретном диске и передает эту информацию в функцию add_volume() Наутилуса. Gio g_volume_monitor_get_volumes() в строках 1139 и g_volume_monitor_get_mounts () 1164 выбирает тома, которые могут быть не связаны с диском (например, ftp или сетевые ресурсы), но эта же информация передается в [ 1113] функции и add_mount() .

  2. Значки запрашиваются для точек монтирования и томов : Внутри функции add_volume() функция g_volume_get_icon() Джио выбирает значок типа GIcon ]. Внутри add_mount() Гио g_mount_get_icon() также типа GIcon. В обоих случаях значок вместе с другой информацией объединяются в объект типа NAUTILUS_TYPE_GTK_PLACES_VIEW_ROW и передаются в функцию insert_row()

  3. Строки, вставленные в Контейнер Places : Меню Places, которое вы показываете в примере, на самом деле является одним из основных типов контейнеров Gtk - Gtk Box. Внутри этого поля есть ListBox для подразделов - вот почему есть разделители для всех пользовательских папок, дисков и томов, а также закладок. Наутилус создает объект, который происходит от типа Gtk Box, G_DEFINE_TYPE_WITH_PRIVATE (NautilusGtkPlacesView, nautilus_gtk_places_view, GTK_TYPE_BOX) . G_DEFINE_TYPE_WITH_PRIVATE - это другая стандартная функция , и, как видно из определения Наутилуса, последний элемент определяет GTK_TYPE_BOX - родительский объект. В файле .c в строке строки 50 определена структура NautilusGtkPlacesViewPrivate, которая, помимо прочего, имеет указатель на виджет ListView. Это фактическое содержание объекта.

    Теперь функция insert_row() берет экземпляр этого типа (NautilusGtkPlacesView *view), подключает всю группу сигналов к элементу строки, полученному в качестве аргумента, и использует gtk_container_add ] вставляет всю информацию (вместе со значком) в виджет ListBox объекта Nautilus Places.

Длинное объяснение и, вероятно, выглядит проще на диаграмме, но также это все написано на C. Давайте попробуем сделать что-то сами в Python, что намного проще и проще.

Пример Python

Вот простое окно, которое использует интерфейс Drive Gio для создания кнопок с иконками, соответствующими подключенным дискам. Это слишком упрощенно и требует доработки, а также встроенных комментариев

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gio,Gtk

class drives_window(Gtk.Window):
    def __init__(self):
        super().__init__(title="Foobar")
        self.volume_monitor = Gio.VolumeMonitor.get()
        # We'll use Gtk.Box to hold all the buttons corresponding to each drive
        # although we haven't connected the buttons to any other function
        # so clicking on the does nothing
        self.box = Gtk.Box()
        for drive in self.volume_monitor.get_connected_drives():
            button = Gtk.Button()
            button.set_label(drive.get_name())  
            button.set_always_show_image(True)
            icon = drive.get_symbolic_icon()
            # buttons need Gtk.Image widget, but .get_symbolic_icon() returns Gio.ThemedIcon
            # so we create new Gtk.Image using .new_From_gicon() function
            # Gtk.IconSize.BUTTON is a constant
            button.set_image(Gtk.Image.new_from_gicon(icon,Gtk.IconSize.BUTTON))
            self.box.pack_start(button,True,True,0)
        # add the box container to this window
        self.add(self.box)

window = drives_window()
window.connect("destroy",Gtk.main_quit)
window.show_all()
Gtk.main()

Более простой подход

Конечно, в настоящее время вам не нужно изобретать велосипед. Gtk предоставляет виджет PlacesSidebar. ​​

#!/usr/bin/env python3
from gi.repository import Gtk,Gio,GLib

w = Gtk.Window()
b1 = Gtk.Box()
p = Gtk.PlacesSidebar()
b1.pack_start(p,True,True,0)
b1.pack_start(Gtk.Button("Hello World"),True,True,0)
b1.pack_start(Gtk.Button("Hello World 2"),True,True,0)

w.add(b1)
w..connect("destroy",Gtk.main_quit)
w.show_all()

Gtk.main()

Sidenote: Наутилус также имеет заголовочный файл nautilus-icon-names.h , который определяет константы с префиксом NAUTILUS_, например

#define NAUTILUS_ICON_FILESYSTEM    "drive-harddisk-symbolic"

, вероятно, для согласованности между разработчиком и кодом, вместо того, чтобы полагаться на поиск реальных имен значков. Единственное место, где используется это конкретное определение, находится в функции get_icon , и эта функция по иронии судьбы не используется для боковой панели Places, но используется внутри функции обновления панели пути . Пойди разберись, верно? ¯\_(ツ)_/¯

<час>
4
ответ дан 23 November 2019 в 07:59

Другие вопросы по тегам:

Похожие вопросы: