changeset 497:a33badd85f16

Allow the copy of file paths to clipboard. This feature is disabled by default, it can be set through Preferences > Advanced > Behavior > Show "Copy path" ... When enabled, it adds a menu entry "Copy path" that let the user copies current selection's paths to X clipboard. It is very convenient to paste paths to xterm for example. Patch by Carles Pina i Estany and me.
author zas_
date Wed, 23 Apr 2008 22:17:21 +0000
parents a1f13fab6686
children 4dd932188d42
files src/collect-table.c src/dupe.c src/globals.c src/img-view.c src/layout_image.c src/layout_util.c src/layout_util.h src/pan-view.c src/preferences.c src/rcfile.c src/search.c src/typedefs.h src/utilops.c src/utilops.h src/view_file_icon.c src/view_file_list.c
diffstat 16 files changed, 185 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/collect-table.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/collect-table.c	Wed Apr 23 22:17:21 2008 +0000
@@ -625,6 +625,13 @@
 	file_util_delete(NULL, collection_table_popup_file_list(ct), ct->listview);
 }
 
+static void collection_table_popup_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	CollectTable *ct = data;
+
+	file_util_copy_path_list_to_clipboard(collection_table_popup_file_list(ct));
+}
+
 static void collection_table_popup_sort_cb(GtkWidget *widget, gpointer data)
 {
 	CollectTable *ct;
@@ -799,6 +806,9 @@
 			G_CALLBACK(collection_table_popup_rename_cb), ct);
 	menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, over_icon,
 			G_CALLBACK(collection_table_popup_delete_cb), ct);
+	if (options->show_copy_path)
+		menu_item_add_sensitive(menu, _("_Copy path"), over_icon,
+					G_CALLBACK(collection_table_popup_copy_path_cb), ct);
 	menu_item_add_divider(menu);
 
 	submenu_add_sort(menu, G_CALLBACK(collection_table_popup_sort_cb), ct, FALSE, TRUE, FALSE, 0);
--- a/src/dupe.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/dupe.c	Wed Apr 23 22:17:21 2008 +0000
@@ -2197,6 +2197,13 @@
 	file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window);
 }
 
+static void dupe_menu_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	DupeWindow *dw = data;
+
+	file_util_copy_path_list_to_clipboard(dupe_listview_get_selection(dw, dw->listview));
+}
+
 static void dupe_menu_remove_cb(GtkWidget *widget, gpointer data)
 {
 	DupeWindow *dw = data;
@@ -2258,6 +2265,9 @@
 				G_CALLBACK(dupe_menu_rename_cb), dw);
 	menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, on_row,
 				G_CALLBACK(dupe_menu_delete_cb), dw);
+	if (options->show_copy_path)
+		menu_item_add_sensitive(menu, _("_Copy path"), on_row,
+					G_CALLBACK(dupe_menu_copy_path_cb), dw);
 	menu_item_add_divider(menu);
 	menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row,
 				G_CALLBACK(dupe_menu_remove_cb), dw);
--- a/src/globals.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/globals.c	Wed Apr 23 22:17:21 2008 +0000
@@ -117,6 +117,7 @@
 	options->panels.sort.selection_state = 0;
 
 	options->progressive_key_scrolling = FALSE;
+	options->show_copy_path = FALSE;
 	options->show_icon_names = TRUE;
 
 	options->slideshow.delay = 150;
--- a/src/img-view.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/img-view.c	Wed Apr 23 22:17:21 2008 +0000
@@ -1183,6 +1183,15 @@
 	file_util_delete(image_get_fd(imd), NULL, imd->widget);
 }
 
+static void view_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	ViewWindow *vw = data;
+	ImageWindow *imd;
+
+	imd = view_window_active_image(vw);
+	file_util_copy_path_to_clipboard(image_get_fd(imd));
+}
+
 static void view_fullscreen_cb(GtkWidget *widget, gpointer data)
 {
 	ViewWindow *vw = data;
@@ -1279,6 +1288,8 @@
 	menu_item_add(menu, _("_Move..."), G_CALLBACK(view_move_cb), vw);
 	menu_item_add(menu, _("_Rename..."), G_CALLBACK(view_rename_cb), vw);
 	menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(view_delete_cb), vw);
+	if (options->show_copy_path)
+		menu_item_add(menu, _("_Copy path"), G_CALLBACK(view_copy_path_cb), vw);
 
 	menu_item_add_divider(menu);
 
--- a/src/layout_image.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/layout_image.c	Wed Apr 23 22:17:21 2008 +0000
@@ -637,6 +637,13 @@
 		       li_pop_menu_click_parent(widget, lw));
 }
 
+static void li_pop_menu_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	LayoutWindow *lw = data;
+
+	file_util_copy_path_to_clipboard(layout_image_get_fd(lw));
+}
+
 static void li_pop_menu_move_cb(GtkWidget *widget, gpointer data)
 {
 	LayoutWindow *lw = data;
@@ -765,6 +772,12 @@
 	if (!path) gtk_widget_set_sensitive(item, FALSE);
 	item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(li_pop_menu_delete_cb), lw);
 	if (!path) gtk_widget_set_sensitive(item, FALSE);
+	
+	if (options->show_copy_path)
+		{
+		item = menu_item_add(menu, _("_Copy path"), G_CALLBACK(li_pop_menu_copy_path_cb), lw);
+		if (!path) gtk_widget_set_sensitive(item, FALSE);
+	}
 
 	menu_item_add_divider(menu);
 
--- a/src/layout_util.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/layout_util.c	Wed Apr 23 22:17:21 2008 +0000
@@ -261,6 +261,13 @@
 	file_util_copy(NULL, layout_selection_list(lw), NULL, layout_window(lw));
 }
 
+static void layout_menu_copy_path_cb(GtkAction *action, gpointer data)
+{
+	LayoutWindow *lw = data;
+
+	file_util_copy_path_list_to_clipboard(layout_selection_list(lw));
+}
+
 static void layout_menu_move_cb(GtkAction *action, gpointer data)
 {
 	LayoutWindow *lw = data;
@@ -987,6 +994,38 @@
 
 /*
  *-----------------------------------------------------------------------------
+ * copy path
+ *-----------------------------------------------------------------------------
+ */
+
+static void layout_copy_path_update(LayoutWindow *lw)
+{
+	GtkWidget *item = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/FileMenu/CopyPath");
+
+	if (!item) return;
+	
+	if (options->show_copy_path)
+		gtk_widget_show(item);
+	else
+		gtk_widget_hide(item);
+}
+
+void layout_copy_path_update_all(void)
+{
+	GList *work;
+
+	work = layout_window_list;
+	while (work)
+		{
+		LayoutWindow *lw = work->data;
+		work = work->next;
+
+		layout_copy_path_update(lw);
+		}
+}
+
+/*
+ *-----------------------------------------------------------------------------
  * menu
  *-----------------------------------------------------------------------------
  */
@@ -1030,6 +1069,7 @@
   { "Delete",	GTK_STOCK_DELETE,	N_("_Delete..."),	"<control>D",	NULL,	CB(layout_menu_delete_cb) },
   { "DeleteAlt1",GTK_STOCK_DELETE,	N_("_Delete..."),	"Delete",	NULL,	CB(layout_menu_delete_cb) },
   { "DeleteAlt2",GTK_STOCK_DELETE,	N_("_Delete..."),	"KP_Delete",	NULL,	CB(layout_menu_delete_cb) },
+  { "CopyPath",		NULL,		N_("_Copy path"),	NULL,		NULL,	CB(layout_menu_copy_path_cb) },
   { "CloseWindow",	GTK_STOCK_CLOSE,N_("C_lose window"),	"<control>W",	NULL,	CB(layout_menu_close_cb) },
   { "Quit",		GTK_STOCK_QUIT, N_("_Quit"),		"<control>Q",	NULL,	CB(layout_menu_exit_cb) },
 
@@ -1146,6 +1186,7 @@
 "      <menuitem action='Move'/>"
 "      <menuitem action='Rename'/>"
 "      <menuitem action='Delete'/>"
+"      <menuitem action='CopyPath'/>"
 "      <separator/>"
 "      <menuitem action='CloseWindow'/>"
 "      <menuitem action='Quit'/>"
@@ -1387,8 +1428,9 @@
 		g_error_free (error);
 		exit (EXIT_FAILURE);
 		}
-
+	
 	layout_actions_setup_marks(lw);
+	layout_copy_path_update(lw);
 }
 
 void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window)
--- a/src/layout_util.h	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/layout_util.h	Wed Apr 23 22:17:21 2008 +0000
@@ -28,6 +28,8 @@
 void layout_recent_update_all(void);
 void layout_recent_add_path(const gchar *path);
 
+void layout_copy_path_update_all(void);
+
 void layout_actions_setup(LayoutWindow *lw);
 void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window);
 GtkWidget *layout_actions_menu_bar(LayoutWindow *lw);
--- a/src/pan-view.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/pan-view.c	Wed Apr 23 22:17:21 2008 +0000
@@ -2737,6 +2737,15 @@
 	if (fd) file_util_delete(fd, NULL, pw->imd->widget);
 }
 
+static void pan_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	PanWindow *pw = data;
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) file_util_copy_path_to_clipboard(fd);
+}
+
 static void pan_exif_date_toggle_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
@@ -2812,6 +2821,9 @@
 				G_CALLBACK(pan_rename_cb), pw);
 	menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, active,
 				      G_CALLBACK(pan_delete_cb), pw);
+	if (options->show_copy_path)
+		menu_item_add_sensitive(menu, _("_Copy path"), active,
+					G_CALLBACK(pan_copy_path_cb), pw);
 
 	menu_item_add_divider(menu);
 	item = menu_item_add_check(menu, _("Sort by E_xif date"), pw->exif_date_enable,
--- a/src/preferences.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/preferences.c	Wed Apr 23 22:17:21 2008 +0000
@@ -270,6 +270,12 @@
 
 	options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
 	options->dnd_icon_size = c_options->dnd_icon_size;
+	
+	if (options->show_copy_path != c_options->show_copy_path)
+		{
+		options->show_copy_path = c_options->show_copy_path;
+		layout_copy_path_update_all();
+		}
 
 #ifdef DEBUG
 	debug = debug_c;
@@ -1396,6 +1402,7 @@
 	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
 	gtk_widget_show(button);
 
+
 	group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
 
 	pref_checkbox_new_int(group, _("Rectangular selection in icon view"),
@@ -1407,6 +1414,9 @@
 	pref_checkbox_new_int(group, _("In place renaming"),
 			      options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
 
+	pref_checkbox_new_int(group, _("Show \"Copy path\" menu item which write the path of selected files to clipboard"),
+			      options->show_copy_path, &c_options->show_copy_path);
+
 	pref_spin_new_int(group, _("Open recent list maximum size"), NULL,
 			  1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
 	
--- a/src/rcfile.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/rcfile.c	Wed Apr 23 22:17:21 2008 +0000
@@ -301,6 +301,7 @@
 	WRITE_SUBTITLE("General Options");
 
 	WRITE_BOOL(show_icon_names);
+	WRITE_BOOL(show_copy_path);
 	WRITE_SEPARATOR();
 
 	WRITE_BOOL(tree_descend_subdirs);
@@ -614,6 +615,7 @@
 
 		/* general options */
 		READ_BOOL(show_icon_names);
+		READ_BOOL(show_copy_path);
 
 		READ_BOOL(tree_descend_subdirs);
 		READ_BOOL(lazy_image_sync);
--- a/src/search.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/search.c	Wed Apr 23 22:17:21 2008 +0000
@@ -946,6 +946,13 @@
 	file_util_delete(NULL, search_result_selection_list(sd), sd->window);
 }
 
+static void sr_menu_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	SearchData *sd = data;
+
+	file_util_copy_path_list_to_clipboard(search_result_selection_list(sd));
+}
+
 static void sr_menu_remove_cb(GtkWidget *widget, gpointer data)
 {
 	SearchData *sd = data;
@@ -993,6 +1000,9 @@
 				G_CALLBACK(sr_menu_rename_cb), sd);
 	menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, on_row,
 				      G_CALLBACK(sr_menu_delete_cb), sd);
+	if (options->show_copy_path)
+		menu_item_add_sensitive(menu, _("_Copy path"), on_row,
+					G_CALLBACK(sr_menu_copy_path_cb), sd);
 	menu_item_add_divider(menu);
 	menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row,
 				      G_CALLBACK(sr_menu_remove_cb), sd);
--- a/src/typedefs.h	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/typedefs.h	Wed Apr 23 22:17:21 2008 +0000
@@ -749,6 +749,7 @@
 	gint place_dialogs_under_mouse;
 	gint mousewheel_scrolls;
 	gint show_icon_names;
+	gint show_copy_path;
 
 	/* various */
 	gint startup_path_enable;
--- a/src/utilops.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/utilops.c	Wed Apr 23 22:17:21 2008 +0000
@@ -1238,6 +1238,40 @@
 	real_file_util_move(source_fd, source_list, dest_path, TRUE, parent);
 }
 
+void file_util_copy_path_to_clipboard(FileData *fd)
+{
+	GtkClipboard *clipboard;
+
+	if (!fd || !*fd->path) return;
+
+	clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+	gtk_clipboard_set_text(clipboard, g_shell_quote(fd->path), -1);
+}
+
+void file_util_copy_path_list_to_clipboard(GList *list)
+{
+	GtkClipboard *clipboard;
+	GList *work;
+	GString *new;
+
+	clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+	
+	new = g_string_new("");
+	work = list;
+	while (work) {
+		FileData *fd = work->data;
+		work = work->next;
+
+		if (!fd || !*fd->path) continue;
+	
+		g_string_append(new, g_shell_quote(fd->path));
+		if (work) g_string_append_c(new, ' ');
+		}
+	
+	gtk_clipboard_set_text(clipboard, new->str, new->len);
+	g_string_free(new, TRUE);
+}
+
 void file_util_move_simple(GList *list, const gchar *dest_path)
 {
 	if (!list) return;
--- a/src/utilops.h	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/utilops.h	Wed Apr 23 22:17:21 2008 +0000
@@ -57,4 +57,7 @@
 gint move_file_ext(FileData *fd);
 gint rename_file_ext(FileData *fd);
 
+void file_util_copy_path_to_clipboard(FileData *fd);
+void file_util_copy_path_list_to_clipboard(GList *list);
+
 #endif
--- a/src/view_file_icon.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/view_file_icon.c	Wed Apr 23 22:17:21 2008 +0000
@@ -242,6 +242,13 @@
 	file_util_delete(NULL, vficon_pop_menu_file_list(vfi), vfi->listview);
 }
 
+static void vficon_pop_menu_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	ViewFileIcon *vfi = data;
+
+	file_util_copy_path_list_to_clipboard(vficon_pop_menu_file_list(vfi));
+}
+
 static void vficon_pop_menu_sort_cb(GtkWidget *widget, gpointer data)
 {
 	ViewFileIcon *vfi;
@@ -336,6 +343,11 @@
 	gtk_widget_set_sensitive(item, active);
 	item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(vficon_pop_menu_delete_cb), vfi);
 	gtk_widget_set_sensitive(item, active);
+	if (options->show_copy_path)
+		{
+		item = menu_item_add(menu, _("_Copy path"), G_CALLBACK(vficon_pop_menu_copy_path_cb), vfi);
+		gtk_widget_set_sensitive(item, active);
+		}
 
 	menu_item_add_divider(menu);
 
--- a/src/view_file_list.c	Wed Apr 23 21:08:29 2008 +0000
+++ b/src/view_file_list.c	Wed Apr 23 22:17:21 2008 +0000
@@ -344,6 +344,13 @@
 	file_util_copy(NULL, vflist_pop_menu_file_list(vfl), NULL, vfl->listview);
 }
 
+static void vflist_pop_menu_copy_path_cb(GtkWidget *widget, gpointer data)
+{
+	ViewFileList *vfl = data;
+
+	file_util_copy_path_list_to_clipboard(vflist_pop_menu_file_list(vfl));
+}
+
 static void vflist_pop_menu_move_cb(GtkWidget *widget, gpointer data)
 {
 	ViewFileList *vfl = data;
@@ -581,7 +588,10 @@
 	menu_item_add_sensitive(menu, _("_Rename..."), active,
 				G_CALLBACK(vflist_pop_menu_rename_cb), vfl);
 	menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, active,
-				G_CALLBACK(vflist_pop_menu_delete_cb), vfl);
+				      G_CALLBACK(vflist_pop_menu_delete_cb), vfl);
+	if (options->show_copy_path)
+		menu_item_add_sensitive(menu, _("_Copy path"), active,
+					G_CALLBACK(vflist_pop_menu_copy_path_cb), vfl);
 
 	menu_item_add_divider(menu);