[evolution/account-mgmt: 9/55] Adapt widgets/misc to the new ESource API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/account-mgmt: 9/55] Adapt widgets/misc to the new ESource API.
- Date: Mon, 28 May 2012 21:26:21 +0000 (UTC)
commit dfe7b41d1f4c24f1bb7fde4fa361ed3555e1a8a6
Author: Matthew Barnes <mbarnes redhat com>
Date: Fri Apr 1 20:43:32 2011 -0400
Adapt widgets/misc to the new ESource API.
po/POTFILES.in | 1 +
widgets/misc/Makefile.am | 69 ++-
widgets/misc/e-alarm-selector.c | 97 +++
widgets/misc/e-auth-combo-box.c | 6 +
widgets/misc/e-autocomplete-selector.c | 99 +++
widgets/misc/e-mail-account-manager.c | 384 -----------
widgets/misc/e-mail-account-manager.h | 77 ---
widgets/misc/e-mail-account-tree-view.c | 575 ----------------
widgets/misc/e-mail-account-tree-view.h | 83 ---
widgets/misc/e-mail-identity-combo-box.c | 165 +++--
widgets/misc/e-mail-identity-combo-box.h | 5 -
widgets/misc/e-mail-signature-combo-box.c | 617 +++++++++++++++++
widgets/misc/e-mail-signature-combo-box.h | 91 +++
widgets/misc/e-mail-signature-editor.c | 910 +++++++++++++++++++++++++
widgets/misc/e-mail-signature-editor.h | 82 +++
widgets/misc/e-mail-signature-manager.c | 705 +++++++++++++++++++
widgets/misc/e-mail-signature-manager.h | 88 +++
widgets/misc/e-mail-signature-preview.c | 360 ++++++++++
widgets/misc/e-mail-signature-preview.h | 79 +++
widgets/misc/e-mail-signature-script-dialog.c | 733 ++++++++++++++++++++
widgets/misc/e-mail-signature-script-dialog.h | 90 +++
widgets/misc/e-mail-signature-tree-view.c | 397 +++++++++++
widgets/misc/e-mail-signature-tree-view.h | 76 ++
widgets/misc/e-signature-combo-box.c | 346 ----------
widgets/misc/e-signature-combo-box.h | 78 ---
widgets/misc/e-signature-editor.c | 587 ----------------
widgets/misc/e-signature-editor.h | 73 --
widgets/misc/e-signature-manager.c | 758 --------------------
widgets/misc/e-signature-manager.h | 100 ---
widgets/misc/e-signature-preview.c | 308 ---------
widgets/misc/e-signature-preview.h | 81 ---
widgets/misc/e-signature-script-dialog.c | 440 ------------
widgets/misc/e-signature-script-dialog.h | 76 --
widgets/misc/e-signature-tree-view.c | 431 ------------
widgets/misc/e-signature-tree-view.h | 78 ---
widgets/misc/e-source-notebook.c | 359 ----------
widgets/misc/e-source-notebook.h | 73 --
widgets/misc/test-mail-accounts.c | 61 --
widgets/misc/test-mail-signatures.c | 199 ++++++
widgets/misc/test-source-config.c | 3 +-
widgets/misc/widgets.error.xml | 28 +
41 files changed, 4791 insertions(+), 5077 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b58380a..2f42762 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -472,6 +472,7 @@ widgets/misc/e-spell-entry.c
widgets/misc/e-url-entry.c
widgets/misc/e-web-view.c
widgets/misc/e-web-view-gtkhtml.c
+widgets/misc/widgets.error.xml
widgets/table/e-cell-combo.c
widgets/table/e-cell-date.c
widgets/table/e-cell-date-edit.c
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index bb3c662..69f5d87 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -37,9 +37,13 @@ widgetsinclude_HEADERS = \
e-image-chooser.h \
e-import-assistant.h \
e-interval-chooser.h \
- e-mail-account-manager.h \
- e-mail-account-tree-view.h \
e-mail-identity-combo-box.h \
+ e-mail-signature-combo-box.h \
+ e-mail-signature-editor.h \
+ e-mail-signature-manager.h \
+ e-mail-signature-preview.h \
+ e-mail-signature-script-dialog.h \
+ e-mail-signature-tree-view.h \
e-map.h \
e-menu-tool-action.h \
e-menu-tool-button.h \
@@ -57,16 +61,9 @@ widgetsinclude_HEADERS = \
e-selection-model-array.h \
e-selection-model-simple.h \
e-send-options.h \
- e-signature-combo-box.h \
- e-signature-editor.h \
- e-signature-manager.h \
- e-signature-preview.h \
- e-signature-script-dialog.h \
- e-signature-tree-view.h \
e-source-config.h \
e-source-config-backend.h \
e-source-config-dialog.h \
- e-source-notebook.h \
e-spell-entry.h \
e-url-entry.h \
e-web-view.h \
@@ -127,9 +124,13 @@ libemiscwidgets_la_SOURCES = \
e-image-chooser.c \
e-import-assistant.c \
e-interval-chooser.c \
- e-mail-account-manager.c \
- e-mail-account-tree-view.c \
e-mail-identity-combo-box.c \
+ e-mail-signature-combo-box.c \
+ e-mail-signature-editor.c \
+ e-mail-signature-manager.c \
+ e-mail-signature-preview.c \
+ e-mail-signature-script-dialog.c \
+ e-mail-signature-tree-view.c \
e-map.c \
e-menu-tool-action.c \
e-menu-tool-button.c \
@@ -147,16 +148,9 @@ libemiscwidgets_la_SOURCES = \
e-selection-model-array.c \
e-selection-model-simple.c \
e-send-options.c \
- e-signature-combo-box.c \
- e-signature-editor.c \
- e-signature-manager.c \
- e-signature-preview.c \
- e-signature-script-dialog.c \
- e-signature-tree-view.c \
e-source-config.c \
e-source-config-backend.c \
e-source-config-dialog.c \
- e-source-notebook.c \
e-spell-entry.c \
e-url-entry.c \
e-web-view.c \
@@ -185,9 +179,15 @@ libemiscwidgets_la_LIBADD = \
$(CLUTTER_LIBS) \
$(GTKHTML_LIBS)
+error_DATA = widgets.error
+errordir = $(privdatadir)/errors
+# provides error rules too
+ EVO_PLUGIN_RULE@
+
noinst_PROGRAMS = \
test-calendar \
test-dateedit \
+ test-mail-signatures \
test-preferences-window \
test-source-config
@@ -205,8 +205,7 @@ test_widgets_misc_CPPFLAGS= \
test_calendar_CPPFLAGS = $(test_widgets_misc_CPPFLAGS)
-test_calendar_SOURCES = \
- test-calendar.c
+test_calendar_SOURCES = test-calendar.c
test_calendar_LDADD = \
libemiscwidgets.la \
@@ -219,8 +218,7 @@ test_calendar_LDADD = \
test_dateedit_CPPFLAGS = $(test_widgets_misc_CPPFLAGS)
-test_dateedit_SOURCES = \
- test-dateedit.c
+test_dateedit_SOURCES = test-dateedit.c
test_dateedit_LDADD = \
libemiscwidgets.la \
@@ -229,12 +227,28 @@ test_dateedit_LDADD = \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS)
+# test-mail-signatures
+
+test_mail_signatures_CPPFLAGS = \
+ $(test_widgets_misc_CPPFLAGS) \
+ $(GTKHTML_CFLAGS)
+
+test_mail_signatures_SOURCES = test-mail-signatures.c
+
+test_mail_signatures_LDADD = \
+ libemiscwidgets.la \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/filter/libfilter.la \
+ $(top_builddir)/libevolution-utils/libevolution-utils.la \
+ $(EVOLUTION_DATA_SERVER_LIBS) \
+ $(GNOME_PLATFORM_LIBS) \
+ $(GTKHTML_LIBS)
+
# test-preferences-window
test_preferences_window_CPPFLAGS = $(test_widgets_misc_CPPFLAGS)
-test_preferences_window_SOURCES = \
- test-preferences-window.c
+test_preferences_window_SOURCES = test-preferences-window.c
test_preferences_window_LDADD = \
libemiscwidgets.la \
@@ -247,8 +261,7 @@ test_preferences_window_LDADD = \
test_source_config_CPPFLAGS = $(test_widgets_misc_CPPFLAGS)
-test_source_config_SOURCES = \
- test-source-config.c
+test_source_config_SOURCES = test-source-config.c
test_source_config_LDADD = \
libemiscwidgets.la \
@@ -257,6 +270,8 @@ test_source_config_LDADD = \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS)
-EXTRA_DIST = $(ui_DATA)
+BUILT_SOURCES = $(error_DATA)
+
+EXTRA_DIST = $(ui_DATA) widgets.error.xml
-include $(top_srcdir)/git.mk
diff --git a/widgets/misc/e-alarm-selector.c b/widgets/misc/e-alarm-selector.c
new file mode 100644
index 0000000..3a61663
--- /dev/null
+++ b/widgets/misc/e-alarm-selector.c
@@ -0,0 +1,97 @@
+/*
+ * e-alarm-selector.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-alarm-selector.h"
+
+#include <libedataserver/e-source-alarms.h>
+#include <libedataserver/e-source-calendar.h>
+
+G_DEFINE_TYPE (
+ EAlarmSelector,
+ e_alarm_selector,
+ E_TYPE_SOURCE_SELECTOR)
+
+static gboolean
+alarm_selector_get_source_selected (ESourceSelector *selector,
+ ESource *source)
+{
+ ESourceAlarms *extension;
+ const gchar *extension_name;
+
+ /* Make sure this source is a calendar. */
+ extension_name = e_source_selector_get_extension_name (selector);
+ if (!e_source_has_extension (source, extension_name))
+ return FALSE;
+
+ extension_name = E_SOURCE_EXTENSION_ALARMS;
+ extension = e_source_get_extension (source, extension_name);
+ g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), FALSE);
+
+ return e_source_alarms_get_include_me (extension);
+}
+
+static void
+alarm_selector_set_source_selected (ESourceSelector *selector,
+ ESource *source,
+ gboolean selected)
+{
+ ESourceAlarms *extension;
+ const gchar *extension_name;
+
+ /* Make sure this source is a calendar. */
+ extension_name = e_source_selector_get_extension_name (selector);
+ if (!e_source_has_extension (source, extension_name))
+ return;
+
+ extension_name = E_SOURCE_EXTENSION_ALARMS;
+ extension = e_source_get_extension (source, extension_name);
+ g_return_if_fail (E_IS_SOURCE_ALARMS (extension));
+
+ if (selected != e_source_alarms_get_include_me (extension)) {
+ e_source_alarms_set_include_me (extension, selected);
+ e_source_selector_queue_write (selector, source);
+ }
+}
+
+static void
+e_alarm_selector_class_init (EAlarmSelectorClass *class)
+{
+ ESourceSelectorClass *source_selector_class;
+
+ source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
+ source_selector_class->get_source_selected =
+ alarm_selector_get_source_selected;
+ source_selector_class->set_source_selected =
+ alarm_selector_set_source_selected;
+}
+
+static void
+e_alarm_selector_init (EAlarmSelector *selector)
+{
+}
+
+GtkWidget *
+e_alarm_selector_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_ALARM_SELECTOR,
+ "extension-name", E_SOURCE_EXTENSION_CALENDAR,
+ "registry", registry, NULL);
+}
diff --git a/widgets/misc/e-auth-combo-box.c b/widgets/misc/e-auth-combo-box.c
index 182e171..bd3d8c7 100644
--- a/widgets/misc/e-auth-combo-box.c
+++ b/widgets/misc/e-auth-combo-box.c
@@ -185,6 +185,12 @@ e_auth_combo_box_init (EAuthComboBox *combo_box)
combo_box->priv = E_AUTH_COMBO_BOX_GET_PRIVATE (combo_box);
}
+GtkWidget *
+e_auth_combo_box_new (void)
+{
+ return g_object_new (E_TYPE_AUTH_COMBO_BOX, NULL);
+}
+
CamelProvider *
e_auth_combo_box_get_provider (EAuthComboBox *combo_box)
{
diff --git a/widgets/misc/e-autocomplete-selector.c b/widgets/misc/e-autocomplete-selector.c
new file mode 100644
index 0000000..38caa83
--- /dev/null
+++ b/widgets/misc/e-autocomplete-selector.c
@@ -0,0 +1,99 @@
+/*
+ * e-autocomplete-selector.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-autocomplete-selector.h"
+
+#include <libedataserver/e-source-address-book.h>
+#include <libedataserver/e-source-autocomplete.h>
+
+G_DEFINE_TYPE (
+ EAutocompleteSelector,
+ e_autocomplete_selector,
+ E_TYPE_SOURCE_SELECTOR)
+
+static gboolean
+autocomplete_selector_get_source_selected (ESourceSelector *selector,
+ ESource *source)
+{
+ ESourceAutocomplete *extension;
+ const gchar *extension_name;
+
+ /* Make sure this source is an address book. */
+ extension_name = e_source_selector_get_extension_name (selector);
+ if (!e_source_has_extension (source, extension_name))
+ return FALSE;
+
+ extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+ extension = e_source_get_extension (source, extension_name);
+ g_return_val_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension), FALSE);
+
+ return e_source_autocomplete_get_include_me (extension);
+}
+
+static void
+autocomplete_selector_set_source_selected (ESourceSelector *selector,
+ ESource *source,
+ gboolean selected)
+{
+ ESourceAutocomplete *extension;
+ const gchar *extension_name;
+
+ /* Make sure this source is an address book. */
+ extension_name = e_source_selector_get_extension_name (selector);
+ if (!e_source_has_extension (source, extension_name))
+ return;
+
+ extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+ extension = e_source_get_extension (source, extension_name);
+ g_return_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension));
+
+ if (selected != e_source_autocomplete_get_include_me (extension)) {
+ e_source_autocomplete_set_include_me (extension, selected);
+ e_source_selector_queue_write (selector, source);
+ }
+}
+
+static void
+e_autocomplete_selector_class_init (EAutocompleteSelectorClass *class)
+{
+ ESourceSelectorClass *source_selector_class;
+
+ source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
+ source_selector_class->get_source_selected =
+ autocomplete_selector_get_source_selected;
+ source_selector_class->set_source_selected =
+ autocomplete_selector_set_source_selected;
+}
+
+static void
+e_autocomplete_selector_init (EAutocompleteSelector *selector)
+{
+ e_source_selector_set_show_colors (
+ E_SOURCE_SELECTOR (selector), FALSE);
+}
+
+GtkWidget *
+e_autocomplete_selector_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_AUTOCOMPLETE_SELECTOR,
+ "extension-name", E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ "registry", registry, NULL);
+}
diff --git a/widgets/misc/e-mail-identity-combo-box.c b/widgets/misc/e-mail-identity-combo-box.c
index 4b83015..e43f41d 100644
--- a/widgets/misc/e-mail-identity-combo-box.c
+++ b/widgets/misc/e-mail-identity-combo-box.c
@@ -79,32 +79,20 @@ mail_identity_combo_box_registry_changed (ESourceRegistry *registry,
combo_box);
}
-static ESource *
-mail_identity_combo_box_get_default (EMailIdentityComboBox *combo_box)
+static void
+mail_identity_combo_box_activate_default (EMailIdentityComboBox *combo_box)
{
ESource *source;
ESourceRegistry *registry;
- ESourceMailAccount *mail_account;
- const gchar *extension_name;
- const gchar *uid;
- extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
registry = e_mail_identity_combo_box_get_registry (combo_box);
- source = e_source_registry_get_default_mail_account (registry);
-
- if (source == NULL)
- return NULL;
-
- if (!e_source_has_extension (source, extension_name))
- return NULL;
-
- mail_account = e_source_get_extension (source, extension_name);
- uid = e_source_mail_account_get_identity (mail_account);
-
- if (uid == NULL)
- return NULL;
+ source = e_source_registry_ref_default_mail_identity (registry);
- return e_source_registry_lookup_by_uid (registry, uid);
+ if (source != NULL) {
+ const gchar *uid = e_source_get_uid (source);
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid);
+ g_object_unref (source);
+ }
}
static void
@@ -225,7 +213,8 @@ e_mail_identity_combo_box_class_init (EMailIdentityComboBoxClass *class)
{
GObjectClass *object_class;
- g_type_class_add_private (class, sizeof (EMailIdentityComboBoxPrivate));
+ g_type_class_add_private (
+ class, sizeof (EMailIdentityComboBoxPrivate));
object_class = G_OBJECT_CLASS (class);
object_class->set_property = mail_identity_combo_box_set_property;
@@ -267,10 +256,12 @@ e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box)
{
ESourceRegistry *registry;
GtkTreeModel *tree_model;
+ GtkComboBox *gtk_combo_box;
ESource *source;
GList *list, *link;
+ GHashTable *address_table;
const gchar *extension_name;
- gchar *saved_uid = NULL;
+ const gchar *saved_uid;
g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
@@ -279,55 +270,112 @@ e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box)
combo_box->priv->refresh_idle_id = 0;
}
- registry = e_mail_identity_combo_box_get_registry (combo_box);
- tree_model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+ gtk_combo_box = GTK_COMBO_BOX (combo_box);
+ tree_model = gtk_combo_box_get_model (gtk_combo_box);
- source = e_mail_identity_combo_box_get_active_source (combo_box);
- if (source != NULL)
- saved_uid = g_strdup (e_source_get_uid (source));
+ /* This is an interned string, which means it's safe
+ * to use even after clearing the combo box model. */
+ saved_uid = gtk_combo_box_get_active_id (gtk_combo_box);
gtk_list_store_clear (GTK_LIST_STORE (tree_model));
extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+ registry = e_mail_identity_combo_box_get_registry (combo_box);
list = e_source_registry_list_sources (registry, extension_name);
+ /* Build a hash table of GQueues by email address so we can
+ * spot duplicate email addresses. Then if the GQueue for a
+ * given email address has multiple elements, we use a more
+ * verbose description in the combo box. */
+
+ address_table = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_queue_free);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ ESourceMailIdentity *extension;
+ GQueue *queue;
+ const gchar *address;
+
+ source = E_SOURCE (link->data);
+ extension = e_source_get_extension (source, extension_name);
+ address = e_source_mail_identity_get_address (extension);
+
+ if (address == NULL)
+ continue;
+
+ queue = g_hash_table_lookup (address_table, address);
+ if (queue == NULL) {
+ queue = g_queue_new ();
+ g_hash_table_insert (
+ address_table,
+ g_strdup (address), queue);
+ }
+
+ g_queue_push_tail (queue, source);
+ }
+
for (link = list; link != NULL; link = g_list_next (link)) {
+ ESourceMailIdentity *extension;
GtkTreeIter iter;
+ GQueue *queue;
+ GString *string;
+ const gchar *address;
const gchar *display_name;
+ const gchar *name;
const gchar *uid;
source = E_SOURCE (link->data);
+ if (!e_source_get_enabled (source))
+ continue;
+
+ extension = e_source_get_extension (source, extension_name);
+ name = e_source_mail_identity_get_name (extension);
+ address = e_source_mail_identity_get_address (extension);
+
+ if (name == NULL || address == NULL)
+ continue;
+
+ queue = g_hash_table_lookup (address_table, address);
+
display_name = e_source_get_display_name (source);
uid = e_source_get_uid (source);
+ string = g_string_sized_new (512);
+ g_string_append_printf (string, "%s <%s>", name, address);
+
+ /* Show the account name for duplicate email addresses. */
+ if (queue != NULL && g_queue_get_length (queue) > 1)
+ g_string_append_printf (string, " (%s)", display_name);
+
gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
gtk_list_store_set (
GTK_LIST_STORE (tree_model), &iter,
- COLUMN_DISPLAY_NAME, display_name,
+ COLUMN_DISPLAY_NAME, string->str,
COLUMN_UID, uid, -1);
+
+ g_string_free (string, TRUE);
}
- g_list_free (list);
+ g_hash_table_destroy (address_table);
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
/* Try and restore the previous selected source, or else pick
* the default identity of the default mail account. If even
* that fails, just pick the first item. */
- source = NULL;
+ if (saved_uid != NULL)
+ gtk_combo_box_set_active_id (gtk_combo_box, saved_uid);
- if (saved_uid != NULL) {
- source = e_source_registry_lookup_by_uid (registry, saved_uid);
- g_free (saved_uid);
- }
-
- if (source == NULL)
- source = mail_identity_combo_box_get_default (combo_box);
+ if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL)
+ mail_identity_combo_box_activate_default (combo_box);
- if (source != NULL)
- e_mail_identity_combo_box_set_active_source (combo_box, source);
- else
- gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+ if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL)
+ gtk_combo_box_set_active (gtk_combo_box, 0);
}
ESourceRegistry *
@@ -337,38 +385,3 @@ e_mail_identity_combo_box_get_registry (EMailIdentityComboBox *combo_box)
return combo_box->priv->registry;
}
-
-ESource *
-e_mail_identity_combo_box_get_active_source (EMailIdentityComboBox *combo_box)
-{
- ESourceRegistry *registry;
- ESource *source = NULL;
- const gchar *uid;
-
- g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL);
-
- registry = e_mail_identity_combo_box_get_registry (combo_box);
- uid = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
-
- if (uid != NULL)
- source = e_source_registry_lookup_by_uid (registry, uid);
-
- return source;
-}
-
-void
-e_mail_identity_combo_box_set_active_source (EMailIdentityComboBox *combo_box,
- ESource *active_source)
-{
- const gchar *uid;
-
- g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
- g_return_if_fail (E_IS_SOURCE (active_source));
-
- /* It is a programming error to pass an ESource that has no
- * "Mail Identity" extension. */
- g_return_if_fail (SOURCE_IS_MAIL_IDENTITY (active_source));
-
- uid = e_source_get_uid (active_source);
- gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid);
-}
diff --git a/widgets/misc/e-mail-identity-combo-box.h b/widgets/misc/e-mail-identity-combo-box.h
index b40957d..a94e0b2 100644
--- a/widgets/misc/e-mail-identity-combo-box.h
+++ b/widgets/misc/e-mail-identity-combo-box.h
@@ -65,11 +65,6 @@ void e_mail_identity_combo_box_refresh
ESourceRegistry *
e_mail_identity_combo_box_get_registry
(EMailIdentityComboBox *combo_box);
-ESource * e_mail_identity_combo_box_get_active_source
- (EMailIdentityComboBox *combo_box);
-void e_mail_identity_combo_box_set_active_source
- (EMailIdentityComboBox *combo_box,
- ESource *active_source);
G_END_DECLS
diff --git a/widgets/misc/e-mail-signature-combo-box.c b/widgets/misc/e-mail-signature-combo-box.c
new file mode 100644
index 0000000..b2c749a
--- /dev/null
+++ b/widgets/misc/e-mail-signature-combo-box.c
@@ -0,0 +1,617 @@
+/*
+ * e-mail-signature-combo-box.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-combo-box.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-signature.h>
+
+#define E_MAIL_SIGNATURE_COMBO_BOX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_COMBO_BOX, EMailSignatureComboBoxPrivate))
+
+#define SOURCE_IS_MAIL_SIGNATURE(source) \
+ (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_SIGNATURE))
+
+struct _EMailSignatureComboBoxPrivate {
+ ESourceRegistry *registry;
+ guint refresh_idle_id;
+ gchar *identity_uid;
+};
+
+enum {
+ PROP_0,
+ PROP_IDENTITY_UID,
+ PROP_REGISTRY
+};
+
+enum {
+ COLUMN_DISPLAY_NAME,
+ COLUMN_UID
+};
+
+G_DEFINE_TYPE (
+ EMailSignatureComboBox,
+ e_mail_signature_combo_box,
+ GTK_TYPE_COMBO_BOX)
+
+static gboolean
+mail_signature_combo_box_refresh_idle_cb (EMailSignatureComboBox *combo_box)
+{
+ /* The refresh function will clear the idle ID. */
+ e_mail_signature_combo_box_refresh (combo_box);
+
+ return FALSE;
+}
+
+static void
+mail_signature_combo_box_registry_changed (ESourceRegistry *registry,
+ ESource *source,
+ EMailSignatureComboBox *combo_box)
+{
+ /* If the ESource in question has a "Mail Signature" extension,
+ * schedule a refresh of the tree model. Otherwise ignore it.
+ * We use an idle callback to limit how frequently we refresh
+ * the tree model, in case the registry is emitting lots of
+ * signals at once. */
+
+ if (!SOURCE_IS_MAIL_SIGNATURE (source))
+ return;
+
+ if (combo_box->priv->refresh_idle_id > 0)
+ return;
+
+ combo_box->priv->refresh_idle_id = gdk_threads_add_idle (
+ (GSourceFunc) mail_signature_combo_box_refresh_idle_cb,
+ combo_box);
+}
+
+static void
+mail_signature_combo_box_set_registry (EMailSignatureComboBox *combo_box,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (combo_box->priv->registry == NULL);
+
+ combo_box->priv->registry = g_object_ref (registry);
+
+ g_signal_connect (
+ registry, "source-added",
+ G_CALLBACK (mail_signature_combo_box_registry_changed),
+ combo_box);
+
+ g_signal_connect (
+ registry, "source-changed",
+ G_CALLBACK (mail_signature_combo_box_registry_changed),
+ combo_box);
+
+ g_signal_connect (
+ registry, "source-removed",
+ G_CALLBACK (mail_signature_combo_box_registry_changed),
+ combo_box);
+}
+
+static void
+mail_signature_combo_box_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_IDENTITY_UID:
+ e_mail_signature_combo_box_set_identity_uid (
+ E_MAIL_SIGNATURE_COMBO_BOX (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_REGISTRY:
+ mail_signature_combo_box_set_registry (
+ E_MAIL_SIGNATURE_COMBO_BOX (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_combo_box_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_IDENTITY_UID:
+ g_value_set_string (
+ value,
+ e_mail_signature_combo_box_get_identity_uid (
+ E_MAIL_SIGNATURE_COMBO_BOX (object)));
+ return;
+
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_combo_box_get_registry (
+ E_MAIL_SIGNATURE_COMBO_BOX (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_combo_box_dispose (GObject *object)
+{
+ EMailSignatureComboBoxPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_COMBO_BOX_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->registry, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->refresh_idle_id > 0) {
+ g_source_remove (priv->refresh_idle_id);
+ priv->refresh_idle_id = 0;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_combo_box_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_combo_box_finalize (GObject *object)
+{
+ EMailSignatureComboBoxPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_COMBO_BOX_GET_PRIVATE (object);
+
+ g_free (priv->identity_uid);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_mail_signature_combo_box_parent_class)->
+ finalize (object);
+}
+
+static void
+mail_signature_combo_box_constructed (GObject *object)
+{
+ GtkListStore *list_store;
+ GtkComboBox *combo_box;
+ GtkCellLayout *cell_layout;
+ GtkCellRenderer *cell_renderer;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_signature_combo_box_parent_class)->
+ constructed (object);
+
+ combo_box = GTK_COMBO_BOX (object);
+ cell_layout = GTK_CELL_LAYOUT (object);
+
+ list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (list_store));
+ gtk_combo_box_set_id_column (combo_box, COLUMN_UID);
+ g_object_unref (list_store);
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (cell_layout, cell_renderer, TRUE);
+ gtk_cell_layout_add_attribute (
+ cell_layout, cell_renderer, "text", COLUMN_DISPLAY_NAME);
+
+ e_mail_signature_combo_box_refresh (
+ E_MAIL_SIGNATURE_COMBO_BOX (object));
+}
+
+static void
+e_mail_signature_combo_box_class_init (EMailSignatureComboBoxClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (
+ class, sizeof (EMailSignatureComboBoxPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_combo_box_set_property;
+ object_class->get_property = mail_signature_combo_box_get_property;
+ object_class->dispose = mail_signature_combo_box_dispose;
+ object_class->finalize = mail_signature_combo_box_finalize;
+ object_class->constructed = mail_signature_combo_box_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_IDENTITY_UID,
+ g_param_spec_string (
+ "identity-uid",
+ "Identity UID",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_signature_combo_box_init (EMailSignatureComboBox *combo_box)
+{
+ combo_box->priv = E_MAIL_SIGNATURE_COMBO_BOX_GET_PRIVATE (combo_box);
+}
+
+GtkWidget *
+e_mail_signature_combo_box_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_COMBO_BOX,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_signature_combo_box_refresh (EMailSignatureComboBox *combo_box)
+{
+ ESourceRegistry *registry;
+ GtkComboBox *gtk_combo_box;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ ESource *source;
+ GList *list, *link;
+ const gchar *extension_name;
+ const gchar *saved_uid;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_COMBO_BOX (combo_box));
+
+ if (combo_box->priv->refresh_idle_id > 0) {
+ g_source_remove (combo_box->priv->refresh_idle_id);
+ combo_box->priv->refresh_idle_id = 0;
+ }
+
+ gtk_combo_box = GTK_COMBO_BOX (combo_box);
+ tree_model = gtk_combo_box_get_model (gtk_combo_box);
+
+ /* This is an interned string, which means it's safe
+ * to use even after clearing the combo box model. */
+ saved_uid = gtk_combo_box_get_active_id (gtk_combo_box);
+
+ gtk_list_store_clear (GTK_LIST_STORE (tree_model));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ registry = e_mail_signature_combo_box_get_registry (combo_box);
+ list = e_source_registry_list_sources (registry, extension_name);
+
+ /* The "None" option always comes first. */
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, _("None"),
+ COLUMN_UID, "none", -1);
+
+ /* The "autogenerated" UID has special meaning. */
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, _("Autogenerated"),
+ COLUMN_UID, E_MAIL_SIGNATURE_AUTOGENERATED_UID, -1);
+
+ /* Followed by the other mail signatures, alphabetized. */
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ GtkTreeIter iter;
+ const gchar *display_name;
+ const gchar *uid;
+
+ source = E_SOURCE (link->data);
+ display_name = e_source_get_display_name (source);
+ uid = e_source_get_uid (source);
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, display_name,
+ COLUMN_UID, uid, -1);
+ }
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+ /* Try and restore the previous selected source, or else "None". */
+
+ if (saved_uid != NULL)
+ gtk_combo_box_set_active_id (gtk_combo_box, saved_uid);
+
+ if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL)
+ gtk_combo_box_set_active (gtk_combo_box, 0);
+}
+
+ESourceRegistry *
+e_mail_signature_combo_box_get_registry (EMailSignatureComboBox *combo_box)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_COMBO_BOX (combo_box), NULL);
+
+ return combo_box->priv->registry;
+}
+
+const gchar *
+e_mail_signature_combo_box_get_identity_uid (EMailSignatureComboBox *combo_box)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_COMBO_BOX (combo_box), NULL);
+
+ return combo_box->priv->identity_uid;
+}
+
+void
+e_mail_signature_combo_box_set_identity_uid (EMailSignatureComboBox *combo_box,
+ const gchar *identity_uid)
+{
+ const gchar *active_id;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_COMBO_BOX (combo_box));
+
+ g_free (combo_box->priv->identity_uid);
+ combo_box->priv->identity_uid = g_strdup (identity_uid);
+
+ g_object_notify (G_OBJECT (combo_box), "identity-uid");
+
+ /* If "Autogenerated" is selected, emit a "changed" signal as
+ * a hint to whomever is listening to reload the signature. */
+ active_id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
+ if (g_strcmp0 (active_id, E_MAIL_SIGNATURE_AUTOGENERATED_UID) == 0)
+ g_signal_emit_by_name (combo_box, "changed");
+}
+
+/**************** e_mail_signature_combo_box_load_selected() *****************/
+
+typedef struct _LoadContext LoadContext;
+
+struct _LoadContext {
+ gchar *contents;
+ gsize length;
+ gboolean is_html;
+};
+
+static void
+load_context_free (LoadContext *context)
+{
+ g_free (context->contents);
+ g_slice_free (LoadContext, context);
+}
+
+static void
+mail_signature_combo_box_autogenerate (EMailSignatureComboBox *combo_box,
+ LoadContext *context)
+{
+ ESourceMailIdentity *extension;
+ ESourceRegistry *registry;
+ ESource *source;
+ GString *buffer;
+ const gchar *extension_name;
+ const gchar *identity_uid;
+ const gchar *text;
+ gchar *escaped;
+
+ identity_uid = e_mail_signature_combo_box_get_identity_uid (combo_box);
+
+ /* If we have no mail identity UID, handle it as though
+ * "None" were selected. No need to report an error. */
+ if (identity_uid == NULL)
+ return;
+
+ registry = e_mail_signature_combo_box_get_registry (combo_box);
+ source = e_source_registry_ref_source (registry, identity_uid);
+
+ /* If the mail identity lookup fails, handle it as though
+ * "None" were selected. No need to report an error. */
+ if (source == NULL)
+ return;
+
+ /* If the source is not actually a mail identity, handle it as
+ * though "None" were selected. No need to report an error. */
+ extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+ if (!e_source_has_extension (source, extension_name)) {
+ g_object_unref (source);
+ return;
+ }
+
+ extension = e_source_get_extension (source, extension_name);
+
+ /* The autogenerated signature format is:
+ *
+ * <NAME> <ADDRESS>
+ * <ORGANIZATION>
+ *
+ * The <ADDRESS> is a mailto link and
+ * the <ORGANIZATION> line is optional.
+ */
+
+ buffer = g_string_sized_new (512);
+
+ text = e_source_mail_identity_get_name (extension);
+ escaped = (text != NULL) ? g_markup_escape_text (text, -1) : NULL;
+ if (escaped != NULL && *escaped != '\0')
+ g_string_append (buffer, escaped);
+ g_free (escaped);
+
+ text = e_source_mail_identity_get_address (extension);
+ escaped = (text != NULL) ? g_markup_escape_text (text, -1) : NULL;
+ if (escaped != NULL && *escaped != '\0')
+ g_string_append_printf (
+ buffer, " <<a href=\"mailto:%s\">%s</a>>",
+ escaped, escaped);
+ g_free (escaped);
+
+ text = e_source_mail_identity_get_organization (extension);
+ escaped = (text != NULL) ? g_markup_escape_text (text, -1) : NULL;
+ if (escaped != NULL && *escaped != '\0')
+ g_string_append_printf (buffer, "<br>%s", escaped);
+ g_free (escaped);
+
+ context->length = buffer->len;
+ context->contents = g_string_free (buffer, FALSE);
+ context->is_html = TRUE;
+
+ g_object_unref (source);
+}
+
+static void
+mail_signature_combo_box_load_cb (ESource *source,
+ GAsyncResult *result,
+ GSimpleAsyncResult *simple)
+{
+ ESourceMailSignature *extension;
+ LoadContext *context;
+ const gchar *extension_name;
+ const gchar *mime_type;
+ GError *error = NULL;
+
+ context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ e_source_mail_signature_load_finish (
+ source, result, &context->contents, &context->length, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ return;
+ }
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ mime_type = e_source_mail_signature_get_mime_type (extension);
+ context->is_html = (g_strcmp0 (mime_type, "text/html") == 0);
+
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+void
+e_mail_signature_combo_box_load_selected (EMailSignatureComboBox *combo_box,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ ESourceRegistry *registry;
+ LoadContext *context;
+ ESource *source;
+ const gchar *active_id;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_COMBO_BOX (combo_box));
+
+ context = g_slice_new0 (LoadContext);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (combo_box), callback, user_data,
+ e_mail_signature_combo_box_load_selected);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, context, (GDestroyNotify) load_context_free);
+
+ active_id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
+
+ if (active_id == NULL) {
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ if (g_strcmp0 (active_id, E_MAIL_SIGNATURE_AUTOGENERATED_UID) == 0) {
+ mail_signature_combo_box_autogenerate (combo_box, context);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ registry = e_mail_signature_combo_box_get_registry (combo_box);
+ source = e_source_registry_ref_source (registry, active_id);
+
+ /* If for some reason the ESource lookup fails, handle it as
+ * though "None" were selected. No need to report an error. */
+ if (source == NULL) {
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ e_source_mail_signature_load (
+ source, io_priority, cancellable, (GAsyncReadyCallback)
+ mail_signature_combo_box_load_cb, simple);
+
+ g_object_unref (source);
+}
+
+gboolean
+e_mail_signature_combo_box_load_selected_finish (EMailSignatureComboBox *combo_box,
+ GAsyncResult *result,
+ gchar **contents,
+ gsize *length,
+ gboolean *is_html,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ LoadContext *context;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (combo_box),
+ e_mail_signature_combo_box_load_selected), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (contents != NULL) {
+ *contents = context->contents;
+ context->contents = NULL;
+ }
+
+ if (length != NULL)
+ *length = context->length;
+
+ if (is_html != NULL)
+ *is_html = context->is_html;
+
+ return TRUE;
+}
diff --git a/widgets/misc/e-mail-signature-combo-box.h b/widgets/misc/e-mail-signature-combo-box.h
new file mode 100644
index 0000000..49abc50
--- /dev/null
+++ b/widgets/misc/e-mail-signature-combo-box.h
@@ -0,0 +1,91 @@
+/*
+ * e-mail-signature-combo-box.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_COMBO_BOX_H
+#define E_MAIL_SIGNATURE_COMBO_BOX_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_COMBO_BOX \
+ (e_mail_signature_combo_box_get_type ())
+#define E_MAIL_SIGNATURE_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_COMBO_BOX, EMailSignatureComboBox))
+#define E_MAIL_SIGNATURE_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_COMBO_BOX, EMailSignatureComboBoxClass))
+#define E_IS_MAIL_SIGNATURE_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_COMBO_BOX))
+#define E_IS_MAIL_SIGNATURE_COMBO_BOX_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_COMBO_BOX))
+#define E_MAIL_SIGNATURE_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_COMBO_BOX, EMailSignatureComboBoxClass))
+
+#define E_MAIL_SIGNATURE_AUTOGENERATED_UID "autogenerated"
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignatureComboBox EMailSignatureComboBox;
+typedef struct _EMailSignatureComboBoxClass EMailSignatureComboBoxClass;
+typedef struct _EMailSignatureComboBoxPrivate EMailSignatureComboBoxPrivate;
+
+struct _EMailSignatureComboBox {
+ GtkComboBox parent;
+ EMailSignatureComboBoxPrivate *priv;
+};
+
+struct _EMailSignatureComboBoxClass {
+ GtkComboBoxClass parent_class;
+};
+
+GType e_mail_signature_combo_box_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_combo_box_new
+ (ESourceRegistry *registry);
+void e_mail_signature_combo_box_refresh
+ (EMailSignatureComboBox *combo_box);
+ESourceRegistry *
+ e_mail_signature_combo_box_get_registry
+ (EMailSignatureComboBox *combo_box);
+const gchar * e_mail_signature_combo_box_get_identity_uid
+ (EMailSignatureComboBox *combo_box);
+void e_mail_signature_combo_box_set_identity_uid
+ (EMailSignatureComboBox *combo_box,
+ const gchar *identity_uid);
+void e_mail_signature_combo_box_load_selected
+ (EMailSignatureComboBox *combo_box,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_mail_signature_combo_box_load_selected_finish
+ (EMailSignatureComboBox *combo_box,
+ GAsyncResult *result,
+ gchar **contents,
+ gsize *length,
+ gboolean *is_html,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SIGNATURE_COMBO_BOX_H */
diff --git a/widgets/misc/e-mail-signature-editor.c b/widgets/misc/e-mail-signature-editor.c
new file mode 100644
index 0000000..4575fff
--- /dev/null
+++ b/widgets/misc/e-mail-signature-editor.c
@@ -0,0 +1,910 @@
+/*
+ * e-mail-signature-editor.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-editor.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-mail-signature.h>
+
+#include <libevolution-utils/e-alert-dialog.h>
+#include <libevolution-utils/e-alert-sink.h>
+#include <misc/e-alert-bar.h>
+#include <misc/e-web-view-gtkhtml.h>
+
+#define E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_EDITOR, EMailSignatureEditorPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailSignatureEditorPrivate {
+ GtkActionGroup *action_group;
+ EFocusTracker *focus_tracker;
+ GCancellable *cancellable;
+ ESourceRegistry *registry;
+ ESource *source;
+ gchar *original_name;
+
+ GtkWidget *entry; /* not referenced */
+ GtkWidget *alert_bar; /* not referenced */
+};
+
+struct _AsyncContext {
+ ESource *source;
+ GCancellable *cancellable;
+ gchar *contents;
+ gsize length;
+};
+
+enum {
+ PROP_0,
+ PROP_FOCUS_TRACKER,
+ PROP_REGISTRY,
+ PROP_SOURCE
+};
+
+static const gchar *ui =
+"<ui>\n"
+" <menubar name='main-menu'>\n"
+" <placeholder name='pre-edit-menu'>\n"
+" <menu action='file-menu'>\n"
+" <menuitem action='save-and-close'/>\n"
+" <separator/>"
+" <menuitem action='close'/>\n"
+" </menu>\n"
+" </placeholder>\n"
+" </menubar>\n"
+" <toolbar name='main-toolbar'>\n"
+" <placeholder name='pre-main-toolbar'>\n"
+" <toolitem action='save-and-close'/>\n"
+" </placeholder>\n"
+" </toolbar>\n"
+"</ui>";
+
+/* Forward Declarations */
+static void e_mail_signature_editor_alert_sink_init
+ (EAlertSinkInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+ EMailSignatureEditor,
+ e_mail_signature_editor,
+ GTKHTML_TYPE_EDITOR,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_ALERT_SINK,
+ e_mail_signature_editor_alert_sink_init))
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+ if (async_context->source != NULL)
+ g_object_unref (async_context->source);
+
+ if (async_context->cancellable != NULL)
+ g_object_unref (async_context->cancellable);
+
+ g_free (async_context->contents);
+
+ g_slice_free (AsyncContext, async_context);
+}
+
+static void
+mail_signature_editor_loaded_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source;
+ EMailSignatureEditor *editor;
+ ESourceMailSignature *extension;
+ const gchar *extension_name;
+ const gchar *mime_type;
+ gchar *contents = NULL;
+ gboolean is_html;
+ GError *error = NULL;
+
+ source = E_SOURCE (object);
+ editor = E_MAIL_SIGNATURE_EDITOR (user_data);
+
+ e_source_mail_signature_load_finish (
+ source, result, &contents, NULL, &error);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warn_if_fail (contents == NULL);
+ g_object_unref (editor);
+ g_error_free (error);
+ return;
+
+ } else if (error != NULL) {
+ g_warn_if_fail (contents == NULL);
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "widgets:no-load-signature",
+ error->message, NULL);
+ g_object_unref (editor);
+ g_error_free (error);
+ return;
+ }
+
+ g_return_if_fail (contents != NULL);
+
+ /* The load operation should have set the MIME type. */
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ mime_type = e_source_mail_signature_get_mime_type (extension);
+ is_html = (g_strcmp0 (mime_type, "text/html") == 0);
+
+ gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (editor), is_html);
+
+ if (is_html)
+ gtkhtml_editor_insert_html (
+ GTKHTML_EDITOR (editor), contents);
+ else
+ gtkhtml_editor_insert_text (
+ GTKHTML_EDITOR (editor), contents);
+
+ g_free (contents);
+
+ g_object_unref (editor);
+}
+
+static gboolean
+mail_signature_editor_delete_event_cb (EMailSignatureEditor *editor,
+ GdkEvent *event)
+{
+ GtkActionGroup *action_group;
+ GtkAction *action;
+
+ action_group = editor->priv->action_group;
+ action = gtk_action_group_get_action (action_group, "close");
+ gtk_action_activate (action);
+
+ return TRUE;
+}
+
+static void
+action_close_cb (GtkAction *action,
+ EMailSignatureEditor *editor)
+{
+ gboolean something_changed = FALSE;
+ const gchar *original_name;
+ const gchar *signature_name;
+
+ original_name = editor->priv->original_name;
+ signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry));
+
+ something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor));
+ something_changed |= (strcmp (signature_name, original_name) != 0);
+
+ if (something_changed) {
+ gint response;
+
+ response = e_alert_run_dialog_for_args (
+ GTK_WINDOW (editor),
+ "widgets:ask-signature-changed", NULL);
+ if (response == GTK_RESPONSE_YES) {
+ GtkActionGroup *action_group;
+
+ action_group = editor->priv->action_group;
+ action = gtk_action_group_get_action (
+ action_group, "save-and-close");
+ gtk_action_activate (action);
+ return;
+ } else if (response == GTK_RESPONSE_CANCEL)
+ return;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static void
+action_save_and_close_cb (GtkAction *action,
+ EMailSignatureEditor *editor)
+{
+ GtkEntry *entry;
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ ESource *source;
+ gchar *display_name;
+ GError *error = NULL;
+
+ entry = GTK_ENTRY (editor->priv->entry);
+ source = e_mail_signature_editor_get_source (editor);
+
+ display_name = g_strstrip (g_strdup (gtk_entry_get_text (entry)));
+
+ /* Make sure the signature name is not blank. */
+ if (*display_name == '\0') {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "widgets:blank-signature", NULL);
+ gtk_widget_grab_focus (GTK_WIDGET (entry));
+ g_free (display_name);
+ return;
+ }
+
+ e_source_set_display_name (source, display_name);
+
+ g_free (display_name);
+
+ /* Cancel any ongoing load or save operations. */
+ if (editor->priv->cancellable != NULL) {
+ g_cancellable_cancel (editor->priv->cancellable);
+ g_object_unref (editor->priv->cancellable);
+ }
+
+ editor->priv->cancellable = g_cancellable_new ();
+
+ closure = e_async_closure_new ();
+
+ e_mail_signature_editor_commit (
+ editor, editor->priv->cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ e_mail_signature_editor_commit_finish (editor, result, &error);
+
+ e_async_closure_free (closure);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (error);
+
+ } else if (error != NULL) {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "widgets:no-save-signature",
+ error->message, NULL);
+ g_error_free (error);
+
+ /* Only destroy the editor if the save was successful. */
+ } else {
+ gtk_widget_destroy (GTK_WIDGET (editor));
+ }
+}
+
+static GtkActionEntry entries[] = {
+
+ { "close",
+ GTK_STOCK_CLOSE,
+ N_("_Close"),
+ "<Control>w",
+ NULL,
+ G_CALLBACK (action_close_cb) },
+
+ { "save-and-close",
+ GTK_STOCK_SAVE,
+ N_("_Save and Close"),
+ "<Control>Return",
+ NULL,
+ G_CALLBACK (action_save_and_close_cb) },
+
+ { "file-menu",
+ NULL,
+ N_("_File"),
+ NULL,
+ NULL,
+ NULL }
+};
+
+static void
+mail_signature_editor_set_registry (EMailSignatureEditor *editor,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (editor->priv->registry == NULL);
+
+ editor->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_signature_editor_set_source (EMailSignatureEditor *editor,
+ ESource *source)
+{
+ GDBusObject *dbus_object = NULL;
+ const gchar *extension_name;
+ GError *error = NULL;
+
+ g_return_if_fail (source == NULL || E_IS_SOURCE (source));
+ g_return_if_fail (editor->priv->source == NULL);
+
+ if (source != NULL)
+ dbus_object = e_source_ref_dbus_object (source);
+
+ /* Clone the source so we can make changes to it freely. */
+ editor->priv->source = e_source_new (dbus_object, NULL, &error);
+
+ if (dbus_object != NULL)
+ g_object_unref (dbus_object);
+
+ /* This should rarely fail. If the file was loaded successfully
+ * once then it should load successfully here as well, unless an
+ * I/O error occurs. */
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ /* Make sure the source has a mail signature extension. */
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ e_source_get_extension (editor->priv->source, extension_name);
+}
+
+static void
+mail_signature_editor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_signature_editor_set_registry (
+ E_MAIL_SIGNATURE_EDITOR (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SOURCE:
+ mail_signature_editor_set_source (
+ E_MAIL_SIGNATURE_EDITOR (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_editor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_FOCUS_TRACKER:
+ g_value_set_object (
+ value,
+ e_mail_signature_editor_get_focus_tracker (
+ E_MAIL_SIGNATURE_EDITOR (object)));
+ return;
+
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_editor_get_registry (
+ E_MAIL_SIGNATURE_EDITOR (object)));
+ return;
+
+ case PROP_SOURCE:
+ g_value_set_object (
+ value,
+ e_mail_signature_editor_get_source (
+ E_MAIL_SIGNATURE_EDITOR (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_editor_dispose (GObject *object)
+{
+ EMailSignatureEditorPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+ if (priv->action_group != NULL) {
+ g_object_unref (priv->action_group);
+ priv->action_group = NULL;
+ }
+
+ if (priv->focus_tracker != NULL) {
+ g_object_unref (priv->focus_tracker);
+ priv->focus_tracker = NULL;
+ }
+
+ if (priv->cancellable != NULL) {
+ g_cancellable_cancel (priv->cancellable);
+ g_object_unref (priv->cancellable);
+ priv->cancellable = NULL;
+ }
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->source != NULL) {
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_editor_finalize (GObject *object)
+{
+ EMailSignatureEditorPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+ g_free (priv->original_name);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
+ finalize (object);
+}
+
+static void
+mail_signature_editor_constructed (GObject *object)
+{
+ EMailSignatureEditor *editor;
+ GtkActionGroup *action_group;
+ EFocusTracker *focus_tracker;
+ GtkhtmlEditor *gtkhtml_editor;
+ GtkUIManager *ui_manager;
+ GDBusObject *dbus_object;
+ ESource *source;
+ GtkAction *action;
+ GtkWidget *container;
+ GtkWidget *widget;
+ const gchar *display_name;
+ GError *error = NULL;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
+ constructed (object);
+
+ editor = E_MAIL_SIGNATURE_EDITOR (object);
+
+ gtkhtml_editor = GTKHTML_EDITOR (editor);
+ ui_manager = gtkhtml_editor_get_ui_manager (gtkhtml_editor);
+
+ /* Because we are loading from a hard-coded string, there is
+ * no chance of I/O errors. Failure here implies a malformed
+ * UI definition. Full stop. */
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
+ if (error != NULL)
+ g_error ("%s", error->message);
+
+ action_group = gtk_action_group_new ("signature");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (
+ action_group, entries,
+ G_N_ELEMENTS (entries), editor);
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+ editor->priv->action_group = g_object_ref (action_group);
+
+ /* Hide page properties because it is not inherited in the mail. */
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "properties-page");
+ gtk_action_set_visible (action, FALSE);
+
+ action = gtkhtml_editor_get_action (
+ gtkhtml_editor, "context-properties-page");
+ gtk_action_set_visible (action, FALSE);
+
+ gtk_ui_manager_ensure_update (ui_manager);
+
+ gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature"));
+
+ /* Construct the signature name entry. */
+
+ container = gtkhtml_editor->vbox;
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ /* Position 2 should be between the main and style toolbars. */
+ gtk_box_reorder_child (GTK_BOX (container), widget, 2);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_entry_new ();
+ gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ editor->priv->entry = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new_with_mnemonic (_("_Signature Name:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry);
+ gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_signal_connect (
+ editor, "delete-event",
+ G_CALLBACK (mail_signature_editor_delete_event_cb), NULL);
+
+ /* Construct the alert bar for errors. */
+
+ container = gtkhtml_editor->vbox;
+
+ widget = e_alert_bar_new ();
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ /* Position 5 should be between the style toolbar and editing area. */
+ gtk_box_reorder_child (GTK_BOX (container), widget, 5);
+ editor->priv->alert_bar = widget; /* not referenced */
+ /* EAlertBar controls its own visibility. */
+
+ /* Configure an EFocusTracker to manage selection actions.
+ *
+ * XXX GtkhtmlEditor does not manage its own selection actions,
+ * which is technically a bug but works in our favor here
+ * because it won't cause any conflicts with EFocusTracker. */
+
+ focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor));
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "cut");
+ e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "copy");
+ e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "paste");
+ e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "select-all");
+ e_focus_tracker_set_select_all_action (focus_tracker, action);
+
+ editor->priv->focus_tracker = focus_tracker;
+
+ source = e_mail_signature_editor_get_source (editor);
+
+ display_name = e_source_get_display_name (source);
+ if (display_name == NULL || *display_name == '\0')
+ display_name = _("Unnamed");
+
+ /* Set the entry text before we grab focus. */
+ g_free (editor->priv->original_name);
+ editor->priv->original_name = g_strdup (display_name);
+ gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), display_name);
+
+ /* Set the focus appropriately. If this is a new signature, draw
+ * the user's attention to the signature name entry. Otherwise go
+ * straight to the editing area. */
+ if (source == NULL)
+ gtk_widget_grab_focus (editor->priv->entry);
+ else {
+ GtkHTML *html;
+
+ html = gtkhtml_editor_get_html (gtkhtml_editor);
+ gtk_widget_grab_focus (GTK_WIDGET (html));
+ }
+
+ /* Load file content only for an existing signature.
+ * (A new signature will not yet have a GDBusObject.) */
+ dbus_object = e_source_ref_dbus_object (source);
+ if (dbus_object != NULL) {
+ GCancellable *cancellable;
+
+ cancellable = g_cancellable_new ();
+
+ e_source_mail_signature_load (
+ source,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ mail_signature_editor_loaded_cb,
+ g_object_ref (editor));
+
+ g_warn_if_fail (editor->priv->cancellable == NULL);
+ editor->priv->cancellable = cancellable;
+
+ g_object_unref (dbus_object);
+ }
+}
+
+static void
+mail_signature_editor_cut_clipboard (GtkhtmlEditor *editor)
+{
+ /* Do nothing. EFocusTracker handles this. */
+}
+
+static void
+mail_signature_editor_copy_clipboard (GtkhtmlEditor *editor)
+{
+ /* Do nothing. EFocusTracker handles this. */
+}
+
+static void
+mail_signature_editor_paste_clipboard (GtkhtmlEditor *editor)
+{
+ /* Do nothing. EFocusTracker handles this. */
+}
+
+static void
+mail_signature_editor_select_all (GtkhtmlEditor *editor)
+{
+ /* Do nothing. EFocusTracker handles this. */
+}
+
+static void
+mail_signature_editor_submit_alert (EAlertSink *alert_sink,
+ EAlert *alert)
+{
+ EMailSignatureEditorPrivate *priv;
+ EAlertBar *alert_bar;
+ GtkWidget *dialog;
+ GtkWindow *parent;
+
+ priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (alert_sink);
+
+ switch (e_alert_get_message_type (alert)) {
+ case GTK_MESSAGE_INFO:
+ case GTK_MESSAGE_WARNING:
+ case GTK_MESSAGE_ERROR:
+ alert_bar = E_ALERT_BAR (priv->alert_bar);
+ e_alert_bar_add_alert (alert_bar, alert);
+ break;
+
+ default:
+ parent = GTK_WINDOW (alert_sink);
+ dialog = e_alert_dialog_new (parent, alert);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ break;
+ }
+}
+
+static void
+e_mail_signature_editor_class_init (EMailSignatureEditorClass *class)
+{
+ GObjectClass *object_class;
+ GtkhtmlEditorClass *editor_class;
+
+ g_type_class_add_private (class, sizeof (EMailSignatureEditorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_editor_set_property;
+ object_class->get_property = mail_signature_editor_get_property;
+ object_class->dispose = mail_signature_editor_dispose;
+ object_class->finalize = mail_signature_editor_finalize;
+ object_class->constructed = mail_signature_editor_constructed;
+
+ editor_class = GTKHTML_EDITOR_CLASS (class);
+ editor_class->cut_clipboard = mail_signature_editor_cut_clipboard;
+ editor_class->copy_clipboard = mail_signature_editor_copy_clipboard;
+ editor_class->paste_clipboard = mail_signature_editor_paste_clipboard;
+ editor_class->select_all = mail_signature_editor_select_all;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FOCUS_TRACKER,
+ g_param_spec_object (
+ "focus-tracker",
+ NULL,
+ NULL,
+ E_TYPE_FOCUS_TRACKER,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ "Data source registry",
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ NULL,
+ NULL,
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_signature_editor_alert_sink_init (EAlertSinkInterface *interface)
+{
+ interface->submit_alert = mail_signature_editor_submit_alert;
+}
+
+static void
+e_mail_signature_editor_init (EMailSignatureEditor *editor)
+{
+ editor->priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (editor);
+}
+
+GtkWidget *
+e_mail_signature_editor_new (ESourceRegistry *registry,
+ ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ if (source != NULL)
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_EDITOR,
+ "html", e_web_view_gtkhtml_new (),
+ "registry", registry,
+ "source", source, NULL);
+}
+
+EFocusTracker *
+e_mail_signature_editor_get_focus_tracker (EMailSignatureEditor *editor)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
+
+ return editor->priv->focus_tracker;
+}
+
+ESourceRegistry *
+e_mail_signature_editor_get_registry (EMailSignatureEditor *editor)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
+
+ return editor->priv->registry;
+}
+
+ESource *
+e_mail_signature_editor_get_source (EMailSignatureEditor *editor)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
+
+ return editor->priv->source;
+}
+
+/********************** e_mail_signature_editor_commit() *********************/
+
+static void
+mail_signature_editor_replace_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ e_source_mail_signature_replace_finish (
+ E_SOURCE (object), result, &error);
+
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+static void
+mail_signature_editor_commit_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ e_source_registry_commit_source_finish (
+ E_SOURCE_REGISTRY (object), result, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* We can call this on our scratch source because only its UID is
+ * really needed, which even a new scratch source already knows. */
+ e_source_mail_signature_replace (
+ async_context->source,
+ async_context->contents,
+ async_context->length,
+ G_PRIORITY_DEFAULT,
+ async_context->cancellable,
+ mail_signature_editor_replace_cb,
+ simple);
+}
+
+void
+e_mail_signature_editor_commit (EMailSignatureEditor *editor,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ ESourceMailSignature *extension;
+ ESourceRegistry *registry;
+ ESource *source;
+ const gchar *extension_name;
+ const gchar *mime_type;
+ gchar *contents;
+ gboolean is_html;
+ gsize length;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor));
+
+ registry = e_mail_signature_editor_get_registry (editor);
+ source = e_mail_signature_editor_get_source (editor);
+ is_html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor));
+
+ if (is_html) {
+ mime_type = "text/html";
+ contents = gtkhtml_editor_get_text_html (
+ GTKHTML_EDITOR (editor), &length);
+ } else {
+ mime_type = "text/plain";
+ contents = gtkhtml_editor_get_text_plain (
+ GTKHTML_EDITOR (editor), &length);
+ }
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ e_source_mail_signature_set_mime_type (extension, mime_type);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->source = g_object_ref (source);
+ async_context->contents = contents; /* takes ownership */
+ async_context->length = length;
+
+ if (G_IS_CANCELLABLE (cancellable))
+ async_context->cancellable = g_object_ref (cancellable);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (editor), callback, user_data,
+ e_mail_signature_editor_commit);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ e_source_registry_commit_source (
+ registry, source,
+ async_context->cancellable,
+ mail_signature_editor_commit_cb,
+ simple);
+}
+
+gboolean
+e_mail_signature_editor_commit_finish (EMailSignatureEditor *editor,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (editor),
+ e_mail_signature_editor_commit), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/widgets/misc/e-mail-signature-editor.h b/widgets/misc/e-mail-signature-editor.h
new file mode 100644
index 0000000..5527100
--- /dev/null
+++ b/widgets/misc/e-mail-signature-editor.h
@@ -0,0 +1,82 @@
+/*
+ * e-mail-signature-editor.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_EDITOR_H
+#define E_MAIL_SIGNATURE_EDITOR_H
+
+#include <gtkhtml-editor.h>
+#include <misc/e-focus-tracker.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_EDITOR \
+ (e_mail_signature_editor_get_type ())
+#define E_MAIL_SIGNATURE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_EDITOR, EMailSignatureEditor))
+#define E_MAIL_SIGNATURE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_EDITOR, EMailSignatureEditorClass))
+#define E_IS_MAIL_SIGNATURE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_EDITOR))
+#define E_IS_MAIL_SIGNATURE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_EDITOR))
+#define E_MAIL_SIGNATURE_EDITOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_EDITOR, EMailSignatureEditorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignatureEditor EMailSignatureEditor;
+typedef struct _EMailSignatureEditorClass EMailSignatureEditorClass;
+typedef struct _EMailSignatureEditorPrivate EMailSignatureEditorPrivate;
+
+struct _EMailSignatureEditor {
+ GtkhtmlEditor parent;
+ EMailSignatureEditorPrivate *priv;
+};
+
+struct _EMailSignatureEditorClass {
+ GtkhtmlEditorClass parent_class;
+};
+
+GType e_mail_signature_editor_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_editor_new (ESourceRegistry *registry,
+ ESource *source);
+EFocusTracker * e_mail_signature_editor_get_focus_tracker
+ (EMailSignatureEditor *editor);
+ESourceRegistry *
+ e_mail_signature_editor_get_registry
+ (EMailSignatureEditor *editor);
+ESource * e_mail_signature_editor_get_source
+ (EMailSignatureEditor *editor);
+void e_mail_signature_editor_commit (EMailSignatureEditor *editor,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_mail_signature_editor_commit_finish
+ (EMailSignatureEditor *editor,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SIGNATURE_EDITOR_H */
diff --git a/widgets/misc/e-mail-signature-manager.c b/widgets/misc/e-mail-signature-manager.c
new file mode 100644
index 0000000..d00787b
--- /dev/null
+++ b/widgets/misc/e-mail-signature-manager.c
@@ -0,0 +1,705 @@
+/*
+ * e-mail-signature-manager.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-manager.h"
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-mail-signature.h>
+
+#include "e-mail-signature-preview.h"
+#include "e-mail-signature-tree-view.h"
+#include "e-mail-signature-script-dialog.h"
+
+#define E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_MANAGER, EMailSignatureManagerPrivate))
+
+#define PREVIEW_HEIGHT 200
+
+struct _EMailSignatureManagerPrivate {
+ ESourceRegistry *registry;
+
+ GtkWidget *tree_view; /* not referenced */
+ GtkWidget *add_button; /* not referenced */
+ GtkWidget *add_script_button; /* not referenced */
+ GtkWidget *edit_button; /* not referenced */
+ GtkWidget *remove_button; /* not referenced */
+ GtkWidget *preview; /* not referenced */
+
+ gboolean prefer_html;
+};
+
+enum {
+ PROP_0,
+ PROP_PREFER_HTML,
+ PROP_REGISTRY
+};
+
+enum {
+ ADD_SIGNATURE,
+ ADD_SIGNATURE_SCRIPT,
+ EDITOR_CREATED,
+ EDIT_SIGNATURE,
+ REMOVE_SIGNATURE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+ EMailSignatureManager,
+ e_mail_signature_manager,
+ GTK_TYPE_PANED)
+
+static void
+mail_signature_manager_emit_editor_created (EMailSignatureManager *manager,
+ GtkWidget *editor)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor));
+
+ g_signal_emit (manager, signals[EDITOR_CREATED], 0, editor);
+}
+
+static gboolean
+mail_signature_manager_key_press_event_cb (EMailSignatureManager *manager,
+ GdkEventKey *event)
+{
+ if (event->keyval == GDK_KEY_Delete) {
+ e_mail_signature_manager_remove_signature (manager);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+mail_signature_manager_run_script_dialog (EMailSignatureManager *manager,
+ ESource *source,
+ const gchar *title)
+{
+ ESourceRegistry *registry;
+ GtkWidget *dialog;
+ gpointer parent;
+
+ registry = e_mail_signature_manager_get_registry (manager);
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+ dialog = e_mail_signature_script_dialog_new (registry, parent, source);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ GError *error = NULL;
+
+ closure = e_async_closure_new ();
+
+ /* FIXME Make this cancellable. */
+ e_mail_signature_script_dialog_commit (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog), NULL,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ e_mail_signature_script_dialog_commit_finish (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog),
+ result, &error);
+
+ e_async_closure_free (closure);
+
+ /* FIXME Make this into an EAlert. */
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+mail_signature_manager_selection_changed_cb (EMailSignatureManager *manager,
+ GtkTreeSelection *selection)
+{
+ EMailSignaturePreview *preview;
+ EMailSignatureTreeView *tree_view;
+ ESource *source;
+ GtkWidget *edit_button;
+ GtkWidget *remove_button;
+ gboolean sensitive;
+ const gchar *uid = NULL;
+
+ edit_button = manager->priv->edit_button;
+ remove_button = manager->priv->remove_button;
+
+ tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
+ source = e_mail_signature_tree_view_ref_selected_source (tree_view);
+
+ if (source != NULL)
+ uid = e_source_get_uid (source);
+
+ preview = E_MAIL_SIGNATURE_PREVIEW (manager->priv->preview);
+ e_mail_signature_preview_set_source_uid (preview, uid);
+
+ sensitive = (source != NULL);
+ gtk_widget_set_sensitive (edit_button, sensitive);
+ gtk_widget_set_sensitive (remove_button, sensitive);
+
+ if (source != NULL)
+ g_object_unref (source);
+}
+
+static void
+mail_signature_manager_set_registry (EMailSignatureManager *manager,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (manager->priv->registry == NULL);
+
+ manager->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_signature_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_PREFER_HTML:
+ e_mail_signature_manager_set_prefer_html (
+ E_MAIL_SIGNATURE_MANAGER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_REGISTRY:
+ mail_signature_manager_set_registry (
+ E_MAIL_SIGNATURE_MANAGER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_PREFER_HTML:
+ g_value_set_boolean (
+ value,
+ e_mail_signature_manager_get_prefer_html (
+ E_MAIL_SIGNATURE_MANAGER (object)));
+ return;
+
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_manager_get_registry (
+ E_MAIL_SIGNATURE_MANAGER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_manager_dispose (GObject *object)
+{
+ EMailSignatureManagerPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_manager_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_manager_constructed (GObject *object)
+{
+ EMailSignatureManager *manager;
+ GtkTreeSelection *selection;
+ ESourceRegistry *registry;
+ GSettings *settings;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GtkWidget *hbox;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_signature_manager_parent_class)->
+ constructed (object);
+
+ manager = E_MAIL_SIGNATURE_MANAGER (object);
+ registry = e_mail_signature_manager_get_registry (manager);
+
+ gtk_orientable_set_orientation (
+ GTK_ORIENTABLE (manager), GTK_ORIENTATION_VERTICAL);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 12, 0, 0);
+ gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = hbox = widget;
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_mail_signature_tree_view_new (registry);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ manager->priv->tree_view = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "key-press-event",
+ G_CALLBACK (mail_signature_manager_key_press_event_cb),
+ manager);
+
+ g_signal_connect_swapped (
+ widget, "row-activated",
+ G_CALLBACK (e_mail_signature_manager_edit_signature),
+ manager);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (mail_signature_manager_selection_changed_cb),
+ manager);
+
+ container = hbox;
+
+ widget = gtk_vbutton_box_new ();
+ gtk_button_box_set_layout (
+ GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing (GTK_BOX (widget), 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_signature_manager_add_signature),
+ manager);
+
+ widget = gtk_button_new_with_mnemonic (_("Add _Script"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON));
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->add_script_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ settings = g_settings_new ("org.gnome.desktop.lockdown");
+
+ g_settings_bind (
+ settings, "disable-command-line",
+ widget, "visible",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ g_object_unref (settings);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_signature_manager_add_signature_script),
+ manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->edit_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_signature_manager_edit_signature),
+ manager);
+
+ widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ manager->priv->remove_button = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (e_mail_signature_manager_remove_signature),
+ manager);
+
+ container = GTK_WIDGET (manager);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_mail_signature_preview_new (registry);
+ gtk_widget_set_size_request (widget, -1, PREVIEW_HEIGHT);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ manager->priv->preview = widget; /* not referenced */
+ gtk_widget_show (widget);
+}
+
+static void
+mail_signature_manager_add_signature (EMailSignatureManager *manager)
+{
+ ESourceRegistry *registry;
+ GtkWidget *editor;
+
+ registry = e_mail_signature_manager_get_registry (manager);
+
+ editor = e_mail_signature_editor_new (registry, NULL);
+ gtkhtml_editor_set_html_mode (
+ GTKHTML_EDITOR (editor), manager->priv->prefer_html);
+ mail_signature_manager_emit_editor_created (manager, editor);
+
+ gtk_widget_grab_focus (manager->priv->tree_view);
+}
+
+static void
+mail_signature_manager_add_signature_script (EMailSignatureManager *manager)
+{
+ const gchar *title;
+
+ title = _("Add Signature Script");
+ mail_signature_manager_run_script_dialog (manager, NULL, title);
+
+ gtk_widget_grab_focus (manager->priv->tree_view);
+}
+
+static void
+mail_signature_manager_editor_created (EMailSignatureManager *manager,
+ EMailSignatureEditor *editor)
+{
+ GtkWindowPosition position;
+ gpointer parent;
+
+ position = GTK_WIN_POS_CENTER_ON_PARENT;
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+ parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+ gtk_window_set_transient_for (GTK_WINDOW (editor), parent);
+ gtk_window_set_position (GTK_WINDOW (editor), position);
+ gtk_widget_show (GTK_WIDGET (editor));
+}
+
+static void
+mail_signature_manager_edit_signature (EMailSignatureManager *manager)
+{
+ EMailSignatureTreeView *tree_view;
+ ESourceMailSignature *extension;
+ ESourceRegistry *registry;
+ GtkWidget *editor;
+ ESource *source;
+ GFileInfo *file_info;
+ GFile *file;
+ const gchar *attribute;
+ const gchar *extension_name;
+ const gchar *title;
+ GError *error = NULL;
+
+ registry = e_mail_signature_manager_get_registry (manager);
+ tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
+ source = e_mail_signature_tree_view_ref_selected_source (tree_view);
+ g_return_if_fail (source != NULL);
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ file = e_source_mail_signature_get_file (extension);
+
+ attribute = G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE;
+
+ /* XXX This blocks but it should just be a local file. */
+ file_info = g_file_query_info (
+ file, attribute, G_FILE_QUERY_INFO_NONE, NULL, &error);
+
+ /* FIXME Make this into an EAlert. */
+ if (error != NULL) {
+ g_warn_if_fail (file_info == NULL);
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_object_unref (source);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_file_info_get_attribute_boolean (file_info, attribute))
+ goto script;
+
+ editor = e_mail_signature_editor_new (registry, source);
+ mail_signature_manager_emit_editor_created (manager, editor);
+
+ goto exit;
+
+script:
+ title = _("Edit Signature Script");
+ mail_signature_manager_run_script_dialog (manager, source, title);
+
+exit:
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+ g_object_unref (file_info);
+ g_object_unref (source);
+}
+
+static void
+mail_signature_manager_remove_signature (EMailSignatureManager *manager)
+{
+ EMailSignatureTreeView *tree_view;
+ ESourceMailSignature *extension;
+ ESource *source;
+ GFile *file;
+ const gchar *extension_name;
+ GError *error = NULL;
+
+ tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
+ source = e_mail_signature_tree_view_ref_selected_source (tree_view);
+
+ if (source == NULL)
+ return;
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+
+ file = e_source_mail_signature_get_file (extension);
+
+ /* XXX This blocks but it should just be a local file. */
+ if (!g_file_delete (file, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ }
+
+ /* Remove the mail signature data source asynchronously.
+ * XXX No callback function because there's not much we can do
+ * if this fails. We should probably implement EAlertSink. */
+ e_source_remove (source, NULL, NULL, NULL);
+
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+ g_object_unref (source);
+}
+
+static void
+e_mail_signature_manager_class_init (EMailSignatureManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (
+ class, sizeof (EMailSignatureManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_manager_set_property;
+ object_class->get_property = mail_signature_manager_get_property;
+ object_class->dispose = mail_signature_manager_dispose;
+ object_class->constructed = mail_signature_manager_constructed;
+
+ class->add_signature = mail_signature_manager_add_signature;
+ class->add_signature_script =
+ mail_signature_manager_add_signature_script;
+ class->editor_created = mail_signature_manager_editor_created;
+ class->edit_signature = mail_signature_manager_edit_signature;
+ class->remove_signature = mail_signature_manager_remove_signature;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PREFER_HTML,
+ g_param_spec_boolean (
+ "prefer-html",
+ "Prefer HTML",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[ADD_SIGNATURE] = g_signal_new (
+ "add-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSignatureManagerClass, add_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[ADD_SIGNATURE_SCRIPT] = g_signal_new (
+ "add-signature-script",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (
+ EMailSignatureManagerClass, add_signature_script),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[EDITOR_CREATED] = g_signal_new (
+ "editor-created",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailSignatureManagerClass, editor_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_MAIL_SIGNATURE_EDITOR);
+
+ signals[EDIT_SIGNATURE] = g_signal_new (
+ "edit-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSignatureManagerClass, edit_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[REMOVE_SIGNATURE] = g_signal_new (
+ "remove-signature",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSignatureManagerClass, remove_signature),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_signature_manager_init (EMailSignatureManager *manager)
+{
+ manager->priv = E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE (manager);
+}
+
+GtkWidget *
+e_mail_signature_manager_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_MANAGER,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_signature_manager_add_signature (EMailSignatureManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_SIGNATURE], 0);
+}
+
+void
+e_mail_signature_manager_add_signature_script (EMailSignatureManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[ADD_SIGNATURE_SCRIPT], 0);
+}
+
+void
+e_mail_signature_manager_edit_signature (EMailSignatureManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[EDIT_SIGNATURE], 0);
+}
+
+void
+e_mail_signature_manager_remove_signature (EMailSignatureManager *manager)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
+
+ g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0);
+}
+
+gboolean
+e_mail_signature_manager_get_prefer_html (EMailSignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager), FALSE);
+
+ return manager->priv->prefer_html;
+}
+
+void
+e_mail_signature_manager_set_prefer_html (EMailSignatureManager *manager,
+ gboolean prefer_html)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
+
+ manager->priv->prefer_html = prefer_html;
+
+ g_object_notify (G_OBJECT (manager), "prefer-html");
+}
+
+ESourceRegistry *
+e_mail_signature_manager_get_registry (EMailSignatureManager *manager)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager), NULL);
+
+ return manager->priv->registry;
+}
diff --git a/widgets/misc/e-mail-signature-manager.h b/widgets/misc/e-mail-signature-manager.h
new file mode 100644
index 0000000..a627bd5
--- /dev/null
+++ b/widgets/misc/e-mail-signature-manager.h
@@ -0,0 +1,88 @@
+/*
+ * e-mail-signature-manager.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_MANAGER_H
+#define E_MAIL_SIGNATURE_MANAGER_H
+
+#include <gtk/gtk.h>
+#include <misc/e-mail-signature-editor.h>
+#include <misc/e-mail-signature-tree-view.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_MANAGER \
+ (e_mail_signature_manager_get_type ())
+#define E_MAIL_SIGNATURE_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_MANAGER, EMailSignatureManager))
+#define E_MAIL_SIGNATURE_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_MANAGER, EMailSignatureManagerClass))
+#define E_IS_MAIL_SIGNATURE_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_MANAGER))
+#define E_IS_MAIL_SIGNATURE_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_MANAGER))
+#define E_MAIL_SIGNATURE_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_MANAGER, EMailSignatureManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignatureManager EMailSignatureManager;
+typedef struct _EMailSignatureManagerClass EMailSignatureManagerClass;
+typedef struct _EMailSignatureManagerPrivate EMailSignatureManagerPrivate;
+
+struct _EMailSignatureManager {
+ GtkPaned parent;
+ EMailSignatureManagerPrivate *priv;
+};
+
+struct _EMailSignatureManagerClass {
+ GtkPanedClass parent_class;
+
+ void (*add_signature) (EMailSignatureManager *manager);
+ void (*add_signature_script) (EMailSignatureManager *manager);
+ void (*editor_created) (EMailSignatureManager *manager,
+ EMailSignatureEditor *editor);
+ void (*edit_signature) (EMailSignatureManager *manager);
+ void (*remove_signature) (EMailSignatureManager *manager);
+};
+
+GType e_mail_signature_manager_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_manager_new
+ (ESourceRegistry *registry);
+void e_mail_signature_manager_add_signature
+ (EMailSignatureManager *manager);
+void e_mail_signature_manager_add_signature_script
+ (EMailSignatureManager *manager);
+void e_mail_signature_manager_edit_signature
+ (EMailSignatureManager *manager);
+void e_mail_signature_manager_remove_signature
+ (EMailSignatureManager *manager);
+gboolean e_mail_signature_manager_get_prefer_html
+ (EMailSignatureManager *manager);
+void e_mail_signature_manager_set_prefer_html
+ (EMailSignatureManager *manager,
+ gboolean prefer_html);
+ESourceRegistry *
+ e_mail_signature_manager_get_registry
+ (EMailSignatureManager *manager);
+
+#endif /* E_MAIL_SIGNATURE_MANAGER_H */
diff --git a/widgets/misc/e-mail-signature-preview.c b/widgets/misc/e-mail-signature-preview.c
new file mode 100644
index 0000000..02d9328
--- /dev/null
+++ b/widgets/misc/e-mail-signature-preview.c
@@ -0,0 +1,360 @@
+/*
+ * e-mail-signature-preview.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-preview.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib/gstdio.h>
+
+#include <libedataserver/e-source-mail-signature.h>
+
+#include <libevolution-utils/e-alert-sink.h>
+
+#define E_MAIL_SIGNATURE_PREVIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_PREVIEW, EMailSignaturePreviewPrivate))
+
+#define SOURCE_IS_MAIL_SIGNATURE(source) \
+ (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_SIGNATURE))
+
+struct _EMailSignaturePreviewPrivate {
+ ESourceRegistry *registry;
+ GCancellable *cancellable;
+ gchar *source_uid;
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY,
+ PROP_SOURCE_UID
+};
+
+enum {
+ REFRESH,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+ EMailSignaturePreview,
+ e_mail_signature_preview,
+ E_TYPE_WEB_VIEW)
+
+static void
+mail_signature_preview_load_cb (ESource *source,
+ GAsyncResult *result,
+ EMailSignaturePreview *preview)
+{
+ ESourceMailSignature *extension;
+ const gchar *extension_name;
+ const gchar *mime_type;
+ gchar *contents = NULL;
+ GError *error = NULL;
+
+ e_source_mail_signature_load_finish (
+ source, result, &contents, NULL, &error);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warn_if_fail (contents == NULL);
+ g_object_unref (preview);
+ g_error_free (error);
+ return;
+
+ } else if (error != NULL) {
+ g_warn_if_fail (contents == NULL);
+ e_alert_submit (
+ E_ALERT_SINK (preview),
+ "widgets:no-load-signature",
+ error->message, NULL);
+ g_object_unref (preview);
+ g_error_free (error);
+ return;
+ }
+
+ g_return_if_fail (contents != NULL);
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ mime_type = e_source_mail_signature_get_mime_type (extension);
+
+ if (g_strcmp0 (mime_type, "text/html") == 0)
+ e_web_view_load_string (E_WEB_VIEW (preview), contents);
+ else {
+ gchar *string;
+
+ string = g_markup_printf_escaped ("<pre>%s</pre>", contents);
+ e_web_view_load_string (E_WEB_VIEW (preview), string);
+ g_free (string);
+ }
+
+ g_free (contents);
+
+ g_object_unref (preview);
+}
+
+static void
+mail_signature_preview_set_registry (EMailSignaturePreview *preview,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (preview->priv->registry == NULL);
+
+ preview->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_signature_preview_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_signature_preview_set_registry (
+ E_MAIL_SIGNATURE_PREVIEW (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SOURCE_UID:
+ e_mail_signature_preview_set_source_uid (
+ E_MAIL_SIGNATURE_PREVIEW (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_preview_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_preview_get_registry (
+ E_MAIL_SIGNATURE_PREVIEW (object)));
+ return;
+
+ case PROP_SOURCE_UID:
+ g_value_set_string (
+ value,
+ e_mail_signature_preview_get_source_uid (
+ E_MAIL_SIGNATURE_PREVIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_preview_dispose (GObject *object)
+{
+ EMailSignaturePreviewPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_PREVIEW_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->cancellable != NULL) {
+ g_cancellable_cancel (priv->cancellable);
+ g_object_unref (priv->cancellable);
+ priv->cancellable = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_preview_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_preview_finalize (GObject *object)
+{
+ EMailSignaturePreviewPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_PREVIEW_GET_PRIVATE (object);
+
+ g_free (priv->source_uid);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_mail_signature_preview_parent_class)->
+ finalize (object);
+}
+
+static void
+mail_signature_preview_refresh (EMailSignaturePreview *preview)
+{
+ ESourceRegistry *registry;
+ ESource *source;
+ const gchar *extension_name;
+ const gchar *source_uid;
+
+ /* Cancel any unfinished refreshes. */
+ if (preview->priv->cancellable != NULL) {
+ g_cancellable_cancel (preview->priv->cancellable);
+ g_object_unref (preview->priv->cancellable);
+ preview->priv->cancellable = NULL;
+ }
+
+ source_uid = e_mail_signature_preview_get_source_uid (preview);
+
+ if (source_uid == NULL)
+ goto fail;
+
+ registry = e_mail_signature_preview_get_registry (preview);
+ source = e_source_registry_ref_source (registry, source_uid);
+
+ if (source == NULL)
+ goto fail;
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ if (!e_source_has_extension (source, extension_name)) {
+ g_object_unref (source);
+ goto fail;
+ }
+
+ preview->priv->cancellable = g_cancellable_new ();
+
+ e_source_mail_signature_load (
+ source, G_PRIORITY_DEFAULT,
+ preview->priv->cancellable, (GAsyncReadyCallback)
+ mail_signature_preview_load_cb, g_object_ref (preview));
+
+ g_object_unref (source);
+
+ return;
+
+fail:
+ e_web_view_clear (E_WEB_VIEW (preview));
+}
+
+static void
+e_mail_signature_preview_class_init (EMailSignaturePreviewClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EMailSignaturePreviewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_preview_set_property;
+ object_class->get_property = mail_signature_preview_get_property;
+ object_class->dispose = mail_signature_preview_dispose;
+ object_class->finalize = mail_signature_preview_finalize;
+
+ class->refresh = mail_signature_preview_refresh;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE_UID,
+ g_param_spec_string (
+ "source-uid",
+ "Source UID",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[REFRESH] = g_signal_new (
+ "refresh",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSignaturePreviewClass, refresh),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_signature_preview_init (EMailSignaturePreview *preview)
+{
+ preview->priv = E_MAIL_SIGNATURE_PREVIEW_GET_PRIVATE (preview);
+}
+
+GtkWidget *
+e_mail_signature_preview_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_PREVIEW,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_signature_preview_refresh (EMailSignaturePreview *preview)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_PREVIEW (preview));
+
+ g_signal_emit (preview, signals[REFRESH], 0);
+}
+
+ESourceRegistry *
+e_mail_signature_preview_get_registry (EMailSignaturePreview *preview)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_PREVIEW (preview), NULL);
+
+ return preview->priv->registry;
+}
+
+const gchar *
+e_mail_signature_preview_get_source_uid (EMailSignaturePreview *preview)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_PREVIEW (preview), NULL);
+
+ return preview->priv->source_uid;
+}
+
+void
+e_mail_signature_preview_set_source_uid (EMailSignaturePreview *preview,
+ const gchar *source_uid)
+{
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_PREVIEW (preview));
+
+ /* Avoid repeatedly loading the same signature file. */
+ if (g_strcmp0 (source_uid, preview->priv->source_uid) == 0)
+ return;
+
+ g_free (preview->priv->source_uid);
+ preview->priv->source_uid = g_strdup (source_uid);
+
+ g_object_notify (G_OBJECT (preview), "source-uid");
+
+ e_mail_signature_preview_refresh (preview);
+}
diff --git a/widgets/misc/e-mail-signature-preview.h b/widgets/misc/e-mail-signature-preview.h
new file mode 100644
index 0000000..205ff62
--- /dev/null
+++ b/widgets/misc/e-mail-signature-preview.h
@@ -0,0 +1,79 @@
+/*
+ * e-mail-signature-preview.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_PREVIEW_H
+#define E_MAIL_SIGNATURE_PREVIEW_H
+
+#include <misc/e-web-view.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_PREVIEW \
+ (e_mail_signature_preview_get_type ())
+#define E_MAIL_SIGNATURE_PREVIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_PREVIEW, EMailSignaturePreview))
+#define E_MAIL_SIGNATURE_PREVIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_PREVIEW, EMailSignaturePreviewClass))
+#define E_IS_MAIL_SIGNATURE_PREVIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_PREVIEW))
+#define E_IS_MAIL_SIGNATURE_PREVIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_PREVIEW))
+#define E_MAIL_SIGNATURE_PREVIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_PREVIEW, EMailSignaturePreview))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignaturePreview EMailSignaturePreview;
+typedef struct _EMailSignaturePreviewClass EMailSignaturePreviewClass;
+typedef struct _EMailSignaturePreviewPrivate EMailSignaturePreviewPrivate;
+
+struct _EMailSignaturePreview {
+ EWebView parent;
+ EMailSignaturePreviewPrivate *priv;
+};
+
+struct _EMailSignaturePreviewClass {
+ EWebViewClass parent_class;
+
+ /* Signals */
+ void (*refresh) (EMailSignaturePreview *preview);
+};
+
+GType e_mail_signature_preview_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_preview_new
+ (ESourceRegistry *registry);
+void e_mail_signature_preview_refresh
+ (EMailSignaturePreview *preview);
+ESourceRegistry *
+ e_mail_signature_preview_get_registry
+ (EMailSignaturePreview *preview);
+const gchar * e_mail_signature_preview_get_source_uid
+ (EMailSignaturePreview *preview);
+void e_mail_signature_preview_set_source_uid
+ (EMailSignaturePreview *preview,
+ const gchar *source_uid);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SIGNATURE_PREVIEW_H */
diff --git a/widgets/misc/e-mail-signature-script-dialog.c b/widgets/misc/e-mail-signature-script-dialog.c
new file mode 100644
index 0000000..757f6a4
--- /dev/null
+++ b/widgets/misc/e-mail-signature-script-dialog.c
@@ -0,0 +1,733 @@
+/*
+ * e-mail-signature-script-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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-script-dialog.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-mail-signature.h>
+
+#define E_MAIL_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG, \
+ EMailSignatureScriptDialogPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailSignatureScriptDialogPrivate {
+ ESourceRegistry *registry;
+ ESource *source;
+
+ GtkWidget *entry; /* not referenced */
+ GtkWidget *file_chooser; /* not referenced */
+ GtkWidget *alert; /* not referenced */
+
+ gchar *symlink_target;
+};
+
+struct _AsyncContext {
+ ESource *source;
+ GCancellable *cancellable;
+ gchar *symlink_target;
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY,
+ PROP_SOURCE,
+ PROP_SYMLINK_TARGET
+};
+
+G_DEFINE_TYPE (
+ EMailSignatureScriptDialog,
+ e_mail_signature_script_dialog,
+ GTK_TYPE_DIALOG)
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+ if (async_context->source != NULL)
+ g_object_unref (async_context->source);
+
+ if (async_context->cancellable != NULL)
+ g_object_unref (async_context->cancellable);
+
+ g_free (async_context->symlink_target);
+
+ g_slice_free (AsyncContext, async_context);
+}
+
+static gboolean
+mail_signature_script_dialog_filter_cb (const GtkFileFilterInfo *filter_info)
+{
+ return g_file_test (filter_info->filename, G_FILE_TEST_IS_EXECUTABLE);
+}
+
+static void
+mail_signature_script_dialog_update_status (EMailSignatureScriptDialog *dialog)
+{
+ ESource *source;
+ const gchar *display_name;
+ const gchar *symlink_target;
+ gboolean show_alert;
+ gboolean sensitive;
+
+ source = e_mail_signature_script_dialog_get_source (dialog);
+
+ display_name = e_source_get_display_name (source);
+ sensitive = (display_name != NULL && *display_name != '\0');
+
+ symlink_target =
+ e_mail_signature_script_dialog_get_symlink_target (dialog);
+
+ if (symlink_target != NULL) {
+ gboolean executable;
+
+ executable = g_file_test (
+ symlink_target, G_FILE_TEST_IS_EXECUTABLE);
+
+ show_alert = !executable;
+ sensitive &= executable;
+ } else {
+ sensitive = FALSE;
+ show_alert = FALSE;
+ }
+
+ if (show_alert)
+ gtk_widget_show (dialog->priv->alert);
+ else
+ gtk_widget_hide (dialog->priv->alert);
+
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
+}
+
+static void
+mail_signature_script_dialog_file_set_cb (GtkFileChooserButton *button,
+ EMailSignatureScriptDialog *dialog)
+{
+ ESource *source;
+ ESourceMailSignature *extension;
+ GtkFileChooser *file_chooser;
+ const gchar *extension_name;
+ gchar *filename;
+
+ file_chooser = GTK_FILE_CHOOSER (button);
+ filename = gtk_file_chooser_get_filename (file_chooser);
+
+ g_free (dialog->priv->symlink_target);
+ dialog->priv->symlink_target = filename; /* takes ownership */
+
+ /* Invalidate the saved MIME type. */
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ source = e_mail_signature_script_dialog_get_source (dialog);
+ extension = e_source_get_extension (source, extension_name);
+ e_source_mail_signature_set_mime_type (extension, NULL);
+
+ g_object_notify (G_OBJECT (dialog), "symlink-target");
+
+ mail_signature_script_dialog_update_status (dialog);
+}
+
+static void
+mail_signature_script_dialog_query_cb (GFile *file,
+ GAsyncResult *result,
+ EMailSignatureScriptDialog *dialog)
+{
+ GFileInfo *file_info;
+ const gchar *symlink_target;
+ GError *error = NULL;
+
+ file_info = g_file_query_info_finish (file, result, &error);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warn_if_fail (file_info == NULL);
+ g_object_unref (dialog);
+ g_error_free (error);
+ return;
+
+ } else if (error != NULL) {
+ g_warn_if_fail (file_info == NULL);
+ g_warning ("%s", error->message);
+ g_object_unref (dialog);
+ g_error_free (error);
+ return;
+ }
+
+ g_return_if_fail (G_IS_FILE_INFO (file_info));
+
+ symlink_target = g_file_info_get_symlink_target (file_info);
+
+ e_mail_signature_script_dialog_set_symlink_target (
+ dialog, symlink_target);
+
+ g_object_unref (file_info);
+ g_object_unref (dialog);
+}
+
+static void
+mail_signature_script_dialog_set_registry (EMailSignatureScriptDialog *dialog,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (dialog->priv->registry == NULL);
+
+ dialog->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_signature_script_dialog_set_source (EMailSignatureScriptDialog *dialog,
+ ESource *source)
+{
+ GDBusObject *dbus_object = NULL;
+ const gchar *extension_name;
+ GError *error = NULL;
+
+ g_return_if_fail (source == NULL || E_IS_SOURCE (source));
+ g_return_if_fail (dialog->priv->source == NULL);
+
+ if (source != NULL)
+ dbus_object = e_source_ref_dbus_object (source);
+
+ /* Clone the source so we can make changes to it freely. */
+ dialog->priv->source = e_source_new (dbus_object, NULL, &error);
+
+ /* This should rarely fail. If the file was loaded successfully
+ * once then it should load successfully here as well, unless an
+ * I/O error occurs. */
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ /* Make sure the source has a mail signature extension. */
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ e_source_get_extension (dialog->priv->source, extension_name);
+
+ /* If we're editing an existing signature, query the symbolic
+ * link target of the signature file so we can initialize the
+ * file chooser button. Note: The asynchronous callback will
+ * run after the dialog initialization is complete. */
+ if (dbus_object != NULL) {
+ ESourceMailSignature *extension;
+ const gchar *extension_name;
+ GFile *file;
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ extension = e_source_get_extension (source, extension_name);
+ file = e_source_mail_signature_get_file (extension);
+
+ g_file_query_info_async (
+ file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+ G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+ NULL, (GAsyncReadyCallback)
+ mail_signature_script_dialog_query_cb,
+ g_object_ref (dialog));
+
+ g_object_unref (dbus_object);
+ }
+}
+
+static void
+mail_signature_script_dialog_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_signature_script_dialog_set_registry (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SOURCE:
+ mail_signature_script_dialog_set_source (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SYMLINK_TARGET:
+ e_mail_signature_script_dialog_set_symlink_target (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_script_dialog_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_script_dialog_get_registry (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object)));
+ return;
+
+ case PROP_SOURCE:
+ g_value_set_object (
+ value,
+ e_mail_signature_script_dialog_get_source (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object)));
+ return;
+
+ case PROP_SYMLINK_TARGET:
+ g_value_set_string (
+ value,
+ e_mail_signature_script_dialog_get_symlink_target (
+ E_MAIL_SIGNATURE_SCRIPT_DIALOG (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_script_dialog_dispose (GObject *object)
+{
+ EMailSignatureScriptDialogPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->source != NULL) {
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_script_dialog_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_script_dialog_finalize (GObject *object)
+{
+ EMailSignatureScriptDialogPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (object);
+
+ g_free (priv->symlink_target);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_mail_signature_script_dialog_parent_class)->
+ finalize (object);
+}
+
+static void
+mail_signature_script_dialog_constructed (GObject *object)
+{
+ EMailSignatureScriptDialog *dialog;
+ GtkFileFilter *filter;
+ GtkWidget *container;
+ GtkWidget *widget;
+ ESource *source;
+ const gchar *display_name;
+ gchar *markup;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_signature_script_dialog_parent_class)->
+ constructed (object);
+
+ dialog = E_MAIL_SIGNATURE_SCRIPT_DIALOG (object);
+
+ source = e_mail_signature_script_dialog_get_source (dialog);
+ display_name = e_source_get_display_name (source);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ gtk_dialog_add_button (
+ GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ gtk_dialog_add_button (
+ GTK_DIALOG (dialog),
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ widget = gtk_table_new (4, 2, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (widget), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (widget), 6);
+ gtk_table_set_row_spacing (GTK_TABLE (widget), 0, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 0, 1, 0, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (_(
+ "The output of this script will be used as your\n"
+ "signature. The name you specify will be used\n"
+ "for display purposes only."));
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_entry_new ();
+ gtk_entry_set_text (GTK_ENTRY (widget), display_name);
+ gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ dialog->priv->entry = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ g_object_bind_property (
+ widget, "text",
+ source, "display-name",
+ G_BINDING_DEFAULT);
+
+ widget = gtk_label_new_with_mnemonic (_("_Name:"));
+ gtk_label_set_mnemonic_widget (
+ GTK_LABEL (widget), dialog->priv->entry);
+ gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_file_chooser_button_new (
+ NULL, GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ dialog->priv->file_chooser = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ /* Restrict file selection to executable files. */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_custom (
+ filter, GTK_FILE_FILTER_FILENAME,
+ (GtkFileFilterFunc) mail_signature_script_dialog_filter_cb,
+ NULL, NULL);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ /* We create symbolic links to script files from the "signatures"
+ * directory, so restrict the selection to local files only. */
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+
+ widget = gtk_label_new_with_mnemonic (_("S_cript:"));
+ gtk_label_set_mnemonic_widget (
+ GTK_LABEL (widget), dialog->priv->file_chooser);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ /* This is just a placeholder. */
+ widget = gtk_label_new (NULL);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_table_attach (
+ GTK_TABLE (container), widget,
+ 1, 2, 3, 4, 0, 0, 0, 0);
+ dialog->priv->alert = widget; /* not referenced */
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ markup = g_markup_printf_escaped (
+ "<small>%s</small>",
+ _("Script file must be executable."));
+ widget = gtk_label_new (markup);
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+ g_free (markup);
+
+ g_signal_connect (
+ dialog->priv->file_chooser, "file-set",
+ G_CALLBACK (mail_signature_script_dialog_file_set_cb), dialog);
+
+ g_signal_connect_swapped (
+ dialog->priv->entry, "changed",
+ G_CALLBACK (mail_signature_script_dialog_update_status), dialog);
+
+ mail_signature_script_dialog_update_status (dialog);
+}
+
+static void
+e_mail_signature_script_dialog_class_init (EMailSignatureScriptDialogClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (
+ class, sizeof (EMailSignatureScriptDialogPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_script_dialog_set_property;
+ object_class->get_property = mail_signature_script_dialog_get_property;
+ object_class->dispose = mail_signature_script_dialog_dispose;
+ object_class->finalize = mail_signature_script_dialog_finalize;
+ object_class->constructed = mail_signature_script_dialog_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ "Data source registry",
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ "Source",
+ NULL,
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SYMLINK_TARGET,
+ g_param_spec_string (
+ "symlink-target",
+ "Symlink Target",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_signature_script_dialog_init (EMailSignatureScriptDialog *dialog)
+{
+ dialog->priv = E_MAIL_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (dialog);
+}
+
+GtkWidget *
+e_mail_signature_script_dialog_new (ESourceRegistry *registry,
+ GtkWindow *parent,
+ ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ if (source != NULL)
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG,
+ "registry", registry,
+ "transient-for", parent,
+ "source", source, NULL);
+}
+
+ESourceRegistry *
+e_mail_signature_script_dialog_get_registry (EMailSignatureScriptDialog *dialog)
+{
+ g_return_val_if_fail (
+ E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+ return dialog->priv->registry;
+}
+
+ESource *
+e_mail_signature_script_dialog_get_source (EMailSignatureScriptDialog *dialog)
+{
+ g_return_val_if_fail (
+ E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+ return dialog->priv->source;
+}
+
+const gchar *
+e_mail_signature_script_dialog_get_symlink_target (EMailSignatureScriptDialog *dialog)
+{
+ g_return_val_if_fail (
+ E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+ return dialog->priv->symlink_target;
+}
+
+void
+e_mail_signature_script_dialog_set_symlink_target (EMailSignatureScriptDialog *dialog,
+ const gchar *symlink_target)
+{
+ GtkFileChooser *file_chooser;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog));
+ g_return_if_fail (symlink_target != NULL);
+
+ g_free (dialog->priv->symlink_target);
+ dialog->priv->symlink_target = g_strdup (symlink_target);
+
+ file_chooser = GTK_FILE_CHOOSER (dialog->priv->file_chooser);
+ gtk_file_chooser_set_filename (file_chooser, symlink_target);
+
+ g_object_notify (G_OBJECT (dialog), "symlink-target");
+
+ mail_signature_script_dialog_update_status (dialog);
+}
+
+/****************** e_mail_signature_script_dialog_commit() ******************/
+
+static void
+mail_signature_script_dialog_symlink_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ e_source_mail_signature_symlink_finish (
+ E_SOURCE (object), result, &error);
+
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+static void
+mail_signature_script_dialog_commit_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ e_source_registry_commit_source_finish (
+ E_SOURCE_REGISTRY (object), result, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* We can call this on our scratch source because only its UID is
+ * really needed, which even a new scratch source already knows. */
+ e_source_mail_signature_symlink (
+ async_context->source,
+ async_context->symlink_target,
+ G_PRIORITY_DEFAULT,
+ async_context->cancellable,
+ mail_signature_script_dialog_symlink_cb,
+ simple);
+}
+
+void
+e_mail_signature_script_dialog_commit (EMailSignatureScriptDialog *dialog,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ ESourceRegistry *registry;
+ ESource *source;
+ const gchar *symlink_target;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog));
+
+ registry = e_mail_signature_script_dialog_get_registry (dialog);
+ source = e_mail_signature_script_dialog_get_source (dialog);
+
+ symlink_target =
+ e_mail_signature_script_dialog_get_symlink_target (dialog);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->source = g_object_ref (source);
+ async_context->symlink_target = g_strdup (symlink_target);
+
+ if (G_IS_CANCELLABLE (cancellable))
+ async_context->cancellable = g_object_ref (cancellable);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (dialog), callback, user_data,
+ e_mail_signature_script_dialog_commit);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ e_source_registry_commit_source (
+ registry, source,
+ async_context->cancellable,
+ mail_signature_script_dialog_commit_cb,
+ simple);
+}
+
+gboolean
+e_mail_signature_script_dialog_commit_finish (EMailSignatureScriptDialog *dialog,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (dialog),
+ e_mail_signature_script_dialog_commit), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/widgets/misc/e-mail-signature-script-dialog.h b/widgets/misc/e-mail-signature-script-dialog.h
new file mode 100644
index 0000000..0b458ab
--- /dev/null
+++ b/widgets/misc/e-mail-signature-script-dialog.h
@@ -0,0 +1,90 @@
+/*
+ * e-mail-signature-script-dialog.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_SCRIPT_DIALOG_H
+#define E_MAIL_SIGNATURE_SCRIPT_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG \
+ (e_mail_signature_script_dialog_get_type ())
+#define E_MAIL_SIGNATURE_SCRIPT_DIALOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG, \
+ EMailSignatureScriptDialog))
+#define E_MAIL_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG, \
+ EMailSignatureScriptDialogClass))
+#define E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG))
+#define E_IS_MAIL_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG))
+#define E_MAIL_SIGNATURE_SCRIPT_DIALOG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_SCRIPT_DIALOG, \
+ EMailSignatureScriptDialogClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignatureScriptDialog EMailSignatureScriptDialog;
+typedef struct _EMailSignatureScriptDialogClass EMailSignatureScriptDialogClass;
+typedef struct _EMailSignatureScriptDialogPrivate EMailSignatureScriptDialogPrivate;
+
+struct _EMailSignatureScriptDialog {
+ GtkDialog parent;
+ EMailSignatureScriptDialogPrivate *priv;
+};
+
+struct _EMailSignatureScriptDialogClass {
+ GtkDialogClass parent_class;
+};
+
+GType e_mail_signature_script_dialog_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_script_dialog_new
+ (ESourceRegistry *registry,
+ GtkWindow *parent,
+ ESource *source);
+ESourceRegistry *
+ e_mail_signature_script_dialog_get_registry
+ (EMailSignatureScriptDialog *dialog);
+ESource * e_mail_signature_script_dialog_get_source
+ (EMailSignatureScriptDialog *dialog);
+const gchar * e_mail_signature_script_dialog_get_symlink_target
+ (EMailSignatureScriptDialog *dialog);
+void e_mail_signature_script_dialog_set_symlink_target
+ (EMailSignatureScriptDialog *dialog,
+ const gchar *symlink_target);
+void e_mail_signature_script_dialog_commit
+ (EMailSignatureScriptDialog *dialog,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_mail_signature_script_dialog_commit_finish
+ (EMailSignatureScriptDialog *dialog,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SIGNATURE_SCRIPT_DIALOG_H */
diff --git a/widgets/misc/e-mail-signature-tree-view.c b/widgets/misc/e-mail-signature-tree-view.c
new file mode 100644
index 0000000..3dd6a85
--- /dev/null
+++ b/widgets/misc/e-mail-signature-tree-view.c
@@ -0,0 +1,397 @@
+/*
+ * e-mail-signature-tree-view.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-signature-tree-view.h"
+
+#include <libedataserver/e-source-mail-signature.h>
+
+#define E_MAIL_SIGNATURE_TREE_VIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_TREE_VIEW, EMailSignatureTreeViewPrivate))
+
+#define SOURCE_IS_MAIL_SIGNATURE(source) \
+ (e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_SIGNATURE))
+
+struct _EMailSignatureTreeViewPrivate {
+ ESourceRegistry *registry;
+ guint refresh_idle_id;
+};
+
+enum {
+ PROP_0,
+ PROP_REGISTRY
+};
+
+enum {
+ COLUMN_DISPLAY_NAME,
+ COLUMN_UID,
+ NUM_COLUMNS
+};
+
+G_DEFINE_TYPE (
+ EMailSignatureTreeView,
+ e_mail_signature_tree_view,
+ GTK_TYPE_TREE_VIEW)
+
+static gboolean
+mail_signature_tree_view_refresh_idle_cb (EMailSignatureTreeView *tree_view)
+{
+ /* The refresh function will clear the idle ID. */
+ e_mail_signature_tree_view_refresh (tree_view);
+
+ return FALSE;
+}
+
+static void
+mail_signature_tree_view_registry_changed (ESourceRegistry *registry,
+ ESource *source,
+ EMailSignatureTreeView *tree_view)
+{
+ /* If the ESource in question has a "Mail Signature" extension,
+ * schedule a refresh of the tree model. Otherwise ignore it.
+ * We use an idle callback to limit how frequently we refresh
+ * the tree model, in case the registry is emitting lots of
+ * signals at once. */
+
+ if (!SOURCE_IS_MAIL_SIGNATURE (source))
+ return;
+
+ if (tree_view->priv->refresh_idle_id > 0)
+ return;
+
+ tree_view->priv->refresh_idle_id = gdk_threads_add_idle (
+ (GSourceFunc) mail_signature_tree_view_refresh_idle_cb,
+ tree_view);
+}
+
+static void
+mail_signature_tree_view_set_registry (EMailSignatureTreeView *tree_view,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (tree_view->priv->registry == NULL);
+
+ tree_view->priv->registry = g_object_ref (registry);
+
+ g_signal_connect (
+ registry, "source-added",
+ G_CALLBACK (mail_signature_tree_view_registry_changed),
+ tree_view);
+
+ g_signal_connect (
+ registry, "source-changed",
+ G_CALLBACK (mail_signature_tree_view_registry_changed),
+ tree_view);
+
+ g_signal_connect (
+ registry, "source-removed",
+ G_CALLBACK (mail_signature_tree_view_registry_changed),
+ tree_view);
+}
+
+static void
+mail_signature_tree_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ mail_signature_tree_view_set_registry (
+ E_MAIL_SIGNATURE_TREE_VIEW (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_tree_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_REGISTRY:
+ g_value_set_object (
+ value,
+ e_mail_signature_tree_view_get_registry (
+ E_MAIL_SIGNATURE_TREE_VIEW (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_signature_tree_view_dispose (GObject *object)
+{
+ EMailSignatureTreeViewPrivate *priv;
+
+ priv = E_MAIL_SIGNATURE_TREE_VIEW_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->registry, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ if (priv->refresh_idle_id > 0) {
+ g_source_remove (priv->refresh_idle_id);
+ priv->refresh_idle_id = 0;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_mail_signature_tree_view_parent_class)->
+ dispose (object);
+}
+
+static void
+mail_signature_tree_view_constructed (GObject *object)
+{
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell_renderer;
+ GtkListStore *list_store;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_signature_tree_view_parent_class)->
+ constructed (object);
+
+ list_store = gtk_list_store_new (
+ NUM_COLUMNS,
+ G_TYPE_STRING, /* COLUMN_DISPLAY_NAME */
+ G_TYPE_STRING); /* COLUMN_UID */
+
+ tree_view = GTK_TREE_VIEW (object);
+ gtk_tree_view_set_headers_visible (tree_view, FALSE);
+ gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store));
+
+ g_object_unref (list_store);
+
+ /* Column: Signature Name */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+
+ cell_renderer = gtk_cell_renderer_text_new ();
+ g_object_set (cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+ gtk_tree_view_column_add_attribute (
+ column, cell_renderer, "text", COLUMN_DISPLAY_NAME);
+
+ gtk_tree_view_append_column (tree_view, column);
+
+ e_mail_signature_tree_view_refresh (
+ E_MAIL_SIGNATURE_TREE_VIEW (object));
+}
+
+static void
+e_mail_signature_tree_view_class_init (EMailSignatureTreeViewClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (
+ class, sizeof (EMailSignatureTreeViewPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_signature_tree_view_set_property;
+ object_class->get_property = mail_signature_tree_view_get_property;
+ object_class->dispose = mail_signature_tree_view_dispose;
+ object_class->constructed = mail_signature_tree_view_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ NULL,
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_signature_tree_view_init (EMailSignatureTreeView *tree_view)
+{
+ tree_view->priv = E_MAIL_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view);
+}
+
+GtkWidget *
+e_mail_signature_tree_view_new (ESourceRegistry *registry)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_SIGNATURE_TREE_VIEW,
+ "registry", registry, NULL);
+}
+
+void
+e_mail_signature_tree_view_refresh (EMailSignatureTreeView *tree_view)
+{
+ ESourceRegistry *registry;
+ GtkTreeModel *tree_model;
+ GtkTreeSelection *selection;
+ ESource *source;
+ GList *list, *link;
+ const gchar *extension_name;
+ gchar *saved_uid = NULL;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_TREE_VIEW (tree_view));
+
+ if (tree_view->priv->refresh_idle_id > 0) {
+ g_source_remove (tree_view->priv->refresh_idle_id);
+ tree_view->priv->refresh_idle_id = 0;
+ }
+
+ registry = e_mail_signature_tree_view_get_registry (tree_view);
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ source = e_mail_signature_tree_view_ref_selected_source (tree_view);
+ if (source != NULL) {
+ saved_uid = e_source_dup_uid (source);
+ g_object_unref (source);
+ }
+
+ gtk_list_store_clear (GTK_LIST_STORE (tree_model));
+
+ extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
+ list = e_source_registry_list_sources (registry, extension_name);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ GtkTreeIter iter;
+ const gchar *display_name;
+ const gchar *uid;
+
+ source = E_SOURCE (link->data);
+ display_name = e_source_get_display_name (source);
+ uid = e_source_get_uid (source);
+
+ gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (tree_model), &iter,
+ COLUMN_DISPLAY_NAME, display_name,
+ COLUMN_UID, uid, -1);
+ }
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+ /* Try and restore the previous selected source. */
+
+ source = NULL;
+
+ if (saved_uid != NULL) {
+ source = e_source_registry_ref_source (registry, saved_uid);
+ g_free (saved_uid);
+ }
+
+ if (source != NULL) {
+ e_mail_signature_tree_view_set_selected_source (
+ tree_view, source);
+ g_object_unref (source);
+ }
+
+ /* Hint to refresh a signature preview. */
+ g_signal_emit_by_name (selection, "changed");
+}
+
+ESourceRegistry *
+e_mail_signature_tree_view_get_registry (EMailSignatureTreeView *tree_view)
+{
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+ return tree_view->priv->registry;
+}
+
+ESource *
+e_mail_signature_tree_view_ref_selected_source (EMailSignatureTreeView *tree_view)
+{
+ ESourceRegistry *registry;
+ GtkTreeSelection *selection;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_MAIL_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+ registry = e_mail_signature_tree_view_get_registry (tree_view);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ if (!gtk_tree_selection_get_selected (selection, &tree_model, &iter))
+ return NULL;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1);
+ source = e_source_registry_ref_source (registry, uid);
+ g_free (uid);
+
+ return source;
+}
+
+void
+e_mail_signature_tree_view_set_selected_source (EMailSignatureTreeView *tree_view,
+ ESource *source)
+{
+ ESourceRegistry *registry;
+ GtkTreeSelection *selection;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ gboolean valid;
+
+ g_return_if_fail (E_IS_MAIL_SIGNATURE_TREE_VIEW (tree_view));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ /* It is a programming error to pass an ESource that has no
+ * "Mail Signature" extension. */
+ g_return_if_fail (SOURCE_IS_MAIL_SIGNATURE (source));
+
+ registry = e_mail_signature_tree_view_get_registry (tree_view);
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+ valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+ while (valid) {
+ ESource *candidate;
+ gchar *uid;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_UID, &uid, -1);
+ candidate = e_source_registry_ref_source (registry, uid);
+ g_free (uid);
+
+ if (candidate != NULL && e_source_equal (source, candidate)) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ g_object_unref (candidate);
+ break;
+ }
+
+ if (candidate != NULL)
+ g_object_unref (candidate);
+
+ valid = gtk_tree_model_iter_next (tree_model, &iter);
+ }
+}
diff --git a/widgets/misc/e-mail-signature-tree-view.h b/widgets/misc/e-mail-signature-tree-view.h
new file mode 100644
index 0000000..e3129c9
--- /dev/null
+++ b/widgets/misc/e-mail-signature-tree-view.h
@@ -0,0 +1,76 @@
+/*
+ * e-mail-signature-tree-view.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_SIGNATURE_TREE_VIEW_H
+#define E_MAIL_SIGNATURE_TREE_VIEW_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SIGNATURE_TREE_VIEW \
+ (e_mail_signature_tree_view_get_type ())
+#define E_MAIL_SIGNATURE_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SIGNATURE_TREE_VIEW, EMailSignatureTreeView))
+#define E_MAIL_SIGNATURE_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SIGNATURE_TREE_VIEW, EMailSignatureTreeViewClass))
+#define E_IS_MAIL_SIGNATURE_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SIGNATURE_TREE_VIEW))
+#define E_IS_MAIL_SIGNATURE_TREE_VIEW_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SIGNATURE_TREE_VIEW))
+#define E_MAIL_SIGNATURE_TREE_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SIGNATURE_TREE_VIEW, EMailSignatureTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSignatureTreeView EMailSignatureTreeView;
+typedef struct _EMailSignatureTreeViewClass EMailSignatureTreeViewClass;
+typedef struct _EMailSignatureTreeViewPrivate EMailSignatureTreeViewPrivate;
+
+struct _EMailSignatureTreeView {
+ GtkTreeView parent;
+ EMailSignatureTreeViewPrivate *priv;
+};
+
+struct _EMailSignatureTreeViewClass {
+ GtkTreeViewClass parent_class;
+};
+
+GType e_mail_signature_tree_view_get_type
+ (void) G_GNUC_CONST;
+GtkWidget * e_mail_signature_tree_view_new
+ (ESourceRegistry *registry);
+void e_mail_signature_tree_view_refresh
+ (EMailSignatureTreeView *tree_view);
+ESourceRegistry *
+ e_mail_signature_tree_view_get_registry
+ (EMailSignatureTreeView *tree_view);
+ESource * e_mail_signature_tree_view_ref_selected_source
+ (EMailSignatureTreeView *tree_view);
+void e_mail_signature_tree_view_set_selected_source
+ (EMailSignatureTreeView *tree_view,
+ ESource *selected_source);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SIGNATURE_TREE_VIEW_H */
diff --git a/widgets/misc/test-mail-signatures.c b/widgets/misc/test-mail-signatures.c
new file mode 100644
index 0000000..7650195
--- /dev/null
+++ b/widgets/misc/test-mail-signatures.c
@@ -0,0 +1,199 @@
+/*
+ * test-mail-signatures.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <stdlib.h>
+
+#include <libedataserver/e-source-mail-identity.h>
+
+#include <libevolution-utils/e-alert-sink.h>
+#include <misc/e-mail-identity-combo-box.h>
+#include <misc/e-mail-signature-combo-box.h>
+#include <misc/e-mail-signature-manager.h>
+#include <misc/e-mail-signature-preview.h>
+
+static GCancellable *cancellable = NULL;
+
+static void
+signature_loaded_cb (EMailSignatureComboBox *combo_box,
+ GAsyncResult *result,
+ EWebView *web_view)
+{
+ gchar *contents = NULL;
+ gboolean is_html;
+ GError *error = NULL;
+
+ e_mail_signature_combo_box_load_selected_finish (
+ combo_box, result, &contents, NULL, &is_html, &error);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warn_if_fail (contents == NULL);
+ g_object_unref (web_view);
+ g_error_free (error);
+ return;
+
+ } else if (error != NULL) {
+ g_warn_if_fail (contents == NULL);
+ e_alert_submit (
+ E_ALERT_SINK (web_view),
+ "widgets:no-load-signature",
+ error->message, NULL);
+ g_object_unref (web_view);
+ g_error_free (error);
+ return;
+ }
+
+ if (contents == NULL)
+ e_web_view_clear (web_view);
+ else if (is_html)
+ e_web_view_load_string (web_view, contents);
+ else {
+ gchar *string;
+
+ string = g_markup_printf_escaped ("<pre>%s</pre>", contents);
+ e_web_view_load_string (web_view, string);
+ g_free (string);
+ }
+
+ g_free (contents);
+
+ g_object_unref (web_view);
+}
+
+static void
+signature_combo_changed_cb (EMailSignatureComboBox *combo_box,
+ EWebView *web_view)
+{
+ if (cancellable != NULL) {
+ g_cancellable_cancel (cancellable);
+ g_object_unref (cancellable);
+ }
+
+ cancellable = g_cancellable_new ();
+
+ e_mail_signature_combo_box_load_selected (
+ combo_box, G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) signature_loaded_cb,
+ g_object_ref (web_view));
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ ESourceRegistry *registry;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GtkWidget *vbox;
+ GtkWidget *identity_combo;
+ GtkWidget *signature_combo;
+ GError *error = NULL;
+
+ gtk_init (&argc, &argv);
+
+ registry = e_source_registry_new_sync (NULL, &error);
+
+ if (error != NULL) {
+ g_printerr ("%s\n", error->message);
+ exit (EXIT_FAILURE);
+ }
+
+ /* Construct the widgets. */
+
+ widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (widget), "Mail Signatures");
+ gtk_window_set_default_size (GTK_WINDOW (widget), 400, 400);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
+ gtk_widget_show (widget);
+
+ g_signal_connect (
+ widget, "delete-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ container = widget;
+
+ widget = gtk_vbox_new (FALSE, 12);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = vbox = widget;
+
+ widget = gtk_label_new ("<b>EMailSignatureComboBox</b>");
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_vbox_new (FALSE, 6);
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_mail_signature_combo_box_new (registry);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ signature_combo = widget;
+ gtk_widget_show (widget);
+
+ widget = e_mail_identity_combo_box_new (registry);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ identity_combo = widget;
+ gtk_widget_show (widget);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_web_view_new ();
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect (
+ signature_combo, "changed",
+ G_CALLBACK (signature_combo_changed_cb), widget);
+
+ container = vbox;
+
+ widget = gtk_label_new ("<b>EMailSignatureManager</b>");
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = e_mail_signature_manager_new (registry);
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ g_object_bind_property (
+ identity_combo, "active-id",
+ signature_combo, "identity-uid",
+ G_BINDING_SYNC_CREATE);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/widgets/misc/test-source-config.c b/widgets/misc/test-source-config.c
index 2fd69bf..c7b8ac8 100644
--- a/widgets/misc/test-source-config.c
+++ b/widgets/misc/test-source-config.c
@@ -13,7 +13,8 @@ dialog_response (GtkDialog *dialog,
}
gint
-main (gint argc, gchar **argv)
+main (gint argc,
+ gchar **argv)
{
ESourceRegistry *registry;
ESource *source = NULL;
diff --git a/widgets/misc/widgets.error.xml b/widgets/misc/widgets.error.xml
new file mode 100644
index 0000000..efaa41c
--- /dev/null
+++ b/widgets/misc/widgets.error.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="widgets">
+
+ <error id="ask-signature-changed" type="question" default="GTK_RESPONSE_YES">
+ <_primary>Do you wish to save your changes?</_primary>
+ <_secondary xml:space="preserve">This signature has been changed, but has not been saved.</_secondary>
+ <button _label="_Discard changes" response="GTK_RESPONSE_NO"/>
+ <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+ <button stock="gtk-save" response="GTK_RESPONSE_YES"/>
+ </error>
+
+ <error id="blank-signature" type="error">
+ <_primary>Blank Signature</_primary>
+ <_secondary>Please provide an unique name to identify this signature.</_secondary>
+ </error>
+
+ <error id="no-load-signature" type="error">
+ <_primary>Could not load signature.</_primary>
+ <secondary xml:space="preserve">{0}</secondary>
+ </error>
+
+ <error id="no-save-signature" type="error">
+ <_primary>Could not save signature.</_primary>
+ <secondary xml:space="preserve">{0}</secondary>
+ </error>
+
+</error-list>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]