Drag a string from the GTK+ Application

GTK+ Drag and Drop #(以下 DnD)
で検索すると自アプリ内で DnD が完結するサンプルコードしか見当たらない。
そんな使い道がゼロに等しいサンプルコードではアプリを作る面白さが伝わらない。

実際の話 GUI アプリで DnD って text/uri-list のドロップ以外の使い道がほとんど無い。
text/uri-list は Content Type のことです。

GTK+ や Qt はプロセス間で選択文字列の OLE DnD がデフォルトで可能だったりするし。
Gedit で文字列選択して Firefox の検索バーに DnD するとあら不思議みたいな。
なので Drag 関連はいままで無視してきたけど勉強せねば。

ということで。

GtkTreeView にある文字列を別アプリにドロップなんてどうだろう。
文字列なら Content Type は text/plain ですね。

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

from gi.repository import Gtk, Gdk

class TextDragWin(Gtk.Window):
    def __init__(self):
        """
            TreeView Text "text/plain" Drag
        """
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        # TreeView
        liststore = Gtk.ListStore.new([str])
        for s in ("CBR1000RR", "YZF-R1", "GSX-R1000", "ZX-10R"):
            liststore.append([s])
        cell = Gtk.CellRendererText.new()
        column = Gtk.TreeViewColumn("Super Sports", cell, text=0)
        treeview = Gtk.TreeView.new_with_model(liststore)
        treeview.append_column(column)
        # Drag Source
        #dnd_list = Gtk.TargetEntry.new("text/plain", 0, 0) # Error
        dnd_list = ("text/plain", 0, 0)
        treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, [dnd_list], Gdk.DragAction.COPY)
        treeview.connect("drag-data-get", self.on_drag_data_get)
        #
        self.add(treeview)
        self.show_all()

    def on_drag_data_get(self, widget, context, data, info, time):
        """
            data @ GtkSelectionData
        """
        selection = widget.get_selection()
        model, it = selection.get_selected()
        text = model.get_value(it, 0)
        data.set_text(text, -1)

TextDragWin()
Gtk.main()

listview_dnd

GtkTargetEntry に text/plain を指定。
Drop 時と違ってタプルのリストという PyGtk と同じ指定でないとエラーになる。
PyGI は互換との整合性がまだまだみたい。

gtk_tree_view_enable_model_drag_source はこんな感じで指定。
GDK_BUTTON1_MASK はマウス左ボタンのこと。

drag-data-get シグナルで GtkTreeView で選択状態の文字列を得る。
それを GtkSelectionData に突っ込むという処理を入れただけ。

ドロップターゲット側が text/plain を受け入れる gtk_drag_dest_set を行っているなら受け入れるエフェクトが入る。
ドロップすると GtkSelectionData から文字列を取得し相応の処理を行ってくれる。
と、これだけで別プロセスのアプリでも文字列を普通にドロップできるようだ。

こんなに簡単だったのか、今まで何故知らなかったのだw
そういうことなら Drag の使い道はある、かな…