Mercurial > geeqie
diff src/dnd.c @ 1:b3e0e515fabf
Initial revision
author | gqview |
---|---|
date | Mon, 03 Apr 2000 18:24:05 +0000 |
parents | |
children | c0e337a01cb7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dnd.c Mon Apr 03 18:24:05 2000 +0000 @@ -0,0 +1,441 @@ +/* + * GQview image viewer + * (C)1999 John Ellis + * + * Author: John Ellis + * + */ + +#include "gqview.h" +#include "image.h" + +enum { + TARGET_URI_LIST, + TARGET_TEXT_PLAIN +}; + +static GtkTargetEntry file_drag_types[] = { + { "text/uri-list", 0, TARGET_URI_LIST }, + { "text/plain", 0, TARGET_TEXT_PLAIN } +}; +static gint n_file_drag_types = 2; + +static GtkTargetEntry file_drop_types[] = { + { "text/uri-list", 0, TARGET_URI_LIST } +}; +static gint n_file_drop_types = 1; + +static GList *get_uri_file_list(gchar *data); + +static void image_get_dnd_data(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data); +static void image_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data); +static void image_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data); + +static void file_list_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data); +static void file_list_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); +static void file_list_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data); + +static void dir_list_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data); +static void dir_clist_set_highlight(gint set); +static void dir_list_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data); +static void dir_list_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data); + +static GList *get_uri_file_list(gchar *data) +{ + GList *list = NULL; + gint b, e; + + b = e = 0; + + while (data[b] != '\0') + { + while (data[e] != '\r' && data[e] != '\n' && data[e] != '\0') e++; + if (!strncmp(data + b, "file:", 5)) + { + b += 5; + list = g_list_append(list, g_strndup(data + b, e - b)); + } + while (data[e] == '\r' || data[e] == '\n') e++; + b = e; + } + + return list; +} + +/* + *----------------------------------------------------------------------------- + * image drag and drop routines + *----------------------------------------------------------------------------- + */ + +static void image_get_dnd_data(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + ImageWindow *imd = data; + + if (info == TARGET_URI_LIST) + { + GList *list = get_uri_file_list(selection_data->data); + if (list) + { + gchar *path; + + path = list->data; + + if (imd == normal_image) + { + if (isfile(path)) + { + gint row; + gchar *dir = remove_level_from_path(path); + if (strcmp(dir, current_path) != 0) + filelist_change_to(dir); + g_free(dir); + + row = find_file_in_list(path); + if (row == -1) + image_change_to(path); + else + file_image_change_to(row); + } + else if (isdir(path)) + { + filelist_change_to(path); + image_change_to(NULL); + } + } + else + { + if (isfile(path)) + { + image_area_set_image(imd, path, get_default_zoom(imd)); + } + } + + if (debug) + { + GList *work = list; + while (work) + { + printf("dropped: %s\n", (gchar *)(work->data)); + work = work->next; + } + } + + g_list_foreach(list, (GFunc)g_free, NULL); + g_list_free(list); + } + } +} + +static void image_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + ImageWindow *imd = data; + gchar *path = image_area_get_path(imd); + + if (path) + { + gchar *text = NULL; + switch (info) + { + case TARGET_URI_LIST: + text = g_strconcat("file:", path, "\r\n", NULL); + break; + case TARGET_TEXT_PLAIN: + text = g_strdup(path); + break; + } + if (text) + { + gtk_selection_data_set (selection_data, selection_data->target, + 8, text, strlen(text)); + g_free(text); + } + } + else + { + gtk_selection_data_set (selection_data, selection_data->target, + 8, NULL, 0); + } +} + +static void image_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + ImageWindow *imd = data; + if (context->action == GDK_ACTION_MOVE) + { + gint row = find_file_in_list(image_area_get_path(imd)); + if (row < 0) return; + if (image_get_path() && strcmp(image_get_path(), image_area_get_path(imd)) == 0) + { + if (row < file_count() - 1) + { + file_next_image(); + } + else + { + file_prev_image(); + } + } + filelist_refresh(); + } +} + +void image_dnd_init(ImageWindow *imd) +{ + gtk_drag_source_set(imd->viewport, GDK_BUTTON2_MASK, + file_drag_types, n_file_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); + gtk_signal_connect(GTK_OBJECT(imd->viewport), "drag_data_get", + image_set_dnd_data, imd); + gtk_signal_connect(GTK_OBJECT(imd->viewport), "drag_end", + image_drag_end, imd); + + gtk_drag_dest_set(imd->viewport, + GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, + file_drop_types, n_file_drop_types, + GDK_ACTION_COPY); + gtk_signal_connect(GTK_OBJECT(imd->viewport), "drag_data_received", + image_get_dnd_data, imd); +} + +/* + *----------------------------------------------------------------------------- + * file list drag and drop routines (private) + *----------------------------------------------------------------------------- + */ + +static void file_list_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + gchar *uri_text = NULL; + gchar *leader = "file:"; + gchar *sep = "\r\n"; + gint total; + gint leader_l; + gint sep_l = strlen(sep); + gchar *ptr; + + switch (info) + { + case TARGET_URI_LIST: + leader_l = strlen(leader); + break; + case TARGET_TEXT_PLAIN: + leader_l = 0; + break; + default: + return; + break; + } + + if (file_clicked_is_selected()) + { + GList *list; + GList *work; + + list = file_get_selected_list(); + if (!list) return; + work = list; + total = 0; + + /* compute length */ + + while (work) + { + gchar *name = work->data; + total += leader_l + strlen(name) + sep_l; + work = work->next; + } + + /* create list */ + uri_text = g_malloc(total + 1); + ptr = uri_text; + + work = list; + while (work) + { + gchar *name = work->data; + if (leader_l > 0) + { + strcpy(ptr, leader); + ptr += leader_l; + } + strcpy(ptr, name); + ptr += strlen(name); + strcpy(ptr, sep); + ptr += sep_l; + work = work->next; + } + ptr[0] = '\0'; + free_selected_list(list); + } + else + { + gchar *path = file_clicked_get_path(); + if (!path) return; + switch (info) + { + case TARGET_URI_LIST: + uri_text = g_strconcat("file:", path, "\r\n", NULL); + break; + case TARGET_TEXT_PLAIN: + uri_text = g_strdup(path); + break; + } + total = strlen(uri_text); + g_free(path); + } + + if (debug) printf(uri_text); + + gtk_selection_data_set (selection_data, selection_data->target, + 8, uri_text, total); + g_free(uri_text); + + file_clist_highlight_unset(); +} + +static void file_list_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + file_clist_highlight_set(); +} + +static void file_list_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + file_clist_highlight_unset(); + + if (context->action == GDK_ACTION_MOVE) + { + filelist_refresh(); + } +} + +/* + *----------------------------------------------------------------------------- + * directory list drag and drop routines (private) + *----------------------------------------------------------------------------- + */ + +static void dir_list_set_dnd_data(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(dir_clist))); + + if (row >= 0) + { + gchar *name = gtk_clist_get_row_data(GTK_CLIST(dir_clist), row); + gchar *new_path; + gchar *text = NULL; + + if (strcmp(name, ".") == 0) + new_path = g_strdup(current_path); + else if (strcmp(name, "..") == 0) + new_path = remove_level_from_path(current_path); + else + { + if (strcmp(current_path, "/") == 0) + new_path = g_strconcat(current_path, name, NULL); + else + new_path = g_strconcat(current_path, "/", name, NULL); + } + + + switch (info) + { + case TARGET_URI_LIST: + text = g_strconcat("file:", new_path, "\r\n", NULL); + break; + case TARGET_TEXT_PLAIN: + text = g_strdup(new_path); + break; + } + if (text) + { + gtk_selection_data_set (selection_data, selection_data->target, + 8, text, strlen(text)); + g_free(text); + } + g_free(new_path); + } +} + +static void dir_clist_set_highlight(gint set) +{ + gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(dir_clist))); + if (set) + { + gtk_clist_set_background(GTK_CLIST(dir_clist), row, + >K_WIDGET (dir_clist)->style->bg[GTK_STATE_SELECTED]); + gtk_clist_set_foreground(GTK_CLIST(dir_clist), row, + >K_WIDGET (dir_clist)->style->fg[GTK_STATE_SELECTED]); + } + else + { + gtk_clist_set_background(GTK_CLIST(dir_clist), row, NULL); + gtk_clist_set_foreground(GTK_CLIST(dir_clist), row, NULL); + } +} + +static void dir_list_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + dir_clist_set_highlight(TRUE); +} + +static void dir_list_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + dir_clist_set_highlight(FALSE); + + if (context->action == GDK_ACTION_MOVE) + { + filelist_refresh(); + } +} + +/* + *----------------------------------------------------------------------------- + * drag and drop initialization (public) + *----------------------------------------------------------------------------- + */ + +void init_dnd() +{ + /* dir clist */ + gtk_drag_source_set(dir_clist, GDK_BUTTON2_MASK, + file_drag_types, n_file_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); + gtk_signal_connect(GTK_OBJECT(dir_clist), "drag_begin", + dir_list_drag_begin, NULL); + gtk_signal_connect(GTK_OBJECT(dir_clist), "drag_data_get", + dir_list_set_dnd_data, NULL); + gtk_signal_connect(GTK_OBJECT(dir_clist), "drag_end", + dir_list_drag_end, NULL); + + /* file clist */ + gtk_drag_source_set(file_clist, GDK_BUTTON2_MASK, + file_drag_types, n_file_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); + gtk_signal_connect(GTK_OBJECT(file_clist), "drag_begin", + file_list_drag_begin, NULL); + gtk_signal_connect(GTK_OBJECT(file_clist), "drag_data_get", + file_list_set_dnd_data, NULL); + gtk_signal_connect(GTK_OBJECT(file_clist), "drag_end", + file_list_drag_end, NULL); + + /* image */ + image_dnd_init(main_image); +} + +