GtkMenuButton “gears” menu

何を今頃気になった。
Nautilus 3.6 からメニューがボタンになったけどアレは新規 Widget だった。

GtkMenuButton

gears_menu

ギアアイコン側の呼び方は gears menu でいいのかな。
GtkMenuButton を作成すると矢印アイコンにはなるけどギアにするには?
今後設定はこのギアアイコンのボタンを使えになるかもしれないし探さなきゃ。

しかしいくら devhelp を漁ってもそんな方法は見つからない。
海外を検索してもよく解らない、ええい面倒だ!
ということで素直に Nautilus のソースコードを落として直接調べてみる。

image = Gtk.Image()
image.set_from_icon_name("emblem-system-symbolic", Gtk.IconSize.MENU)
menubutton.set_image(image)

とやっていた、いや元は当然 C 言語なんだけど。
ということは /usr/share/icons 以下のどこかにギアの画像がありそうだ。

/usr/share/icons/gnome/scalable/emblems/emblem-system-symbolic.svg

svg ファイルを見つけた、コレを貼り付けるってことか。
gnome ディレクトリ以下なら Ubuntu でも問題なく使えそうなので試してみる。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from gi.repository import Gtk

GEARS_MENU = """<ui>
    <popup name="Popup">
        <menuitem action="open"/>
        <menuitem action="quit"/>
    </popup>
</ui>"""

class GearsMenuWin(Gtk.Window):
    """
        Gears Menu Sample
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_title("Nautilus 3.6 Menu")
        self.connect("delete-event", self.on_quit)
        # GtkUIManager
        uimanager = Gtk.UIManager()
        self.add_accel_group(uimanager.get_accel_group())
        actiongroup = Gtk.ActionGroup("NautilusMenu")
        actiongroup.add_actions([
            ("open", Gtk.STOCK_OPEN, None, None, "Null", self.on_open),
            ("quit", Gtk.STOCK_QUIT, None, None, "Quit", self.on_quit) ])
        uimanager.insert_action_group(actiongroup, 0)
        uimanager.add_ui_from_string(GEARS_MENU)
        # PopupMenu
        popup = uimanager.get_widget("/Popup")
        popup.props.halign = Gtk.Align.CENTER
        # GtkMenuButton
        menubutton = Gtk.MenuButton.new()
        menubutton.set_popup(popup)
        # Arrow Direction
        #menubutton.set_direction(Gtk.ArrowType.UP)
        # Gear Image
        image = Gtk.Image()
        image.set_from_icon_name("emblem-system-symbolic", Gtk.IconSize.MENU)
        menubutton.set_image(image)
        # Widget etc...
        label = Gtk.Label("Nautilus 3.6 Menu")
        drawingarea = Gtk.DrawingArea()
        # Pack
        hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(menubutton, False, False, 0)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(hbox, False, False, 0)
        vbox.pack_start(drawingarea, True, True, 0)
        self.add(vbox)
        #
        self.resize(320, 240)
        self.show_all()

    def on_open(self, action, data=None):
        pass

    def on_quit(self, action, data=None):
        Gtk.main_quit()

GearsMenuWin()
Gtk.main()

gears_menu_for_ubuntu

GNOME3 環境だけでなく Ubuntu 12.10 でもしっかり gears-menu になるようだ。
多分 GTK+ 3.6 以降が使える環境ならどのディストリでもいいと思うが保証はしない。
ストックメニューなので日本語化もアクセラレーターもバッチリ。

コレって右クリックメニューとも共用なんかもできるのかな。
GNOME は右クリックメニューを無くしたいのだろうけど当面は無理だよね。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from gi.repository import Gtk, Gdk

class GearsMenuWin(Gtk.Window):
    """
        This code accelerator keys are displayed
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_title("Nautilus 3.6 Menu")
        self.connect("delete-event", self.on_quit)
        # Add Accelerator
        accelgroup = Gtk.AccelGroup.new()
        self.add_accel_group(accelgroup)
        # MenuIten
        item_open = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_OPEN, accelgroup)
        item_open.connect("activate", self.on_open)
        item_quit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, accelgroup)
        item_quit.connect("activate", self.on_quit)
        # Show
        item_open.show()
        item_quit.show()
        # Menu
        popup = Gtk.Menu.new()
        popup.append(item_open)
        popup.append(item_quit)
        popup.props.halign = Gtk.Align.CENTER
        # GtkMenuButton
        menubutton = Gtk.MenuButton.new()
        menubutton.set_popup(popup)
        # Gear Image
        image = Gtk.Image()
        image.set_from_icon_name("emblem-system-symbolic", Gtk.IconSize.MENU)
        menubutton.set_image(image)
        # Widget etc...
        label = Gtk.Label("Nautilus 3.6 Menu")
        drawingarea = Gtk.DrawingArea()
        # Pack
        hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(menubutton, False, False, 0)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(hbox, False, False, 0)
        vbox.pack_start(drawingarea, True, True, 0)
        self.add(vbox)
        # Mouse Right Button Clicked
        self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.STRUCTURE_MASK )
        self.connect("button_press_event", self.on_button_press, popup)
        #
        self.resize(320, 240)
        self.show_all()

    def on_open(self, action, data=None):
        pass

    def on_quit(self, action, data=None):
        Gtk.main_quit()

    def on_button_press(self, widget, event, popup):
        if event.button == 3:
            popup.popup(None, None, None, None, 0, event.time)

GearsMenuWin()
Gtk.main()

gears_menu_into_accelerator

ものは試しで GtkUIManager を使わずコードで書いてみたんだが…
コッチだとアクセラレーターキーが表示されているじゃないの、何故だ?

ついでにコードで作ると show() しないと GtkMenuItem が表示されないと今頃知った。
これが関係あるのかもと思って以下をやってみたけど関係ないようだ。

uimanager.get_widget("/Popup/open").show() # No...

どちらでも Ctrl+Q で終了できるからアクセラレーターは問題ないのだが。
とにかく表示する手段があるなら次期 Nautilus はキーを表示してほしいです。

とにかくストック svg を利用する方法もオマケで解ったし得した気分。