[evolution] Bug 217066 - Rename folders directly inside folder list



commit cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Sep 12 16:33:07 2009 -0500

    Bug 217066 - Rename folders directly inside folder list

 e-util/Makefile.am                       |    2 -
 e-util/e-request.c                       |   99 --------------------
 e-util/e-request.h                       |   33 -------
 mail/em-folder-tree.c                    |  149 +++++++++++++++++++++++++++++-
 mail/em-folder-tree.h                    |    1 +
 mail/em-folder-utils.c                   |   82 ----------------
 mail/em-folder-utils.h                   |    1 -
 modules/mail/e-mail-shell-view-actions.c |    5 +-
 8 files changed, 150 insertions(+), 222 deletions(-)
---
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index e5c0886..2f6602f 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -64,7 +64,6 @@ eutilinclude_HEADERS = 				\
 	e-plugin.h				\
 	e-plugin-ui.h				\
 	e-profile-event.h			\
-	e-request.h				\
 	e-signature.h				\
 	e-signature-list.h			\
 	e-signature-utils.h			\
@@ -106,7 +105,6 @@ libeutil_la_SOURCES =				\
 	e-plugin.c				\
 	e-print.c				\
 	e-profile-event.c			\
-	e-request.c				\
 	e-signature.c				\
 	e-signature-list.c			\
 	e-signature-utils.c			\
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 053bed2..fd7e933 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -50,7 +50,6 @@
 
 #include "e-util/e-account-utils.h"
 #include "e-util/e-mktemp.h"
-#include "e-util/e-request.h"
 #include "e-util/e-icon-factory.h"
 #include "e-util/e-error.h"
 #include "e-util/e-util.h"
@@ -108,6 +107,8 @@ struct _EMFolderTreePrivate {
 
 	GtkTreeRowReference *drag_row;
 	gboolean skip_double_click;
+
+	GtkCellRenderer *text_renderer;
 };
 
 enum {
@@ -380,6 +381,94 @@ folder_tree_clear_selected_list(EMFolderTree *folder_tree)
 }
 
 static void
+folder_tree_cell_edited_cb (EMFolderTree *folder_tree,
+                            const gchar *path_string,
+                            const gchar *new_name)
+{
+	CamelFolderInfo *folder_info;
+	CamelException ex;
+	CamelStore *store;
+	GtkTreeView *tree_view;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gchar *display_name;
+	gchar *old_full_name = NULL;
+	gchar *new_full_name = NULL;
+	gchar **strv;
+	gpointer parent;
+	guint index;
+
+	/* XXX Consider splitting this into separate async functions:
+	 *     em_folder_tree_rename_folder_async()
+	 *     em_folder_tree_rename_folder_finish() */
+
+	camel_exception_init (&ex);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (folder_tree));
+	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+	tree_view = GTK_TREE_VIEW (folder_tree);
+	model = gtk_tree_view_get_model (tree_view);
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_path_free (path);
+
+	gtk_tree_model_get (
+		model, &iter,
+		COL_POINTER_CAMEL_STORE, &store,
+		COL_STRING_DISPLAY_NAME, &display_name,
+		COL_STRING_FULL_NAME, &old_full_name, -1);
+
+	if (g_strcmp0 (new_name, display_name) == 0)
+		goto exit;
+
+	/* Check for invalid characters. */
+	if (strchr (new_name, '/') != NULL) {
+		e_error_run (
+			parent, "mail:no-rename-folder",
+			display_name, new_name,
+			_("Folder names cannot contain '/'"), NULL);
+		goto exit;
+	}
+
+	/* Build the new name from the old name. */
+	strv = g_strsplit_set (old_full_name, "/", 0);
+	index = g_strv_length (strv) - 1;
+	g_free (strv[index]);
+	strv[index] = g_strdup (new_name);
+	new_full_name = g_strjoinv ("/", strv);
+	g_strfreev (strv);
+
+	/* Check for duplicate folder name. */
+	folder_info = camel_store_get_folder_info (
+		store, new_full_name, CAMEL_STORE_FOLDER_INFO_FAST, &ex);
+	if (folder_info != NULL) {
+		e_error_run (
+			parent, "mail:no-rename-folder-exists",
+			display_name, new_name, NULL);
+		camel_store_free_folder_info (store, folder_info);
+		goto exit;
+	}
+
+	/* XXX This needs to be asynchronous. */
+	camel_store_rename_folder (store, old_full_name, new_full_name, &ex);
+	if (camel_exception_is_set (&ex)) {
+		e_error_run (
+			parent, "mail:no-rename-folder",
+			old_full_name, new_full_name, ex.desc, NULL);
+		goto exit;
+	}
+
+exit:
+	camel_exception_clear (&ex);
+
+	g_free (display_name);
+	g_free (old_full_name);
+	g_free (new_full_name);
+}
+
+static void
 folder_tree_selection_changed_cb (EMFolderTree *folder_tree,
                            GtkTreeSelection *selection)
 {
@@ -424,6 +513,22 @@ exit:
 }
 
 static void
+folder_tree_dispose (GObject *object)
+{
+	EMFolderTreePrivate *priv;
+
+	priv = EM_FOLDER_TREE_GET_PRIVATE (object);
+
+	if (priv->text_renderer != NULL) {
+		g_object_unref (priv->text_renderer);
+		priv->text_renderer = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
 folder_tree_finalize (GObject *object)
 {
 	EMFolderTreePrivate *priv;
@@ -664,6 +769,7 @@ folder_tree_class_init (EMFolderTreeClass *class)
 	g_type_class_add_private (class, sizeof (EMFolderTreePrivate));
 
 	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = folder_tree_dispose;
 	object_class->finalize = folder_tree_finalize;
 
 	gtk_object_class = GTK_OBJECT_CLASS (class);
@@ -921,6 +1027,11 @@ folder_tree_new (EMFolderTree *folder_tree)
 		g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
 	gtk_tree_view_column_set_cell_data_func (column, renderer, render_display_name, NULL, NULL);
+	folder_tree->priv->text_renderer = g_object_ref (renderer);
+
+	g_signal_connect_swapped (
+		renderer, "edited",
+		G_CALLBACK (folder_tree_cell_edited_cb), folder_tree);
 
 	selection = gtk_tree_view_get_selection ((GtkTreeView *) tree);
 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
@@ -2229,6 +2340,42 @@ em_folder_tree_select_prev_path (EMFolderTree *folder_tree, gboolean skip_read_f
 	return;
 }
 
+void
+em_folder_tree_edit_selected (EMFolderTree *folder_tree)
+{
+	GtkTreeSelection *selection;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *renderer;
+	GtkTreeView *tree_view;
+	GtkTreeModel *model;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+
+	g_return_if_fail (EM_IS_FOLDER_TREE (folder_tree));
+
+	tree_view = GTK_TREE_VIEW (folder_tree);
+	column = gtk_tree_view_get_column (tree_view, 0);
+	selection = gtk_tree_view_get_selection (tree_view);
+	renderer = folder_tree->priv->text_renderer;
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+		path = gtk_tree_model_get_path (model, &iter);
+
+	if (path == NULL)
+		return;
+
+	/* Make the text cell renderer editable, but only temporarily.
+	 * We don't want editing to be activated by simply clicking on
+	 * the folder name.  Too easy for accidental edits to occur. */
+	g_object_set (renderer, "editable", TRUE, NULL);
+	gtk_tree_view_expand_to_path (tree_view, path);
+	gtk_tree_view_set_cursor_on_cell (
+		tree_view, path, column, renderer, TRUE);
+	g_object_set (renderer, "editable", FALSE, NULL);
+
+	gtk_tree_path_free (path);
+}
+
 gchar *
 em_folder_tree_get_selected_uri (EMFolderTree *folder_tree)
 {
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index 453e407..cca5432 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -106,6 +106,7 @@ void		em_folder_tree_select_next_path	(EMFolderTree *folder_tree,
 						 gboolean skip_read_folders);
 void		em_folder_tree_select_prev_path	(EMFolderTree *folder_tree,
 						 gboolean skip_read_folders);
+void		em_folder_tree_edit_selected	(EMFolderTree *folder_tree);
 gchar *		em_folder_tree_get_selected_uri	(EMFolderTree *folder_tree);
 gchar *		em_folder_tree_get_selected_path(EMFolderTree *folder_tree);
 CamelFolder *	em_folder_tree_get_selected_folder
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index 3a4636a..ac808ad 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -47,7 +47,6 @@
 #include <camel/camel-stream-fs.h>
 
 #include "e-util/e-mktemp.h"
-#include "e-util/e-request.h"
 
 #include "e-util/e-error.h"
 
@@ -483,87 +482,6 @@ em_folder_utils_delete_folder (CamelFolder *folder)
 	gtk_widget_show (dialog);
 }
 
-/* FIXME: this must become threaded */
-/* FIXME: these functions must be documented */
-void
-em_folder_utils_rename_folder (CamelFolder *folder)
-{
-	gchar *prompt, *new_name;
-	const gchar *p;
-	CamelStore *local_store;
-	gboolean done = FALSE;
-	gsize base_len;
-
-	local_store = e_mail_local_get_store ();
-
-	/* don't allow user to rename one of the special local folders */
-	if (folder->parent_store == local_store && emfu_is_special_local_folder (folder->full_name)) {
-		e_error_run(NULL,
-			    "mail:no-rename-special-folder", folder->full_name, NULL);
-		return;
-	}
-
-	if ((p = strrchr (folder->full_name, '/')))
-		base_len = (gsize) (p - folder->full_name);
-	else
-		base_len = 0;
-
-	prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), folder->name);
-	while (!done) {
-		new_name = e_request_string (NULL, _("Rename Folder"), prompt, folder->name);
-		if (new_name == NULL || !strcmp (folder->name, new_name)) {
-			/* old name == new name */
-			done = TRUE;
-		} else if (strchr(new_name, '/') != NULL) {
-			e_error_run(NULL,
-				    "mail:no-rename-folder", folder->name, new_name, _("Folder names cannot contain '/'"), NULL);
-			done = TRUE;
-		} else {
-			CamelFolderInfo *fi;
-			CamelException ex;
-			gchar *path, *tmp;
-
-			if (base_len > 0) {
-				path = g_malloc (base_len + strlen (new_name) + 2);
-				memcpy (path, folder->full_name, base_len);
-				tmp = path + base_len;
-				*tmp++ = '/';
-				strcpy (tmp, new_name);
-			} else {
-				path = g_strdup (new_name);
-			}
-
-			camel_exception_init (&ex);
-			if ((fi = camel_store_get_folder_info (folder->parent_store, path, CAMEL_STORE_FOLDER_INFO_FAST, &ex)) != NULL) {
-				camel_store_free_folder_info (folder->parent_store, fi);
-				e_error_run(NULL,
-					    "mail:no-rename-folder-exists", folder->name, new_name, NULL);
-			} else {
-				const gchar *oldpath, *newpath;
-
-				oldpath = folder->full_name;
-				newpath = path;
-
-				d(printf ("renaming %s to %s\n", oldpath, newpath));
-
-				camel_exception_clear (&ex);
-				camel_store_rename_folder (folder->parent_store, oldpath, newpath, &ex);
-				if (camel_exception_is_set (&ex)) {
-					e_error_run(NULL,
-						    "mail:no-rename-folder", oldpath, newpath, ex.desc, NULL);
-					camel_exception_clear (&ex);
-				}
-
-				done = TRUE;
-			}
-
-			g_free (path);
-		}
-
-		g_free (new_name);
-	}
-}
-
 struct _EMCreateFolder {
 	MailMsg base;
 
diff --git a/mail/em-folder-utils.h b/mail/em-folder-utils.h
index 78c2f81..ec150f3 100644
--- a/mail/em-folder-utils.h
+++ b/mail/em-folder-utils.h
@@ -44,7 +44,6 @@ void		em_folder_utils_copy_folder	(GtkWindow *parent,
 						 CamelFolderInfo *folderinfo,
 						 gboolean delete);
 void		em_folder_utils_delete_folder	(CamelFolder *folder);
-void		em_folder_utils_rename_folder	(CamelFolder *folder);
 void		em_folder_utils_create_folder	(CamelFolderInfo *folderinfo,
 						 EMFolderTree *emft,
 						 GtkWindow *parent);
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index ca82272..e47c9fd 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -347,14 +347,11 @@ action_mail_folder_rename_cb (GtkAction *action,
 {
 	EMailShellSidebar *mail_shell_sidebar;
 	EMFolderTree *folder_tree;
-	CamelFolder *folder;
 
 	mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
-	folder = em_folder_tree_get_selected_folder (folder_tree);
-	g_return_if_fail (folder != NULL);
 
-	em_folder_utils_rename_folder (folder);
+	em_folder_tree_edit_selected (folder_tree);
 }
 
 /* Helper for action_mail_folder_select_all_cb() */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]