/*
* 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);
/* Can be NULL during dispose, when the folder tree model is being cleared */
if (dialog->priv->name_entry)
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;
}