aboutsummaryrefslogtreecommitdiffstats
path: root/mail/e-mail-folder-create-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/e-mail-folder-create-dialog.c')
-rw-r--r--mail/e-mail-folder-create-dialog.c498
1 files changed, 498 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "e-mail-folder-create-dialog.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#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;
+}
+