From 5ebf0fd3c3ff08fc34fb1157ac54c818661bf2a1 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 24 Mar 2014 09:26:24 -0400 Subject: Add EMailFolderCreateDialog. Subclass of EMFolderSelector, replaces em_folder_utils_create_folder(). --- mail/Makefile.am | 2 + mail/e-mail-folder-create-dialog.c | 498 +++++++++++++++++++++++++++++++ mail/e-mail-folder-create-dialog.h | 76 +++++ mail/em-folder-selector.c | 181 +++-------- mail/em-folder-selector.h | 2 - mail/em-folder-utils.c | 164 ---------- mail/em-folder-utils.h | 4 - modules/mail/e-mail-shell-backend.c | 40 ++- modules/mail/e-mail-shell-view-actions.c | 46 ++- modules/mail/e-mail-shell-view-private.h | 1 + 10 files changed, 702 insertions(+), 312 deletions(-) create mode 100644 mail/e-mail-folder-create-dialog.c create mode 100644 mail/e-mail-folder-create-dialog.h diff --git a/mail/Makefile.am b/mail/Makefile.am index e5cc9daf34..d40922e605 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -84,6 +84,7 @@ mailinclude_HEADERS = \ e-mail-display-popup-extension.h \ e-mail-enums.h \ e-mail-enumtypes.h \ + e-mail-folder-create-dialog.h \ e-mail-folder-pane.h \ e-mail-junk-options.h \ e-mail-label-action.h \ @@ -160,6 +161,7 @@ libevolution_mail_la_SOURCES = \ e-mail-display.c \ e-mail-display-popup-extension.c \ e-mail-enumtypes.c \ + e-mail-folder-create-dialog.c \ e-mail-folder-pane.c \ e-mail-junk-options.c \ e-mail-label-action.c \ diff --git a/mail/e-mail-folder-create-dialog.c b/mail/e-mail-folder-create-dialog.c new file mode 100644 index 0000000000..bca14de1d9 --- /dev/null +++ b/mail/e-mail-folder-create-dialog.c @@ -0,0 +1,498 @@ +/* + * e-mail-folder-create-dialog.c + * + * 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. + * + * 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 General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see . + * + */ + +#include "e-mail-folder-create-dialog.h" + +#include +#include + +#include "em-vfolder-editor-rule.h" +#include "mail-vfolder-ui.h" + +#define E_MAIL_FOLDER_CREATE_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_FOLDER_CREATE_DIALOG, EMailFolderCreateDialogPrivate)) + +typedef struct _AsyncContext AsyncContext; + +struct _EMailFolderCreateDialogPrivate { + EMailUISession *session; + GtkWidget *name_entry; +}; + +struct _AsyncContext { + EMailFolderCreateDialog *dialog; + EActivity *activity; +}; + +enum { + PROP_0, + PROP_SESSION +}; + +enum { + FOLDER_CREATED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EMailFolderCreateDialog, + e_mail_folder_create_dialog, + EM_TYPE_FOLDER_SELECTOR) + +static void +async_context_free (AsyncContext *async_context) +{ + g_clear_object (&async_context->dialog); + g_clear_object (&async_context->activity); + + g_slice_free (AsyncContext, async_context); +} + +static void +mail_folder_create_dialog_create_folder_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EMailFolderCreateDialog *dialog; + EActivity *activity; + EAlertSink *alert_sink; + GdkWindow *gdk_window; + AsyncContext *async_context; + GError *local_error = NULL; + + async_context = (AsyncContext *) user_data; + + dialog = async_context->dialog; + activity = async_context->activity; + alert_sink = e_activity_get_alert_sink (activity); + + /* Set the cursor back to normal. */ + gdk_window = gtk_widget_get_window (GTK_WIDGET (dialog)); + gdk_window_set_cursor (gdk_window, NULL); + + e_mail_store_create_folder_finish ( + CAMEL_STORE (source_object), result, &local_error); + + /* Ignore cancellations. */ + if (e_activity_handle_cancellation (activity, local_error)) { + g_error_free (local_error); + + } else if (local_error != NULL) { + e_alert_submit ( + alert_sink, + "system:simple-error", + local_error->message, NULL); + g_error_free (local_error); + + } else { + gtk_widget_destroy (GTK_WIDGET (dialog)); + } + + async_context_free (async_context); +} + +static void +mail_folder_create_dialog_create_folder (EMailFolderCreateDialog *dialog) +{ + CamelStore *store = NULL; + gchar *create_folder_name; + gchar *parent_folder_name = NULL; + const gchar *text; + + em_folder_selector_get_selected ( + EM_FOLDER_SELECTOR (dialog), &store, &parent_folder_name); + + g_return_if_fail (store != NULL); + + text = gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry)); + + if (parent_folder_name != NULL) { + create_folder_name = g_strconcat ( + parent_folder_name, "/", text, NULL); + } else { + create_folder_name = g_strdup (text); + } + + /* For the vfolder store, we just open the editor window. */ + if (CAMEL_IS_VEE_STORE (store)) { + EMailUISession *session; + EFilterRule *rule; + + session = e_mail_folder_create_dialog_get_session (dialog); + rule = em_vfolder_editor_rule_new (E_MAIL_SESSION (session)); + e_filter_rule_set_name (rule, create_folder_name); + vfolder_gui_add_rule (EM_VFOLDER_RULE (rule)); + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + } else { + AsyncContext *async_context; + EActivity *activity; + GCancellable *cancellable; + GdkCursor *gdk_cursor; + GdkWindow *gdk_window; + + /* Make the cursor appear busy. */ + gdk_cursor = gdk_cursor_new (GDK_WATCH); + gdk_window = gtk_widget_get_window (GTK_WIDGET (dialog)); + gdk_window_set_cursor (gdk_window, gdk_cursor); + g_object_unref (gdk_cursor); + + activity = em_folder_selector_new_activity ( + EM_FOLDER_SELECTOR (dialog)); + + async_context = g_slice_new0 (AsyncContext); + async_context->dialog = g_object_ref (dialog); + async_context->activity = g_object_ref (activity); + + cancellable = e_activity_get_cancellable (activity); + + e_mail_store_create_folder ( + store, create_folder_name, + G_PRIORITY_DEFAULT, cancellable, + mail_folder_create_dialog_create_folder_cb, + async_context); + + g_object_unref (activity); + } + + g_free (create_folder_name); + g_free (parent_folder_name); + + g_object_unref (store); +} + +static gboolean +mail_folder_create_dialog_inputs_are_valid (EMailFolderCreateDialog *dialog) +{ + GtkEntry *entry; + const gchar *original_text; + gchar *stripped_text; + gboolean folder_or_store_is_selected; + gboolean inputs_are_valid; + + entry = GTK_ENTRY (dialog->priv->name_entry); + + original_text = gtk_entry_get_text (entry); + stripped_text = e_util_strdup_strip (original_text); + + folder_or_store_is_selected = + em_folder_selector_get_selected ( + EM_FOLDER_SELECTOR (dialog), NULL, NULL); + + inputs_are_valid = + folder_or_store_is_selected && + (stripped_text != NULL) && + (strchr (stripped_text, '/') == NULL); + + g_free (stripped_text); + + return inputs_are_valid; +} + +static void +mail_folder_create_dialog_entry_activate_cb (GtkEntry *entry, + EMailFolderCreateDialog *dialog) +{ + if (mail_folder_create_dialog_inputs_are_valid (dialog)) + gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); +} + +static void +mail_folder_create_dialog_entry_changed_cb (GtkEntry *entry, + EMailFolderCreateDialog *dialog) +{ + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_OK, + mail_folder_create_dialog_inputs_are_valid (dialog)); +} + +static void +mail_folder_create_dialog_set_session (EMailFolderCreateDialog *dialog, + EMailUISession *session) +{ + g_return_if_fail (E_IS_MAIL_UI_SESSION (session)); + g_return_if_fail (dialog->priv->session == NULL); + + dialog->priv->session = g_object_ref (session); +} + +static void +mail_folder_create_dialog_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SESSION: + mail_folder_create_dialog_set_session ( + E_MAIL_FOLDER_CREATE_DIALOG (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_folder_create_dialog_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SESSION: + g_value_set_object ( + value, + e_mail_folder_create_dialog_get_session ( + E_MAIL_FOLDER_CREATE_DIALOG (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_folder_create_dialog_dispose (GObject *object) +{ + EMailFolderCreateDialogPrivate *priv; + + priv = E_MAIL_FOLDER_CREATE_DIALOG_GET_PRIVATE (object); + + g_clear_object (&priv->session); + g_clear_object (&priv->name_entry); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_mail_folder_create_dialog_parent_class)-> + dispose (object); +} + +static void +mail_folder_create_dialog_constructed (GObject *object) +{ + EMailFolderCreateDialog *dialog; + EMailAccountStore *account_store; + EMailUISession *session; + EMFolderTree *folder_tree; + EMFolderTreeModel *model; + GQueue queue = G_QUEUE_INIT; + GtkWidget *container; + GtkWidget *widget; + GtkLabel *label; + + dialog = E_MAIL_FOLDER_CREATE_DIALOG (object); + session = e_mail_folder_create_dialog_get_session (dialog); + model = em_folder_selector_get_model (EM_FOLDER_SELECTOR (dialog)); + + /* Populate the tree model before chaining up, since the + * subclass will immediately try to restore the tree state. */ + + account_store = e_mail_ui_session_get_account_store (session); + e_mail_account_store_queue_enabled_services (account_store, &queue); + + while (!g_queue_is_empty (&queue)) { + CamelService *service; + CamelStoreFlags flags; + + service = g_queue_pop_head (&queue); + g_warn_if_fail (CAMEL_IS_STORE (service)); + + flags = CAMEL_STORE (service)->flags; + if ((flags & CAMEL_STORE_CAN_EDIT_FOLDERS) == 0) + continue; + + em_folder_tree_model_add_store (model, CAMEL_STORE (service)); + } + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mail_folder_create_dialog_parent_class)-> + constructed (object); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Create Folder")); + + em_folder_selector_set_caption ( + EM_FOLDER_SELECTOR (dialog), + _("Specify where to create the folder:")); + + em_folder_selector_set_default_button_label ( + EM_FOLDER_SELECTOR (dialog), _("C_reate")); + + folder_tree = em_folder_selector_get_folder_tree ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_tree_set_excluded (folder_tree, EMFT_EXCLUDE_NOINFERIORS); + + /* Add a folder name entry field to the dialog. */ + + container = em_folder_selector_get_content_area ( + EM_FOLDER_SELECTOR (dialog)); + + widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new_with_mnemonic (_("Folder _name:")); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = gtk_entry_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + dialog->priv->name_entry = g_object_ref (widget); + gtk_widget_grab_focus (widget); + gtk_widget_show (widget); + + g_signal_connect ( + widget, "activate", + G_CALLBACK (mail_folder_create_dialog_entry_activate_cb), + dialog); + + g_signal_connect ( + widget, "changed", + G_CALLBACK (mail_folder_create_dialog_entry_changed_cb), + dialog); +} + +static void +mail_folder_create_dialog_response (GtkDialog *dialog, + gint response_id) +{ + /* Do not chain up. GtkDialog does not implement this method. */ + + switch (response_id) { + case GTK_RESPONSE_OK: + mail_folder_create_dialog_create_folder ( + E_MAIL_FOLDER_CREATE_DIALOG (dialog)); + break; + case GTK_RESPONSE_CANCEL: + gtk_widget_destroy (GTK_WIDGET (dialog)); + break; + default: + break; + } +} + +static void +mail_folder_create_dialog_folder_selected (EMFolderSelector *selector, + CamelStore *store, + const gchar *folder_name) +{ + EMailFolderCreateDialog *dialog; + + /* Do not chain up. This overrides the subclass behavior. */ + + dialog = E_MAIL_FOLDER_CREATE_DIALOG (selector); + + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_OK, + mail_folder_create_dialog_inputs_are_valid (dialog)); +} + +static void +e_mail_folder_create_dialog_class_init (EMailFolderCreateDialogClass *class) +{ + GObjectClass *object_class; + GtkDialogClass *dialog_class; + EMFolderSelectorClass *selector_class; + + g_type_class_add_private ( + class, sizeof (EMailFolderCreateDialogPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_folder_create_dialog_set_property; + object_class->get_property = mail_folder_create_dialog_get_property; + object_class->dispose = mail_folder_create_dialog_dispose; + object_class->constructed = mail_folder_create_dialog_constructed; + + dialog_class = GTK_DIALOG_CLASS (class); + dialog_class->response = mail_folder_create_dialog_response; + + selector_class = EM_FOLDER_SELECTOR_CLASS (class); + selector_class->folder_selected = mail_folder_create_dialog_folder_selected; + + g_object_class_install_property ( + object_class, + PROP_SESSION, + g_param_spec_object ( + "session", + "Session", + "An EMailUISession from which " + "to list enabled mail stores", + E_TYPE_MAIL_UI_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[FOLDER_CREATED] = g_signal_new ( + "folder-created", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailFolderCreateDialogClass, folder_created), + NULL, NULL, NULL, + G_TYPE_NONE, 2, + CAMEL_TYPE_STORE, + G_TYPE_STRING); +} + +static void +e_mail_folder_create_dialog_init (EMailFolderCreateDialog *dialog) +{ + dialog->priv = E_MAIL_FOLDER_CREATE_DIALOG_GET_PRIVATE (dialog); +} + +GtkWidget * +e_mail_folder_create_dialog_new (GtkWindow *parent, + EMailUISession *session) +{ + GtkWidget *dialog; + EMFolderTreeModel *model; + + g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL); + + /* XXX The folder tree model is a construct-only property in + * EMFolderSelector, so create an empty model here and then + * populate it during instance initialization. Already too + * much logic here for a "new" function, but works for now. */ + + model = em_folder_tree_model_new (); + em_folder_tree_model_set_session (model, E_MAIL_SESSION (session)); + + dialog = g_object_new ( + E_TYPE_MAIL_FOLDER_CREATE_DIALOG, + "transient-for", parent, + "model", model, + "session", session, NULL); + + g_object_unref (model); + + return dialog; +} + +EMailUISession * +e_mail_folder_create_dialog_get_session (EMailFolderCreateDialog *dialog) +{ + g_return_val_if_fail (E_IS_MAIL_FOLDER_CREATE_DIALOG (dialog), NULL); + + return dialog->priv->session; +} + diff --git a/mail/e-mail-folder-create-dialog.h b/mail/e-mail-folder-create-dialog.h new file mode 100644 index 0000000000..f0db614a98 --- /dev/null +++ b/mail/e-mail-folder-create-dialog.h @@ -0,0 +1,76 @@ +/* + * e-mail-folder-create-dialog.h + * + * 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. + * + * 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 General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see . + * + */ + +#ifndef E_MAIL_FOLDER_CREATE_DIALOG_H +#define E_MAIL_FOLDER_CREATE_DIALOG_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MAIL_FOLDER_CREATE_DIALOG \ + (e_mail_folder_create_dialog_get_type ()) +#define E_MAIL_FOLDER_CREATE_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_FOLDER_CREATE_DIALOG, EMailFolderCreateDialog)) +#define E_MAIL_FOLDER_CREATE_DIALOG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_FOLDER_CREATE_DIALOG, EMailFolderCreateDialogClass)) +#define E_IS_MAIL_FOLDER_CREATE_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_FOLDER_CREATE_DIALOG)) +#define E_IS_MAIL_FOLDER_CREATE_DIALOG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_FOLDER_CREATE_DIALOG)) +#define E_MAIL_FOLDER_CREATE_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_FOLDER_CREATE_DIALOG, EMailFolderCreateDialogClass)) + +G_BEGIN_DECLS + +typedef struct _EMailFolderCreateDialog EMailFolderCreateDialog; +typedef struct _EMailFolderCreateDialogClass EMailFolderCreateDialogClass; +typedef struct _EMailFolderCreateDialogPrivate EMailFolderCreateDialogPrivate; + +struct _EMailFolderCreateDialog { + EMFolderSelector parent; + EMailFolderCreateDialogPrivate *priv; +}; + +struct _EMailFolderCreateDialogClass { + EMFolderSelectorClass parent_class; + + /* Signals */ + void (*folder_created) + (EMailFolderCreateDialog *dialog, + CamelStore *store, + const gchar *folder_name); +}; + +GType e_mail_folder_create_dialog_get_type + (void) G_GNUC_CONST; +GtkWidget * e_mail_folder_create_dialog_new + (GtkWindow *parent, + EMailUISession *session); +EMailUISession * + e_mail_folder_create_dialog_get_session + (EMailFolderCreateDialog *dialog); + +G_END_DECLS + +#endif /* E_MAIL_FOLDER_CREATE_DIALOG_H */ + diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c index fcdd66e007..1a512f707f 100644 --- a/mail/em-folder-selector.c +++ b/mail/em-folder-selector.c @@ -29,6 +29,7 @@ #include #include +#include "e-mail-folder-create-dialog.h" #include "em-folder-tree.h" #include "em-folder-utils.h" #include "em-utils.h" @@ -49,7 +50,6 @@ struct _EMFolderSelectorPrivate { GtkWidget *content_area; GtkWidget *tree_view_frame; - GtkEntry *name_entry; gchar *selected_uri; gboolean can_create; @@ -84,28 +84,6 @@ G_DEFINE_TYPE_WITH_CODE ( E_TYPE_ALERT_SINK, em_folder_selector_alert_sink_init)) -static void -folder_selector_create_name_changed (GtkEntry *entry, - EMFolderSelector *selector) -{ - EMFolderTree *folder_tree; - gchar *path; - const gchar *text = NULL; - gboolean active; - - if (gtk_entry_get_text_length (selector->priv->name_entry) > 0) - text = gtk_entry_get_text (selector->priv->name_entry); - - folder_tree = em_folder_selector_get_folder_tree (selector); - - path = em_folder_tree_get_selected_uri (folder_tree); - active = text && path && !strchr (text, '/'); - g_free (path); - - gtk_dialog_set_response_sensitive ( - GTK_DIALOG (selector), GTK_RESPONSE_OK, active); -} - static void folder_selector_selected_cb (EMFolderTree *emft, CamelStore *store, @@ -126,27 +104,61 @@ folder_selector_activated_cb (EMFolderTree *emft, gtk_dialog_response (GTK_DIALOG (selector), GTK_RESPONSE_OK); } +static void +folder_selector_folder_created_cb (EMailFolderCreateDialog *dialog, + CamelStore *store, + const gchar *folder_name, + GWeakRef *folder_tree_weak_ref) +{ + EMFolderTree *folder_tree; + + folder_tree = g_weak_ref_get (folder_tree_weak_ref); + + if (folder_tree != NULL) { + gchar *folder_uri; + + /* Select the newly created folder. */ + folder_uri = e_mail_folder_uri_build (store, folder_name); + em_folder_tree_set_selected (folder_tree, folder_uri, TRUE); + g_free (folder_uri); + + g_object_unref (folder_tree); + } +} + static void folder_selector_action_add_cb (ETreeViewFrame *tree_view_frame, GtkAction *action, EMFolderSelector *selector) { - EMFolderTree *folder_tree; + GtkWidget *new_dialog; EMailSession *session; - const gchar *uri; + EMFolderTree *folder_tree; + const gchar *initial_uri; folder_tree = em_folder_selector_get_folder_tree (selector); + session = em_folder_tree_get_session (folder_tree); - g_object_set_data ( - G_OBJECT (folder_tree), - "select", GUINT_TO_POINTER (1)); + new_dialog = e_mail_folder_create_dialog_new ( + GTK_WINDOW (selector), + E_MAIL_UI_SESSION (session)); - session = em_folder_tree_get_session (folder_tree); + gtk_window_set_modal (GTK_WINDOW (new_dialog), TRUE); + + g_signal_connect_data ( + new_dialog, "folder-created", + G_CALLBACK (folder_selector_folder_created_cb), + e_weak_ref_new (folder_tree), + (GClosureNotify) e_weak_ref_free, 0); + + initial_uri = em_folder_selector_get_selected_uri (selector); - uri = em_folder_selector_get_selected_uri (selector); + folder_tree = em_folder_selector_get_folder_tree ( + EM_FOLDER_SELECTOR (new_dialog)); - em_folder_utils_create_folder ( - GTK_WINDOW (selector), session, folder_tree, uri); + em_folder_tree_set_selected (folder_tree, initial_uri, FALSE); + + gtk_widget_show (new_dialog); } static void @@ -392,14 +404,9 @@ folder_selector_folder_selected (EMFolderSelector *selector, CamelStore *store, const gchar *folder_name) { - if (selector->priv->name_entry != NULL) { - folder_selector_create_name_changed ( - selector->priv->name_entry, selector); - } else { - gtk_dialog_set_response_sensitive ( - GTK_DIALOG (selector), GTK_RESPONSE_OK, - (store != NULL) && (folder_name != NULL)); - } + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (selector), GTK_RESPONSE_OK, + (store != NULL) && (folder_name != NULL)); } static void @@ -531,87 +538,6 @@ em_folder_selector_new (GtkWindow *parent, "model", model, NULL); } -static void -folder_selector_create_name_activate (GtkEntry *entry, - EMFolderSelector *selector) -{ - if (gtk_entry_get_text_length (selector->priv->name_entry) > 0) { - EMFolderTree *folder_tree; - gchar *path; - const gchar *text; - gboolean emit_response; - - text = gtk_entry_get_text (selector->priv->name_entry); - - folder_tree = em_folder_selector_get_folder_tree (selector); - path = em_folder_tree_get_selected_uri (folder_tree); - - emit_response = - (path != NULL) && - (text != NULL) && - (strchr (text, '/') == NULL); - - if (emit_response) { - g_signal_emit_by_name ( - selector, "response", GTK_RESPONSE_OK); - } - - g_free (path); - } -} - -GtkWidget * -em_folder_selector_create_new (GtkWindow *parent, - EMFolderTreeModel *model) -{ - EMFolderSelector *selector; - EMFolderTree *folder_tree; - GtkWidget *container; - GtkWidget *widget; - GtkLabel *label; - - g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - - selector = g_object_new ( - EM_TYPE_FOLDER_SELECTOR, - "transient-for", parent, - "model", model, - "default-button-label", _("C_reate"), NULL); - - folder_tree = em_folder_selector_get_folder_tree (selector); - em_folder_tree_set_excluded (folder_tree, EMFT_EXCLUDE_NOINFERIORS); - - container = selector->priv->content_area; - - widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_label_new_with_mnemonic (_("Folder _name:")); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - label = GTK_LABEL (widget); - - widget = gtk_entry_new (); - gtk_label_set_mnemonic_widget (label, widget); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - selector->priv->name_entry = GTK_ENTRY (widget); - gtk_widget_grab_focus (widget); - gtk_widget_show (widget); - - g_signal_connect ( - widget, "changed", - G_CALLBACK (folder_selector_create_name_changed), selector); - g_signal_connect ( - widget, "activate", - G_CALLBACK (folder_selector_create_name_activate), selector); - - return GTK_WIDGET (selector); -} - /** * em_folder_selector_get_can_create: * @selector: an #EMFolderSelector @@ -871,19 +797,6 @@ em_folder_selector_get_selected_uri (EMFolderSelector *selector) if (uri == NULL) return NULL; - if (selector->priv->name_entry != NULL) { - const gchar *name; - gchar *temp_uri, *escaped_name; - - name = gtk_entry_get_text (selector->priv->name_entry); - escaped_name = g_uri_escape_string (name, NULL, TRUE); - temp_uri = g_strconcat (uri, "/", escaped_name, NULL); - - g_free (escaped_name); - g_free (uri); - uri = temp_uri; - } - g_free (selector->priv->selected_uri); selector->priv->selected_uri = uri; /* takes ownership */ diff --git a/mail/em-folder-selector.h b/mail/em-folder-selector.h index bb093be8e9..8093d71d9a 100644 --- a/mail/em-folder-selector.h +++ b/mail/em-folder-selector.h @@ -68,8 +68,6 @@ struct _EMFolderSelectorClass { GType em_folder_selector_get_type (void); GtkWidget * em_folder_selector_new (GtkWindow *parent, EMFolderTreeModel *model); -GtkWidget * em_folder_selector_create_new (GtkWindow *parent, - EMFolderTreeModel *model); gboolean em_folder_selector_get_can_create (EMFolderSelector *selector); void em_folder_selector_set_can_create diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index b3d754369d..479d8783f6 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -51,24 +51,6 @@ #define d(x) -typedef struct _AsyncContext AsyncContext; - -struct _AsyncContext { - EMFolderTree *folder_tree; - gchar *folder_uri; -}; - -static void -async_context_free (AsyncContext *context) -{ - if (context->folder_tree != NULL) - g_object_unref (context->folder_tree); - - g_free (context->folder_uri); - - g_slice_free (AsyncContext, context); -} - static gboolean emfu_is_special_local_folder (const gchar *name) { @@ -530,152 +512,6 @@ em_folder_utils_copy_folder (GtkWindow *parent, gtk_widget_destroy (dialog); } -static void -new_folder_created_cb (CamelStore *store, - GAsyncResult *result, - AsyncContext *context) -{ - GError *error = NULL; - - e_mail_store_create_folder_finish (store, result, &error); - - /* FIXME Use an EActivity here. */ - if (error != NULL) { - e_notice (NULL, GTK_MESSAGE_ERROR, "%s", error->message); - g_error_free (error); - - } else if (context->folder_tree != NULL) { - gpointer data; - gboolean expand_only; - - /* XXX What in the hell kind of lazy hack is this? */ - data = g_object_get_data ( - G_OBJECT (context->folder_tree), "select"); - expand_only = GPOINTER_TO_INT (data) ? FALSE : TRUE; - - em_folder_tree_set_selected ( - context->folder_tree, - context->folder_uri, expand_only); - } - - async_context_free (context); -} - -void -em_folder_utils_create_folder (GtkWindow *parent, - EMailSession *session, - EMFolderTree *emft, - const gchar *initial_uri) -{ - EMFolderSelector *selector; - EMFolderTree *folder_tree; - EMFolderTreeModel *model; - EMailAccountStore *account_store; - CamelStore *store = NULL; - GtkWidget *dialog; - GQueue queue = G_QUEUE_INIT; - const gchar *caption; - const gchar *folder_uri; - gchar *folder_name = NULL; - GError *error = NULL; - - g_return_if_fail (GTK_IS_WINDOW (parent)); - g_return_if_fail (E_IS_MAIL_SESSION (session)); - - model = em_folder_tree_model_new (); - em_folder_tree_model_set_session (model, session); - - account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session)); - e_mail_account_store_queue_enabled_services (account_store, &queue); - - while (!g_queue_is_empty (&queue)) { - CamelService *service; - CamelStoreFlags flags; - - service = g_queue_pop_head (&queue); - g_warn_if_fail (CAMEL_IS_STORE (service)); - - flags = CAMEL_STORE (service)->flags; - if ((flags & CAMEL_STORE_CAN_EDIT_FOLDERS) == 0) - continue; - - em_folder_tree_model_add_store (model, CAMEL_STORE (service)); - } - - dialog = em_folder_selector_create_new (parent, model); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Create Folder")); - - g_object_unref (model); - - selector = EM_FOLDER_SELECTOR (dialog); - - caption = _("Specify where to create the folder:"); - em_folder_selector_set_caption (selector, caption); - - folder_tree = em_folder_selector_get_folder_tree (selector); - - if (initial_uri != NULL) - em_folder_tree_set_selected (folder_tree, initial_uri, FALSE); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) - goto exit; - - folder_uri = em_folder_selector_get_selected_uri (selector); - g_return_if_fail (folder_uri != NULL); - - e_mail_folder_uri_parse ( - CAMEL_SESSION (session), folder_uri, - &store, &folder_name, &error); - - /* XXX This is unlikely to fail since the URI comes straight from - * EMFolderSelector, but leave a breadcrumb if it does fail. */ - if (error != NULL) { - g_warn_if_fail (store == NULL); - g_warn_if_fail (folder_name == NULL); - e_notice (parent, GTK_MESSAGE_ERROR, "%s", error->message); - g_error_free (error); - goto exit; - } - - g_return_if_fail (folder_name != NULL); - - /* HACK: we need to create vfolders using the vfolder editor */ - if (CAMEL_IS_VEE_STORE (store)) { - EFilterRule *rule; - const gchar *skip_slash; - - if (*folder_name == '/') - skip_slash = folder_name + 1; - else - skip_slash = folder_name; - - rule = em_vfolder_editor_rule_new (session); - e_filter_rule_set_name (rule, skip_slash); - vfolder_gui_add_rule (EM_VFOLDER_RULE (rule)); - } else { - AsyncContext *context; - - context = g_slice_new0 (AsyncContext); - context->folder_uri = e_mail_folder_uri_build (store, folder_name); - - if (EM_IS_FOLDER_TREE (emft)) - context->folder_tree = g_object_ref (emft); - - /* FIXME Not passing a GCancellable. */ - e_mail_store_create_folder ( - store, folder_name, G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback) new_folder_created_cb, - context); - } - - g_free (folder_name); - g_object_unref (store); - -exit: - gtk_widget_destroy (dialog); -} - const gchar * em_folder_utils_get_icon_name (guint32 flags) { diff --git a/mail/em-folder-utils.h b/mail/em-folder-utils.h index 3d034ac928..7b9f66664c 100644 --- a/mail/em-folder-utils.h +++ b/mail/em-folder-utils.h @@ -44,10 +44,6 @@ void em_folder_utils_copy_folder (GtkWindow *parent, EAlertSink *alert_sink, const gchar *folder_uri, gboolean delete); -void em_folder_utils_create_folder (GtkWindow *parent, - EMailSession *session, - EMFolderTree *emft, - const gchar *initial_uri); const gchar * em_folder_utils_get_icon_name (guint32 flags); diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c index b8afd2c2d3..e74086f204 100644 --- a/modules/mail/e-mail-shell-backend.c +++ b/modules/mail/e-mail-shell-backend.c @@ -34,9 +34,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -193,6 +193,28 @@ mail_shell_backend_mail_icon_cb (EShellWindow *shell_window, gtk_action_set_icon_name (action, icon_name); } +static void +mail_shell_backend_folder_created_cb (EMailFolderCreateDialog *dialog, + CamelStore *store, + const gchar *folder_name, + GWeakRef *folder_tree_weak_ref) +{ + EMFolderTree *folder_tree; + + folder_tree = g_weak_ref_get (folder_tree_weak_ref); + + if (folder_tree != NULL) { + gchar *folder_uri; + + /* Select the newly created folder. */ + folder_uri = e_mail_folder_uri_build (store, folder_name); + em_folder_tree_set_selected (folder_tree, folder_uri, FALSE); + g_free (folder_uri); + + g_object_unref (folder_tree); + } +} + static void action_mail_folder_new_cb (GtkAction *action, EShellWindow *shell_window) @@ -202,6 +224,7 @@ action_mail_folder_new_cb (GtkAction *action, EMailSession *session; EShellSidebar *shell_sidebar; EShellView *shell_view; + GtkWidget *dialog; const gchar *view_name; /* Take care not to unnecessarily load the mail shell view. */ @@ -231,8 +254,19 @@ action_mail_folder_new_cb (GtkAction *action, session = em_folder_tree_get_session (folder_tree); exit: - em_folder_utils_create_folder ( - GTK_WINDOW (shell_window), session, folder_tree, NULL); + dialog = e_mail_folder_create_dialog_new ( + GTK_WINDOW (shell_window), + E_MAIL_UI_SESSION (session)); + + if (folder_tree != NULL) { + g_signal_connect_data ( + dialog, "folder-created", + G_CALLBACK (mail_shell_backend_folder_created_cb), + e_weak_ref_new (folder_tree), + (GClosureNotify) e_weak_ref_free, 0); + } + + gtk_widget_show (GTK_WIDGET (dialog)); } static void diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c index a93191cf7c..76159950a5 100644 --- a/modules/mail/e-mail-shell-view-actions.c +++ b/modules/mail/e-mail-shell-view-actions.c @@ -24,6 +24,28 @@ #include "e-mail-shell-view-private.h" +static void +mail_shell_view_folder_created_cb (EMailFolderCreateDialog *dialog, + CamelStore *store, + const gchar *folder_name, + GWeakRef *folder_tree_weak_ref) +{ + EMFolderTree *folder_tree; + + folder_tree = g_weak_ref_get (folder_tree_weak_ref); + + if (folder_tree != NULL) { + gchar *folder_uri; + + /* Select the newly created folder. */ + folder_uri = e_mail_folder_uri_build (store, folder_name); + em_folder_tree_set_selected (folder_tree, folder_uri, FALSE); + g_free (folder_uri); + + g_object_unref (folder_tree); + } +} + static void action_mail_account_disable_cb (GtkAction *action, EMailShellView *mail_shell_view) @@ -775,7 +797,9 @@ action_mail_folder_new_cb (GtkAction *action, EMailSession *session; EMailShellSidebar *mail_shell_sidebar; EMFolderTree *folder_tree; - gchar *selected_uri; + GtkWidget *dialog; + CamelStore *store = NULL; + gchar *folder_name = NULL; shell_view = E_SHELL_VIEW (mail_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); @@ -784,13 +808,25 @@ action_mail_folder_new_cb (GtkAction *action, folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); session = em_folder_tree_get_session (folder_tree); - selected_uri = em_folder_tree_get_selected_uri (folder_tree); - em_folder_utils_create_folder ( + dialog = e_mail_folder_create_dialog_new ( GTK_WINDOW (shell_window), - session, folder_tree, selected_uri); + E_MAIL_UI_SESSION (session)); - g_free (selected_uri); + g_signal_connect_data ( + dialog, "folder-created", + G_CALLBACK (mail_shell_view_folder_created_cb), + e_weak_ref_new (folder_tree), + (GClosureNotify) e_weak_ref_free, 0); + + if (em_folder_tree_get_selected (folder_tree, &store, &folder_name)) { + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), store, folder_name); + g_object_unref (store); + g_free (folder_name); + } + + gtk_widget_show (GTK_WIDGET (dialog)); } static void diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h index 377ebd8025..2925f4e63c 100644 --- a/modules/mail/e-mail-shell-view-private.h +++ b/modules/mail/e-mail-shell-view-private.h @@ -27,6 +27,7 @@ #include #include /* for camel_search_word */ +#include #include #include #include -- cgit v1.2.3