aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-09-13 05:33:07 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-09-13 05:46:43 +0800
commitcbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af (patch)
tree6ff582bc77fab2594a5394afd247e1ef92d24e64
parentabb6b433052b9c32762dbfb8233aaff7799f736a (diff)
downloadgsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.gz
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.bz2
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.lz
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.xz
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.tar.zst
gsoc2013-evolution-cbf5c62ee8d0bf9d1529f65a1baa25c9a8ff46af.zip
Bug 217066 - Rename folders directly inside folder list
-rw-r--r--e-util/Makefile.am2
-rw-r--r--e-util/e-request.c99
-rw-r--r--e-util/e-request.h33
-rw-r--r--mail/em-folder-tree.c149
-rw-r--r--mail/em-folder-tree.h1
-rw-r--r--mail/em-folder-utils.c82
-rw-r--r--mail/em-folder-utils.h1
-rw-r--r--modules/mail/e-mail-shell-view-actions.c5
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() */