aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc/e-source-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/misc/e-source-config.c')
-rw-r--r--widgets/misc/e-source-config.c1448
1 files changed, 0 insertions, 1448 deletions
diff --git a/widgets/misc/e-source-config.c b/widgets/misc/e-source-config.c
deleted file mode 100644
index f5ef35287c..0000000000
--- a/widgets/misc/e-source-config.c
+++ /dev/null
@@ -1,1448 +0,0 @@
-/*
- * e-source-config.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-source-config.h"
-
-#include <config.h>
-#include <glib/gi18n-lib.h>
-
-#include <libebackend/libebackend.h>
-
-#include <e-util/e-marshal.h>
-#include <misc/e-interval-chooser.h>
-
-#include "e-source-config-backend.h"
-
-#define E_SOURCE_CONFIG_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_SOURCE_CONFIG, ESourceConfigPrivate))
-
-typedef struct _Candidate Candidate;
-
-struct _ESourceConfigPrivate {
- ESource *original_source;
- ESource *collection_source;
- ESourceRegistry *registry;
-
- GHashTable *backends;
- GPtrArray *candidates;
-
- GtkWidget *type_label;
- GtkWidget *type_combo;
- GtkWidget *name_label;
- GtkWidget *name_entry;
- GtkWidget *backend_box;
- GtkSizeGroup *size_group;
-
- gboolean complete;
-};
-
-struct _Candidate {
- GtkWidget *page;
- ESource *scratch_source;
- ESourceConfigBackend *backend;
- gulong changed_handler_id;
-};
-
-enum {
- PROP_0,
- PROP_COLLECTION_SOURCE,
- PROP_COMPLETE,
- PROP_ORIGINAL_SOURCE,
- PROP_REGISTRY
-};
-
-enum {
- CHECK_COMPLETE,
- COMMIT_CHANGES,
- INIT_CANDIDATE,
- RESIZE_WINDOW,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-G_DEFINE_TYPE_WITH_CODE (
- ESourceConfig,
- e_source_config,
- GTK_TYPE_BOX,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_EXTENSIBLE, NULL))
-
-static void
-source_config_init_backends (ESourceConfig *config)
-{
- GList *list, *iter;
-
- config->priv->backends = g_hash_table_new_full (
- (GHashFunc) g_str_hash,
- (GEqualFunc) g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_object_unref);
-
- e_extensible_load_extensions (E_EXTENSIBLE (config));
-
- list = e_extensible_list_extensions (
- E_EXTENSIBLE (config), E_TYPE_SOURCE_CONFIG_BACKEND);
-
- for (iter = list; iter != NULL; iter = g_list_next (iter)) {
- ESourceConfigBackend *backend;
- ESourceConfigBackendClass *class;
-
- backend = E_SOURCE_CONFIG_BACKEND (iter->data);
- class = E_SOURCE_CONFIG_BACKEND_GET_CLASS (backend);
-
- if (class->backend_name != NULL)
- g_hash_table_insert (
- config->priv->backends,
- g_strdup (class->backend_name),
- g_object_ref (backend));
- }
-
- g_list_free (list);
-}
-
-static gint
-source_config_compare_sources (gconstpointer a,
- gconstpointer b,
- gpointer user_data)
-{
- ESource *source_a;
- ESource *source_b;
- ESource *parent_a;
- ESource *parent_b;
- ESourceConfig *config;
- ESourceRegistry *registry;
- const gchar *parent_uid_a;
- const gchar *parent_uid_b;
- gint result;
-
- source_a = E_SOURCE (a);
- source_b = E_SOURCE (b);
- config = E_SOURCE_CONFIG (user_data);
-
- if (e_source_equal (source_a, source_b))
- return 0;
-
- /* "On This Computer" always comes first. */
-
- parent_uid_a = e_source_get_parent (source_a);
- parent_uid_b = e_source_get_parent (source_b);
-
- if (g_strcmp0 (parent_uid_a, "local-stub") == 0)
- return -1;
-
- if (g_strcmp0 (parent_uid_b, "local-stub") == 0)
- return 1;
-
- registry = e_source_config_get_registry (config);
-
- parent_a = e_source_registry_ref_source (registry, parent_uid_a);
- parent_b = e_source_registry_ref_source (registry, parent_uid_b);
-
- g_return_val_if_fail (parent_a != NULL, 1);
- g_return_val_if_fail (parent_b != NULL, -1);
-
- result = e_source_compare_by_display_name (parent_a, parent_b);
-
- g_object_unref (parent_a);
- g_object_unref (parent_b);
-
- return result;
-}
-
-static void
-source_config_add_candidate (ESourceConfig *config,
- ESource *scratch_source,
- ESourceConfigBackend *backend)
-{
- Candidate *candidate;
- GtkBox *backend_box;
- GtkLabel *type_label;
- GtkComboBoxText *type_combo;
- ESource *parent_source;
- ESourceRegistry *registry;
- const gchar *display_name;
- const gchar *parent_uid;
- gulong handler_id;
-
- backend_box = GTK_BOX (config->priv->backend_box);
- type_label = GTK_LABEL (config->priv->type_label);
- type_combo = GTK_COMBO_BOX_TEXT (config->priv->type_combo);
-
- registry = e_source_config_get_registry (config);
- parent_uid = e_source_get_parent (scratch_source);
- parent_source = e_source_registry_ref_source (registry, parent_uid);
- g_return_if_fail (parent_source != NULL);
-
- candidate = g_slice_new (Candidate);
- candidate->backend = g_object_ref (backend);
- candidate->scratch_source = g_object_ref (scratch_source);
-
- /* Do not show the page here. */
- candidate->page = g_object_ref_sink (gtk_vbox_new (FALSE, 6));
- gtk_box_pack_start (backend_box, candidate->page, FALSE, FALSE, 0);
-
- g_ptr_array_add (config->priv->candidates, candidate);
-
- display_name = e_source_get_display_name (parent_source);
- gtk_combo_box_text_append_text (type_combo, display_name);
- gtk_label_set_text (type_label, display_name);
-
- /* Make sure the combo box has a valid active item before
- * adding widgets. Otherwise we'll get run-time warnings
- * as property bindings are set up. */
- if (gtk_combo_box_get_active (GTK_COMBO_BOX (type_combo)) == -1)
- gtk_combo_box_set_active (GTK_COMBO_BOX (type_combo), 0);
-
- /* Bind the standard widgets to the new scratch source. */
- g_signal_emit (
- config, signals[INIT_CANDIDATE], 0,
- candidate->scratch_source);
-
- /* Insert any backend-specific widgets. */
- e_source_config_backend_insert_widgets (
- candidate->backend, candidate->scratch_source);
-
- handler_id = g_signal_connect_swapped (
- candidate->scratch_source, "changed",
- G_CALLBACK (e_source_config_check_complete), config);
-
- candidate->changed_handler_id = handler_id;
-
- /* Trigger the "changed" handler we just connected to set the
- * initial "complete" state based on the widgets we just added. */
- e_source_changed (candidate->scratch_source);
-
- g_object_unref (parent_source);
-}
-
-static void
-source_config_free_candidate (Candidate *candidate)
-{
- g_signal_handler_disconnect (
- candidate->scratch_source,
- candidate->changed_handler_id);
-
- g_object_unref (candidate->page);
- g_object_unref (candidate->scratch_source);
- g_object_unref (candidate->backend);
-
- g_slice_free (Candidate, candidate);
-}
-
-static Candidate *
-source_config_get_active_candidate (ESourceConfig *config)
-{
- GtkComboBox *type_combo;
- gint index;
-
- type_combo = GTK_COMBO_BOX (config->priv->type_combo);
- index = gtk_combo_box_get_active (type_combo);
- g_return_val_if_fail (index >= 0, NULL);
-
- return g_ptr_array_index (config->priv->candidates, index);
-}
-
-static void
-source_config_type_combo_changed_cb (GtkComboBox *type_combo,
- ESourceConfig *config)
-{
- Candidate *candidate;
- GPtrArray *array;
- gint index;
-
- array = config->priv->candidates;
-
- for (index = 0; index < array->len; index++) {
- candidate = g_ptr_array_index (array, index);
- gtk_widget_hide (candidate->page);
- }
-
- index = gtk_combo_box_get_active (type_combo);
- if (index == CLAMP (index, 0, array->len)) {
- candidate = g_ptr_array_index (array, index);
- gtk_widget_show (candidate->page);
- }
-
- e_source_config_resize_window (config);
- e_source_config_check_complete (config);
-}
-
-static gboolean
-source_config_init_for_adding_source_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- ESource *scratch_source;
- ESourceBackend *extension;
- ESourceConfig *config;
- ESourceConfigBackend *backend;
- ESourceConfigBackendClass *class;
- const gchar *extension_name;
-
- scratch_source = E_SOURCE (key);
- backend = E_SOURCE_CONFIG_BACKEND (value);
- config = E_SOURCE_CONFIG (user_data);
-
- /* This may not be the correct backend name for the child of a
- * collection. For example, the "yahoo" collection backend uses
- * the "caldav" calender backend for calendar children. But the
- * ESourceCollectionBackend can override our setting if needed. */
- class = E_SOURCE_CONFIG_BACKEND_GET_CLASS (backend);
- extension_name = e_source_config_get_backend_extension_name (config);
- extension = e_source_get_extension (scratch_source, extension_name);
- e_source_backend_set_backend_name (extension, class->backend_name);
-
- source_config_add_candidate (config, scratch_source, backend);
-
- return FALSE; /* don't stop traversal */
-}
-
-static void
-source_config_init_for_adding_source (ESourceConfig *config)
-{
- GList *list, *link;
- ESourceRegistry *registry;
- GTree *scratch_source_tree;
-
- /* Candidates are drawn from two sources:
- *
- * ESourceConfigBackend classes that specify a fixed parent UID,
- * meaning there exists one only possible parent source for any
- * scratch source created by the backend. The fixed parent UID
- * should be a built-in "stub" placeholder ("local-stub", etc).
- *
- * -and-
- *
- * Collection sources. We let ESourceConfig subclasses gather
- * eligible collection sources to serve as parents for scratch
- * sources. A scratch source is matched to a backend based on
- * the collection's backend name. The "calendar-enabled" and
- * "contacts-enabled" settings also factor into eligibility.
- */
-
- /* Use a GTree instead of a GHashTable so inserted scratch
- * sources automatically sort themselves by their parent's
- * display name. */
- scratch_source_tree = g_tree_new_full (
- source_config_compare_sources, config,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) g_object_unref);
-
- registry = e_source_config_get_registry (config);
-
- /* First pick out the backends with a fixed parent UID. */
-
- list = g_hash_table_get_values (config->priv->backends);
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- ESourceConfigBackend *backend;
- ESourceConfigBackendClass *class;
- ESource *scratch_source;
- ESource *parent_source;
- gboolean parent_is_disabled;
-
- backend = E_SOURCE_CONFIG_BACKEND (link->data);
- class = E_SOURCE_CONFIG_BACKEND_GET_CLASS (backend);
-
- if (class->parent_uid == NULL)
- continue;
-
- /* Verify the fixed parent UID is valid. */
- parent_source = e_source_registry_ref_source (
- registry, class->parent_uid);
- if (parent_source == NULL) {
- g_warning (
- "%s: %sClass specifies "
- "an invalid parent_uid '%s'",
- G_STRFUNC,
- G_OBJECT_TYPE_NAME (backend),
- class->parent_uid);
- continue;
- }
- parent_is_disabled = !e_source_get_enabled (parent_source);
- g_object_unref (parent_source);
-
- /* It's unusual for a fixed parent source to be disabled.
- * A user would have to go out of his way to do this, but
- * we should honor it regardless. */
- if (parent_is_disabled)
- continue;
-
- /* Some backends don't allow new sources to be created.
- * The "contacts" calendar backend is one such example. */
- if (!e_source_config_backend_allow_creation (backend))
- continue;
-
- scratch_source = e_source_new (NULL, NULL, NULL);
- g_return_if_fail (scratch_source != NULL);
-
- e_source_set_parent (scratch_source, class->parent_uid);
-
- g_tree_insert (
- scratch_source_tree,
- g_object_ref (scratch_source),
- g_object_ref (backend));
-
- g_object_unref (scratch_source);
- }
-
- g_list_free (list);
-
- /* Next gather eligible collection sources to serve as parents. */
-
- list = e_source_config_list_eligible_collections (config);
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- ESource *parent_source;
- ESource *scratch_source;
- ESourceBackend *extension;
- ESourceConfigBackend *backend = NULL;
- const gchar *backend_name;
- const gchar *parent_uid;
-
- parent_source = E_SOURCE (link->data);
- parent_uid = e_source_get_uid (parent_source);
-
- extension = e_source_get_extension (
- parent_source, E_SOURCE_EXTENSION_COLLECTION);
- backend_name = e_source_backend_get_backend_name (extension);
-
- if (backend_name != NULL)
- backend = g_hash_table_lookup (
- config->priv->backends, backend_name);
-
- if (backend == NULL)
- continue;
-
- /* Some backends disallow creating certain types of
- * resources. For example, the Exchange Web Services
- * backend disallows creating new memo lists. */
- if (!e_source_config_backend_allow_creation (backend))
- continue;
-
- scratch_source = e_source_new (NULL, NULL, NULL);
- g_return_if_fail (scratch_source != NULL);
-
- e_source_set_parent (scratch_source, parent_uid);
-
- g_tree_insert (
- scratch_source_tree,
- g_object_ref (scratch_source),
- g_object_ref (backend));
-
- g_object_unref (scratch_source);
- }
-
- g_list_free_full (list, (GDestroyNotify) g_object_unref);
-
- /* XXX GTree doesn't get as much love as GHashTable.
- * It's missing an equivalent to GHashTableIter. */
- g_tree_foreach (
- scratch_source_tree,
- source_config_init_for_adding_source_foreach, config);
-
- g_tree_unref (scratch_source_tree);
-}
-
-static void
-source_config_init_for_editing_source (ESourceConfig *config)
-{
- ESource *original_source;
- ESource *scratch_source;
- ESourceBackend *extension;
- ESourceConfigBackend *backend;
- GDBusObject *dbus_object;
- const gchar *backend_name;
- const gchar *extension_name;
-
- original_source = e_source_config_get_original_source (config);
- g_return_if_fail (original_source != NULL);
-
- extension_name = e_source_config_get_backend_extension_name (config);
- extension = e_source_get_extension (original_source, extension_name);
- backend_name = e_source_backend_get_backend_name (extension);
- g_return_if_fail (backend_name != NULL);
-
- backend = g_hash_table_lookup (config->priv->backends, backend_name);
- g_return_if_fail (backend != NULL);
-
- dbus_object = e_source_ref_dbus_object (original_source);
- g_return_if_fail (dbus_object != NULL);
-
- scratch_source = e_source_new (dbus_object, NULL, NULL);
- g_return_if_fail (scratch_source != NULL);
-
- source_config_add_candidate (config, scratch_source, backend);
-
- g_object_unref (scratch_source);
- g_object_unref (dbus_object);
-}
-
-static void
-source_config_set_original_source (ESourceConfig *config,
- ESource *original_source)
-{
- g_return_if_fail (config->priv->original_source == NULL);
-
- if (original_source != NULL)
- g_object_ref (original_source);
-
- config->priv->original_source = original_source;
-}
-
-static void
-source_config_set_registry (ESourceConfig *config,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_return_if_fail (config->priv->registry == NULL);
-
- config->priv->registry = g_object_ref (registry);
-}
-
-static void
-source_config_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ORIGINAL_SOURCE:
- source_config_set_original_source (
- E_SOURCE_CONFIG (object),
- g_value_get_object (value));
- return;
-
- case PROP_REGISTRY:
- source_config_set_registry (
- E_SOURCE_CONFIG (object),
- g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_config_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_COLLECTION_SOURCE:
- g_value_set_object (
- value,
- e_source_config_get_collection_source (
- E_SOURCE_CONFIG (object)));
- return;
-
- case PROP_COMPLETE:
- g_value_set_boolean (
- value,
- e_source_config_check_complete (
- E_SOURCE_CONFIG (object)));
- return;
-
- case PROP_ORIGINAL_SOURCE:
- g_value_set_object (
- value,
- e_source_config_get_original_source (
- E_SOURCE_CONFIG (object)));
- return;
-
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_source_config_get_registry (
- E_SOURCE_CONFIG (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_config_dispose (GObject *object)
-{
- ESourceConfigPrivate *priv;
-
- priv = E_SOURCE_CONFIG_GET_PRIVATE (object);
-
- if (priv->original_source != NULL) {
- g_object_unref (priv->original_source);
- priv->original_source = NULL;
- }
-
- if (priv->collection_source != NULL) {
- g_object_unref (priv->collection_source);
- priv->collection_source = NULL;
- }
-
- if (priv->registry != NULL) {
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- if (priv->type_label != NULL) {
- g_object_unref (priv->type_label);
- priv->type_label = NULL;
- }
-
- if (priv->type_combo != NULL) {
- g_object_unref (priv->type_combo);
- priv->type_combo = NULL;
- }
-
- if (priv->name_label != NULL) {
- g_object_unref (priv->name_label);
- priv->name_label = NULL;
- }
-
- if (priv->name_entry != NULL) {
- g_object_unref (priv->name_entry);
- priv->name_entry = NULL;
- }
-
- if (priv->backend_box != NULL) {
- g_object_unref (priv->backend_box);
- priv->backend_box = NULL;
- }
-
- if (priv->size_group != NULL) {
- g_object_unref (priv->size_group);
- priv->size_group = NULL;
- }
-
- g_hash_table_remove_all (priv->backends);
- g_ptr_array_set_size (priv->candidates, 0);
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_source_config_parent_class)->dispose (object);
-}
-
-static void
-source_config_finalize (GObject *object)
-{
- ESourceConfigPrivate *priv;
-
- priv = E_SOURCE_CONFIG_GET_PRIVATE (object);
-
- g_hash_table_destroy (priv->backends);
- g_ptr_array_free (priv->candidates, TRUE);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_source_config_parent_class)->finalize (object);
-}
-
-static void
-source_config_constructed (GObject *object)
-{
- ESourceConfig *config;
- ESourceRegistry *registry;
- ESource *original_source;
- ESource *collection_source = NULL;
-
- config = E_SOURCE_CONFIG (object);
- registry = e_source_config_get_registry (config);
- original_source = e_source_config_get_original_source (config);
-
- /* If we have an original source, see if it's part
- * of a collection and note the collection source. */
- if (original_source != NULL) {
- const gchar *extension_name;
-
- extension_name = E_SOURCE_EXTENSION_COLLECTION;
- collection_source = e_source_registry_find_extension (
- registry, original_source, extension_name);
- config->priv->collection_source = collection_source;
- }
-
- if (original_source != NULL)
- e_source_config_insert_widget (
- config, NULL, _("Type:"),
- config->priv->type_label);
- else
- e_source_config_insert_widget (
- config, NULL, _("Type:"),
- config->priv->type_combo);
-
- /* If the original source is part of a collection then we assume
- * the display name is server-assigned and not user-assigned, at
- * least not assigned through Evolution. */
- if (collection_source != NULL)
- e_source_config_insert_widget (
- config, NULL, _("Name:"),
- config->priv->name_label);
- else
- e_source_config_insert_widget (
- config, NULL, _("Name:"),
- config->priv->name_entry);
-
- source_config_init_backends (config);
-}
-
-static void
-source_config_realize (GtkWidget *widget)
-{
- ESourceConfig *config;
- ESource *original_source;
-
- /* Chain up to parent's realize() method. */
- GTK_WIDGET_CLASS (e_source_config_parent_class)->realize (widget);
-
- /* Do this after constructed() so subclasses can fully
- * initialize themselves before we add candidates. */
-
- config = E_SOURCE_CONFIG (widget);
- original_source = e_source_config_get_original_source (config);
-
- if (original_source == NULL)
- source_config_init_for_adding_source (config);
- else
- source_config_init_for_editing_source (config);
-}
-
-static GList *
-source_config_list_eligible_collections (ESourceConfig *config)
-{
- ESourceRegistry *registry;
- GQueue trash = G_QUEUE_INIT;
- GList *list, *link;
- const gchar *extension_name;
-
- extension_name = E_SOURCE_EXTENSION_COLLECTION;
- registry = e_source_config_get_registry (config);
-
- list = e_source_registry_list_sources (registry, extension_name);
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- ESource *source = E_SOURCE (link->data);
- gboolean elligible;
-
- elligible =
- e_source_get_enabled (source) &&
- e_source_get_remote_creatable (source);
-
- if (!elligible)
- g_queue_push_tail (&trash, link);
- }
-
- /* Remove ineligible collections from the list. */
- while ((link = g_queue_pop_head (&trash)) != NULL) {
- g_object_unref (link->data);
- list = g_list_delete_link (list, link);
- }
-
- return list;
-}
-
-static void
-source_config_init_candidate (ESourceConfig *config,
- ESource *scratch_source)
-{
- g_object_bind_property (
- scratch_source, "display-name",
- config->priv->name_label, "label",
- G_BINDING_SYNC_CREATE);
-
- g_object_bind_property (
- scratch_source, "display-name",
- config->priv->name_entry, "text",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-}
-
-static gboolean
-source_config_check_complete (ESourceConfig *config,
- ESource *scratch_source)
-{
- GtkEntry *name_entry;
- GtkComboBox *type_combo;
- const gchar *text;
-
- /* Make sure the Type: combo box has a valid item. */
- type_combo = GTK_COMBO_BOX (config->priv->type_combo);
- if (gtk_combo_box_get_active (type_combo) < 0)
- return FALSE;
-
- /* Make sure the Name: entry field is not empty. */
- name_entry = GTK_ENTRY (config->priv->name_entry);
- text = gtk_entry_get_text (name_entry);
- if (text == NULL || *text == '\0')
- return FALSE;
-
- return TRUE;
-}
-
-static void
-source_config_commit_changes (ESourceConfig *config,
- ESource *scratch_source)
-{
- /* Placeholder so subclasses can safely chain up. */
-}
-
-static void
-source_config_resize_window (ESourceConfig *config)
-{
- GtkWidget *toplevel;
-
- /* Expand or shrink our parent window vertically to accommodate
- * the newly selected backend's options. Some backends have tons
- * of options, some have few. This avoids the case where you
- * select a backend with tons of options and then a backend with
- * few options and wind up with lots of unused vertical space. */
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (config));
-
- if (GTK_IS_WINDOW (toplevel)) {
- GtkWindow *window = GTK_WINDOW (toplevel);
- GtkAllocation allocation;
-
- gtk_widget_get_allocation (toplevel, &allocation);
- gtk_window_resize (window, allocation.width, 1);
- }
-}
-
-static gboolean
-source_config_check_complete_accumulator (GSignalInvocationHint *ihint,
- GValue *return_accu,
- const GValue *handler_return,
- gpointer unused)
-{
- gboolean v_boolean;
-
- /* Abort emission if a handler returns FALSE. */
- v_boolean = g_value_get_boolean (handler_return);
- g_value_set_boolean (return_accu, v_boolean);
-
- return v_boolean;
-}
-
-static void
-e_source_config_class_init (ESourceConfigClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- g_type_class_add_private (class, sizeof (ESourceConfigPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = source_config_set_property;
- object_class->get_property = source_config_get_property;
- object_class->dispose = source_config_dispose;
- object_class->finalize = source_config_finalize;
- object_class->constructed = source_config_constructed;
-
- widget_class = GTK_WIDGET_CLASS (class);
- widget_class->realize = source_config_realize;
-
- class->list_eligible_collections =
- source_config_list_eligible_collections;
- class->init_candidate = source_config_init_candidate;
- class->check_complete = source_config_check_complete;
- class->commit_changes = source_config_commit_changes;
- class->resize_window = source_config_resize_window;
-
- g_object_class_install_property (
- object_class,
- PROP_COLLECTION_SOURCE,
- g_param_spec_object (
- "collection-source",
- "Collection Source",
- "The collection ESource to which "
- "the ESource being edited belongs",
- E_TYPE_SOURCE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_COMPLETE,
- g_param_spec_boolean (
- "complete",
- "Complete",
- "Are the required fields complete?",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_ORIGINAL_SOURCE,
- g_param_spec_object (
- "original-source",
- "Original Source",
- "The original ESource",
- E_TYPE_SOURCE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Registry of ESources",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- signals[CHECK_COMPLETE] = g_signal_new (
- "check-complete",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceConfigClass, check_complete),
- source_config_check_complete_accumulator, NULL,
- e_marshal_BOOLEAN__OBJECT,
- G_TYPE_BOOLEAN, 1,
- E_TYPE_SOURCE);
-
- signals[COMMIT_CHANGES] = g_signal_new (
- "commit-changes",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceConfigClass, commit_changes),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- E_TYPE_SOURCE);
-
- signals[INIT_CANDIDATE] = g_signal_new (
- "init-candidate",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceConfigClass, init_candidate),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- E_TYPE_SOURCE);
-
- signals[RESIZE_WINDOW] = g_signal_new (
- "resize-window",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceConfigClass, resize_window),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-e_source_config_init (ESourceConfig *config)
-{
- GPtrArray *candidates;
- GtkSizeGroup *size_group;
- PangoAttribute *attr;
- PangoAttrList *attr_list;
- GtkWidget *widget;
-
- /* The candidates array holds scratch ESources, one for each
- * item in the "type" combo box. Scratch ESources are never
- * added to the registry, so backend extensions can make any
- * changes they want to them. Whichever scratch ESource is
- * "active" (selected in the "type" combo box) when the user
- * clicks OK wins and is written to disk. The others are
- * discarded. */
- candidates = g_ptr_array_new_with_free_func (
- (GDestroyNotify) source_config_free_candidate);
-
- /* The size group is used for caption labels. */
- size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-
- gtk_box_set_spacing (GTK_BOX (config), 6);
-
- gtk_orientable_set_orientation (
- GTK_ORIENTABLE (config), GTK_ORIENTATION_VERTICAL);
-
- config->priv = E_SOURCE_CONFIG_GET_PRIVATE (config);
- config->priv->candidates = candidates;
- config->priv->size_group = size_group;
-
- attr_list = pango_attr_list_new ();
-
- attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
- pango_attr_list_insert (attr_list, attr);
-
- /* Either the source type combo box or the label is shown,
- * never both. But we create both widgets and keep them
- * both up-to-date because it makes the logic simpler. */
-
- widget = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_label_set_attributes (GTK_LABEL (widget), attr_list);
- config->priv->type_label = g_object_ref_sink (widget);
- gtk_widget_show (widget);
-
- widget = gtk_combo_box_text_new ();
- config->priv->type_combo = g_object_ref_sink (widget);
- gtk_widget_show (widget);
-
- /* Similarly for the display name. Either the text entry
- * or the label is shown, depending on whether the source
- * is a collection member (new sources never are). */
-
- widget = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_label_set_attributes (GTK_LABEL (widget), attr_list);
- config->priv->name_label = g_object_ref_sink (widget);
- gtk_widget_show (widget);
-
- widget = gtk_entry_new ();
- gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
- config->priv->name_entry = g_object_ref_sink (widget);
- gtk_widget_show (widget);
-
- /* The backend box holds backend-specific options. Each backend
- * gets a child widget. Only one child widget is visible at once. */
- widget = gtk_vbox_new (FALSE, 12);
- gtk_box_pack_end (GTK_BOX (config), widget, TRUE, TRUE, 0);
- config->priv->backend_box = g_object_ref (widget);
- gtk_widget_show (widget);
-
- pango_attr_list_unref (attr_list);
-
- g_signal_connect (
- config->priv->type_combo, "changed",
- G_CALLBACK (source_config_type_combo_changed_cb), config);
-}
-
-GtkWidget *
-e_source_config_new (ESourceRegistry *registry,
- ESource *original_source)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- if (original_source != NULL)
- g_return_val_if_fail (E_IS_SOURCE (original_source), NULL);
-
- return g_object_new (
- E_TYPE_SOURCE_CONFIG, "registry", registry,
- "original-source", original_source, NULL);
-}
-
-void
-e_source_config_insert_widget (ESourceConfig *config,
- ESource *scratch_source,
- const gchar *caption,
- GtkWidget *widget)
-{
- GtkWidget *hbox;
- GtkWidget *vbox;
- GtkWidget *label;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- if (scratch_source == NULL)
- vbox = GTK_WIDGET (config);
- else
- vbox = e_source_config_get_page (config, scratch_source);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
-
- g_object_bind_property (
- widget, "visible",
- hbox, "visible",
- G_BINDING_SYNC_CREATE);
-
- label = gtk_label_new (caption);
- gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
- gtk_size_group_add_widget (config->priv->size_group, label);
- gtk_widget_show (label);
-
- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
-}
-
-GtkWidget *
-e_source_config_get_page (ESourceConfig *config,
- ESource *scratch_source)
-{
- Candidate *candidate;
- GtkWidget *page = NULL;
- GPtrArray *array;
- gint index;
-
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
- g_return_val_if_fail (E_IS_SOURCE (scratch_source), NULL);
-
- array = config->priv->candidates;
-
- for (index = 0; page == NULL && index < array->len; index++) {
- candidate = g_ptr_array_index (array, index);
- if (e_source_equal (scratch_source, candidate->scratch_source))
- page = candidate->page;
- }
-
- g_return_val_if_fail (GTK_IS_BOX (page), NULL);
-
- return page;
-}
-
-const gchar *
-e_source_config_get_backend_extension_name (ESourceConfig *config)
-{
- ESourceConfigClass *class;
-
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
-
- class = E_SOURCE_CONFIG_GET_CLASS (config);
- g_return_val_if_fail (class->get_backend_extension_name != NULL, NULL);
-
- return class->get_backend_extension_name (config);
-}
-
-GList *
-e_source_config_list_eligible_collections (ESourceConfig *config)
-{
- ESourceConfigClass *class;
-
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
-
- class = E_SOURCE_CONFIG_GET_CLASS (config);
- g_return_val_if_fail (class->list_eligible_collections != NULL, NULL);
-
- return class->list_eligible_collections (config);
-}
-
-gboolean
-e_source_config_check_complete (ESourceConfig *config)
-{
- Candidate *candidate;
- gboolean complete;
-
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), FALSE);
-
- candidate = source_config_get_active_candidate (config);
- g_return_val_if_fail (candidate != NULL, FALSE);
-
- g_signal_emit (
- config, signals[CHECK_COMPLETE], 0,
- candidate->scratch_source, &complete);
-
- complete &= e_source_config_backend_check_complete (
- candidate->backend, candidate->scratch_source);
-
- /* XXX Emitting "notify::complete" may cause this function
- * to be called repeatedly by signal handlers. The IF
- * check below should break any recursive cycles. Not
- * very efficient but I think we can live with it. */
-
- if (complete != config->priv->complete) {
- config->priv->complete = complete;
- g_object_notify (G_OBJECT (config), "complete");
- }
-
- return complete;
-}
-
-ESource *
-e_source_config_get_original_source (ESourceConfig *config)
-{
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
-
- return config->priv->original_source;
-}
-
-ESource *
-e_source_config_get_collection_source (ESourceConfig *config)
-{
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
-
- return config->priv->collection_source;
-}
-
-ESourceRegistry *
-e_source_config_get_registry (ESourceConfig *config)
-{
- g_return_val_if_fail (E_IS_SOURCE_CONFIG (config), NULL);
-
- return config->priv->registry;
-}
-
-void
-e_source_config_resize_window (ESourceConfig *config)
-{
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
-
- g_signal_emit (config, signals[RESIZE_WINDOW], 0);
-}
-
-/* Helper for e_source_config_commit() */
-static void
-source_config_commit_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
- GError *error = NULL;
-
- simple = G_SIMPLE_ASYNC_RESULT (user_data);
-
- 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);
-}
-
-void
-e_source_config_commit (ESourceConfig *config,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
- ESourceRegistry *registry;
- Candidate *candidate;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
-
- registry = e_source_config_get_registry (config);
-
- candidate = source_config_get_active_candidate (config);
- g_return_if_fail (candidate != NULL);
-
- e_source_config_backend_commit_changes (
- candidate->backend, candidate->scratch_source);
-
- g_signal_emit (
- config, signals[COMMIT_CHANGES], 0,
- candidate->scratch_source);
-
- simple = g_simple_async_result_new (
- G_OBJECT (config), callback,
- user_data, e_source_config_commit);
-
- e_source_registry_commit_source (
- registry, candidate->scratch_source,
- cancellable, source_config_commit_cb, simple);
-}
-
-gboolean
-e_source_config_commit_finish (ESourceConfig *config,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (
- g_simple_async_result_is_valid (
- result, G_OBJECT (config),
- e_source_config_commit), FALSE);
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
-
- /* Assume success unless a GError is set. */
- return !g_simple_async_result_propagate_error (simple, error);
-}
-
-void
-e_source_config_add_refresh_interval (ESourceConfig *config,
- ESource *scratch_source)
-{
- GtkWidget *widget;
- GtkWidget *container;
- ESourceExtension *extension;
- const gchar *extension_name;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
- g_return_if_fail (E_IS_SOURCE (scratch_source));
-
- extension_name = E_SOURCE_EXTENSION_REFRESH;
- extension = e_source_get_extension (scratch_source, extension_name);
-
- widget = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
- e_source_config_insert_widget (config, scratch_source, NULL, widget);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_hbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (container), widget);
- gtk_widget_show (widget);
-
- container = widget;
-
- /* Translators: This is the first of a sequence of widgets:
- * "Refresh every [NUMERIC_ENTRY] [TIME_UNITS_COMBO]" */
- widget = gtk_label_new (_("Refresh every"));
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- widget = e_interval_chooser_new ();
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- g_object_bind_property (
- extension, "interval-minutes",
- widget, "interval-minutes",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-}
-
-void
-e_source_config_add_secure_connection (ESourceConfig *config,
- ESource *scratch_source)
-{
- GtkWidget *widget;
- ESourceExtension *extension;
- const gchar *extension_name;
- const gchar *label;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
- g_return_if_fail (E_IS_SOURCE (scratch_source));
-
- extension_name = E_SOURCE_EXTENSION_SECURITY;
- extension = e_source_get_extension (scratch_source, extension_name);
-
- label = _("Use a secure connection");
- widget = gtk_check_button_new_with_label (label);
- e_source_config_insert_widget (config, scratch_source, NULL, widget);
- gtk_widget_show (widget);
-
- g_object_bind_property (
- extension, "secure",
- widget, "active",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-}
-
-static gboolean
-secure_to_port_cb (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- GObject *authentication_extension;
- guint16 port;
-
- authentication_extension = g_binding_get_target (binding);
- g_object_get (authentication_extension, "port", &port, NULL);
-
- if (port == 80 || port == 443 || port == 0)
- port = g_value_get_boolean (source_value) ? 443 : 80;
-
- g_value_set_uint (target_value, port);
-
- return TRUE;
-}
-
-void
-e_source_config_add_secure_connection_for_webdav (ESourceConfig *config,
- ESource *scratch_source)
-{
- GtkWidget *widget1;
- GtkWidget *widget2;
- ESourceExtension *extension;
- ESourceAuthentication *authentication_extension;
- const gchar *extension_name;
- const gchar *label;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
- g_return_if_fail (E_IS_SOURCE (scratch_source));
-
- extension_name = E_SOURCE_EXTENSION_SECURITY;
- extension = e_source_get_extension (scratch_source, extension_name);
-
- label = _("Use a secure connection");
- widget1 = gtk_check_button_new_with_label (label);
- e_source_config_insert_widget (config, scratch_source, NULL, widget1);
- gtk_widget_show (widget1);
-
- g_object_bind_property (
- extension, "secure",
- widget1, "active",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- authentication_extension = e_source_get_extension (scratch_source, extension_name);
-
- g_object_bind_property_full (
- extension, "secure",
- authentication_extension, "port",
- G_BINDING_DEFAULT,
- secure_to_port_cb,
- NULL, NULL, NULL);
-
- extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
- extension = e_source_get_extension (scratch_source, extension_name);
-
- label = _("Ignore invalid SSL certificate");
- widget2 = gtk_check_button_new_with_label (label);
- gtk_widget_set_margin_left (widget2, 24);
- e_source_config_insert_widget (config, scratch_source, NULL, widget2);
- gtk_widget_show (widget2);
-
- g_object_bind_property (
- widget1, "active",
- widget2, "sensitive",
- G_BINDING_SYNC_CREATE);
-
- g_object_bind_property (
- extension, "ignore-invalid-cert",
- widget2, "active",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-}
-
-void
-e_source_config_add_user_entry (ESourceConfig *config,
- ESource *scratch_source)
-{
- GtkWidget *widget;
- ESource *original_source;
- ESourceExtension *extension;
- const gchar *extension_name;
-
- g_return_if_fail (E_IS_SOURCE_CONFIG (config));
- g_return_if_fail (E_IS_SOURCE (scratch_source));
-
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- extension = e_source_get_extension (scratch_source, extension_name);
-
- original_source = e_source_config_get_original_source (config);
-
- widget = gtk_entry_new ();
- e_source_config_insert_widget (
- config, scratch_source, _("User"), widget);
- gtk_widget_show (widget);
-
- g_object_bind_property (
- extension, "user",
- widget, "text",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-
- /* If this is a new data source, initialize the
- * GtkEntry to the user name of the current user. */
- if (original_source == NULL)
- gtk_entry_set_text (GTK_ENTRY (widget), g_get_user_name ());
-}
-