aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/reference/libeutil/libeutil-docs.sgml3
-rw-r--r--doc/reference/libeutil/libeutil-sections.txt23
-rw-r--r--doc/reference/libeutil/libeutil.types1
-rw-r--r--e-util/Makefile.am2
-rw-r--r--e-util/e-client-selector.c419
-rw-r--r--e-util/e-client-selector.h87
-rw-r--r--e-util/e-util.h1
7 files changed, 535 insertions, 1 deletions
diff --git a/doc/reference/libeutil/libeutil-docs.sgml b/doc/reference/libeutil/libeutil-docs.sgml
index 1733a48eea..3ec7742373 100644
--- a/doc/reference/libeutil/libeutil-docs.sgml
+++ b/doc/reference/libeutil/libeutil-docs.sgml
@@ -181,6 +181,8 @@
<xi:include href="xml/e-source-selector-dialog.xml"/>
<xi:include href="xml/e-source-combo-box.xml"/>
<xi:include href="xml/e-source-util.xml"/>
+ <xi:include href="xml/e-client-cache.xml"/>
+ <xi:include href="xml/e-client-selector.xml"/>
</chapter>
<chapter>
@@ -226,7 +228,6 @@
<xi:include href="xml/e-calendar.xml"/>
<xi:include href="xml/e-cell-renderer-color.xml"/>
<xi:include href="xml/e-charset-combo-box.xml"/>
- <xi:include href="xml/e-client-cache.xml"/>
<xi:include href="xml/e-contact-store.xml"/>
<xi:include href="xml/e-dateedit.xml"/>
<xi:include href="xml/e-destination-store.xml"/>
diff --git a/doc/reference/libeutil/libeutil-sections.txt b/doc/reference/libeutil/libeutil-sections.txt
index 6b5449224e..7f092b083f 100644
--- a/doc/reference/libeutil/libeutil-sections.txt
+++ b/doc/reference/libeutil/libeutil-sections.txt
@@ -1274,6 +1274,29 @@ EClientCachePrivate
</SECTION>
<SECTION>
+<FILE>e-client-selector</FILE>
+<TITLE>EClientSelector</TITLE>
+EClientSelector
+e_client_selector_new
+e_client_selector_ref_client_cache
+e_client_selector_get_client_sync
+e_client_selector_get_client
+e_client_selector_get_client_finish
+e_client_selector_ref_cached_client
+<SUBSECTION Standard>
+E_CLIENT_SELECTOR
+E_IS_CLIENT_SELECTOR
+E_TYPE_CLIENT_SELECTOR
+E_CLIENT_SELECTOR_CLASS
+E_IS_CLIENT_SELECTOR_CLASS
+E_CLIENT_SELECTOR_GET_CLASS
+EClientSelectorClass
+e_client_selector_get_type
+<SUBSECTION Private>
+EClientSelectorPrivate
+</SECTION>
+
+<SECTION>
<FILE>e-config</FILE>
<TITLE>EConfig</TITLE>
EConfig
diff --git a/doc/reference/libeutil/libeutil.types b/doc/reference/libeutil/libeutil.types
index 181231561e..bfbbfd91a1 100644
--- a/doc/reference/libeutil/libeutil.types
+++ b/doc/reference/libeutil/libeutil.types
@@ -54,6 +54,7 @@ e_cell_tree_get_type
e_cell_vbox_get_type
e_charset_combo_box_get_type
e_client_cache_get_type
+e_client_selector_get_type
e_config_get_type
e_config_hook_get_type
e_contact_store_get_type
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 738ce8559d..f802218db3 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -159,6 +159,7 @@ eutilinclude_HEADERS = \
e-charset-combo-box.h \
e-charset.h \
e-client-cache.h \
+ e-client-selector.h \
e-config.h \
e-contact-store.h \
e-dateedit.h \
@@ -404,6 +405,7 @@ libeutil_la_SOURCES = \
e-charset-combo-box.c \
e-charset.c \
e-client-cache.c \
+ e-client-selector.c \
e-config.c \
e-contact-store.c \
e-dateedit.c \
diff --git a/e-util/e-client-selector.c b/e-util/e-client-selector.c
new file mode 100644
index 0000000000..bdff0594a3
--- /dev/null
+++ b/e-util/e-client-selector.c
@@ -0,0 +1,419 @@
+/*
+ * e-client-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/>
+ *
+ */
+
+/**
+ * SECTION: e-client-selector
+ * @include: e-util/e-util.h
+ * @short_description: Tree view of #EClient instances
+ *
+ * #EClientSelector extends the functionality of #ESourceSelector by
+ * utilizing an #EClientCache to display status information about the
+ * backends associated with the displayed data sources.
+ **/
+
+#include "e-client-selector.h"
+
+#define E_CLIENT_SELECTOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_CLIENT_SELECTOR, EClientSelectorPrivate))
+
+struct _EClientSelectorPrivate {
+ EClientCache *client_cache;
+};
+
+enum {
+ PROP_0,
+ PROP_CLIENT_CACHE
+};
+
+G_DEFINE_TYPE (
+ EClientSelector,
+ e_client_selector,
+ E_TYPE_SOURCE_SELECTOR)
+
+static void
+client_selector_set_client_cache (EClientSelector *selector,
+ EClientCache *client_cache)
+{
+ g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
+ g_return_if_fail (selector->priv->client_cache == NULL);
+
+ selector->priv->client_cache = g_object_ref (client_cache);
+}
+
+static void
+client_selector_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CLIENT_CACHE:
+ client_selector_set_client_cache (
+ E_CLIENT_SELECTOR (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+client_selector_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CLIENT_CACHE:
+ g_value_take_object (
+ value,
+ e_client_selector_ref_client_cache (
+ E_CLIENT_SELECTOR (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+client_selector_dispose (GObject *object)
+{
+ EClientSelectorPrivate *priv;
+
+ priv = E_CLIENT_SELECTOR_GET_PRIVATE (object);
+
+ g_clear_object (&priv->client_cache);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_client_selector_parent_class)->dispose (object);
+}
+
+static void
+e_client_selector_class_init (EClientSelectorClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EClientSelectorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = client_selector_set_property;
+ object_class->get_property = client_selector_get_property;
+ object_class->dispose = client_selector_dispose;
+
+ /**
+ * EClientSelector:client-cache:
+ *
+ * Cache of shared #EClient instances.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_CLIENT_CACHE,
+ g_param_spec_object (
+ "client-cache",
+ "Client Cache",
+ "Cache of shared EClient instances",
+ E_TYPE_CLIENT_CACHE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_client_selector_init (EClientSelector *selector)
+{
+ selector->priv = E_CLIENT_SELECTOR_GET_PRIVATE (selector);
+}
+
+/**
+ * e_client_selector_new:
+ * @client_cache: an #EClientCache
+ * @extension_name: the name of an #ESource extension
+ *
+ * Displays a list of sources having an extension named @extension_name,
+ * along with status information about the backends associated with them.
+ * The sources are grouped by backend or groupware account, which are
+ * described by the parent source.
+ *
+ * Returns: a new #EClientSelector
+ **/
+GtkWidget *
+e_client_selector_new (EClientCache *client_cache,
+ const gchar *extension_name)
+{
+ ESourceRegistry *registry;
+ GtkWidget *widget;
+
+ g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL);
+ g_return_val_if_fail (extension_name != NULL, NULL);
+
+ registry = e_client_cache_ref_registry (client_cache);
+
+ widget = g_object_new (
+ E_TYPE_CLIENT_SELECTOR,
+ "client-cache", client_cache,
+ "extension-name", extension_name,
+ "registry", registry, NULL);
+
+ g_object_unref (registry);
+
+ return widget;
+}
+
+/**
+ * e_client_selector_ref_client_cache:
+ * @selector: an #EClientSelector
+ *
+ * Returns the #EClientCache passed to e_client_selector_new().
+ *
+ * The returned #EClientCache is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * Returns: an #EClientCache
+ **/
+EClientCache *
+e_client_selector_ref_client_cache (EClientSelector *selector)
+{
+ g_return_val_if_fail (E_IS_CLIENT_SELECTOR (selector), NULL);
+
+ return g_object_ref (selector->priv->client_cache);
+}
+
+/**
+ * e_client_selector_get_client_sync:
+ * @selector: an #ESourceSelector
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains a shared #EClient instance for @source, or else creates a new
+ * #EClient instance to be shared.
+ *
+ * The #ESourceSelector:extension-name property determines the type of
+ * #EClient to obtain. See e_client_cache_get_client_sync() for a list
+ * of valid extension names.
+ *
+ * If a request for the same @source and #ESourceSelector:extension-name
+ * is already in progress when this function is called, this request will
+ * "piggyback" on the in-progress request such that they will both succeed
+ * or fail simultaneously.
+ *
+ * Unreference the returned #EClient with g_object_unref() when finished
+ * with it. If an error occurs, the function will set @error and return
+ * %NULL.
+ *
+ * Returns: an #EClient, or %NULL
+ **/
+EClient *
+e_client_selector_get_client_sync (EClientSelector *selector,
+ ESource *source,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ EClient *client;
+
+ closure = e_async_closure_new ();
+
+ e_client_selector_get_client (
+ selector, source, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ client = e_client_selector_get_client_finish (
+ selector, result, error);
+
+ e_async_closure_free (closure);
+
+ return client;
+}
+
+/* Helper for e_client_selector_get_client() */
+static void
+client_selector_get_client_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EClient *client;
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ client = e_client_cache_get_client_finish (
+ E_CLIENT_CACHE (source_object), result, &error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((client != NULL) && (error == NULL)) ||
+ ((client == NULL) && (error != NULL)));
+
+ if (client != NULL) {
+ g_simple_async_result_set_op_res_gpointer (
+ simple, g_object_ref (client),
+ (GDestroyNotify) g_object_unref);
+ g_object_unref (client);
+ }
+
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_client_selector_get_client:
+ * @selector: an #ESourceSelector
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously obtains a shared #EClient instance for @source, or else
+ * creates a new #EClient instance to be shared.
+ *
+ * The #ESourceSelector:extension-name property determines the type of
+ * #EClient to obtain. See e_client_cache_get_client_sync() for a list
+ * of valid extension names.
+ *
+ * If a request for the same @source and #ESourceSelector:extension-name
+ * is already in progress when this function is called, this request will
+ * "piggyback" on the in-progress request such that they will both succeed
+ * or fail simultaneously.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call e_client_selector_get_client_finish() to get the result of
+ * the operation.
+ **/
+void
+e_client_selector_get_client (EClientSelector *selector,
+ ESource *source,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ EClientCache *client_cache;
+ GSimpleAsyncResult *simple;
+ const gchar *extension_name;
+
+ g_return_if_fail (E_IS_CLIENT_SELECTOR (selector));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (selector), callback,
+ user_data, e_client_selector_get_client);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ extension_name = e_source_selector_get_extension_name (
+ E_SOURCE_SELECTOR (selector));
+
+ client_cache = e_client_selector_ref_client_cache (selector);
+
+ e_client_cache_get_client (
+ client_cache, source,
+ extension_name, cancellable,
+ client_selector_get_client_done_cb,
+ g_object_ref (simple));
+
+ g_object_unref (client_cache);
+
+ g_object_unref (simple);
+}
+
+/**
+ * e_client_selector_get_client_finish:
+ * @selector: an #EClientSelector
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_client_selector_get_client().
+ *
+ * Unreference the returned #EClient with g_object_unref() when finished
+ * with it. If an error occurred, the function will set @error and return
+ * %NULL.
+ *
+ * Returns: an #EClient, or %NULL
+ **/
+EClient *
+e_client_selector_get_client_finish (EClientSelector *selector,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ EClient *client;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (selector),
+ e_client_selector_get_client), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ client = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+
+ return g_object_ref (client);
+}
+
+/**
+ * e_client_selector_ref_cached_client:
+ * @selector: an #EClientSelector
+ * @source: an #ESource
+ *
+ * Returns a shared #EClient instance for @source and the value of
+ * #ESourceSelector:extension-name if such an instance is already cached,
+ * or else %NULL. This function does not create a new #EClient instance,
+ * and therefore does not block.
+ *
+ * The returned #EClient is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * Returns: an #EClient, or %NULL
+ **/
+EClient *
+e_client_selector_ref_cached_client (EClientSelector *selector,
+ ESource *source)
+{
+ EClient *client;
+ EClientCache *client_cache;
+ const gchar *extension_name;
+
+ g_return_val_if_fail (E_IS_CLIENT_SELECTOR (selector), NULL);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ extension_name = e_source_selector_get_extension_name (
+ E_SOURCE_SELECTOR (selector));
+
+ client_cache = e_client_selector_ref_client_cache (selector);
+
+ client = e_client_cache_ref_cached_client (
+ client_cache, source, extension_name);
+
+ g_object_unref (client_cache);
+
+ return client;
+}
+
diff --git a/e-util/e-client-selector.h b/e-util/e-client-selector.h
new file mode 100644
index 0000000000..25974237d1
--- /dev/null
+++ b/e-util/e-client-selector.h
@@ -0,0 +1,87 @@
+/*
+ * e-client-selector.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_CLIENT_SELECTOR_H
+#define E_CLIENT_SELECTOR_H
+
+#include <e-util/e-client-cache.h>
+#include <e-util/e-source-selector.h>
+
+/* Standard GObject macros */
+#define E_TYPE_CLIENT_SELECTOR \
+ (e_client_selector_get_type ())
+#define E_CLIENT_SELECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CLIENT_SELECTOR, EClientSelector))
+#define E_CLIENT_SELECTOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CLIENT_SELECTOR, EClientSelectorClass))
+#define E_IS_CLIENT_SELECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CLIENT_SELECTOR))
+#define E_IS_CLIENT_SELECTOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_CLIENT_SELECTOR))
+#define E_CLIENT_SELECTOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CLIENT_SELECTOR, EClientSelectorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EClientSelector EClientSelector;
+typedef struct _EClientSelectorClass EClientSelectorClass;
+typedef struct _EClientSelectorPrivate EClientSelectorPrivate;
+
+struct _EClientSelector {
+ ESourceSelector parent;
+ EClientSelectorPrivate *priv;
+};
+
+struct _EClientSelectorClass {
+ ESourceSelectorClass parent_class;
+};
+
+GType e_client_selector_get_type (void) G_GNUC_CONST;
+GtkWidget * e_client_selector_new (EClientCache *client_cache,
+ const gchar *extension_name);
+EClientCache * e_client_selector_ref_client_cache
+ (EClientSelector *selector);
+EClient * e_client_selector_get_client_sync
+ (EClientSelector *selector,
+ ESource *source,
+ GCancellable *cancellable,
+ GError **error);
+void e_client_selector_get_client (EClientSelector *selector,
+ ESource *source,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+EClient * e_client_selector_get_client_finish
+ (EClientSelector *selector,
+ GAsyncResult *result,
+ GError **error);
+EClient * e_client_selector_ref_cached_client
+ (EClientSelector *selector,
+ ESource *source);
+
+#endif /* E_CLIENT_SELECTOR_H */
+
diff --git a/e-util/e-util.h b/e-util/e-util.h
index cd8f08b5b8..6b3934fa8d 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -81,6 +81,7 @@
#include <e-util/e-charset-combo-box.h>
#include <e-util/e-charset.h>
#include <e-util/e-client-cache.h>
+#include <e-util/e-client-selector.h>
#include <e-util/e-config.h>
#include <e-util/e-contact-store.h>
#include <e-util/e-dateedit.h>