diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2007-11-28 04:24:44 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2007-11-28 04:24:44 +0800 |
commit | f5bed9bf7b143fff9bd258ea31fdac192e00a0d9 (patch) | |
tree | 46dca324c927780390cfbc8f4ddf200184462926 /composer/e-composer-post-header.c | |
parent | 8aa60af54eee1092e8963c0927c53e8f738eb4cd (diff) | |
download | gsoc2013-evolution-f5bed9bf7b143fff9bd258ea31fdac192e00a0d9.tar.gz gsoc2013-evolution-f5bed9bf7b143fff9bd258ea31fdac192e00a0d9.tar.zst gsoc2013-evolution-f5bed9bf7b143fff9bd258ea31fdac192e00a0d9.zip |
** Fixes bug #495123
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
** Fixes bug #495123
* composer/Makefile.am:
Add a bunch of files for managing composer headers.
* composer/e-msg-composer.c (build_message), (from_changed_cb),
(set_editor_signature), (e_msg_composer_set_body),
(e_msg_composer_get_preferred_account):
* plugins/exchange-operations/exchange-mail-send-options.c
(append_to_header):
Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount.
* composer/e-msg-composer-hdrs.c:
* composer/e-msg-composer-hdrs.h:
Massive refactoring to use new EComposerHeader classes.
* composer/e-composer-header.c:
* composer/e-composer-header.h:
* composer/e-composer-from-header.c:
* composer/e-composer-from-header.h:
* composer/e-composer-name-header.c:
* composer/e-composer-name-header.h:
* composer/e-composer-post-header.c:
* composer/e-composer-post-header.h:
* composer/e-composer-text-header.c:
* composer/e-composer-text-header.h:
New GObject classes manage different types of composer headers.
See bug #495123 for a more detailed description of each class.
* mail/mail-session.c (mail_session_init):
Pass the CamelSession to the EAccountComboBox class (ugly hack).
* widgets/misc/Makefile.am:
Add e-account-combo-box.[ch].
* widgets/misc/e-account-combo-box.c:
* widgets/misc/e-account-combo-box.h:
New widget renders an EAccountList as a combo box. Also listens
for changes to the EAccountList and updates itself accordingly.
svn path=/trunk/; revision=34600
Diffstat (limited to 'composer/e-composer-post-header.c')
-rw-r--r-- | composer/e-composer-post-header.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/composer/e-composer-post-header.c b/composer/e-composer-post-header.c new file mode 100644 index 0000000000..ea16eeb684 --- /dev/null +++ b/composer/e-composer-post-header.c @@ -0,0 +1,401 @@ +#include "e-composer-post-header.h" + +#include <string.h> +#include <glib/gi18n.h> + +#include "mail/em-folder-selector.h" +#include "mail/em-folder-tree.h" + +#define E_COMPOSER_POST_HEADER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeaderPrivate)) + +enum { + PROP_0, + PROP_ACCOUNT +}; + +struct _EComposerPostHeaderPrivate { + EAccount *account; + gchar *base_url; /* derived from account */ + gboolean custom; +}; + +static gpointer parent_class; + +/* Forward Declarations (to avoid pulling in Bonobo stuff) */ +struct _MailComponent *mail_component_peek (void); +struct _EMFolderTreeModel *mail_component_peek_tree_model (struct _MailComponent *component); + +static gchar * +composer_post_header_folder_name_to_string (EComposerPostHeader *header, + const gchar *url) +{ + const gchar *base_url = header->priv->base_url; + + if (base_url != NULL) { + gsize length = strlen (base_url); + + if (g_ascii_strncasecmp (url, base_url, length) == 0) + return g_strdup (url + length); + } + + return g_strdup (url); +} + +static void +composer_post_header_set_base_url (EComposerPostHeader *header) +{ + EAccount *account = header->priv->account; + CamelURL *camel_url; + gchar *url; + + if (account == NULL || account->source == NULL) + return; + + url = account->source->url; + if (url == NULL || *url == '\0') + return; + + camel_url = camel_url_new (url, NULL); + if (camel_url == NULL) + return; + + url = camel_url_to_string (camel_url, CAMEL_URL_HIDE_ALL); + camel_url_free (camel_url); + + header->priv->base_url = url; +} + +static GList * +composer_post_header_split_csv (const gchar *csv) +{ + GList *list = NULL; + gchar **strv; + guint length, ii; + + strv = g_strsplit (csv, ",", 0); + length = g_strv_length (strv); + + for (ii = 0; ii < length; ii++) + if (*g_strstrip (strv[ii]) != '\0') + list = g_list_prepend (list, g_strdup (strv[ii])); + + g_strfreev (strv); + + 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; + + model = mail_component_peek_tree_model (mail_component_peek ()); + 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, + GObjectConstructParam *construct_properties) +{ + GObject *object; + + /* Chain up to parent's constructor() method. */ + object = G_OBJECT_CLASS (parent_class)->constructor ( + type, n_construct_properties, construct_properties); + + e_composer_header_set_title_tooltip ( + 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; +} + +static void +composer_post_header_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT: + e_composer_post_header_set_account ( + E_COMPOSER_POST_HEADER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +composer_post_header_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACCOUNT: + g_value_set_object ( + value, e_composer_post_header_get_account ( + E_COMPOSER_POST_HEADER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +composer_post_header_dispose (GObject *object) +{ + EComposerPostHeaderPrivate *priv; + + priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (object); + + if (priv->account != NULL) { + g_object_unref (priv->account); + priv->account = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +composer_post_header_class_init (EComposerPostHeaderClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EComposerPostHeaderPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructor = composer_post_header_constructor; + object_class->set_property = composer_post_header_set_property; + object_class->get_property = composer_post_header_get_property; + object_class->dispose = composer_post_header_dispose; + + g_object_class_install_property ( + object_class, + PROP_ACCOUNT, + g_param_spec_object ( + "account", + NULL, + NULL, + E_TYPE_ACCOUNT, + G_PARAM_READWRITE)); +} + +static void +composer_post_header_init (EComposerPostHeader *header) +{ + header->priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header); +} + +GType +e_composer_post_header_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EComposerPostHeaderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) composer_post_header_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EComposerPostHeader), + 0, /* n_preallocs */ + (GInstanceInitFunc) composer_post_header_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_COMPOSER_TEXT_HEADER, + "EComposerPostHeader", &type_info, 0); + } + + return type; +} + +EComposerHeader * +e_composer_post_header_new (const gchar *label) +{ + return g_object_new ( + E_TYPE_COMPOSER_POST_HEADER, + "label", label, "button", TRUE, NULL); +} + +EAccount * +e_composer_post_header_get_account (EComposerPostHeader *header) +{ + g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL); + + return header->priv->account; +} + +void +e_composer_post_header_set_account (EComposerPostHeader *header, + EAccount *account) +{ + GList *folders = NULL; + + g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header)); + + if (account != NULL) { + g_return_if_fail (E_IS_ACCOUNT (account)); + g_object_ref (account); + } + + if (!header->priv->custom) + folders = e_composer_post_header_get_folders (header); + + if (header->priv->account != NULL) + g_object_unref (header->priv->account); + + header->priv->account = account; + composer_post_header_set_base_url (header); + + /* Make folders relative to the new account. */ + if (!header->priv->custom) { + e_composer_post_header_set_folders (header, folders); + g_list_foreach (folders, (GFunc) g_free, NULL); + g_list_free (folders); + } + + g_object_notify (G_OBJECT (header), "account"); +} + +GList * +e_composer_post_header_get_folders (EComposerPostHeader *header) +{ + GList *folders, *iter; + gchar *base_url; + + g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL); + + folders = composer_post_header_split_csv ( + e_composer_text_header_get_text ( + E_COMPOSER_TEXT_HEADER (header))); + + base_url = header->priv->base_url; + if (base_url == NULL) + return folders; + + for (iter = folders; iter != NULL; iter = iter->next) { + /* Convert relative folder names to absolute. */ + /* XXX Should use CamelURL for this. */ + if (strstr (iter->data, ":/") == NULL) { + gchar *abs_url; + + abs_url = g_strconcat (base_url, iter->data, NULL); + g_free (iter->data); + iter->data = abs_url; + } + } + + return folders; +} + +void +e_composer_post_header_set_folders (EComposerPostHeader *header, + GList *folders) +{ + GList *iter; + gint ii = 0; + gchar **strv; + gchar *text; + gboolean custom_save; + + g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header)); + + strv = g_new0 (gchar *, g_list_length (folders) + 1); + + for (iter = folders; iter != NULL; iter = iter->next) + strv[ii++] = composer_post_header_folder_name_to_string ( + header, iter->data); + + text = g_strjoinv (", ", strv); + custom_save = header->priv->custom; + e_composer_text_header_set_text ( + E_COMPOSER_TEXT_HEADER (header), text); + header->priv->custom = custom_save; + g_free (text); + + g_strfreev (strv); +} + +void +e_composer_post_header_set_folders_base (EComposerPostHeader *header, + const gchar *base_url, + const gchar *folders) +{ + GList *list, *iter; + + list = composer_post_header_split_csv (folders); + for (iter = list; iter != NULL; iter = iter->next) { + gchar *abs_url; + + /* FIXME This doesn't handle all folder names properly. */ + abs_url = g_strdup_printf ( + "%s/%s", base_url, (gchar *) iter->data); + g_free (iter->data); + iter->data = abs_url; + } + + e_composer_post_header_set_folders (header, list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); +} |