GtkWidget *listview;
FileData *fd;
- gchar *sel_key;
};
enum {
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)
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)
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);
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);
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);
}
#include "ui_menu.h"
#include "rcfile.h"
#include "layout.h"
+#include "dnd.h"
static const gchar *keyword_favorite_defaults[] = {
N_("Favorite"),
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)
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));
*/
}
+
+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;
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);
#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
};
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;
if (!find_string_in_list_utf8nocase(*kw_list, name))
{
*kw_list = g_list_append(*kw_list, name);
- printf("set %s\n", name);
}
else
{
if (found)
{
*kw_list = g_list_remove(*kw_list, found);
- printf("remove %s\n", found);
g_free(found);
}
g_free(name);
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);