GtkTreeViewで選択された項目のデータを取得する

GtkTreeView は MVC (モデル・ビュー・コントロール) に従って構成されていますが、 devhelp のマニュアルを見ても、データの取得方法がよくわかりませんでした。こういう場合は、 zenity の tree.c を見れば良いのですが、 zenity-3.2.0 の tree.c では gtk_tree_selection_selected_foreach () を使って、GList 形式の行のすべてのデータを持ってきているのですが、 devhelp では gtk_tree_selection_get_selected_rows() を使えば良いとなっています。

ということで、今回参考にした URL は、 http://foobar.blog23.fc2.com/blog-entry-164.html です。私が勘違いしていたのは、リスト形式の GtkTreeView で model を GList にした場合、それぞれの行が GList の一項目になっていると思っていたのですが、実際はそれぞれの行が GList になっていて、単一のデータ (例えばテキスト)が一行に書かれている場合は、 GList の最初の項目を持ってこなければならないという事です。

プログラムで書くと、 GtkTreeView *treeview の GtkTreeSelection *selection を取得し、 gtk_tree_selection_get_selected () を利用して、GtkTreeView で利用されている model (GtkTreeModel *model ですが、今回は GList だと分かっている) と、現在選択されている行 (GtkTreeIter iter)を取得し、それから GtkTreeModel を使って、 gtk_tree_model_get () を使って、 iter が示す行から 0 番目の項目だけを取得するって感じになります。

gchar*
get_package_name_from_list ()
{
        GtkTreeView *treeview;
        GtkTreeSelection *selection;
        GtkTreeModel *model;
        GtkTreeIter iter;
        gchar *row_string;

        /* get Widget GtkTreeVew and GtkTreeSelection */
        treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview1"));
        selection = gtk_tree_view_get_selection (treeview);

        /* get selected iter and iter value as a string */
        gtk_tree_selection_get_selected (selection, &model, &iter);
        gtk_tree_model_get (model, &iter, 0, &row_string, -1);

        return row_string;
}

glade 使っているので、 GtkBuilder *builder はファイル static な変数にしてます。 builder から treeview を取得する説明は割愛して、 selection = gtk_tree_view_get_selection (treeview); でGtkTreeSelection オブジェクトを取得します。 GtkTreeSelection は GtkTreeView に乗っかっていて、この GtkTreeSelection オブジェクトで GtkTreeView の選択情況を知ることができます。
選択されている行を GtkTreeIter として取得し、 GList の最初の項目をコピーした row_string を返しているのが上のプログラムの一部です。

gtk_tree_model_get () は、引数を複数取ることができる関数なので、最後は -1 を入れて終わりにしています。 GTK+ では時々見る番犬ですね。

GtkTreeView は奥が深く、表示は GtkCellRenderer オブジェクトを使って変更したりできるようです。しかし、そこまでするのなら、 glade 使うのではなく、個別にプログラムを書いていったほうが良いような気がします。 devhelp の glade サンプルを以下に引用します。

<object class="GtkTreeView" id="treeview">
  <property name="model">liststore1</property>
  <child>
    <object class="GtkTreeViewColumn" id="test-column">
      <property name="title">Test</property>
      <child>
        <object class="GtkCellRendererText" id="test-renderer"/>
        <attributes>
          <attribute name="text">1</attribute>
        </attributes>
      </child>
    </object>
  </child>
  <child internal-child="selection">
    <object class="GtkTreeSelection" id="selection">
      <signal name="changed" handler="on_treeview_selection_changed"/>
    </object>
  </child>
</object>

これを見て、ツリー構造ではなくリスト構造になっていて、リストはテキスト形式になっていることが予想できれば、おそらく問題なく使えると思いますが、これじゃわからないんだよな〜。