Paepoi

Paepoi » Gedit Tips » Gedit プラグインの作り方

Gedit プラグインの作り方

このページは Gedit 3.12 以降 GtkHeaderBar 化後の解説です。

Gedit 2 はこちら
Gedit 3.10 以前はこちら

魔改造版である Ubuntu 用を除くすべての Gedit で動作します
とはいえプログラミングをする人なら Ubuntu を選ばないので問題は無い

# 最終更新日 2018.07.22

準備

プラグインは C か Python3、又は vala でしか作れません。
一応 vala でも作れるようですが実装例を見たことがありません。
ココでは Python3 のみを解説します。

公式 HowTo Apps/Gedit/PythonPluginHowTo - GNOME Wiki!
は残念ながら 2018 年現在でも 3.10 以前のままです。
メニューバーなんてとうの昔に無くなっているのに。
サブクラスの作成方法が変わっただけでメソッドは共通なので参考にはなります。

*.plugin
*.py

の最低 2 つのファイルが必要、Python コードはもちろん分割してもよい。

*.plugin

下記の要領で testtest.plugin という名前にして保存しておきます。
[Plugin]
Loader=python3
Module=testtest
IAge=3
Name=testtest
Name[ja]=テストテスト
Description=plugin test
Description[ja]=プラグインのテスト
Authors=sasakima-nao <sasakimanao@gmail.com>
Copyright=Copyright © 2015 sasakima-nao <sasakimanao@gmail.com>
Website=http://palepoli.skr.jp/

キー
Loaderpython3(固定)
Module読み込む Python スクリプトから拡張子を除いた名前
IAge3(固定)
NameGedit の設定でプラグインタブを開いた時に表示される名前
DescriptionGedit の設定でプラグインタブを開いた時に表示される説明
***[ja]各国ごとに翻訳
見ての通り

*.py

上記 Module で指定した testtest.py スクリプトを作成します。
複雑になった気がしますが完全にお約束化したので実は簡単です。
なんたってメニューバーという癌が無いので。

3.18 からは PyGObject 側の仕様変更で gi バージョン指定が必要。
無くても動きますが警告が標準出力に書き出されます。

gtk_application_add_accelerator は現在非推奨になっています

#!/usr/bin/env python3

# @ 3.18 からバージョン指定必須
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gedit", "3.0")
gi.require_version("Peas", "1.0")
 
from gi.repository import GObject, Gedit, Gtk, Gio
 
class TestTestAppActivatable(GObject.Object, Gedit.AppActivatable):
    """
        Set GMenu and Accelerator
    """
    app = GObject.property(type=Gedit.App)
 
    def __init__(self):
        GObject.Object.__init__(self)
 
    def do_activate(self):
        # Set Keyboard Shortcuts
        self.app.set_accels_for_action("win.action_name", ["<Control>B"])
        #self.app.add_accelerator("<Control>B", "win.action_name", None) # deprecated
        #
        # Append Menu
        item = Gio.MenuItem.new("メニュー文字列",  "win.action_name")
        self.menu_ext = self.extend_menu("tools-section")
        self.menu_ext.append_menu_item(item)
 
    def do_deactivate(self):
        # Remove Accelerator
        self.app.remove_accelerator("win.action_name", None)
 
class TestTest(GObject.Object, Gedit.WindowActivatable):
    """
        Set GAction
    """
    __gtype_name__ = "TestTest"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)
        self.messagebox("init")
 
    def do_activate(self):
        # Set Action
        # (action name, parameter or None)
        action = Gio.SimpleAction.new("action_name", None)
        action.connect('activate', self.on_test_activate)
        self.window.add_action(action)
        self.messagebox("activate")
 
    def do_deactivate(self):
        # Remove Action
        self.window.remove_action("action_name")
        self.messagebox("deactivate")
 
    def do_update_state(self):
        pass
 
    def on_test_activate(self, action, param):
        self.messagebox("はろぉプラグイン!")
 
    def messagebox(self, text):
        dlg = Gtk.MessageDialog(
                self.window,
                Gtk.DialogFlags.MODAL,
                Gtk.MessageType.WARNING,
                Gtk.ButtonsType.OK,
                text)
        r = dlg.run()
        dlg.destroy()

直接実行ではないので本当は #!/usr/bin/env python3 というシバンは不要です。
ただし GNOME の ContentType に text/x-python3 が追加されました。
Gedit 等で編集する場合に Python3 だと明確に認識させたい場合には必要です。

もちろん __main__ もいりません、クラスとメソッドのみを記述する。

サブクラスは 2 つ必要。
上側は GtkApplication へ、下側は GtkApplicationWindow へ登録になる。

do_ で始まるメソッドはオーバーライドなのは知っていると思う。
知らないのに作ろうとしてるなら、ぼーくぼーくワラっちゃいます♪
actibate シグナルを捕まえたら登録、deactivate で破棄します。

まずはアクション名を決める(上記では 'action_name')。
GtkApplicationWindow に登録するには win.action_name とプリフィクスを付ける。
GtkApplication に登録するには app.action_name とプリフィクスを付ける。

次はアクション名にアクセラレータキーに紐付ける
そしてメニューに表示する文字列を決め GMenu を作成。
メニューの file-section, tools-section, view-section-2 等々に突っ込む。
GtkApplication 側はここまで。

次に GtkApplicationWindow 側。
先程のアクション名で GAction を作成しシグナルハンドラをセット。
そのシグナルハンドラにメニューで選択された場合の処理を記述していきます。

基本的に以上、以下は細かいこと。

__init__(self) は Python お約束の初期化。
この時点では self.app, self.window は None ですので何もしない。

__gtype_name__ は class 名と同じにしなければいけない。

do_update_state は表示状態が少しでも変わると飛んでくるので注意。
メニューの有効無効を切り換える際等に利用する。

この messagebox 関数は下記にある実験用です。
__init__ では何もしないほうが無難です。

配置

作成した2つのファイルは以下のディレクトリを作成し配置、これで準備は完了。

~/.local/share/gedit/plugins

このスクリプトを Gedit で書いた場合は Gedit を再起動しないと指定できません。
起動時にプラグインディレクトリをスキャンするようなので間違えないように。

試してみる


再起動すると設定のプラグインタブに「テスト」がある。

img/activate312.png
チェックを入れたり外したりして有効無効を試してみましょう。
有効にすると init と activate のダイアログが出ました。
deactivate は無効にすると反応しますね。

init では self.window は None として処理されるので親ウインドウ無しになる。
なので Gedit のセンターではなく画面センターに出ます。

有効にしたまま Gedit を再起動すると起動枚にダイアログが出ます。
動的処理なので v2 時とは違い init は有効にする毎に反応します。

しかしプラグインコードの書き換えは有効無効の切り替えのみでは反映されない。
素直に Gedit を再起動してください。

最後に、メニューのツールを選択してみましょう。

img/gedit_plugin_menu.png

上記は tools-section に登録したのでココに配置されます。
そのメニューを選択するとダイアログが出るのを確認できるはず。

その他

パネルを自作して本体に挿入や削除をする場合も activate で行います。
def do_activate(self):
    # etc...
    bottom = self.window.get_bottom_panel()
    bottom.add_item(self.outputpanel, "Test", "Test", image)

def do_deactivate(self):
    # etc...
    bottom = self.window.get_bottom_panel()
    bottom.remove_item(self.outputpanel)
この作業は Gtk+ そのものなので Gtk+ のヘルプで。

Gedit 及び Eye of Gnome プラグイン
ページに自作プラグインを置いていますのでよかったら参考に。
Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.