dnd in keywords tree
authorVladimir Nadvornik <nadvornik@suse.cz>
Sun, 8 Mar 2009 09:56:40 +0000 (09:56 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Sun, 8 Mar 2009 09:56:40 +0000 (09:56 +0000)
improved dnd in advanced exif

src/advanced_exif.c
src/bar_exif.c
src/bar_keywords.c
src/dnd.h
src/metadata.c
src/metadata.h

index dcc07ea..667f332 100644 (file)
@@ -45,7 +45,6 @@ struct _ExifWin
        GtkWidget *listview;
 
        FileData *fd;
-       gchar *sel_key;
 };
 
 enum {
@@ -230,13 +229,31 @@ static GtkTargetEntry advanced_exif_drag_types[] = {
 static gint n_exif_drag_types = 1;
 
 
-static void advanced_exif_dnd_get(GtkWidget *entry, GdkDragContext *context,
+static void advanced_exif_dnd_get(GtkWidget *listview, GdkDragContext *context,
                                     GtkSelectionData *selection_data, guint info,
                                     guint time, gpointer data)
 {
        ExifWin *ew = data;
+       GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); 
+       GtkTreeIter iter;
+
+       if (gtk_tree_selection_get_selected(sel, NULL, &iter)) 
+               {
+               GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
+               gchar *key;
+
+               gtk_tree_model_get(store, &iter, EXIF_ADVCOL_NAME, &key, -1);
+               gtk_selection_data_set_text(selection_data, key, -1);
+               printf("%s\n",key);
+               g_free(key);
+               }
+
+}
 
-       gtk_selection_data_set_text(selection_data, ew->sel_key, -1);
+static void advanced_exif_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
+{
+       GtkWidget *window = data;
+       gtk_widget_destroy(window);
 }
 
 static void advanced_exif_dnd_begin(GtkWidget *listview, GdkDragContext *context, gpointer data)
@@ -244,24 +261,30 @@ static void advanced_exif_dnd_begin(GtkWidget *listview, GdkDragContext *context
        ExifWin *ew = data;
        GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); 
        GtkTreeIter iter;
-       ew->sel_key = NULL;
 
        if (gtk_tree_selection_get_selected(sel, NULL, &iter)) 
                {
                GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
+               gchar *key;
+               GtkWidget *window;
+               GtkWidget *label;
+
+               gtk_tree_model_get(store, &iter, EXIF_ADVCOL_NAME, &key, -1);
+
+               window = gtk_window_new(GTK_WINDOW_POPUP);
+               gtk_widget_realize (window);
+
+               label = gtk_label_new(key);
+               gtk_container_add(GTK_CONTAINER (window), label);
+               gtk_widget_show(label);
+               gtk_drag_set_icon_widget(context, window, -15, 10);
+               g_signal_connect(G_OBJECT(listview), "drag_end",
+                                G_CALLBACK(advanced_exif_dnd_end), window);
 
-               gtk_tree_model_get(store, &iter, EXIF_ADVCOL_NAME, &ew->sel_key, -1);
-               printf("%s\n",ew->sel_key);
+               g_free(key);
                }
-               
 }
 
-static void advanced_exif_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
-{
-       ExifWin *ew = data;
-       g_free(ew->sel_key);
-       ew->sel_key = NULL;
-}
 
 
 static void advanced_exif_add_column(GtkWidget *listview, const gchar *title, gint n, gint sizable)
@@ -343,8 +366,6 @@ GtkWidget *advanced_exif_new(void)
 
        gtk_tree_view_set_search_column(GTK_TREE_VIEW(ew->listview), EXIF_ADVCOL_NAME);
 
-//     advanced_exif_add_column_check(ew->listview, "", EXIF_ADVCOL_ENABLED);
-
        advanced_exif_add_column(ew->listview, _("Description"), EXIF_ADVCOL_DESCRIPTION, FALSE);
        advanced_exif_add_column(ew->listview, _("Value"), EXIF_ADVCOL_VALUE, TRUE);
        advanced_exif_add_column(ew->listview, _("Name"), EXIF_ADVCOL_NAME, FALSE);
@@ -352,18 +373,16 @@ GtkWidget *advanced_exif_new(void)
        advanced_exif_add_column(ew->listview, _("Format"), EXIF_ADVCOL_FORMAT, FALSE);
        advanced_exif_add_column(ew->listview, _("Elements"), EXIF_ADVCOL_ELEMENTS, FALSE);
 
-       gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(ew->listview),
-                                              GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
-                                              advanced_exif_drag_types, n_exif_drag_types,
-                                              GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
+       gtk_drag_source_set(ew->listview,
+                          GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+                          advanced_exif_drag_types, n_exif_drag_types,
+                          GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
 
        g_signal_connect(G_OBJECT(ew->listview), "drag_data_get",
                         G_CALLBACK(advanced_exif_dnd_get), ew);
 
        g_signal_connect(G_OBJECT(ew->listview), "drag_begin",
                         G_CALLBACK(advanced_exif_dnd_begin), ew);
-       g_signal_connect(G_OBJECT(ew->listview), "drag_end",
-                        G_CALLBACK(advanced_exif_dnd_end), ew);
 
        ew->scrolled = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ew->scrolled), GTK_SHADOW_IN);
index 37f3b2f..03b68ce 100644 (file)
@@ -350,7 +350,7 @@ static void bar_pane_exif_dnd_init(GtkWidget *pane)
        gtk_drag_dest_set(pane,
                          GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
                          bar_pane_exif_drop_types, n_exif_entry_drop_types,
-                         GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
+                         GDK_ACTION_COPY | GDK_ACTION_MOVE);
        g_signal_connect(G_OBJECT(pane), "drag_data_received",
                         G_CALLBACK(bar_pane_exif_dnd_receive), NULL);
 }
index ea98a41..a5dade2 100644 (file)
@@ -27,6 +27,7 @@
 #include "ui_menu.h"
 #include "rcfile.h"
 #include "layout.h"
+#include "dnd.h"
 
 static const gchar *keyword_favorite_defaults[] = {
        N_("Favorite"),
@@ -285,7 +286,10 @@ static void bar_pane_keywords_keyword_toggle(GtkCellRendererToggle *toggle, cons
                
        keyword_list_push(pkd->keyword_view, list);
        string_list_free(list);
+       /*
+         keyword_list_push triggers bar_pane_keywords_change which calls bar_keyword_tree_sync, no need to do it again
        bar_keyword_tree_sync(pkd);
+       */
 }
 
 void bar_pane_keywords_filter_modify(GtkTreeModel *model, GtkTreeIter *iter, GValue *value, gint column, gpointer data)
@@ -293,7 +297,7 @@ void bar_pane_keywords_filter_modify(GtkTreeModel *model, GtkTreeIter *iter, GVa
        PaneKeywordsData *pkd = data;
        GtkTreeModel *keyword_tree = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model));
        GtkTreeIter child_iter;
-       
+
        gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), &child_iter, iter);
        
        memset(value, 0, sizeof (GValue));
@@ -440,6 +444,180 @@ static void bar_pane_keywords_mark_edited(GtkCellRendererText *cell, const gchar
 */
 }
 
+
+static GtkTargetEntry bar_pane_keywords_drag_types[] = {
+       { TARGET_APP_KEYWORD_PATH_STRING, GTK_TARGET_SAME_WIDGET, TARGET_APP_KEYWORD_PATH },
+       { "text/plain", 0, TARGET_TEXT_PLAIN }
+};
+static gint n_keywords_drag_types = 2;
+
+
+static GtkTargetEntry bar_pane_keywords_drop_types[] = {
+       { TARGET_APP_KEYWORD_PATH_STRING, GTK_TARGET_SAME_WIDGET, TARGET_APP_KEYWORD_PATH },
+       { "text/plain", 0, TARGET_TEXT_PLAIN }
+};
+static gint n_keywords_drop_types = 2;
+
+
+static void bar_pane_keywords_dnd_get(GtkWidget *tree_view, GdkDragContext *context,
+                                    GtkSelectionData *selection_data, guint info,
+                                    guint time, gpointer data)
+{
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+       GtkTreeIter child_iter;
+       GtkTreeModel *keyword_tree;
+
+       GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); 
+
+        if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return;
+
+       keyword_tree = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model));
+       gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), &child_iter, &iter);
+
+       switch (info)
+               {
+               case TARGET_APP_KEYWORD_PATH:
+                       {
+                       GList *path = keyword_tree_get_path(keyword_tree, &child_iter);
+                       gtk_selection_data_set(selection_data, selection_data->target,
+                                              8, (gpointer) &path, sizeof(path));
+                       break;
+                       }
+
+               case TARGET_TEXT_PLAIN:
+               default:
+                       {
+                       gchar *name = keyword_get_name(keyword_tree, &child_iter);
+                       gtk_selection_data_set_text(selection_data, name, -1);
+printf("name %s\n", name);
+                       g_free(name);
+                       }
+                       break;
+               }
+}
+
+static void bar_pane_keywords_dnd_begin(GtkWidget *treeview, GdkDragContext *context, gpointer data)
+{
+}
+
+static void bar_pane_keywords_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
+{
+}
+
+static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *context,
+                                         gint x, gint y,
+                                         GtkSelectionData *selection_data, guint info,
+                                         guint time, gpointer data)
+{
+       GtkTreePath *tpath = NULL;
+        GtkTreeViewDropPosition pos;
+       GtkTreeModel *model;
+
+       GtkTreeModel *keyword_tree;
+       gboolean src_valid = FALSE;
+       gchar *new_keyword = NULL;
+
+       /* iterators for keyword_tree */
+       GtkTreeIter src_kw_iter;
+       GtkTreeIter dest_kw_iter;
+       GtkTreeIter new_kw_iter;
+
+       g_signal_stop_emission_by_name(tree_view, "drag_data_received");
+
+       gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(tree_view), NULL, pos);
+
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
+       keyword_tree = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model));
+
+       gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(tree_view), x, y, &tpath, &pos);
+
+
+       switch (info)
+               {
+               case TARGET_APP_KEYWORD_PATH:
+                       {
+                       GList *path = *(gpointer *)selection_data->data;
+                       src_valid = keyword_tree_get_iter(keyword_tree, &src_kw_iter, path);
+                       string_list_free(path);
+                       break;
+                       }
+               default:
+                       new_keyword = (gchar *)selection_data->data;
+                       break;
+               }
+
+       if (tpath)
+               {
+               GtkTreeIter dest_iter;
+                gtk_tree_model_get_iter(model, &dest_iter, tpath);
+               gtk_tree_path_free(tpath);
+               gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), &dest_kw_iter, &dest_iter);
+
+
+               if ((pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER) &&
+                   !gtk_tree_model_iter_has_child(keyword_tree, &dest_kw_iter))
+                       {
+                       gtk_tree_store_append(GTK_TREE_STORE(keyword_tree), &new_kw_iter, &dest_kw_iter);
+                       }
+               else
+                       {
+                       switch (pos)
+                               {
+                               case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+                               case GTK_TREE_VIEW_DROP_BEFORE:
+                                       gtk_tree_store_insert_before(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL, &dest_kw_iter);
+                                       break;
+                               case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+                               case GTK_TREE_VIEW_DROP_AFTER:
+                                       gtk_tree_store_insert_after(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL, &dest_kw_iter);
+                                       break;
+                               }
+                       }
+               }
+       else
+               {
+               gtk_tree_store_append(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL);
+               }
+               
+               
+       if (src_valid)
+               {
+               keyword_move_recursive(GTK_TREE_STORE(keyword_tree), &new_kw_iter, &src_kw_iter);
+               }
+       
+       if (new_keyword)
+               {
+               keyword_set(GTK_TREE_STORE(keyword_tree), &new_kw_iter, new_keyword, TRUE);
+               }
+}
+
+static gint bar_pane_keywords_dnd_motion(GtkWidget *tree_view, GdkDragContext *context,
+                                       gint x, gint y, guint time, gpointer data)
+{
+       GtkTreePath *tpath = NULL;
+        GtkTreeViewDropPosition pos;
+       gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(tree_view), x, y, &tpath, &pos);
+       if (tpath)
+               {
+               GtkTreeModel *model;
+               GtkTreeIter dest_iter;
+               model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
+                gtk_tree_model_get_iter(model, &dest_iter, tpath);
+               if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE && gtk_tree_model_iter_has_child(model, &dest_iter))
+                       pos = GTK_TREE_VIEW_DROP_BEFORE;
+               
+               if (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER && gtk_tree_model_iter_has_child(model, &dest_iter))
+                       pos = GTK_TREE_VIEW_DROP_AFTER;
+               }
+
+       gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(tree_view), tpath, pos);
+       gtk_tree_path_free(tpath);
+       gdk_drag_status(context, GDK_ACTION_COPY, time);
+       return TRUE;
+}
+
+
 void bar_pane_keywords_close(GtkWidget *bar)
 {
        PaneKeywordsData *pkd;
@@ -591,6 +769,30 @@ GtkWidget *bar_pane_keywords_new(const gchar *title, const gchar *key, gboolean
        gtk_tree_view_append_column(GTK_TREE_VIEW(pkd->keyword_treeview), column);
        gtk_tree_view_set_expander_column(GTK_TREE_VIEW(pkd->keyword_treeview), column);
 
+       gtk_drag_source_set(pkd->keyword_treeview,
+                           GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+                           bar_pane_keywords_drag_types, n_keywords_drag_types,
+                           GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
+
+       g_signal_connect(G_OBJECT(pkd->keyword_treeview), "drag_data_get",
+                        G_CALLBACK(bar_pane_keywords_dnd_get), pkd);
+
+       g_signal_connect(G_OBJECT(pkd->keyword_treeview), "drag_begin",
+                        G_CALLBACK(bar_pane_keywords_dnd_begin), pkd);
+       g_signal_connect(G_OBJECT(pkd->keyword_treeview), "drag_end",
+                        G_CALLBACK(bar_pane_keywords_dnd_end), pkd);
+
+       gtk_drag_dest_set(pkd->keyword_treeview,
+                         GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
+                         bar_pane_keywords_drop_types, n_keywords_drop_types,
+                         GDK_ACTION_COPY | GDK_ACTION_MOVE);
+                         
+       g_signal_connect(G_OBJECT(pkd->keyword_treeview), "drag_data_received",
+                        G_CALLBACK(bar_pane_keywords_dnd_receive), pkd);
+
+       g_signal_connect(G_OBJECT(pkd->keyword_treeview), "drag_motion",
+                        G_CALLBACK(bar_pane_keywords_dnd_motion), pkd);
+
        gtk_container_add(GTK_CONTAINER(scrolled), pkd->keyword_treeview);
        gtk_widget_show(pkd->keyword_treeview);
 
index 2091c17..17ccfcd 100644 (file)
--- a/src/dnd.h
+++ b/src/dnd.h
 
 #define TARGET_APP_COLLECTION_MEMBER_STRING "application/x-" GQ_APPNAME_LC "-collection-member"
 #define TARGET_APP_EXIF_ENTRY_STRING "application/x-" GQ_APPNAME_LC "-exif-entry"
+#define TARGET_APP_KEYWORD_PATH_STRING "application/x-" GQ_APPNAME_LC "-keyword-path"
 
 enum {
        TARGET_APP_COLLECTION_MEMBER,
        TARGET_APP_EXIF_ENTRY,
+       TARGET_APP_KEYWORD_PATH,
        TARGET_URI_LIST,
        TARGET_TEXT_PLAIN
 };
index 31c142e..5c2b372 100644 (file)
@@ -729,6 +729,93 @@ void keyword_set(GtkTreeStore *keyword_tree, GtkTreeIter *iter, const gchar *nam
        g_free(casefold);
 }
 
+void keyword_copy(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from)
+{
+
+       gchar *mark, *name, *casefold;
+       gboolean is_keyword;
+
+       gtk_tree_model_get(GTK_TREE_MODEL(keyword_tree), from, KEYWORD_COLUMN_MARK, &mark,
+                                               KEYWORD_COLUMN_NAME, &name,
+                                               KEYWORD_COLUMN_CASEFOLD, &casefold,
+                                               KEYWORD_COLUMN_IS_KEYWORD, &is_keyword, -1);
+
+       gtk_tree_store_set(keyword_tree, to, KEYWORD_COLUMN_MARK, mark,
+                                               KEYWORD_COLUMN_NAME, name,
+                                               KEYWORD_COLUMN_CASEFOLD, casefold,
+                                               KEYWORD_COLUMN_IS_KEYWORD, is_keyword, -1);
+       g_free(mark);
+       g_free(name);
+       g_free(casefold);
+}
+
+void keyword_copy_recursive(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from)
+{
+       GtkTreeIter from_child;
+       
+       keyword_copy(keyword_tree, to, from);
+       
+       if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(keyword_tree), &from_child, from)) return;
+       
+       while (TRUE)
+               {
+               GtkTreeIter to_child;
+               gtk_tree_store_append(keyword_tree, &to_child, to);
+               keyword_copy_recursive(keyword_tree, &to_child, &from_child);
+               if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(keyword_tree), &from_child)) return;
+               }
+}
+
+void keyword_move_recursive(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from)
+{
+       keyword_copy_recursive(keyword_tree, to, from);
+       gtk_tree_store_remove(keyword_tree, from);
+}
+
+GList *keyword_tree_get_path(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr)
+{
+       GList *path = NULL;
+       GtkTreeIter iter = *iter_ptr;
+       
+       while (TRUE)
+               {
+               GtkTreeIter parent;
+               path = g_list_prepend(path, keyword_get_name(keyword_tree, &iter));
+               if (!gtk_tree_model_iter_parent(keyword_tree, &parent, &iter)) break;
+               iter = parent;
+               }
+       return path;
+}
+
+gboolean keyword_tree_get_iter(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr, GList *path)
+{
+       GtkTreeIter iter;
+
+       if (!gtk_tree_model_get_iter_first(keyword_tree, &iter)) return FALSE;
+       
+       while (TRUE)
+               {
+               GtkTreeIter children;
+               while (TRUE)
+                       {
+                       gchar *name = keyword_get_name(keyword_tree, &iter);
+                       if (strcmp(name, path->data) == 0) break;
+                       g_free(name);
+                       if (!gtk_tree_model_iter_next(keyword_tree, &iter)) return FALSE;
+                       }
+               path = path->next;
+               if (!path) 
+                       {
+                       *iter_ptr = iter;
+                       return TRUE;
+                       }
+                       
+               if (!gtk_tree_model_iter_children(keyword_tree, &children, &iter)) return FALSE;
+               iter = children;
+               }
+}
+
+
 static gboolean keyword_tree_is_set_casefold(GtkTreeModel *keyword_tree, GtkTreeIter iter, GList *casefold_list)
 {
        if (!casefold_list) return FALSE;
@@ -798,7 +885,6 @@ void keyword_tree_set(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr, GList *
                        if (!find_string_in_list_utf8nocase(*kw_list, name))
                                {
                                *kw_list = g_list_append(*kw_list, name);
-                               printf("set %s\n", name);
                                }
                        else
                                {
@@ -823,7 +909,6 @@ static void keyword_tree_reset1(GtkTreeModel *keyword_tree, GtkTreeIter *iter, G
        if (found)
                {
                *kw_list = g_list_remove(*kw_list, found);
-               printf("remove %s\n", found);
                g_free(found);
                }
        g_free(name);
index 2783fc4..a1ce98e 100644 (file)
@@ -54,6 +54,14 @@ extern GtkTreeStore *keyword_tree;
 gchar *keyword_get_name(GtkTreeModel *keyword_tree, GtkTreeIter *iter);
 gchar *keyword_get_casefold(GtkTreeModel *keyword_tree, GtkTreeIter *iter);
 gboolean keyword_get_is_keyword(GtkTreeModel *keyword_tree, GtkTreeIter *iter);
+
+void keyword_copy(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from);
+void keyword_copy_recursive(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from);
+void keyword_move_recursive(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from);
+
+GList *keyword_tree_get_path(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr);
+gboolean keyword_tree_get_iter(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr, GList *path);
+
 void keyword_set(GtkTreeStore *keyword_tree, GtkTreeIter *iter, const gchar *name, gboolean is_keyword);
 gboolean keyword_tree_is_set(GtkTreeModel *keyword_tree, GtkTreeIter *iter, GList *kw_list);
 void keyword_tree_set(GtkTreeModel *keyword_tree, GtkTreeIter *iter_ptr, GList **kw_list);