diff options
-rw-r--r-- | doc/reference/libeutil/libeutil-docs.sgml | 3 | ||||
-rw-r--r-- | doc/reference/libeutil/libeutil-sections.txt | 23 | ||||
-rw-r--r-- | doc/reference/libeutil/libeutil.types | 1 | ||||
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-client-selector.c | 419 | ||||
-rw-r--r-- | e-util/e-client-selector.h | 87 | ||||
-rw-r--r-- | e-util/e-util.h | 1 |
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> |