From 7986af5369482c4feeaad6880045bf92a4d3f744 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 13 Feb 2009 04:32:51 +0000 Subject: Let the mail module handle composer "Post To:" button clicks, since EMFolderSelector and EMFolderTree are off-limits to the composer. This further weakens the composer's mail module dependency. Add class methods to EComposerHeader for "changed" and "clicked" signals. Allows subclasses to implement them without connecting to their own signals. svn path=/branches/kill-bonobo/; revision=37260 --- composer/e-composer-header-table.c | 54 -------------- composer/e-composer-header-table.h | 7 -- composer/e-composer-header.c | 6 +- composer/e-composer-header.h | 6 +- composer/e-composer-name-header.c | 35 +++++---- composer/e-composer-post-header.c | 148 +++++++------------------------------ composer/e-composer-post-header.h | 7 -- mail/em-composer-utils.c | 74 +++++++++++++++++-- 8 files changed, 124 insertions(+), 213 deletions(-) diff --git a/composer/e-composer-header-table.c b/composer/e-composer-header-table.c index c3af87a76d..461c11efa1 100644 --- a/composer/e-composer-header-table.c +++ b/composer/e-composer-header-table.c @@ -78,7 +78,6 @@ enum { PROP_DESTINATIONS_BCC, PROP_DESTINATIONS_CC, PROP_DESTINATIONS_TO, - PROP_MODEL, PROP_POST_TO, PROP_REPLY_TO, PROP_SIGNATURE, @@ -91,7 +90,6 @@ struct _EComposerHeaderTablePrivate { GtkWidget *signature_label; GtkWidget *signature_combo_box; ENameSelector *name_selector; - EMFolderTreeModel *model; }; static gpointer parent_class; @@ -346,12 +344,6 @@ composer_header_table_set_property (GObject *object, e_destination_freev (destinations); return; - case PROP_MODEL: - e_composer_header_table_set_folder_tree_model ( - E_COMPOSER_HEADER_TABLE (object), - g_value_get_object (value)); - return; - case PROP_POST_TO: list = g_value_dup_string_list (value); e_composer_header_table_set_post_to_list ( @@ -443,13 +435,6 @@ composer_header_table_get_property (GObject *object, e_destination_freev (destinations); return; - case PROP_MODEL: - g_value_set_object ( - value, - e_composer_header_table_get_folder_tree_model ( - E_COMPOSER_HEADER_TABLE (object))); - return; - case PROP_POST_TO: list = e_composer_header_table_get_post_to ( E_COMPOSER_HEADER_TABLE (object)); @@ -515,11 +500,6 @@ composer_header_table_dispose (GObject *object) priv->name_selector = NULL; } - if (priv->model != NULL) { - g_object_unref (priv->model); - priv->model = NULL; - } - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -607,17 +587,6 @@ composer_header_table_class_init (EComposerHeaderTableClass *class) element_spec, G_PARAM_READWRITE)); - g_object_class_install_property ( - object_class, - PROP_MODEL, - g_param_spec_object ( - "model", - NULL, - NULL, - EM_TYPE_FOLDER_TREE_MODEL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( object_class, PROP_REPLY_TO, @@ -1000,29 +969,6 @@ e_composer_header_table_set_destinations_to (EComposerHeaderTable *table, e_composer_name_header_set_destinations (header, destinations); } -EMFolderTreeModel * -e_composer_header_table_get_folder_tree_model (EComposerHeaderTable *table) -{ - EComposerPostHeader *header; - - g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL); - - header = E_COMPOSER_HEADER_TABLE_GET_POST_TO_HEADER (table); - return e_composer_post_header_get_folder_tree_model (header); -} - -void -e_composer_header_table_set_folder_tree_model (EComposerHeaderTable *table, - EMFolderTreeModel *model) -{ - EComposerPostHeader *header; - - g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table)); - - header = E_COMPOSER_HEADER_TABLE_GET_POST_TO_HEADER (table); - e_composer_post_header_set_folder_tree_model (header, model); -} - GList * e_composer_header_table_get_post_to (EComposerHeaderTable *table) { diff --git a/composer/e-composer-header-table.h b/composer/e-composer-header-table.h index 565880f324..b3150c409a 100644 --- a/composer/e-composer-header-table.h +++ b/composer/e-composer-header-table.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "e-composer-header.h" @@ -126,12 +125,6 @@ EDestination ** e_composer_header_table_get_destinations_to void e_composer_header_table_set_destinations_to (EComposerHeaderTable *table, EDestination **destinations); -EMFolderTreeModel * - e_composer_header_table_get_folder_tree_model - (EComposerHeaderTable *table); -void e_composer_header_table_set_folder_tree_model - (EComposerHeaderTable *table, - EMFolderTreeModel *model); GList * e_composer_header_table_get_post_to (EComposerHeaderTable *table); void e_composer_header_table_set_post_to_base diff --git a/composer/e-composer-header.c b/composer/e-composer-header.c index 8cbcf64f1f..8a6d553921 100644 --- a/composer/e-composer-header.c +++ b/composer/e-composer-header.c @@ -240,7 +240,8 @@ composer_header_class_init (EComposerHeaderClass *class) "changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, + G_STRUCT_OFFSET (EComposerHeaderClass, changed), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -248,7 +249,8 @@ composer_header_class_init (EComposerHeaderClass *class) "clicked", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, + G_STRUCT_OFFSET (EComposerHeaderClass, clicked), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } diff --git a/composer/e-composer-header.h b/composer/e-composer-header.h index d1edd110fe..4845816faf 100644 --- a/composer/e-composer-header.h +++ b/composer/e-composer-header.h @@ -28,7 +28,7 @@ ((obj), E_TYPE_COMPOSER_HEADER, EComposerHeader)) #define E_COMPOSER_HEADER_CLASS(cls) \ (G_TYPE_CHECK_CLASS_CAST \ - ((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderClass)) + ((cls), E_TYPE_COMPOSER_HEADER, EComposerHeaderClass)) #define E_IS_COMPOSER_HEADER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE \ ((obj), E_TYPE_COMPOSER_HEADER)) @@ -54,6 +54,10 @@ struct _EComposerHeader { struct _EComposerHeaderClass { GObjectClass parent_class; + + /* Signals */ + void (*changed) (EComposerHeader *header); + void (*clicked) (EComposerHeader *header); }; GType e_composer_header_get_type (void); diff --git a/composer/e-composer-name-header.c b/composer/e-composer-name-header.c index 70a126b1e0..1b5acc19d5 100644 --- a/composer/e-composer-name-header.c +++ b/composer/e-composer-name-header.c @@ -46,18 +46,6 @@ struct _EComposerNameHeaderPrivate { static gpointer parent_class; -static void -composer_name_header_clicked_cb (EComposerNameHeader *header) -{ - ENameSelectorDialog *dialog; - - dialog = e_name_selector_peek_dialog (header->priv->name_selector); - e_name_selector_dialog_set_destination_index ( - dialog, header->priv->destination_index); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (GTK_WIDGET (dialog)); -} - static void composer_name_header_entry_changed_cb (ENameSelectorEntry *entry, EComposerNameHeader *header) @@ -130,10 +118,6 @@ composer_name_header_constructor (GType type, NULL); E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (entry); - g_signal_connect ( - object, "clicked", - G_CALLBACK (composer_name_header_clicked_cb), NULL); - return object; } @@ -191,10 +175,26 @@ composer_name_header_dispose (GObject *object) G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +composer_name_header_clicked (EComposerHeader *header) +{ + EComposerNameHeaderPrivate *priv; + ENameSelectorDialog *dialog; + + priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (header); + + dialog = e_name_selector_peek_dialog (priv->name_selector); + e_name_selector_dialog_set_destination_index ( + dialog, priv->destination_index); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide (GTK_WIDGET (dialog)); +} + static void composer_name_header_class_init (EComposerNameHeaderClass *class) { GObjectClass *object_class; + EComposerHeaderClass *header_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EComposerNameHeaderPrivate)); @@ -205,6 +205,9 @@ composer_name_header_class_init (EComposerNameHeaderClass *class) object_class->get_property = composer_name_header_get_property; object_class->dispose = composer_name_header_dispose; + header_class = E_COMPOSER_HEADER_CLASS (class); + header_class->clicked = composer_name_header_clicked; + g_object_class_install_property ( object_class, PROP_NAME_SELECTOR, diff --git a/composer/e-composer-post-header.c b/composer/e-composer-post-header.c index 5a5ca2e610..88d20d5f58 100644 --- a/composer/e-composer-post-header.c +++ b/composer/e-composer-post-header.c @@ -22,9 +22,7 @@ #include #include - -#include "mail/em-folder-selector.h" -#include "mail/em-folder-tree.h" +#include #define E_COMPOSER_POST_HEADER_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ @@ -32,12 +30,10 @@ enum { PROP_0, - PROP_ACCOUNT, - PROP_FOLDER_TREE_MODEL + PROP_ACCOUNT }; struct _EComposerPostHeaderPrivate { - EMFolderTreeModel *model; EAccount *account; gchar *base_url; /* derived from account */ gboolean custom; @@ -104,58 +100,6 @@ composer_post_header_split_csv (const gchar *csv) return g_list_reverse (list); } -static void -composer_post_header_changed_cb (EComposerPostHeader *header) -{ - header->priv->custom = TRUE; -} - -static void -composer_post_header_clicked_cb (EComposerPostHeader *header) -{ - EMFolderTreeModel *model; - GtkWidget *folder_tree; - GtkWidget *dialog; - GList *list; - - g_return_if_fail (header->priv->model != NULL); - - model = header->priv->model; - folder_tree = em_folder_tree_new_with_model (model); - - em_folder_tree_set_multiselect ( - EM_FOLDER_TREE (folder_tree), TRUE); - em_folder_tree_set_excluded ( - EM_FOLDER_TREE (folder_tree), - EMFT_EXCLUDE_NOSELECT | - EMFT_EXCLUDE_VIRTUAL | - EMFT_EXCLUDE_VTRASH); - - dialog = em_folder_selector_new ( - EM_FOLDER_TREE (folder_tree), - EM_FOLDER_SELECTOR_CAN_CREATE, - _("Posting destination"), - _("Choose folders to post the message to."), - NULL); - - list = e_composer_post_header_get_folders (header); - em_folder_selector_set_selected_list ( - EM_FOLDER_SELECTOR (dialog), list); - g_list_foreach (list, (GFunc) g_free, NULL); - g_list_free (list); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { - list = em_folder_selector_get_selected_uris ( - EM_FOLDER_SELECTOR (dialog)); - e_composer_post_header_set_folders (header, list); - header->priv->custom = FALSE; - g_list_foreach (list, (GFunc) g_free, NULL); - g_list_free (list); - } - - gtk_widget_destroy (dialog); -} - static GObject * composer_post_header_constructor (GType type, guint n_construct_properties, @@ -171,14 +115,6 @@ composer_post_header_constructor (GType type, E_COMPOSER_HEADER (object), _("Click here to select folders to post to")); - g_signal_connect ( - object, "changed", - G_CALLBACK (composer_post_header_changed_cb), NULL); - - g_signal_connect ( - object, "clicked", - G_CALLBACK (composer_post_header_clicked_cb), NULL); - return object; } @@ -194,12 +130,6 @@ composer_post_header_set_property (GObject *object, E_COMPOSER_POST_HEADER (object), g_value_get_object (value)); return; - - case PROP_FOLDER_TREE_MODEL: - e_composer_post_header_set_folder_tree_model ( - E_COMPOSER_POST_HEADER (object), - g_value_get_object (value)); - return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -217,13 +147,6 @@ composer_post_header_get_property (GObject *object, value, e_composer_post_header_get_account ( E_COMPOSER_POST_HEADER (object))); return; - - case PROP_FOLDER_TREE_MODEL: - g_value_set_object ( - value, - e_composer_post_header_get_folder_tree_model ( - E_COMPOSER_POST_HEADER (object))); - return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -241,11 +164,6 @@ composer_post_header_dispose (GObject *object) priv->account = NULL; } - if (priv->model != NULL) { - g_object_unref (priv->model); - priv->model = NULL; - } - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -263,10 +181,31 @@ composer_post_header_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +composer_post_header_changed (EComposerHeader *header) +{ + EComposerPostHeaderPrivate *priv; + + priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header); + + priv->custom = TRUE; +} + +static void +composer_post_header_clicked (EComposerHeader *header) +{ + EComposerPostHeaderPrivate *priv; + + priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header); + + priv->custom = FALSE; +} + static void composer_post_header_class_init (EComposerPostHeaderClass *class) { GObjectClass *object_class; + EComposerHeaderClass *header_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EComposerPostHeaderPrivate)); @@ -278,6 +217,10 @@ composer_post_header_class_init (EComposerPostHeaderClass *class) object_class->dispose = composer_post_header_dispose; object_class->finalize = composer_post_header_finalize; + header_class = E_COMPOSER_HEADER_CLASS (class); + header_class->changed = composer_post_header_changed; + header_class->clicked = composer_post_header_clicked; + g_object_class_install_property ( object_class, PROP_ACCOUNT, @@ -287,16 +230,6 @@ composer_post_header_class_init (EComposerPostHeaderClass *class) NULL, E_TYPE_ACCOUNT, G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_FOLDER_TREE_MODEL, - g_param_spec_object ( - "folder-tree-model", - NULL, - NULL, - EM_TYPE_FOLDER_TREE_MODEL, - G_PARAM_READWRITE)); } static void @@ -380,33 +313,6 @@ e_composer_post_header_set_account (EComposerPostHeader *header, g_object_notify (G_OBJECT (header), "account"); } -EMFolderTreeModel * -e_composer_post_header_get_folder_tree_model (EComposerPostHeader *header) -{ - g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL); - - return header->priv->model; -} - -void -e_composer_post_header_set_folder_tree_model (EComposerPostHeader *header, - EMFolderTreeModel *model) -{ - g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header)); - - if (model != NULL) { - g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); - g_object_ref (model); - } - - if (header->priv->model != NULL) - g_object_unref (header->priv->model); - - header->priv->model = model; - - g_object_notify (G_OBJECT (header), "folder-tree-model"); -} - GList * e_composer_post_header_get_folders (EComposerPostHeader *header) { diff --git a/composer/e-composer-post-header.h b/composer/e-composer-post-header.h index f2a1a5057c..92b582600b 100644 --- a/composer/e-composer-post-header.h +++ b/composer/e-composer-post-header.h @@ -22,7 +22,6 @@ #define E_COMPOSER_POST_HEADER_H #include -#include #include "e-composer-text-header.h" @@ -70,12 +69,6 @@ EAccount * e_composer_post_header_get_account void e_composer_post_header_set_account (EComposerPostHeader *header, EAccount *account); -EMFolderTreeModel * - e_composer_post_header_get_folder_tree_model - (EComposerPostHeader *header); -void e_composer_post_header_set_folder_tree_model - (EComposerPostHeader *header, - EMFolderTreeModel *model); GList * e_composer_post_header_get_folders (EComposerPostHeader *header); void e_composer_post_header_set_folders diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 065cd325df..381e7fbfc5 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -45,6 +45,9 @@ #include "em-composer-utils.h" #include "composer/e-msg-composer.h" #include "composer/e-composer-autosave.h" +#include "composer/e-composer-post-header.h" +#include "em-folder-selector.h" +#include "em-folder-tree.h" #include "em-format-html.h" #include "em-format-html-print.h" #include "em-format-quote.h" @@ -2525,6 +2528,56 @@ em_utils_post_reply_to_message_by_uid (CamelFolder *folder, const char *uid) mail_get_message (folder, uid, post_reply_to_message, NULL, mail_msg_unordered_push); } +static void +post_header_clicked_cb (EComposerPostHeader *header, + EShellModule *shell_module) +{ + EMFolderTreeModel *model; + GtkWidget *folder_tree; + GtkWidget *dialog; + GList *list; + + model = e_mail_shell_module_get_folder_tree_model (shell_module); + folder_tree = em_folder_tree_new_with_model (model); + + em_folder_tree_set_multiselect ( + EM_FOLDER_TREE (folder_tree), TRUE); + em_folder_tree_set_excluded ( + EM_FOLDER_TREE (folder_tree), + EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | + EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + EM_FOLDER_TREE (folder_tree), + EM_FOLDER_SELECTOR_CAN_CREATE, + _("Posting destination"), + _("Choose folders to post the message to."), + NULL); + + list = e_composer_post_header_get_folders (header); + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) { + /* Prevent the header's "custom" flag from being reset, + * which is what the default method will do next. */ + g_signal_stop_emission_by_name (header, "clicked"); + goto exit; + } + + list = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + e_composer_post_header_set_folders (header, list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + +exit: + gtk_widget_destroy (dialog); +} + /** * em_configure_new_composer: * @composer: a newly created #EMsgComposer @@ -2538,11 +2591,16 @@ void em_configure_new_composer (EMsgComposer *composer) { EComposerHeaderTable *table; - EMFolderTreeModel *model; + EComposerHeaderType header_type; + EComposerHeader *header; struct emcs_t *emcs; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + header_type = E_COMPOSER_HEADER_POST_TO; + table = e_msg_composer_get_header_table (composer); + header = e_composer_header_table_get_header (table, header_type); + emcs = emcs_new (); g_object_set_data_full ( @@ -2561,8 +2619,14 @@ em_configure_new_composer (EMsgComposer *composer) composer, "print", G_CALLBACK (em_utils_composer_print_cb), NULL); - /* Supply the composer with a folder tree model. */ - table = e_msg_composer_get_header_table (composer); - model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); - e_composer_header_table_set_folder_tree_model (table, model); + /* Handle "Post To:" button clicks, which displays a folder tree + * widget. The composer doesn't know about folder tree widgets, + * so it can't handle this itself. + * + * Note: This is a G_SIGNAL_RUN_LAST signal, which allows us to + * stop the signal emission if the user cancels or closes + * the folder selector dialog. See the handler function. */ + g_signal_connect ( + header, "clicked", + G_CALLBACK (post_header_clicked_cb), mail_shell_module); } -- cgit v1.2.3