aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--composer/ChangeLog19
-rw-r--r--composer/e-composer-from-header.c53
-rw-r--r--composer/e-composer-from-header.h2
-rw-r--r--composer/e-composer-name-header.c18
-rw-r--r--composer/e-composer-text-header.c19
-rw-r--r--composer/e-msg-composer-hdrs.c82
-rw-r--r--composer/e-msg-composer-hdrs.h4
-rw-r--r--composer/e-msg-composer.c310
-rw-r--r--widgets/misc/ChangeLog15
-rw-r--r--widgets/misc/Makefile.am3
-rw-r--r--widgets/misc/e-account-combo-box.c4
-rw-r--r--widgets/misc/e-signature-combo-box.c338
-rw-r--r--widgets/misc/e-signature-combo-box.h55
13 files changed, 606 insertions, 316 deletions
diff --git a/composer/ChangeLog b/composer/ChangeLog
index 9a08ccf025..96984e9059 100644
--- a/composer/ChangeLog
+++ b/composer/ChangeLog
@@ -1,3 +1,22 @@
+2007-12-01 Matthew Barnes <mbarnes@redhat.com>
+
+ ** Fixes part of bug #495123
+
+ * e-msg-composer.c:
+ * e-msg-composer-hdrs.h:
+ * e-msg-composer-hdrs.c:
+ Move signature handling to e-msg-composer-hdrs.c.
+ Use an ESignatureComboBox.
+
+ * e-composer-from-header.h:
+ * e-composer-from-header.c:
+ Clean up the GtkHBox hack. The signature combo is now packed
+ directly into the GtkTable.
+
+ * e-composer-name-header.c:
+ * e-composer-text-header.c:
+ Code cleanup.
+
2007-11-29 Milan Crha <mcrha@redhat.com>
** Part of fix for bug #271551
diff --git a/composer/e-composer-from-header.c b/composer/e-composer-from-header.c
index de4f8ac8e0..55f525326e 100644
--- a/composer/e-composer-from-header.c
+++ b/composer/e-composer-from-header.c
@@ -1,12 +1,8 @@
#include "e-composer-from-header.h"
-#define E_COMPOSER_FROM_HEADER_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_COMPOSER_FROM_HEADER, EComposerFromHeaderPrivate))
-
-struct _EComposerFromHeaderPrivate {
- GtkWidget *combo_box;
-};
+/* Convenience macro */
+#define E_COMPOSER_FROM_HEADER_GET_COMBO_BOX(header) \
+ (E_ACCOUNT_COMBO_BOX (E_COMPOSER_HEADER (header)->input_widget))
static gpointer parent_class;
@@ -18,50 +14,21 @@ composer_from_header_changed_cb (EAccountComboBox *combo_box,
}
static void
-composer_from_header_dispose (GObject *object)
-{
- EComposerFromHeaderPrivate *priv;
-
- priv = E_COMPOSER_FROM_HEADER_GET_PRIVATE (object);
-
- if (priv->combo_box != NULL) {
- g_object_unref (priv->combo_box);
- priv->combo_box = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
composer_from_header_class_init (EComposerFromHeaderClass *class)
{
- GObjectClass *object_class;
-
parent_class = g_type_class_peek_parent (class);
- g_type_class_add_private (class, sizeof (EComposerFromHeaderPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->dispose = composer_from_header_dispose;
}
static void
composer_from_header_init (EComposerFromHeader *header)
{
- GtkWidget *hbox;
GtkWidget *widget;
- header->priv = E_COMPOSER_FROM_HEADER_GET_PRIVATE (header);
-
- hbox = g_object_ref_sink (gtk_hbox_new (FALSE, 6));
- E_COMPOSER_HEADER (header)->input_widget = hbox;
-
- widget = e_account_combo_box_new ();
+ widget = g_object_ref_sink (e_account_combo_box_new ());
g_signal_connect (
widget, "changed",
G_CALLBACK (composer_from_header_changed_cb), header);
- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
- header->priv->combo_box = g_object_ref_sink (widget);
+ E_COMPOSER_HEADER (header)->input_widget = widget;
gtk_widget_show (widget);
}
@@ -108,7 +75,7 @@ e_composer_from_header_set_account_list (EComposerFromHeader *header,
g_return_if_fail (E_IS_COMPOSER_FROM_HEADER (header));
- combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
+ combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
e_account_combo_box_set_account_list (combo_box, account_list);
}
@@ -119,7 +86,7 @@ e_composer_from_header_get_active (EComposerFromHeader *header)
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
- combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
+ combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
return e_account_combo_box_get_active (combo_box);
}
@@ -131,7 +98,7 @@ e_composer_from_header_set_active (EComposerFromHeader *header,
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
- combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
+ combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
return e_account_combo_box_set_active (combo_box, account);
}
@@ -142,7 +109,7 @@ e_composer_from_header_get_active_name (EComposerFromHeader *header)
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
- combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
+ combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
return e_account_combo_box_get_active_name (combo_box);
}
@@ -154,7 +121,7 @@ e_composer_from_header_set_active_name (EComposerFromHeader *header,
g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
- combo_box = E_ACCOUNT_COMBO_BOX (header->priv->combo_box);
+ combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
return e_account_combo_box_set_active_name (combo_box, account_name);
}
diff --git a/composer/e-composer-from-header.h b/composer/e-composer-from-header.h
index 39fb09ca6b..cc5aa78235 100644
--- a/composer/e-composer-from-header.h
+++ b/composer/e-composer-from-header.h
@@ -33,11 +33,9 @@ G_BEGIN_DECLS
typedef struct _EComposerFromHeader EComposerFromHeader;
typedef struct _EComposerFromHeaderClass EComposerFromHeaderClass;
-typedef struct _EComposerFromHeaderPrivate EComposerFromHeaderPrivate;
struct _EComposerFromHeader {
EComposerHeader parent;
- EComposerFromHeaderPrivate *priv;
};
struct _EComposerFromHeaderClass {
diff --git a/composer/e-composer-name-header.c b/composer/e-composer-name-header.c
index f54b50d87e..d9af95c500 100644
--- a/composer/e-composer-name-header.c
+++ b/composer/e-composer-name-header.c
@@ -10,6 +10,10 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_COMPOSER_NAME_HEADER, EComposerNameHeaderPrivate))
+/* Convenience macro */
+#define E_COMPOSER_NAME_HEADER_GET_ENTRY(header) \
+ (E_NAME_SELECTOR_ENTRY (E_COMPOSER_HEADER (header)->input_widget))
+
enum {
PROP_0,
PROP_NAME_SELECTOR
@@ -250,15 +254,14 @@ e_composer_name_header_get_destinations (EComposerNameHeader *header)
{
EDestinationStore *store;
EDestination **destinations;
- GtkWidget *input_widget;
+ ENameSelectorEntry *entry;
GList *list, *iter;
gint ii = 0;
g_return_val_if_fail (E_IS_COMPOSER_NAME_HEADER (header), NULL);
- input_widget = E_COMPOSER_HEADER (header)->input_widget;
- store = e_name_selector_entry_peek_destination_store (
- E_NAME_SELECTOR_ENTRY (input_widget));
+ entry = E_COMPOSER_NAME_HEADER_GET_ENTRY (header);
+ store = e_name_selector_entry_peek_destination_store (entry);
list = e_destination_store_list_destinations (store);
destinations = g_new0 (EDestination *, g_list_length (list) + 1);
@@ -276,15 +279,14 @@ e_composer_name_header_set_destinations (EComposerNameHeader *header,
EDestination **destinations)
{
EDestinationStore *store;
- GtkWidget *input_widget;
+ ENameSelectorEntry *entry;
GList *list, *iter;
gint ii;
g_return_if_fail (E_IS_COMPOSER_NAME_HEADER (header));
- input_widget = E_COMPOSER_HEADER (header)->input_widget;
- store = e_name_selector_entry_peek_destination_store (
- E_NAME_SELECTOR_ENTRY (input_widget));
+ entry = E_COMPOSER_NAME_HEADER_GET_ENTRY (header);
+ store = e_name_selector_entry_peek_destination_store (entry);
/* Clear the destination store. */
list = e_destination_store_list_destinations (store);
diff --git a/composer/e-composer-text-header.c b/composer/e-composer-text-header.c
index 4ef761e450..6d3626218f 100644
--- a/composer/e-composer-text-header.c
+++ b/composer/e-composer-text-header.c
@@ -1,5 +1,9 @@
#include "e-composer-text-header.h"
+/* Convenience macro */
+#define E_COMPOSER_TEXT_HEADER_GET_ENTRY(header) \
+ (GTK_ENTRY (E_COMPOSER_HEADER (header)->input_widget))
+
static gpointer parent_class;
static void
@@ -96,25 +100,22 @@ e_composer_text_header_new_button (const gchar *label)
const gchar *
e_composer_text_header_get_text (EComposerTextHeader *header)
{
- GtkWidget *input_widget;
+ GtkEntry *entry;
g_return_val_if_fail (E_IS_COMPOSER_TEXT_HEADER (header), NULL);
- input_widget = E_COMPOSER_HEADER (header)->input_widget;
- return gtk_entry_get_text (GTK_ENTRY (input_widget));
+ entry = E_COMPOSER_TEXT_HEADER_GET_ENTRY (header);
+ return gtk_entry_get_text (entry);
}
void
e_composer_text_header_set_text (EComposerTextHeader *header,
const gchar *text)
{
- GtkWidget *input_widget;
+ GtkEntry *entry;
g_return_if_fail (E_IS_COMPOSER_TEXT_HEADER (header));
- if (text == NULL)
- text = "";
-
- input_widget = E_COMPOSER_HEADER (header)->input_widget;
- gtk_entry_set_text (GTK_ENTRY (input_widget), text);
+ entry = E_COMPOSER_TEXT_HEADER_GET_ENTRY (header);
+ gtk_entry_set_text (entry, (text != NULL) ? text : "");
}
diff --git a/composer/e-msg-composer-hdrs.c b/composer/e-msg-composer-hdrs.c
index 02208c14fa..471cc40dc2 100644
--- a/composer/e-msg-composer-hdrs.c
+++ b/composer/e-msg-composer-hdrs.c
@@ -41,6 +41,7 @@
#include "mail/mail-config.h"
#include "mail/mail-session.h"
#include "e-account-combo-box.h"
+#include "e-signature-combo-box.h"
#include "e-composer-header.h"
#include "e-composer-from-header.h"
@@ -68,6 +69,7 @@ enum {
SUBJECT_CHANGED,
HDRS_CHANGED,
FROM_CHANGED,
+ SIGNATURE_CHANGED,
LAST_SIGNAL
};
@@ -78,6 +80,7 @@ struct _EMsgComposerHdrsPrivate {
BonoboUIComponent *uic;
EComposerHeader *headers[NUM_HEADERS];
+ GtkWidget *signature_combo_box;
};
static gpointer parent_class;
@@ -105,6 +108,12 @@ from_changed (EComposerFromHeader *from_header, EMsgComposerHdrs *hdrs)
}
static void
+signature_changed (EMsgComposerHdrs *hdrs)
+{
+ g_signal_emit (hdrs, signal_ids[SIGNATURE_CHANGED], 0);
+}
+
+static void
headers_set_visibility (EMsgComposerHdrs *h, int visible_flags)
{
EMsgComposerHdrsPrivate *p = h->priv;
@@ -176,6 +185,7 @@ msg_composer_hdrs_constructor (GType type,
{
GObject *object;
EMsgComposerHdrsPrivate *priv;
+ GtkWidget *widget;
guint rows, ii;
/* Chain up to parent's constructor() method. */
@@ -185,7 +195,7 @@ msg_composer_hdrs_constructor (GType type,
priv = E_MSG_COMPOSER_HDRS_GET_PRIVATE (object);
rows = G_N_ELEMENTS (priv->headers);
- gtk_table_resize (GTK_TABLE (object), rows, 2);
+ gtk_table_resize (GTK_TABLE (object), rows, 4);
gtk_table_set_row_spacings (GTK_TABLE (object), 0);
gtk_table_set_col_spacings (GTK_TABLE (object), 6);
@@ -198,9 +208,27 @@ msg_composer_hdrs_constructor (GType type,
0, 1, ii, ii + 1, GTK_FILL, GTK_FILL, 0, 3);
gtk_table_attach (
GTK_TABLE (object), priv->headers[ii]->input_widget,
- 1, 2, ii, ii + 1, GTK_FILL | GTK_EXPAND, 0, 0, 3);
+ 1, 4, ii, ii + 1, GTK_FILL | GTK_EXPAND, 0, 0, 3);
}
+ /* Leave room in the "From" row for signature stuff. */
+ gtk_container_child_set (
+ GTK_CONTAINER (object),
+ priv->headers[HEADER_FROM]->input_widget,
+ "right-attach", 2, NULL);
+
+ /* Now add the signature stuff. */
+ widget = gtk_label_new_with_mnemonic (_("Si_gnature:"));
+ gtk_table_attach (
+ GTK_TABLE (object), widget,
+ 2, 3, HEADER_FROM, HEADER_FROM + 1, 0, 0, 0, 3);
+ gtk_table_attach (
+ GTK_TABLE (object), priv->signature_combo_box,
+ 3, 4, HEADER_FROM, HEADER_FROM + 1, 0, 0, 0, 3);
+ gtk_label_set_mnemonic_widget (
+ GTK_LABEL (widget), priv->signature_combo_box);
+ gtk_widget_show (widget);
+
return object;
}
@@ -224,6 +252,11 @@ msg_composer_hdrs_dispose (GObject *object)
}
}
+ if (priv->signature_combo_box != NULL) {
+ g_object_unref (priv->signature_combo_box);
+ priv->signature_combo_box = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -267,6 +300,14 @@ msg_composer_hdrs_class_init (EMsgComposerHdrsClass *class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+
+ signal_ids[SIGNATURE_CHANGED] =
+ g_signal_new ("signature_changed",
+ E_TYPE_MSG_COMPOSER_HDRS,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
@@ -274,6 +315,7 @@ msg_composer_hdrs_init (EMsgComposerHdrs *hdrs)
{
EComposerHeader *header;
ENameSelector *name_selector;
+ GtkWidget *widget;
hdrs->priv = E_MSG_COMPOSER_HDRS_GET_PRIVATE (hdrs);
@@ -318,6 +360,19 @@ msg_composer_hdrs_init (EMsgComposerHdrs *hdrs)
e_composer_from_header_set_account_list (
E_COMPOSER_FROM_HEADER (hdrs->priv->headers[HEADER_FROM]),
mail_config_get_accounts ());
+
+ widget = e_signature_combo_box_new ();
+ e_signature_combo_box_set_signature_list (
+ E_SIGNATURE_COMBO_BOX (widget),
+ mail_config_get_signatures ());
+ g_signal_connect_swapped (
+ widget, "changed",
+ G_CALLBACK (signature_changed), hdrs);
+ g_signal_connect_swapped (
+ widget, "refreshed",
+ G_CALLBACK (signature_changed), hdrs);
+ hdrs->priv->signature_combo_box = g_object_ref_sink (widget);
+ gtk_widget_show (widget);
}
GType
@@ -559,6 +614,29 @@ e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
return e_composer_from_header_set_active_name (header, account_name);
}
+ESignature *
+e_msg_composer_hdrs_get_signature (EMsgComposerHdrs *hdrs)
+{
+ ESignatureComboBox *combo_box;
+
+ g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+ combo_box = E_SIGNATURE_COMBO_BOX (hdrs->priv->signature_combo_box);
+ return e_signature_combo_box_get_active (combo_box);
+}
+
+gboolean
+e_msg_composer_hdrs_set_signature (EMsgComposerHdrs *hdrs,
+ ESignature *signature)
+{
+ ESignatureComboBox *combo_box;
+
+ g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), FALSE);
+
+ combo_box = E_SIGNATURE_COMBO_BOX (hdrs->priv->signature_combo_box);
+ return e_signature_combo_box_set_active (combo_box, signature);
+}
+
void
e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
const gchar *text)
diff --git a/composer/e-msg-composer-hdrs.h b/composer/e-msg-composer-hdrs.h
index 1e983272a5..41a4299cc6 100644
--- a/composer/e-msg-composer-hdrs.h
+++ b/composer/e-msg-composer-hdrs.h
@@ -28,6 +28,7 @@
#include <bonobo/bonobo-ui-component.h>
+#include <e-util/e-signature.h>
#include <libedataserver/e-account.h>
#include <camel/camel-mime-message.h>
#include <libebook/e-destination.h>
@@ -118,6 +119,9 @@ void e_msg_composer_hdrs_to_redirect (EMsgComposerHdrs *hdrs,
EAccount * e_msg_composer_hdrs_get_from_account (EMsgComposerHdrs *hdrs);
gboolean e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
const char *account_name);
+ESignature *e_msg_composer_hdrs_get_signature (EMsgComposerHdrs *hdrs);
+gboolean e_msg_composer_hdrs_set_signature (EMsgComposerHdrs *hdrs,
+ ESignature *signature);
void e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
const char *reply_to);
void e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs,
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 087e36ce39..8c47ceaaec 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -88,6 +88,7 @@
#include "e-util/e-util-private.h"
#include "e-util/e-util.h"
#include <mail/em-event.h>
+#include "e-signature-combo-box.h"
#include <camel/camel-session.h>
#include <camel/camel-charset-map.h>
@@ -188,7 +189,7 @@ struct _EMsgComposerPrivate {
char *mime_type, *mime_body, *charset;
char *autosave_file;
- int autosave_fd;
+ int autosave_fd;
guint32 enable_autosave : 1;
guint32 attachment_bar_visible : 1;
@@ -214,12 +215,6 @@ struct _EMsgComposerPrivate {
guint32 in_signature_insert : 1;
- struct _ESignature *signature;
- struct _GtkOptionMenu *sig_menu;
- guint sig_added_id;
- guint sig_removed_id;
- guint sig_changed_id;
-
CamelMimeMessage *redirect;
guint notify_id;
@@ -1247,23 +1242,27 @@ decode_signature_name (const char *name)
static char *
get_signature_html (EMsgComposer *composer)
{
- EMsgComposerPrivate *p = composer->priv;
+ EMsgComposerHdrs *hdrs;
char *text = NULL, *html = NULL;
+ ESignature *signature;
gboolean format_html;
- if (!p->signature)
+ hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
+ signature = e_msg_composer_hdrs_get_signature (hdrs);
+
+ if (!signature)
return NULL;
- if (!p->signature->autogen) {
- if (!p->signature->filename)
+ if (!signature->autogen) {
+ if (!signature->filename)
return NULL;
- format_html = p->signature->html;
+ format_html = signature->html;
- if (p->signature->script) {
- text = mail_config_signature_run_script (p->signature->filename);
+ if (signature->script) {
+ text = mail_config_signature_run_script (signature->filename);
} else {
- text = e_msg_composer_get_sig_file_content (p->signature->filename, format_html);
+ text = e_msg_composer_get_sig_file_content (signature->filename, format_html);
}
} else {
EAccountIdentity *id;
@@ -1271,8 +1270,7 @@ get_signature_html (EMsgComposer *composer)
char *address;
char *name;
- id = e_msg_composer_hdrs_get_from_account (
- E_MSG_COMPOSER_HDRS (p->hdrs))->id;
+ id = e_msg_composer_hdrs_get_from_account (hdrs)->id;
address = id->address ? camel_text_to_html (id->address, CONVERT_SPACES, 0) : NULL;
name = id->name ? camel_text_to_html (id->name, CONVERT_SPACES, 0) : NULL;
organization = id->organization ? camel_text_to_html (id->organization, CONVERT_SPACES, 0) : NULL;
@@ -1296,8 +1294,8 @@ get_signature_html (EMsgComposer *composer)
if (text) {
char *encoded_uid = NULL;
- if (p->signature)
- encoded_uid = encode_signature_name (p->signature->uid);
+ if (signature)
+ encoded_uid = encode_signature_name (signature->uid);
/* The signature dash convention ("-- \n") is specified in the
* "Son of RFC 1036": http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html,
@@ -1606,7 +1604,7 @@ autosave_load_draft (const char *filename)
static gboolean
autosave_is_owned (AutosaveManager *am, const char *file)
{
- return g_hash_table_lookup (am->table, file) != NULL;
+ return g_hash_table_lookup (am->table, file) != NULL;
}
static void
@@ -2011,7 +2009,7 @@ menu_send_options_cb (BonoboUIComponent *component, void *data, const char *path
EMsgComposer *composer = data;
target = em_event_target_new_composer (e, composer, EM_EVENT_COMPOSER_SEND_OPTION);
- e_msg_composer_set_send_options (composer, FALSE);
+ e_msg_composer_set_send_options (composer, FALSE);
e_event_emit((EEvent *)e, "composer.selectsendoption", (EEventTarget *)target);
if (!composer->priv->send_invoked) {
e_error_run ((GtkWindow *)composer, "mail-composer:send-options-support", NULL);
@@ -2296,176 +2294,6 @@ static EPixmap pixcache [] = {
static void
-signature_activate_cb (GtkWidget *menu, EMsgComposer *composer)
-{
- GtkWidget *active;
- ESignature *sig;
- EMsgComposerPrivate *p = composer->priv;
-
- active = gtk_menu_get_active (GTK_MENU (menu));
- sig = g_object_get_data ((GObject *) active, "sig");
-
- if (p->signature != sig) {
- p->signature = sig;
- e_msg_composer_show_sig_file (composer);
- }
-}
-
-static void
-signature_added (ESignatureList *signatures, ESignature *sig, EMsgComposer *composer)
-{
- GtkWidget *menu, *item;
- EMsgComposerPrivate *p = composer->priv;
-
- menu = gtk_option_menu_get_menu (p->sig_menu);
-
- if (sig->autogen)
- item = gtk_menu_item_new_with_label (_("Autogenerated"));
- else
- item = gtk_menu_item_new_with_label (sig->name);
- g_object_set_data ((GObject *) item, "sig", sig);
- gtk_widget_show (item);
-
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-}
-
-static void
-signature_removed (ESignatureList *signatures, ESignature *sig, EMsgComposer *composer)
-{
- GtkWidget *menu;
- ESignature *cur;
- GList *items;
- EMsgComposerPrivate *p = composer->priv;
-
- if (p->signature == sig) {
- p->signature = NULL;
- e_msg_composer_show_sig_file (composer);
- }
-
- menu = gtk_option_menu_get_menu (p->sig_menu);
- items = GTK_MENU_SHELL (menu)->children;
- while (items != NULL) {
- cur = g_object_get_data (items->data, "sig");
- if (cur == sig) {
- gtk_widget_destroy (items->data);
- break;
- }
- items = items->next;
- }
-}
-
-static void
-menu_item_set_label (GtkMenuItem *item, const char *label)
-{
- GtkWidget *widget;
-
- widget = gtk_bin_get_child ((GtkBin *) item);
- if (GTK_IS_LABEL (widget))
- gtk_label_set_text ((GtkLabel *) widget, label);
-}
-
-static void
-signature_changed (ESignatureList *signatures, ESignature *sig, EMsgComposer *composer)
-{
- GtkWidget *menu;
- ESignature *cur;
- GList *items;
- EMsgComposerPrivate *p = composer->priv;
-
- menu = gtk_option_menu_get_menu (p->sig_menu);
- items = GTK_MENU_SHELL (menu)->children;
- while (items != NULL) {
- cur = g_object_get_data (items->data, "sig");
- if (cur == sig) {
- menu_item_set_label (items->data, sig->name);
- break;
- }
- items = items->next;
- }
-}
-
-static void
-sig_select_item (EMsgComposer *composer)
-{
- ESignature *cur;
- GtkWidget *menu;
- GList *items;
- int i = 0;
- EMsgComposerPrivate *p = composer->priv;
-
- if (!p->signature) {
- gtk_option_menu_set_history (p->sig_menu, 0);
- return;
- }
-
- menu = gtk_option_menu_get_menu (p->sig_menu);
- items = GTK_MENU_SHELL (menu)->children;
- while (items != NULL) {
- cur = g_object_get_data ((GObject *) items->data, "sig");
- if (cur == p->signature) {
- gtk_option_menu_set_history (p->sig_menu, i);
- return;
- }
- items = items->next;
- i++;
- }
-}
-
-static void
-setup_signatures_menu (EMsgComposer *composer)
-{
- GtkWidget *hbox, *hspace, *label;
- ESignatureList *signatures;
- GtkWidget *menu, *item;
- ESignature *sig;
- EIterator *it;
- EMsgComposerPrivate *p = composer->priv;
-
- hbox = e_msg_composer_hdrs_get_from_hbox (E_MSG_COMPOSER_HDRS (p->hdrs));
-
- label = gtk_label_new_with_mnemonic (_("Si_gnature:"));
- gtk_widget_show (label);
-
- p->sig_menu = (GtkOptionMenu *) gtk_option_menu_new ();
-
- gtk_label_set_mnemonic_widget ((GtkLabel *) label, (GtkWidget *)p->sig_menu);
-
- gtk_box_pack_end_defaults (GTK_BOX (hbox), (GtkWidget *) p->sig_menu);
- gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, TRUE, 0);
- hspace = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hspace);
- gtk_box_pack_start (GTK_BOX (hbox), hspace, FALSE, FALSE, 0);
-
- menu = gtk_menu_new ();
- gtk_widget_show (menu);
- gtk_option_menu_set_menu (p->sig_menu, menu);
-
- item = gtk_menu_item_new_with_label (_("None"));
- gtk_widget_show (item);
-
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- signatures = mail_config_get_signatures ();
- it = e_list_get_iterator ((EList *) signatures);
-
- while (e_iterator_is_valid (it)) {
- sig = (ESignature *) e_iterator_get (it);
- signature_added (signatures, sig, composer);
- e_iterator_next (it);
- }
-
- g_object_unref (it);
-
- g_signal_connect (menu, "selection-done", G_CALLBACK (signature_activate_cb), composer);
-
- gtk_widget_show ((GtkWidget *) p->sig_menu);
-
- p->sig_added_id = g_signal_connect (signatures, "signature-added", G_CALLBACK (signature_added), composer);
- p->sig_removed_id = g_signal_connect (signatures, "signature-removed", G_CALLBACK (signature_removed), composer);
- p->sig_changed_id = g_signal_connect (signatures, "signature-changed", G_CALLBACK (signature_changed), composer);
-}
-
-static void
setup_ui (EMsgComposer *composer)
{
EMMenuTargetWidget *target;
@@ -2672,7 +2500,7 @@ attachment_bar_changed_cb (EAttachmentBar *bar,
/* Mark the composer as changed so it prompts about unsaved
- changes on close */
+ changes on close */
e_msg_composer_set_changed (composer);
}
static void
@@ -2851,11 +2679,8 @@ from_changed_cb (EMsgComposerHdrs *hdrs, void *data)
static void
composer_finalise (GObject *object)
{
- EMsgComposer *composer;
- EMsgComposerPrivate *p;
-
- composer = E_MSG_COMPOSER (object);
- p = composer->priv;
+ EMsgComposer *composer = E_MSG_COMPOSER (object);
+ EMsgComposerPrivate *p = composer->priv;
if (p->extra_hdr_names) {
int i;
@@ -2908,7 +2733,6 @@ destroy (GtkObject *object)
EMsgComposer *composer = (EMsgComposer *)object;
EMsgComposerPrivate *p = composer->priv;
CORBA_Environment ev;
- ESignatureList *signatures;
CORBA_exception_init (&ev);
@@ -2939,7 +2763,7 @@ destroy (GtkObject *object)
}
/* FIXME? I assume the Bonobo widget will get destroyed
- normally? */
+ normally? */
if (p->address_dialog != NULL) {
gtk_widget_destroy (p->address_dialog);
p->address_dialog = NULL;
@@ -2981,23 +2805,6 @@ destroy (GtkObject *object)
p->eeditor_listener = NULL;
}
- signatures = mail_config_get_signatures ();
-
- if (p->sig_added_id != 0) {
- g_signal_handler_disconnect (signatures, p->sig_added_id);
- p->sig_added_id = 0;
- }
-
- if (p->sig_removed_id != 0) {
- g_signal_handler_disconnect (signatures, p->sig_removed_id);
- p->sig_removed_id = 0;
- }
-
- if (p->sig_changed_id != 0) {
- g_signal_handler_disconnect (signatures, p->sig_changed_id);
- p->sig_changed_id = 0;
- }
-
if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
@@ -3925,14 +3732,14 @@ button_press_event (GtkWidget *widget, GdkEventButton *event)
static gint
key_press_event(GtkWidget *widget, GdkEventKey *event)
{
- EAttachmentBar *bar = E_ATTACHMENT_BAR(widget);
+ EAttachmentBar *bar = E_ATTACHMENT_BAR(widget);
- if (event->keyval == GDK_Delete) {
- e_attachment_bar_remove_selected (bar);
- return TRUE;
- }
+ if (event->keyval == GDK_Delete) {
+ e_attachment_bar_remove_selected (bar);
+ return TRUE;
+ }
- return FALSE;
+ return FALSE;
}
static EMsgComposer *
@@ -3999,10 +3806,11 @@ create_composer (int visible_mask)
G_CALLBACK (hdrs_changed_cb), composer);
g_signal_connect (p->hdrs, "from_changed",
G_CALLBACK (from_changed_cb), composer);
+ g_signal_connect_swapped (
+ p->hdrs, "signature_changed",
+ G_CALLBACK (e_msg_composer_show_sig_file), composer);
gtk_widget_show (p->hdrs);
- setup_signatures_menu (composer);
-
from_changed_cb((EMsgComposerHdrs *)p->hdrs, composer);
/* Editor component. */
@@ -4047,7 +3855,7 @@ create_composer (int visible_mask)
gtk_box_pack_start (GTK_BOX (vbox), p->eeditor, TRUE, TRUE, 0);
/* Attachment editor, wrapped into an EScrollFrame. It's
- hidden in an EExpander. */
+ hidden in an EExpander. */
p->attachment_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (p->attachment_scrolled_window),
@@ -4143,22 +3951,18 @@ create_composer (int visible_mask)
static void
set_editor_signature (EMsgComposer *composer)
{
- EAccountIdentity *id;
- EMsgComposerPrivate *p = composer->priv;
+ EMsgComposerHdrs *hdrs;
+ ESignature *signature;
EAccount *account;
+ const gchar *uid;
- account = e_msg_composer_hdrs_get_from_account (
- E_MSG_COMPOSER_HDRS (p->hdrs));
-
+ hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
+ account = e_msg_composer_hdrs_get_from_account (hdrs);
g_return_if_fail (account != NULL);
- id = account->id;
- if (id->sig_uid)
- p->signature = mail_config_get_signature_by_uid (id->sig_uid);
- else
- p->signature = NULL;
-
- sig_select_item (composer);
+ uid = account->id->sig_uid;
+ signature = uid ? mail_config_get_signature_by_uid (uid) : NULL;
+ e_msg_composer_hdrs_set_signature (hdrs, signature);
}
/**
@@ -4238,7 +4042,7 @@ e_msg_composer_set_pending_body (EMsgComposer *composer, char *text, ssize_t len
char *old;
old = g_object_get_data ((GObject *) composer, "body:text");
- g_free (old);
+ g_free (old);
g_object_set_data ((GObject *) composer, "body:text", text);
g_object_set_data ((GObject *) composer, "body:len", GSIZE_TO_POINTER (len));
}
@@ -4246,7 +4050,7 @@ e_msg_composer_set_pending_body (EMsgComposer *composer, char *text, ssize_t len
static void
e_msg_composer_flush_pending_body (EMsgComposer *composer, gboolean apply)
{
- char *body;
+ char *body;
ssize_t len;
body = g_object_get_data ((GObject *) composer, "body:text");
@@ -4368,9 +4172,9 @@ handle_multipart_signed (EMsgComposer *composer, CamelMultipart *multipart, int
multipart = CAMEL_MULTIPART (content);
/* Note: depth is preserved here because we're not
- counting multipart/signed as a multipart, instead
- we want to treat the content part as our mime part
- here. */
+ counting multipart/signed as a multipart, instead
+ we want to treat the content part as our mime part
+ here. */
if (CAMEL_IS_MULTIPART_SIGNED (content)) {
/* handle the signed content and configure the composer to sign outgoing messages */
@@ -4427,9 +4231,9 @@ handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *multipart, in
CamelMultipart *content_multipart = CAMEL_MULTIPART (content);
/* Note: depth is preserved here because we're not
- counting multipart/encrypted as a multipart, instead
- we want to treat the content part as our mime part
- here. */
+ counting multipart/encrypted as a multipart, instead
+ we want to treat the content part as our mime part
+ here. */
if (CAMEL_IS_MULTIPART_SIGNED (content)) {
/* handle the signed content and configure the composer to sign outgoing messages */
@@ -4577,8 +4381,10 @@ set_signature_gui (EMsgComposer *composer)
{
CORBA_Environment ev;
EMsgComposerPrivate *p = composer->priv;
+ EMsgComposerHdrs *hdrs;
+ ESignature *signature = NULL;
- p->signature = NULL;
+ hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
CORBA_exception_init (&ev);
if (GNOME_GtkHTML_Editor_Engine_searchByData (p->eeditor_engine, 1, "ClueFlow", "signature", "1", &ev)) {
@@ -4588,17 +4394,17 @@ set_signature_gui (EMsgComposer *composer)
if (ev._major == CORBA_NO_EXCEPTION && str) {
if (!strncmp (str, "uid:", 4)) {
name = decode_signature_name (str + 4);
- p->signature = mail_config_get_signature_by_uid (name);
+ signature = mail_config_get_signature_by_uid (name);
g_free (name);
} else if (!strncmp (str, "name:", 5)) {
name = decode_signature_name (str + 4);
- p->signature = mail_config_get_signature_by_name (name);
+ signature = mail_config_get_signature_by_name (name);
g_free (name);
}
CORBA_free (str);
}
- sig_select_item (composer);
+ e_msg_composer_hdrs_set_signature (hdrs, signature);
}
CORBA_exception_free (&ev);
}
@@ -5037,7 +4843,7 @@ handle_mailto (EMsgComposer *composer, const char *mailto)
"attachment");
}
gtk_widget_show (priv->attachment_expander);
- gtk_widget_show (priv->attachment_scrolled_window);
+ gtk_widget_show (priv->attachment_scrolled_window);
} else if (!g_ascii_strcasecmp (header, "from")) {
/* Ignore */
} else if (!g_ascii_strcasecmp (header, "reply-to")) {
@@ -5193,7 +4999,7 @@ void
e_msg_composer_set_body_text (EMsgComposer *composer, const char *text, ssize_t len)
{
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
- g_return_if_fail (text != NULL);
+ g_return_if_fail (text != NULL);
set_editor_text (composer, text, len, TRUE, *text == '\0');
}
@@ -6447,7 +6253,7 @@ e_msg_composer_get_raw_message_text (EMsgComposer *composer)
data = get_text (p->persist_stream_interface, "text/plain");
if (data)
- return (const gchar *)data->data;
+ return (const gchar *)data->data;
return NULL;
}
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index 559bf58055..93934b2bbc 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,18 @@
+2007-12-01 Matthew Barnes <mbarnes@redhat.com>
+
+ ** Fixes part of bug #495123
+
+ * Makefile.am:
+ Add e-signature-combo-box.[ch].
+
+ * e-account-combo-box.c (account_combo_box_refresh_cb):
+ Make sure the EAccount isn't lost while swapping models.
+
+ * e-signature-combo-box.c:
+ * e-signature-combo-box.h:
+ New widget renders an ESignatureList as a combo box. Also listens
+ for changes to the ESignatureList and updates itself accordingly.
+
2007-11-27 Matthew Barnes <mbarnes@redhat.com>
** Fixes part of bug #495123
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index c35d7a9f2c..267ded9aab 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -76,6 +76,7 @@ widgetsinclude_HEADERS = \
e-selection-model-array.h \
e-selection-model-simple.h \
e-selection-model.h \
+ e-signature-combo-box.h \
e-unicode.h \
e-colors.h
@@ -122,6 +123,7 @@ libemiscwidgets_la_SOURCES = \
e-selection-model-array.c \
e-selection-model-simple.c \
e-selection-model.c \
+ e-signature-combo-box.c \
e-unicode.c \
e-colors.c
@@ -136,6 +138,7 @@ libemiscwidgets_la_LIBADD = $(top_builddir)/e-util/libeutil.la \
$(top_builddir)/a11y/libevolution-a11y.la \
$(CAMEL_LIBS) \
$(GNOME_PLATFORM_LIBS) \
+ $(EVOLUTON_MAIL_LIBS) \
$(ICONV_LIBS)
libefilterbar_la_SOURCES = \
diff --git a/widgets/misc/e-account-combo-box.c b/widgets/misc/e-account-combo-box.c
index 064ed2bd10..6a96644bfd 100644
--- a/widgets/misc/e-account-combo-box.c
+++ b/widgets/misc/e-account-combo-box.c
@@ -155,8 +155,12 @@ account_combo_box_refresh_cb (EAccountList *account_list,
skip:
/* Restore the previously selected account. */
account = e_account_combo_box_get_active (combo_box);
+ if (account != NULL)
+ g_object_ref (account);
gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), model);
e_account_combo_box_set_active (combo_box, account);
+ if (account != NULL)
+ g_object_unref (account);
}
static GObject *
diff --git a/widgets/misc/e-signature-combo-box.c b/widgets/misc/e-signature-combo-box.c
new file mode 100644
index 0000000000..be19755ef6
--- /dev/null
+++ b/widgets/misc/e-signature-combo-box.c
@@ -0,0 +1,338 @@
+#include "e-signature-combo-box.h"
+
+#include <glib/gi18n.h>
+
+#define E_SIGNATURE_COMBO_BOX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SIGNATURE_COMBO_BOX, ESignatureComboBoxPrivate))
+
+enum {
+ COLUMN_STRING,
+ COLUMN_SIGNATURE
+};
+
+enum {
+ REFRESHED,
+ LAST_SIGNAL
+};
+
+struct _ESignatureComboBoxPrivate {
+ ESignatureList *signature_list;
+ GHashTable *index;
+};
+
+static gpointer parent_class;
+static guint signal_ids[LAST_SIGNAL];
+
+static void
+signature_combo_box_refresh_cb (ESignatureList *signature_list,
+ ESignature *unused,
+ ESignatureComboBox *combo_box)
+{
+ GtkListStore *store;
+ GtkTreeModel *model;
+ GtkTreeIter tree_iter;
+ EIterator *signature_iter;
+ ESignature *signature;
+ GHashTable *index;
+ GList *list = NULL;
+ GList *iter;
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_SIGNATURE);
+ model = GTK_TREE_MODEL (store);
+ index = combo_box->priv->index;
+
+ g_hash_table_remove_all (index);
+
+ gtk_list_store_append (store, &tree_iter);
+ gtk_list_store_set (
+ store, &tree_iter,
+ COLUMN_STRING, _("None"),
+ COLUMN_SIGNATURE, NULL, -1);
+
+ if (signature_list == NULL)
+ goto skip;
+
+ /* Build a list of ESignatures to display. */
+ signature_iter = e_list_get_iterator (E_LIST (signature_list));
+ while (e_iterator_is_valid (signature_iter)) {
+
+ /* XXX EIterator misuses const. */
+ signature = (ESignature *) e_iterator_get (signature_iter);
+ list = g_list_prepend (list, signature);
+ e_iterator_next (signature_iter);
+ }
+ g_object_unref (signature_iter);
+
+ list = g_list_reverse (list);
+
+ /* Populate the list store and index. */
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GtkTreeRowReference *reference;
+ GtkTreePath *path;
+ const gchar *string;
+
+ signature = iter->data;
+
+ if (signature->autogen)
+ string = _("Autogenerated");
+ else
+ string = signature->name;
+
+ gtk_list_store_append (store, &tree_iter);
+ gtk_list_store_set (
+ store, &tree_iter,
+ COLUMN_STRING, string,
+ COLUMN_SIGNATURE, signature, -1);
+
+ path = gtk_tree_model_get_path (model, &tree_iter);
+ reference = gtk_tree_row_reference_new (model, path);
+ g_hash_table_insert (index, signature, reference);
+ gtk_tree_path_free (path);
+ }
+
+skip:
+ /* Restore the previously selected signature. */
+ signature = e_signature_combo_box_get_active (combo_box);
+ if (signature != NULL)
+ g_object_ref (signature);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), model);
+ e_signature_combo_box_set_active (combo_box, signature);
+ if (signature != NULL)
+ g_object_unref (signature);
+
+ g_signal_emit (combo_box, signal_ids[REFRESHED], 0);
+}
+
+static GObject *
+signature_combo_box_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GtkCellRenderer *renderer;
+
+ /* Chain up to parent's constructor() method. */
+ object = G_OBJECT_CLASS (parent_class)->constructor (
+ type, n_construct_properties, construct_properties);
+
+ renderer = gtk_cell_renderer_text_new ();
+
+ gtk_cell_layout_pack_start (
+ GTK_CELL_LAYOUT (object), renderer, TRUE);
+ gtk_cell_layout_add_attribute (
+ GTK_CELL_LAYOUT (object), renderer, "text", COLUMN_STRING);
+
+ e_signature_combo_box_set_signature_list (
+ E_SIGNATURE_COMBO_BOX (object), NULL);
+
+ return object;
+}
+
+static void
+signature_combo_box_dispose (GObject *object)
+{
+ ESignatureComboBoxPrivate *priv;
+
+ priv = E_SIGNATURE_COMBO_BOX_GET_PRIVATE (object);
+
+ if (priv->signature_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->signature_list,
+ signature_combo_box_refresh_cb, object);
+ g_object_unref (priv->signature_list);
+ priv->signature_list = NULL;
+ }
+
+ g_hash_table_remove_all (priv->index);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_combo_box_finalize (GObject *object)
+{
+ ESignatureComboBoxPrivate *priv;
+
+ priv = E_SIGNATURE_COMBO_BOX_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->index);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+signature_combo_box_class_init (ESignatureComboBoxClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ESignatureComboBoxPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructor = signature_combo_box_constructor;
+ object_class->dispose = signature_combo_box_dispose;
+ object_class->finalize = signature_combo_box_finalize;
+
+ signal_ids[REFRESHED] = g_signal_new (
+ "refreshed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+signature_combo_box_init (ESignatureComboBox *combo_box)
+{
+ GHashTable *index;
+
+ /* Reverse-lookup index */
+ index = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+
+ combo_box->priv = E_SIGNATURE_COMBO_BOX_GET_PRIVATE (combo_box);
+ combo_box->priv->index = index;
+}
+
+GType
+e_signature_combo_box_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESignatureComboBoxClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) signature_combo_box_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ESignatureComboBox),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) signature_combo_box_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_COMBO_BOX, "ESignatureComboBox",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_signature_combo_box_new (void)
+{
+ return g_object_new (E_TYPE_SIGNATURE_COMBO_BOX, NULL);
+}
+
+void
+e_signature_combo_box_set_signature_list (ESignatureComboBox *combo_box,
+ ESignatureList *signature_list)
+{
+ ESignatureComboBoxPrivate *priv;
+
+ g_return_if_fail (E_IS_SIGNATURE_COMBO_BOX (combo_box));
+
+ if (signature_list != NULL)
+ g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list));
+
+ priv = E_SIGNATURE_COMBO_BOX_GET_PRIVATE (combo_box);
+
+ if (priv->signature_list != NULL) {
+ g_signal_handlers_disconnect_by_func (
+ priv->signature_list,
+ signature_combo_box_refresh_cb, combo_box);
+ g_object_unref (priv->signature_list);
+ priv->signature_list = NULL;
+ }
+
+ if (signature_list != NULL) {
+ priv->signature_list = g_object_ref (signature_list);
+
+ /* Listen for changes to the signature list. */
+ g_signal_connect (
+ priv->signature_list, "signature-added",
+ G_CALLBACK (signature_combo_box_refresh_cb),
+ combo_box);
+ g_signal_connect (
+ priv->signature_list, "signature-changed",
+ G_CALLBACK (signature_combo_box_refresh_cb),
+ combo_box);
+ g_signal_connect (
+ priv->signature_list, "signature-removed",
+ G_CALLBACK (signature_combo_box_refresh_cb),
+ combo_box);
+ }
+
+ signature_combo_box_refresh_cb (signature_list, NULL, combo_box);
+}
+
+ESignature *
+e_signature_combo_box_get_active (ESignatureComboBox *combo_box)
+{
+ ESignature *signature;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean iter_set;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_COMBO_BOX (combo_box), NULL);
+
+ iter_set = gtk_combo_box_get_active_iter (
+ GTK_COMBO_BOX (combo_box), &iter);
+ if (!iter_set)
+ return NULL;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_tree_model_get (model, &iter, COLUMN_SIGNATURE, &signature, -1);
+
+ return signature;
+}
+
+gboolean
+e_signature_combo_box_set_active (ESignatureComboBox *combo_box,
+ ESignature *signature)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean iter_set;
+
+ g_return_val_if_fail (E_IS_SIGNATURE_COMBO_BOX (combo_box), FALSE);
+
+ if (signature != NULL)
+ g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE);
+
+ /* NULL means select "None" (always the first item). */
+ if (signature == NULL) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+ return TRUE;
+ }
+
+ /* Lookup the tree row reference for the signature. */
+ reference = g_hash_table_lookup (combo_box->priv->index, signature);
+ if (reference == NULL)
+ return FALSE;
+
+ /* Convert the reference to a tree iterator. */
+ path = gtk_tree_row_reference_get_path (reference);
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ iter_set = gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ if (!iter_set)
+ return FALSE;
+
+ /* Activate the corresponding combo box item. */
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
+
+ return TRUE;
+}
diff --git a/widgets/misc/e-signature-combo-box.h b/widgets/misc/e-signature-combo-box.h
new file mode 100644
index 0000000000..31786978ef
--- /dev/null
+++ b/widgets/misc/e-signature-combo-box.h
@@ -0,0 +1,55 @@
+#ifndef E_SIGNATURE_COMBO_BOX_H
+#define E_SIGNATURE_COMBO_BOX_H
+
+#include <gtk/gtk.h>
+#include "e-util/e-signature.h"
+#include "e-util/e-signature-list.h"
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_COMBO_BOX \
+ (e_signature_combo_box_get_type ())
+#define E_SIGNATURE_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SIGNATURE_COMBO_BOX, ESignatureComboBox))
+#define E_SIGNATURE_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SIGNATURE_COMBO_BOX, ESignatureComboBoxClass))
+#define E_IS_SIGNATURE_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SIGNATURE_COMBO_BOX))
+#define E_IS_SIGNATURE_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SIGNATURE_COMBO_BOX))
+#define E_SIGNATURE_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SIGNATURE_COMBO_BOX, ESignatureComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureComboBox ESignatureComboBox;
+typedef struct _ESignatureComboBoxClass ESignatureComboBoxClass;
+typedef struct _ESignatureComboBoxPrivate ESignatureComboBoxPrivate;
+
+struct _ESignatureComboBox {
+ GtkComboBox parent;
+ ESignatureComboBoxPrivate *priv;
+};
+
+struct _ESignatureComboBoxClass {
+ GtkComboBoxClass parent_class;
+};
+
+GType e_signature_combo_box_get_type (void);
+GtkWidget * e_signature_combo_box_new (void);
+void e_signature_combo_box_set_signature_list
+ (ESignatureComboBox *combo_box,
+ ESignatureList *signature_list);
+ESignature * e_signature_combo_box_get_active
+ (ESignatureComboBox *combo_box);
+gboolean e_signature_combo_box_set_active
+ (ESignatureComboBox *combo_box,
+ ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_COMBO_BOX_H */