diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-09-13 05:33:07 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-09-13 05:46:43 +0800 |
commit | cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af (patch) | |
tree | 6ff582bc77fab2594a5394afd247e1ef92d24e64 | |
parent | abb6b433052b9c32762dbfb8233aaff7799f736a (diff) | |
download | gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.gz gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.zst gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.zip |
Bug 217066 - Rename folders directly inside folder list
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-request.c | 99 | ||||
-rw-r--r-- | e-util/e-request.h | 33 | ||||
-rw-r--r-- | mail/em-folder-tree.c | 149 | ||||
-rw-r--r-- | mail/em-folder-tree.h | 1 | ||||
-rw-r--r-- | mail/em-folder-utils.c | 82 | ||||
-rw-r--r-- | mail/em-folder-utils.h | 1 | ||||
-rw-r--r-- | 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 e5c0886735..2f6602f9f0 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/e-util/e-request.c b/e-util/e-request.c deleted file mode 100644 index 58784ee1ae..0000000000 --- a/e-util/e-request.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-request.h" - - -/** - * e_request_string: - * @parent: parent window, or %NULL - * @title: the dialog title (in the locale character set) - * @prompt: the prompt (in the locale character set) - * @default: default value (in UTF8) - * - * Request a string from the user. - * - * Return value: %NULL if the user cancelled the dialog, the inserted - * string (in UTF8) otherwise. The string must be freed by the caller. - **/ -gchar * -e_request_string (GtkWindow *parent, - const gchar *title, - const gchar *prompt, - const gchar *default_string) -{ - GtkWidget *prompt_label; - gchar *text; - GtkWidget *dialog; - GtkWidget *entry; - GtkWidget *vbox; - - g_return_val_if_fail (title != NULL, NULL); - g_return_val_if_fail (prompt != NULL, NULL); - - dialog = gtk_dialog_new_with_buttons (title, parent, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); - gtk_window_set_default_size (GTK_WINDOW (dialog), 275, -1); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 6); - - vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - - prompt_label = gtk_label_new (prompt); - gtk_box_pack_start (GTK_BOX (vbox), prompt_label, TRUE, TRUE, 6); - gtk_box_set_spacing (GTK_BOX (vbox), 6); - - entry = gtk_entry_new (); - gtk_entry_set_text (GTK_ENTRY (entry), default_string); - gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); - gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); - gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 3); - - atk_object_set_description (gtk_widget_get_accessible (entry), prompt); - - gtk_widget_grab_focus (entry); - - gtk_widget_show (prompt_label); - gtk_widget_show (entry); - gtk_widget_show (dialog); - - switch (gtk_dialog_run (GTK_DIALOG (dialog))) { - case GTK_RESPONSE_OK: - text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); - break; - default: - text = NULL; - break; - } - - gtk_widget_destroy (dialog); - - return text; -} diff --git a/e-util/e-request.h b/e-util/e-request.h deleted file mode 100644 index 63eacdf8bb..0000000000 --- a/e-util/e-request.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_REQUEST_H -#define E_REQUEST_H - -#include <gtk/gtk.h> - -gchar *e_request_string (GtkWindow *parent, - const gchar *title, - const gchar *prompt, - const gchar *default_string); - -#endif diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 053bed289c..fd7e933cd9 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 453e40763c..cca5432306 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 3a4636a87b..ac808adb23 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 78c2f81a34..ec150f3066 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 ca82272fee..e47c9fd7c6 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() */ |