[evolution] Add EProxyPreferences.



commit ad6059bc0d63ab8503fe631dd3583c6ef8816b54
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Oct 15 11:12:05 2013 -0400

    Add EProxyPreferences.

 .../evolution-util/evolution-util-docs.sgml        |    1 +
 .../evolution-util/evolution-util-sections.txt     |   22 +
 doc/reference/evolution-util/evolution-util.types  |    1 +
 e-util/Makefile.am                                 |    7 +
 e-util/e-proxy-preferences.c                       |  694 ++++++++++++++++++++
 e-util/e-proxy-preferences.h                       |   84 +++
 e-util/e-util.h                                    |    1 +
 e-util/test-proxy-preferences.c                    |   86 +++
 po/POTFILES.in                                     |    1 +
 9 files changed, 897 insertions(+), 0 deletions(-)
---
diff --git a/doc/reference/evolution-util/evolution-util-docs.sgml 
b/doc/reference/evolution-util/evolution-util-docs.sgml
index 9075c3a..f91ea62 100644
--- a/doc/reference/evolution-util/evolution-util-docs.sgml
+++ b/doc/reference/evolution-util/evolution-util-docs.sgml
@@ -250,6 +250,7 @@
     <xi:include href="xml/e-proxy-combo-box.xml"/>
     <xi:include href="xml/e-proxy-editor.xml"/>
     <xi:include href="xml/e-proxy-link-selector.xml"/>
+    <xi:include href="xml/e-proxy-preferences.xml"/>
     <xi:include href="xml/e-proxy-selector.xml"/>
     <xi:include href="xml/e-search-bar.xml"/>
     <xi:include href="xml/e-selectable.xml"/>
diff --git a/doc/reference/evolution-util/evolution-util-sections.txt 
b/doc/reference/evolution-util/evolution-util-sections.txt
index 30e92b6..d777c09 100644
--- a/doc/reference/evolution-util/evolution-util-sections.txt
+++ b/doc/reference/evolution-util/evolution-util-sections.txt
@@ -2815,6 +2815,28 @@ EProxyLinkSelectorPrivate
 </SECTION>
 
 <SECTION>
+<FILE>e-proxy-preferences</FILE>
+<TITLE>EProxyPreferences</TITLE>
+EProxyPreferences
+e_proxy_preferences_new
+e_proxy_preferences_submit
+e_proxy_preferences_get_registry
+e_proxy_preferences_get_show_advanced
+e_proxy_preferences_set_show_advanced
+<SUBSECTION Standard>
+E_PROXY_PREFERENCES
+E_IS_PROXY_PREFERENCES
+E_TYPE_PROXY_PREFERENCES
+E_PROXY_PREFERENCES_CLASS
+E_IS_PROXY_PREFERENCES_CLASS
+E_PROXY_PREFERENCES_GET_CLASS
+EProxyPreferencesClass
+e_proxy_preferences_get_type
+<SUBSECTION Private>
+EProxyPreferencesPrivate
+</SECTION>
+
+<SECTION>
 <FILE>e-proxy-selector</FILE>
 <TITLE>EProxySelector</TITLE>
 EProxySelector
diff --git a/doc/reference/evolution-util/evolution-util.types 
b/doc/reference/evolution-util/evolution-util.types
index 778e3b8..c47d820 100644
--- a/doc/reference/evolution-util/evolution-util.types
+++ b/doc/reference/evolution-util/evolution-util.types
@@ -104,6 +104,7 @@ e_printable_get_type
 e_proxy_combo_box_get_type
 e_proxy_editor_get_type
 e_proxy_link_selector_get_type
+e_proxy_preferences_get_type
 e_proxy_selector_get_type
 e_reflow_get_type
 e_reflow_model_get_type
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index d3c5800..54ef384 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -63,6 +63,7 @@ noinst_PROGRAMS = \
        test-mail-signatures \
        test-name-selector \
        test-preferences-window \
+       test-proxy-preferences \
        test-source-combo-box \
        test-source-config \
        test-source-selector \
@@ -227,6 +228,7 @@ evolution_util_include_HEADERS =  \
        e-proxy-combo-box.h \
        e-proxy-editor.h \
        e-proxy-link-selector.h \
+       e-proxy-preferences.h \
        e-proxy-selector.h \
        e-reflow-model.h \
        e-reflow.h \
@@ -469,6 +471,7 @@ libevolution_util_la_SOURCES = \
        e-proxy-combo-box.c \
        e-proxy-editor.c \
        e-proxy-link-selector.c \
+       e-proxy-preferences.c \
        e-proxy-selector.c \
        e-reflow-model.c \
        e-reflow.c \
@@ -627,6 +630,10 @@ test_preferences_window_CPPFLAGS = $(TEST_CPPFLAGS)
 test_preferences_window_SOURCES = test-preferences-window.c
 test_preferences_window_LDADD = $(TEST_LDADD)
 
+test_proxy_preferences_CPPFLAGS = $(TEST_CPPFLAGS)
+test_proxy_preferences_SOURCES = test-proxy-preferences.c
+test_proxy_preferences_LDADD = $(TEST_LDADD)
+
 test_source_combo_box_CPPFLAGS = $(TEST_CPPFLAGS)
 test_source_combo_box_SOURCES = test-source-combo-box.c
 test_source_combo_box_LDADD = $(TEST_LDADD)
diff --git a/e-util/e-proxy-preferences.c b/e-util/e-proxy-preferences.c
new file mode 100644
index 0000000..57c3d32
--- /dev/null
+++ b/e-util/e-proxy-preferences.c
@@ -0,0 +1,694 @@
+/*
+ * e-proxy-preferences.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/>
+ *
+ */
+
+/**
+ * SECTION: e-proxy-preferences
+ * @include: e-util/e-util.h
+ * @short_description: Manage network proxy preferences
+ *
+ * #EProxyPreferences is the main widget for displaying network proxy
+ * preferences.  A link button toggles between a basic mode (for most
+ * users) and advanced mode.  Basic mode only shows proxy details for
+ * the built-in proxy profile, which all new accounts use by default.
+ * Advanced mode reveals a sidebar of proxy profiles, allowing users
+ * to create or delete custom profiles and apply them to particular
+ * accounts.
+ **/
+
+#include "e-proxy-preferences.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <e-util/e-proxy-editor.h>
+#include <e-util/e-proxy-link-selector.h>
+#include <e-util/e-proxy-selector.h>
+
+#define E_PROXY_PREFERENCES_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_PROXY_PREFERENCES, EProxyPreferencesPrivate))
+
+/* Rate-limit committing proxy changes to the registry. */
+#define COMMIT_DELAY_SECS 2
+
+struct _EProxyPreferencesPrivate {
+       ESourceRegistry *registry;
+       gulong source_changed_handler_id;
+
+       /* The widgets are not referenced. */
+       GtkWidget *proxy_selector;
+       GtkWidget *proxy_editor;
+
+       GMutex commit_lock;
+       guint commit_timeout_id;
+       GHashTable *commit_sources;
+
+       gboolean show_advanced;
+};
+
+enum {
+       PROP_0,
+       PROP_REGISTRY,
+       PROP_SHOW_ADVANCED
+};
+
+/* Forward Declarations */
+static void    proxy_preferences_commit_changes
+                                       (EProxyPreferences *preferences);
+
+G_DEFINE_TYPE (
+       EProxyPreferences,
+       e_proxy_preferences,
+       GTK_TYPE_BOX)
+
+static gboolean
+proxy_preferences_commit_timeout_cb (gpointer user_data)
+{
+       EProxyPreferences *preferences = user_data;
+
+       proxy_preferences_commit_changes (preferences);
+
+       return FALSE;
+}
+
+static void
+proxy_preferences_commit_stash (EProxyPreferences *preferences,
+                                ESource *source,
+                                gboolean start_timeout)
+{
+       g_mutex_lock (&preferences->priv->commit_lock);
+
+       g_hash_table_replace (
+               preferences->priv->commit_sources,
+               e_source_dup_uid (source),
+               e_weak_ref_new (source));
+
+       if (preferences->priv->commit_timeout_id > 0) {
+               g_source_remove (preferences->priv->commit_timeout_id);
+               preferences->priv->commit_timeout_id = 0;
+       }
+
+       if (start_timeout) {
+               preferences->priv->commit_timeout_id =
+                       g_timeout_add_seconds (
+                               COMMIT_DELAY_SECS,
+                               proxy_preferences_commit_timeout_cb,
+                               preferences);
+       }
+
+       g_mutex_unlock (&preferences->priv->commit_lock);
+}
+
+static GList *
+proxy_preferences_commit_claim (EProxyPreferences *preferences)
+{
+       GQueue queue = G_QUEUE_INIT;
+       GList *list, *link;
+
+       g_mutex_lock (&preferences->priv->commit_lock);
+
+       if (preferences->priv->commit_timeout_id > 0) {
+               g_source_remove (preferences->priv->commit_timeout_id);
+               preferences->priv->commit_timeout_id = 0;
+       }
+
+       /* Returns a list of GWeakRefs which may hold an ESource. */
+       list = g_hash_table_get_values (preferences->priv->commit_sources);
+
+       for (link = list; link != NULL; link = g_list_next (link)) {
+               ESource *source;
+
+               source = g_weak_ref_get ((GWeakRef *) link->data);
+               if (source != NULL)
+                       g_queue_push_tail (&queue, source);
+       }
+
+       g_list_free (list);
+
+       g_hash_table_remove_all (preferences->priv->commit_sources);
+
+       g_mutex_unlock (&preferences->priv->commit_lock);
+
+       return g_queue_peek_head_link (&queue);
+}
+
+static gboolean
+proxy_preferences_activate_link_cb (GtkLinkButton *button,
+                                    EProxyPreferences *preferences)
+{
+       EProxySelector *selector;
+
+       selector = E_PROXY_SELECTOR (preferences->priv->proxy_selector);
+
+       if (e_proxy_preferences_get_show_advanced (preferences)) {
+               /* Basic mode always shows the built-in proxy profile. */
+               e_proxy_preferences_set_show_advanced (preferences, FALSE);
+               e_proxy_selector_set_selected (selector, NULL);
+       } else {
+               e_proxy_preferences_set_show_advanced (preferences, TRUE);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+proxy_preferences_switch_to_label (GBinding *binding,
+                                   const GValue *source_value,
+                                   GValue *target_value,
+                                   gpointer user_data)
+{
+       const gchar *string;
+
+       if (g_value_get_boolean (source_value))
+               string = _("Switch to Basic Proxy Preferences");
+       else
+               string = _("Switch to Advanced Proxy Preferences");
+
+       g_value_set_string (target_value, string);
+
+       return TRUE;
+}
+
+static gboolean
+proxy_preferences_source_to_display_name (GBinding *binding,
+                                          const GValue *source_value,
+                                          GValue *target_value,
+                                          gpointer user_data)
+{
+       ESource *source;
+       gchar *display_name;
+
+       source = g_value_get_object (source_value);
+       g_return_val_if_fail (source != NULL, FALSE);
+
+       display_name = e_source_dup_display_name (source);
+       g_value_take_string (target_value, display_name);
+
+       return TRUE;
+}
+
+static void
+proxy_preferences_write_done_cb (GObject *source_object,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
+{
+       ESource *source;
+       EProxyPreferences *preferences;
+       GError *error = NULL;
+
+       source = E_SOURCE (source_object);
+       preferences = E_PROXY_PREFERENCES (user_data);
+
+       e_source_write_finish (source, result, &error);
+
+       /* FIXME Display the error in an alert sink. */
+       if (error != NULL) {
+               g_warning ("%s: %s", G_STRFUNC, error->message);
+               g_error_free (error);
+       }
+
+       g_object_unref (preferences);
+}
+
+static void
+proxy_preferences_commit_changes (EProxyPreferences *preferences)
+{
+       GList *list, *link;
+
+       list = proxy_preferences_commit_claim (preferences);
+
+       for (link = list; link != NULL; link = g_list_next (link)) {
+               e_source_write (
+                       E_SOURCE (link->data), NULL,
+                       proxy_preferences_write_done_cb,
+                       g_object_ref (preferences));
+       }
+
+       g_list_free_full (list, (GDestroyNotify) g_object_unref);
+}
+
+static void
+proxy_preferences_source_changed_cb (ESourceRegistry *registry,
+                                     ESource *source,
+                                     EProxyPreferences *preferences)
+{
+       if (e_source_has_extension (source, E_SOURCE_EXTENSION_PROXY))
+               proxy_preferences_commit_stash (preferences, source, TRUE);
+}
+
+static void
+proxy_preferences_set_registry (EProxyPreferences *preferences,
+                                ESourceRegistry *registry)
+{
+       gulong handler_id;
+
+       g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+       g_return_if_fail (preferences->priv->registry == NULL);
+
+       preferences->priv->registry = g_object_ref (registry);
+
+       handler_id = g_signal_connect (
+               registry, "source-changed",
+               G_CALLBACK (proxy_preferences_source_changed_cb), preferences);
+       preferences->priv->source_changed_handler_id = handler_id;
+}
+
+static void
+proxy_preferences_set_property (GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_REGISTRY:
+                       proxy_preferences_set_registry (
+                               E_PROXY_PREFERENCES (object),
+                               g_value_get_object (value));
+                       return;
+
+               case PROP_SHOW_ADVANCED:
+                       e_proxy_preferences_set_show_advanced (
+                               E_PROXY_PREFERENCES (object),
+                               g_value_get_boolean (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+proxy_preferences_get_property (GObject *object,
+                                guint property_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_REGISTRY:
+                       g_value_set_object (
+                               value,
+                               e_proxy_preferences_get_registry (
+                               E_PROXY_PREFERENCES (object)));
+                       return;
+
+               case PROP_SHOW_ADVANCED:
+                       g_value_set_boolean (
+                               value,
+                               e_proxy_preferences_get_show_advanced (
+                               E_PROXY_PREFERENCES (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+proxy_preferences_dispose (GObject *object)
+{
+       EProxyPreferencesPrivate *priv;
+
+       priv = E_PROXY_PREFERENCES_GET_PRIVATE (object);
+
+       if (priv->source_changed_handler_id > 0) {
+               g_signal_handler_disconnect (
+                       priv->registry,
+                       priv->source_changed_handler_id);
+               priv->source_changed_handler_id = 0;
+       }
+
+       if (priv->commit_timeout_id > 0) {
+               g_source_remove (priv->commit_timeout_id);
+               priv->commit_timeout_id = 0;
+       }
+
+       g_clear_object (&priv->registry);
+
+       g_hash_table_remove_all (priv->commit_sources);
+
+       /* Chain up to parent's dispose() method. */
+       G_OBJECT_CLASS (e_proxy_preferences_parent_class)->dispose (object);
+}
+
+static void
+proxy_preferences_finalize (GObject *object)
+{
+       EProxyPreferencesPrivate *priv;
+
+       priv = E_PROXY_PREFERENCES_GET_PRIVATE (object);
+
+       g_mutex_clear (&priv->commit_lock);
+       g_hash_table_destroy (priv->commit_sources);
+
+       /* Chain up to parent's finalize() method. */
+       G_OBJECT_CLASS (e_proxy_preferences_parent_class)->finalize (object);
+}
+
+static void
+proxy_preferences_constructed (GObject *object)
+{
+       EProxyPreferences *preferences;
+       ESourceRegistry *registry;
+       GtkWidget *widget;
+       GtkWidget *container;
+       GtkWidget *container2;
+       PangoAttribute *attr;
+       PangoAttrList *attr_list;
+       GList *list;
+       const gchar *extension_name;
+       gboolean show_advanced;
+
+       /* Chain up to parent's constructed() method. */
+       G_OBJECT_CLASS (e_proxy_preferences_parent_class)->
+               constructed (object);
+
+       preferences = E_PROXY_PREFERENCES (object);
+       registry = e_proxy_preferences_get_registry (preferences);
+
+       gtk_orientable_set_orientation (
+               GTK_ORIENTABLE (preferences), GTK_ORIENTATION_VERTICAL);
+       gtk_box_set_spacing (GTK_BOX (preferences), 12);
+
+       widget = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (widget), 12);
+       gtk_grid_set_column_spacing (GTK_GRID (widget), 12);
+       gtk_box_pack_start (GTK_BOX (preferences), widget, TRUE, TRUE, 0);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       widget = e_proxy_selector_new (registry);
+       gtk_widget_set_vexpand (widget, TRUE);
+       gtk_widget_set_size_request (widget, 200, -1);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 3);
+       preferences->priv->proxy_selector = widget;  /* do not reference */
+
+       g_object_bind_property (
+               preferences, "show-advanced",
+               widget, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       attr_list = pango_attr_list_new ();
+       attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+       pango_attr_list_insert (attr_list, attr);
+
+       widget = gtk_label_new ("");
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_widget_set_valign (widget, GTK_ALIGN_START);
+       gtk_label_set_attributes (GTK_LABEL (widget), attr_list);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1);
+       gtk_widget_show (widget);
+
+       g_object_bind_property_full (
+               preferences->priv->proxy_selector, "selected",
+               widget, "label",
+               G_BINDING_SYNC_CREATE,
+               proxy_preferences_source_to_display_name,
+               NULL, NULL, NULL);
+
+       pango_attr_list_unref (attr_list);
+
+       widget = e_proxy_editor_new (registry);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_widget_set_valign (widget, GTK_ALIGN_START);
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+       preferences->priv->proxy_editor = widget;  /* do not reference */
+       gtk_widget_show (widget);
+
+       g_object_bind_property (
+               preferences->priv->proxy_selector, "selected",
+               widget, "source",
+               G_BINDING_SYNC_CREATE);
+
+       widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_widget_set_vexpand (widget, TRUE);
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       /* Nested containers to control multiple levels of visibility. */
+
+       widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+       gtk_widget_set_vexpand (widget, TRUE);
+       gtk_container_add (GTK_CONTAINER (container), widget);
+
+       g_object_bind_property (
+               preferences, "show-advanced",
+               widget, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       container = widget;
+
+       widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+       gtk_container_add (GTK_CONTAINER (container), widget);
+
+       container = widget;
+
+       widget = gtk_label_new (
+               _("Apply custom proxy settings to these accounts:"));
+       gtk_widget_set_halign (widget, GTK_ALIGN_START);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       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);
+
+       container2 = widget;
+
+       widget = e_proxy_link_selector_new (registry);
+       gtk_container_add (GTK_CONTAINER (container2), widget);
+       gtk_widget_show (widget);
+
+       g_object_bind_property (
+               preferences->priv->proxy_selector, "selected",
+               widget, "target-source",
+               G_BINDING_SYNC_CREATE);
+
+       /* This is bound to the GtkBox created above. */
+       g_object_bind_property (
+               widget, "show-toggles",
+               container, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       widget = gtk_link_button_new ("");
+       gtk_widget_set_halign (widget, GTK_ALIGN_START);
+       gtk_widget_set_tooltip_markup (
+               widget, _(
+               "<b>Advanced Proxy Preferences</b> lets you "
+               "define alternate network proxies and apply "
+               "them to specific accounts"));
+       gtk_box_pack_start (GTK_BOX (preferences), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       g_object_bind_property_full (
+               preferences, "show-advanced",
+               widget, "label",
+               G_BINDING_SYNC_CREATE,
+               proxy_preferences_switch_to_label,
+               NULL, NULL, NULL);
+
+       g_object_bind_property (
+               preferences, "show-advanced",
+               widget, "has-tooltip",
+               G_BINDING_SYNC_CREATE |
+               G_BINDING_INVERT_BOOLEAN);
+
+       g_signal_connect (
+               widget, "activate-link",
+               G_CALLBACK (proxy_preferences_activate_link_cb),
+               preferences);
+
+       extension_name = E_SOURCE_EXTENSION_PROXY;
+       list = e_source_registry_list_sources (registry, extension_name);
+       show_advanced = (g_list_length (list) > 1);
+       g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+       /* Switch to advanced mode if there are multiple proxy profiles. */
+       e_proxy_preferences_set_show_advanced (preferences, show_advanced);
+}
+
+static void
+e_proxy_preferences_class_init (EProxyPreferencesClass *class)
+{
+       GObjectClass *object_class;
+
+       g_type_class_add_private (class, sizeof (EProxyPreferencesPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = proxy_preferences_set_property;
+       object_class->get_property = proxy_preferences_get_property;
+       object_class->dispose = proxy_preferences_dispose;
+       object_class->finalize = proxy_preferences_finalize;
+       object_class->constructed = proxy_preferences_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_SHOW_ADVANCED,
+               g_param_spec_boolean (
+                       "show-advanced",
+                       "Show Advanced",
+                       "Show advanced proxy preferences",
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_proxy_preferences_init (EProxyPreferences *preferences)
+{
+       GHashTable *commit_sources;
+
+       /* Keys are UIDs, values are allocated GWeakRefs. */
+       commit_sources = g_hash_table_new_full (
+               (GHashFunc) g_str_hash,
+               (GEqualFunc) g_str_equal,
+               (GDestroyNotify) g_free,
+               (GDestroyNotify) e_weak_ref_free);
+
+       preferences->priv = E_PROXY_PREFERENCES_GET_PRIVATE (preferences);
+
+       g_mutex_init (&preferences->priv->commit_lock);
+       preferences->priv->commit_sources = commit_sources;
+}
+
+/**
+ * e_proxy_preferences_new:
+ * @registry: an #ESourceRegistry
+ *
+ * Creates a new #EProxyPreferences widget using #ESource instances in
+ * @registry.
+ *
+ * Returns: a new #EProxyPreferences
+ **/
+GtkWidget *
+e_proxy_preferences_new (ESourceRegistry *registry)
+{
+       g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+       return g_object_new (
+               E_TYPE_PROXY_PREFERENCES,
+               "registry", registry, NULL);
+}
+
+/**
+ * e_proxy_preferences_submit:
+ * @preferences: an #EProxyPreferences
+ *
+ * Writes the displayed proxy profile details to the #ESource being edited,
+ * and submits the changes to the registry service asynchronously.
+ *
+ * Normally changes are submitted to the registry service automatically
+ * after a brief delay, but changes may sometimes need to be submitted
+ * explicitly such as when the top-level window is closing.
+ **/
+void
+e_proxy_preferences_submit (EProxyPreferences *preferences)
+{
+       EProxyEditor *proxy_editor;
+       ESource *source;
+
+       g_return_if_fail (E_IS_PROXY_PREFERENCES (preferences));
+
+       proxy_editor = E_PROXY_EDITOR (preferences->priv->proxy_editor);
+
+       /* Save user changes to the proxy source. */
+       e_proxy_editor_save (proxy_editor);
+
+       /* This part normally happens from a "source-changed"
+        * signal handler, but we can't wait for that here. */
+       source = e_proxy_editor_ref_source (proxy_editor);
+       proxy_preferences_commit_stash (preferences, source, FALSE);
+       g_object_unref (source);
+
+       /* Commit any pending changes immediately. */
+       proxy_preferences_commit_changes (preferences);
+}
+
+/**
+ * e_proxy_preferences_get_registry:
+ * @preferences: an #EProxyPreferences
+ *
+ * Returns the #ESourceRegistry passed to e_proxy_preferences_new().
+ *
+ * Returns: an #ESourceRegistry
+ **/
+ESourceRegistry *
+e_proxy_preferences_get_registry (EProxyPreferences *preferences)
+{
+       g_return_val_if_fail (E_IS_PROXY_PREFERENCES (preferences), NULL);
+
+       return preferences->priv->registry;
+}
+
+/**
+ * e_proxy_preferences_get_show_advanced:
+ * @preferences: an #EProxyPreferences
+ *
+ * Returns whether @preferences is currently in advanced mode.
+ *
+ * Returns: whether advanced proxy preferences are visible
+ **/
+gboolean
+e_proxy_preferences_get_show_advanced (EProxyPreferences *preferences)
+{
+       g_return_val_if_fail (E_IS_PROXY_PREFERENCES (preferences), FALSE);
+
+       return preferences->priv->show_advanced;
+}
+
+/**
+ * e_proxy_preferences_set_show_advanced:
+ * @preferences: an #EProxyPreferences
+ * @show_advanced: whether to show advanced proxy preferences
+ *
+ * Switches @preferences to advanced mode if @show_advanced is %TRUE,
+ * or to basic mode if @show_advanced is %FALSE.
+ **/
+void
+e_proxy_preferences_set_show_advanced (EProxyPreferences *preferences,
+                                       gboolean show_advanced)
+{
+       g_return_if_fail (E_IS_PROXY_PREFERENCES (preferences));
+
+       if (show_advanced == preferences->priv->show_advanced)
+               return;
+
+       preferences->priv->show_advanced = show_advanced;
+
+       g_object_notify (G_OBJECT (preferences), "show-advanced");
+}
+
diff --git a/e-util/e-proxy-preferences.h b/e-util/e-proxy-preferences.h
new file mode 100644
index 0000000..859c16b
--- /dev/null
+++ b/e-util/e-proxy-preferences.h
@@ -0,0 +1,84 @@
+/*
+ * e-proxy-preferences.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/>
+ *
+ */
+
+#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
+#error "Only <e-util/e-util.h> should be included directly."
+#endif
+
+#ifndef E_PROXY_PREFERENCES_H
+#define E_PROXY_PREFERENCES_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/libedataserver.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PROXY_PREFERENCES \
+       (e_proxy_preferences_get_type ())
+#define E_PROXY_PREFERENCES(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_PROXY_PREFERENCES, EProxyPreferences))
+#define E_PROXY_PREFERENCES_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_PROXY_PREFERENCES, EProxyPreferencesClass))
+#define E_IS_PROXY_PREFERENCES(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_PROXY_PREFERENCES))
+#define E_IS_PROXY_PREFERENCES_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_PROXY_PREFERENCES))
+#define E_PROXY_PREFERENCES_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_PROXY_PREFERENCES, EProxyPreferencesClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EProxyPreferences EProxyPreferences;
+typedef struct _EProxyPreferencesClass EProxyPreferencesClass;
+typedef struct _EProxyPreferencesPrivate EProxyPreferencesPrivate;
+
+/**
+ * EProxyPreferences:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ **/
+struct _EProxyPreferences {
+       GtkBox parent;
+       EProxyPreferencesPrivate *priv;
+};
+
+struct _EProxyPreferencesClass {
+       GtkBoxClass parent_class;
+};
+
+GType          e_proxy_preferences_get_type    (void) G_GNUC_CONST;
+GtkWidget *    e_proxy_preferences_new         (ESourceRegistry *registry);
+void           e_proxy_preferences_submit      (EProxyPreferences *preferences);
+ESourceRegistry *
+               e_proxy_preferences_get_registry
+                                               (EProxyPreferences *preferences);
+gboolean       e_proxy_preferences_get_show_advanced
+                                               (EProxyPreferences *preferences);
+void           e_proxy_preferences_set_show_advanced
+                                               (EProxyPreferences *preferences,
+                                                gboolean show_advanced);
+
+G_END_DECLS
+
+#endif /* E_PROXY_PREFERENCES_H */
+
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 494e410..f2022ff 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -146,6 +146,7 @@
 #include <e-util/e-proxy-combo-box.h>
 #include <e-util/e-proxy-editor.h>
 #include <e-util/e-proxy-link-selector.h>
+#include <e-util/e-proxy-preferences.h>
 #include <e-util/e-proxy-selector.h>
 #include <e-util/e-reflow-model.h>
 #include <e-util/e-reflow.h>
diff --git a/e-util/test-proxy-preferences.c b/e-util/test-proxy-preferences.c
new file mode 100644
index 0000000..bd86cda
--- /dev/null
+++ b/e-util/test-proxy-preferences.c
@@ -0,0 +1,86 @@
+/*
+ * test-proxy-preferences.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-util/e-util.h>
+
+static EProxyPreferences *preferences;
+
+static gboolean
+quit_delay_cb (gpointer user_data)
+{
+       gtk_main_quit ();
+
+       return FALSE;
+}
+
+static gint
+delete_event_cb (GtkWidget *widget,
+                 GdkEventAny *event,
+                 gpointer data)
+{
+       e_proxy_preferences_submit (preferences);
+
+       /* Cycle the main loop for a bit longer to
+        * give the commit operation time to finish. */
+       g_timeout_add_seconds (1, quit_delay_cb, NULL);
+
+       return FALSE;
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       ESourceRegistry *registry;
+       GtkWidget *window;
+       GtkWidget *widget;
+       GError *local_error = NULL;
+
+       gtk_init (&argc, &argv);
+
+       registry = e_source_registry_new_sync (NULL, &local_error);
+
+       if (local_error != NULL) {
+               g_error (
+                       "Failed to load ESource registry: %s",
+                       local_error->message);
+               g_assert_not_reached ();
+       }
+
+       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+       gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
+       gtk_window_set_title (GTK_WINDOW (window), "Proxy Preferences");
+       gtk_widget_show (window);
+
+       g_signal_connect (
+               window, "delete-event",
+               G_CALLBACK (delete_event_cb), NULL);
+
+       widget = e_proxy_preferences_new (registry);
+       gtk_container_add (GTK_CONTAINER (window), widget);
+       preferences = E_PROXY_PREFERENCES (widget);
+       gtk_widget_show (widget);
+
+       g_object_unref (registry);
+
+       gtk_main ();
+
+       return 0;
+}
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 92f975b..d4d4de7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -244,6 +244,7 @@ e-util/e-popup-action.c
 e-util/e-preferences-window.c
 e-util/e-print.c
 e-util/e-proxy-editor.c
+e-util/e-proxy-preferences.c
 e-util/e-proxy-selector.c
 e-util/e-rule-context.c
 e-util/e-rule-editor.c


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]