*/
#include <config.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xmlmemory.h>
-#include <libedataserver/e-data-server-util.h>
+#include <glib/gi18n-lib.h>
#include "e-cal-backend.h"
#include "e-cal-backend-cache.h"
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_CAL_BACKEND, ECalBackendPrivate))
-/* For convenience */
-#define CLASS(backend) (E_CAL_BACKEND_GET_CLASS(backend))
-
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EDC_OPENING_ERROR e_data_cal_create_error (Busy, _("Cannot process, calendar backend is opening"))
+#define EDC_NOT_OPENED_ERROR e_data_cal_create_error (NotOpened, NULL)
/* Private part of the CalBackend structure */
struct _ECalBackendPrivate {
- /* The source for this backend */
- ESource *source;
- /* signal handler ID for source's 'changed' signal */
- gulong source_changed_id;
-
- /* URI, from source. This is cached, since we return const. */
- gchar *uri;
-
- gchar *cache_dir;
+ ESourceRegistry *registry;
/* The kind of components for this backend */
icalcomponent_kind kind;
+ gboolean opening, opened, readonly, removed;
+
+ gchar *cache_dir;
+
/* List of Cal objects */
- GMutex *clients_mutex;
+ GMutex clients_mutex;
GList *clients;
- GMutex *queries_mutex;
- EList *queries;
+ GMutex views_mutex;
+ GList *views;
+
+ GHashTable *zone_cache;
+ GMutex zone_cache_lock;
/* ECalBackend to pass notifications on to */
ECalBackend *notification_proxy;
- /* used when notifying clients about progress of some operation,
- * we do not send multiple notifications with the same percent
- * value */
- gint last_percent_notified;
};
/* Property IDs */
PROP_0,
PROP_CACHE_DIR,
PROP_KIND,
- PROP_SOURCE,
- PROP_URI
-};
-
-/* Signal IDs */
-enum {
- LAST_CLIENT_GONE,
- LAST_SIGNAL
+ PROP_REGISTRY
};
-static guint signals[LAST_SIGNAL];
-
-static void e_cal_backend_remove_client_private (ECalBackend *backend, EDataCal *cal, gboolean weak_unref);
-
-G_DEFINE_TYPE (ECalBackend, e_cal_backend, G_TYPE_OBJECT);
+/* Forward Declarations */
+static void e_cal_backend_remove_client_private
+ (ECalBackend *backend,
+ EDataCal *cal,
+ gboolean weak_unref);
+static void e_cal_backend_timezone_cache_init
+ (ETimezoneCacheInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+ ECalBackend,
+ e_cal_backend,
+ E_TYPE_BACKEND,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_TIMEZONE_CACHE,
+ e_cal_backend_timezone_cache_init))
static void
-source_changed_cb (ESource *source, ECalBackend *backend)
+cal_backend_free_zone (icaltimezone *zone)
{
- ECalBackendPrivate *priv;
- gchar *suri;
-
- g_return_if_fail (source != NULL);
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- priv = backend->priv;
- g_return_if_fail (priv != NULL);
- g_return_if_fail (priv->source == source);
-
- suri = e_source_get_uri (priv->source);
- if (!priv->uri || (suri && !g_str_equal (priv->uri, suri))) {
- g_free (priv->uri);
- priv->uri = suri;
- } else {
- g_free (suri);
- }
+ icaltimezone_free (zone, 1);
}
static void
icalcomponent_kind kind;
const gchar *component_type;
const gchar *user_cache_dir;
- gchar *mangled_uri;
+ const gchar *uid;
gchar *filename;
user_cache_dir = e_get_user_cache_dir ();
kind = e_cal_backend_get_kind (backend);
- source = e_cal_backend_get_source (backend);
- g_return_if_fail (source != NULL);
+ source = e_backend_get_source (E_BACKEND (backend));
+
+ uid = e_source_get_uid (source);
+ g_return_if_fail (uid != NULL);
switch (kind) {
case ICAL_VEVENT_COMPONENT:
g_return_if_reached ();
}
- /* Mangle the URI to not contain invalid characters. */
- mangled_uri = g_strdelimit (e_source_get_uri (source), ":/", '_');
-
filename = g_build_filename (
- user_cache_dir, component_type, mangled_uri, NULL);
+ user_cache_dir, component_type, uid, NULL);
e_cal_backend_set_cache_dir (backend, filename);
g_free (filename);
-
- g_free (mangled_uri);
}
static void
-cal_backend_set_source (ECalBackend *backend,
- ESource *source)
-{
- if (backend->priv->source != NULL) {
- if (backend->priv->source_changed_id > 0) {
- g_signal_handler_disconnect (
- backend->priv->source,
- backend->priv->source_changed_id);
- backend->priv->source_changed_id = 0;
- }
- g_object_unref (backend->priv->source);
- }
-
- if (source != NULL)
- backend->priv->source_changed_id = g_signal_connect (
- g_object_ref (source), "changed",
- G_CALLBACK (source_changed_cb), backend);
-
- backend->priv->source = source;
-
- /* Cache the URI */
- if (source != NULL) {
- g_free (backend->priv->uri);
- backend->priv->uri = e_source_get_uri (source);
+cal_backend_get_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opened (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opening (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_backend_get_online (E_BACKEND (backend)) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_readonly (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_get_cache_dir (backend));
+ } else {
+ e_data_cal_respond_get_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Unknown calendar property '%s'"), prop_name), NULL);
}
}
static void
-cal_backend_set_uri (ECalBackend *backend,
- const gchar *uri)
+cal_backend_set_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name,
+ const gchar *prop_value)
{
- /* ESource's URI gets priority. */
- if (backend->priv->source == NULL) {
- g_free (backend->priv->uri);
- backend->priv->uri = g_strdup (uri);
- }
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ e_data_cal_respond_set_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Cannot change value of calendar property '%s'"), prop_name));
}
static void
}
static void
+cal_backend_set_registry (ECalBackend *backend,
+ ESourceRegistry *registry)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (backend->priv->registry == NULL);
+
+ backend->priv->registry = g_object_ref (registry);
+}
+
+static void
cal_backend_set_property (GObject *object,
guint property_id,
const GValue *value,
E_CAL_BACKEND (object),
g_value_get_string (value));
return;
+
case PROP_KIND:
cal_backend_set_kind (
E_CAL_BACKEND (object),
g_value_get_ulong (value));
return;
- case PROP_SOURCE:
- cal_backend_set_source (
+
+ case PROP_REGISTRY:
+ cal_backend_set_registry (
E_CAL_BACKEND (object),
g_value_get_object (value));
return;
- case PROP_URI:
- cal_backend_set_uri (
- E_CAL_BACKEND (object),
- g_value_get_string (value));
- return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
value, e_cal_backend_get_cache_dir (
E_CAL_BACKEND (object)));
return;
+
case PROP_KIND:
g_value_set_ulong (
value, e_cal_backend_get_kind (
E_CAL_BACKEND (object)));
return;
- case PROP_SOURCE:
+
+ case PROP_REGISTRY:
g_value_set_object (
- value, e_cal_backend_get_source (
- E_CAL_BACKEND (object)));
- return;
- case PROP_URI:
- g_value_set_string (
- value, e_cal_backend_get_uri (
+ value, e_cal_backend_get_registry (
E_CAL_BACKEND (object)));
return;
}
}
static void
+cal_backend_dispose (GObject *object)
+{
+ ECalBackendPrivate *priv;
+
+ priv = E_CAL_BACKEND_GET_PRIVATE (object);
+
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_cal_backend_parent_class)->dispose (object);
+}
+
+static void
cal_backend_finalize (GObject *object)
{
ECalBackendPrivate *priv;
g_assert (priv->clients == NULL);
- g_object_unref (priv->queries);
+ /* should be NULL, anyway */
+ g_list_free (priv->clients);
+ g_mutex_clear (&priv->clients_mutex);
- g_mutex_free (priv->clients_mutex);
- g_mutex_free (priv->queries_mutex);
+ g_list_free (priv->views);
+ g_mutex_clear (&priv->views_mutex);
- g_free (priv->uri);
- g_free (priv->cache_dir);
+ g_hash_table_destroy (priv->zone_cache);
+ g_mutex_clear (&priv->zone_cache_lock);
- if (priv->source_changed_id && priv->source) {
- g_signal_handler_disconnect (priv->source, priv->source_changed_id);
- priv->source_changed_id = 0;
- }
- g_object_unref (priv->source);
+ g_free (priv->cache_dir);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
cal_backend_constructed (GObject *object)
{
cal_backend_set_default_cache_dir (E_CAL_BACKEND (object));
+
+ G_OBJECT_CLASS (e_cal_backend_parent_class)->constructed (object);
+}
+
+static gboolean
+cal_backend_authenticate_sync (EBackend *backend,
+ ESourceAuthenticator *auth,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ECalBackend *cal_backend;
+ ESourceRegistry *registry;
+ ESource *source;
+
+ cal_backend = E_CAL_BACKEND (backend);
+ registry = e_cal_backend_get_registry (cal_backend);
+ source = e_backend_get_source (backend);
+
+ return e_source_registry_authenticate_sync (
+ registry, source, auth, cancellable, error);
+}
+
+static void
+cal_backend_add_cached_timezone (ETimezoneCache *cache,
+ icaltimezone *zone)
+{
+ ECalBackendPrivate *priv;
+ const gchar *tzid;
+
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
+
+ g_mutex_lock (&priv->zone_cache_lock);
+
+ tzid = icaltimezone_get_tzid (zone);
+
+ /* Avoid replacing an existing cache entry. We don't want to
+ * invalidate any icaltimezone pointers that may have already
+ * been returned through e_timezone_cache_get_timezone(). */
+ if (!g_hash_table_contains (priv->zone_cache, tzid)) {
+ icalcomponent *icalcomp;
+ icaltimezone *cached_zone;
+
+ cached_zone = icaltimezone_new ();
+ icalcomp = icaltimezone_get_component (zone);
+ icalcomp = icalcomponent_new_clone (icalcomp);
+ icaltimezone_set_component (cached_zone, icalcomp);
+
+ g_hash_table_insert (
+ priv->zone_cache,
+ g_strdup (tzid), cached_zone);
+
+ /* FIXME Should emit this from an idle GSource on
+ * a stored GMainContext, but we don't have
+ * a stored GMainContext. Check back after
+ * the D-Bus API rewrite. */
+ g_signal_emit_by_name (cache, "timezone-added", zone);
+ }
+
+ g_mutex_unlock (&priv->zone_cache_lock);
+}
+
+static icaltimezone *
+cal_backend_get_cached_timezone (ETimezoneCache *cache,
+ const gchar *tzid)
+{
+ ECalBackendPrivate *priv;
+ icaltimezone *zone = NULL;
+ icaltimezone *builtin_zone = NULL;
+ icalcomponent *icalcomp;
+ icalproperty *prop;
+ const gchar *builtin_tzid;
+
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
+
+ if (g_str_equal (tzid, "UTC"))
+ return icaltimezone_get_utc_timezone ();
+
+ g_mutex_lock (&priv->zone_cache_lock);
+
+ /* See if we already have it in the cache. */
+ zone = g_hash_table_lookup (priv->zone_cache, tzid);
+
+ if (zone != NULL)
+ goto exit;
+
+ /* Try to replace the original time zone with a more complete
+ * and/or potentially updated built-in time zone. Note this also
+ * applies to TZIDs which match built-in time zones exactly: they
+ * are extracted via icaltimezone_get_builtin_timezone_from_tzid(). */
+
+ builtin_tzid = e_cal_match_tzid (tzid);
+
+ if (builtin_tzid != NULL)
+ builtin_zone = icaltimezone_get_builtin_timezone_from_tzid (
+ builtin_tzid);
+
+ if (builtin_zone == NULL)
+ goto exit;
+
+ /* Use the built-in time zone *and* rename it. Likely the caller
+ * is asking for a specific TZID because it has an event with such
+ * a TZID. Returning an icaltimezone with a different TZID would
+ * lead to broken VCALENDARs in the caller. */
+
+ icalcomp = icaltimezone_get_component (builtin_zone);
+ icalcomp = icalcomponent_new_clone (icalcomp);
+
+ prop = icalcomponent_get_first_property (
+ icalcomp, ICAL_ANY_PROPERTY);
+
+ while (prop != NULL) {
+ if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
+ icalproperty_set_value_from_string (prop, tzid, "NO");
+ break;
+ }
+
+ prop = icalcomponent_get_next_property (
+ icalcomp, ICAL_ANY_PROPERTY);
+ }
+
+ if (icalcomp != NULL) {
+ zone = icaltimezone_new ();
+ if (icaltimezone_set_component (zone, icalcomp)) {
+ tzid = icaltimezone_get_tzid (zone);
+ g_hash_table_insert (
+ priv->zone_cache,
+ g_strdup (tzid), zone);
+ } else {
+ icalcomponent_free (icalcomp);
+ icaltimezone_free (zone, 1);
+ zone = NULL;
+ }
+ }
+
+exit:
+ g_mutex_unlock (&priv->zone_cache_lock);
+
+ return zone;
+}
+
+static GList *
+cal_backend_list_cached_timezones (ETimezoneCache *cache)
+{
+ ECalBackendPrivate *priv;
+ GList *list;
+
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
+
+ g_mutex_lock (&priv->zone_cache_lock);
+
+ list = g_hash_table_get_values (priv->zone_cache);
+
+ g_mutex_unlock (&priv->zone_cache_lock);
+
+ return list;
}
static void
e_cal_backend_class_init (ECalBackendClass *class)
{
GObjectClass *object_class;
+ EBackendClass *backend_class;
g_type_class_add_private (class, sizeof (ECalBackendPrivate));
object_class = G_OBJECT_CLASS (class);
object_class->set_property = cal_backend_set_property;
object_class->get_property = cal_backend_get_property;
+ object_class->dispose = cal_backend_dispose;
object_class->finalize = cal_backend_finalize;
object_class->constructed = cal_backend_constructed;
+ backend_class = E_BACKEND_CLASS (class);
+ backend_class->authenticate_sync = cal_backend_authenticate_sync;
+
+ class->get_backend_property = cal_backend_get_backend_property;
+ class->set_backend_property = cal_backend_set_backend_property;
+
g_object_class_install_property (
object_class,
PROP_CACHE_DIR,
g_param_spec_string (
"cache-dir",
+ "Cache Dir",
+ "The backend's cache directory",
NULL,
- NULL,
- NULL,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
g_object_class_install_property (
object_class,
PROP_KIND,
g_param_spec_ulong (
"kind",
- NULL,
- NULL,
+ "Kind",
+ "The kind of iCalendar components "
+ "this backend manages",
ICAL_NO_COMPONENT,
ICAL_XLICMIMEPART_COMPONENT,
ICAL_NO_COMPONENT,
G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
g_object_class_install_property (
object_class,
- PROP_SOURCE,
+ PROP_REGISTRY,
g_param_spec_object (
- "source",
- NULL,
- NULL,
- E_TYPE_SOURCE,
+ "registry",
+ "Registry",
+ "Data source registry",
+ E_TYPE_SOURCE_REGISTRY,
G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (
- object_class,
- PROP_URI,
- g_param_spec_string (
- "uri",
- NULL,
- NULL,
- "",
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
- signals[LAST_CLIENT_GONE] = g_signal_new (
- "last_client_gone",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECalBackendClass, last_client_gone),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+static void
+e_cal_backend_timezone_cache_init (ETimezoneCacheInterface *interface)
+{
+ interface->add_timezone = cal_backend_add_cached_timezone;
+ interface->get_timezone = cal_backend_get_cached_timezone;
+ interface->list_timezones = cal_backend_list_cached_timezones;
}
static void
e_cal_backend_init (ECalBackend *backend)
{
- backend->priv = E_CAL_BACKEND_GET_PRIVATE (backend);
+ GHashTable *zone_cache;
- backend->priv->clients = NULL;
- backend->priv->clients_mutex = g_mutex_new ();
+ zone_cache = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) cal_backend_free_zone);
- backend->priv->queries = e_list_new (
- (EListCopyFunc) g_object_ref,
- (EListFreeFunc) g_object_unref, NULL);
- backend->priv->queries_mutex = g_mutex_new ();
-}
-
-/**
- * e_cal_backend_get_cache_dir:
- * @backend: an #ECalBackend
- *
- * Returns the cache directory for the given backend.
- *
- * Returns: the cache directory for the backend
- **/
-const gchar *
-e_cal_backend_get_cache_dir (ECalBackend *backend)
-{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ backend->priv = E_CAL_BACKEND_GET_PRIVATE (backend);
- return backend->priv->cache_dir;
-}
+ backend->priv->clients = NULL;
+ g_mutex_init (&backend->priv->clients_mutex);
-/**
- * e_cal_backend_set_cache_dir:
- * @backend: an #ECalBackend
- * @cache_dir: a local cache directory
- *
- * Sets the cache directory for the given backend.
- *
- * Note that #ECalBackend is initialized with a usable default based on
- * #ECalBackend:source and #ECalBackend:kind properties. Backends should
- * not override the default without good reason.
- **/
-void
-e_cal_backend_set_cache_dir (ECalBackend *backend,
- const gchar *cache_dir)
-{
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (cache_dir != NULL);
+ backend->priv->views = NULL;
+ g_mutex_init (&backend->priv->views_mutex);
- g_free (backend->priv->cache_dir);
- backend->priv->cache_dir = g_strdup (cache_dir);
+ backend->priv->zone_cache = zone_cache;
+ g_mutex_init (&backend->priv->zone_cache_lock);
- g_object_notify (G_OBJECT (backend), "cache-dir");
+ backend->priv->readonly = TRUE;
}
/**
}
/**
- * e_cal_backend_get_source:
+ * e_cal_backend_get_registry:
* @backend: an #ECalBackend
*
- * Gets the #ESource associated with the given backend.
+ * Returns the data source registry to which #EBackend:source belongs.
*
- * Returns: The #ESource for the backend.
- */
-ESource *
-e_cal_backend_get_source (ECalBackend *backend)
+ * Returns: an #ESourceRegistry
+ *
+ * Since: 3.6
+ **/
+ESourceRegistry *
+e_cal_backend_get_registry (ECalBackend *backend)
{
g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- return backend->priv->source;
+ return backend->priv->registry;
}
/**
- * e_cal_backend_get_uri:
+ * e_cal_backend_is_opened:
* @backend: an #ECalBackend
*
- * Queries the URI of a calendar backend, which must already have an open
- * calendar.
+ * Checks if @backend's storage has been opened (and
+ * authenticated, if necessary) and the backend itself
+ * is ready for accessing. This property is changed automatically
+ * within call of e_cal_backend_notify_opened().
+ *
+ * Returns: %TRUE if fully opened, %FALSE otherwise.
*
- * Returns: The URI where the calendar is stored.
+ * Since: 3.2
**/
-const gchar *
-e_cal_backend_get_uri (ECalBackend *backend)
+gboolean
+e_cal_backend_is_opened (ECalBackend *backend)
{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
-
- return backend->priv->uri;
-}
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
-static void
-cal_destroy_cb (gpointer data, GObject *where_cal_was)
-{
- e_cal_backend_remove_client_private (E_CAL_BACKEND (data),
- (EDataCal *) where_cal_was, FALSE);
+ return backend->priv->opened;
}
/**
- * e_cal_backend_add_client:
+ * e_cal_backend_is_opening:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
*
- * Adds a new client to the given backend. For any event, the backend will
- * notify all clients added via this function.
- */
-void
-e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal)
+ * Checks if @backend is processing its opening phase, which
+ * includes everything since the e_cal_backend_open() call,
+ * through authentication, up to e_cal_backend_notify_opened().
+ * This property is managed automatically and the backend deny
+ * every operation except of cancel and authenticate_user while
+ * it is being opening.
+ *
+ * Returns: %TRUE if opening phase is in the effect, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_is_opening (ECalBackend *backend)
{
- ECalBackendPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
-
- priv = backend->priv;
-
- g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
- g_mutex_lock (priv->clients_mutex);
- priv->clients = g_list_append (priv->clients, cal);
- g_mutex_unlock (priv->clients_mutex);
+ return backend->priv->opening;
}
-static void
-e_cal_backend_remove_client_private (ECalBackend *backend, EDataCal *cal, gboolean weak_unref)
+/**
+ * e_cal_backend_is_readonly:
+ * @backend: an #ECalBackend
+ *
+ * Returns: Whether is backend read-only. This value is the last used
+ * in a call of e_cal_backend_notify_readonly().
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_is_readonly (ECalBackend *backend)
{
- ECalBackendPrivate *priv;
-
- /* XXX this needs a bit more thinking wrt the mutex - we
- should be holding it when we check to see if clients is
- NULL */
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
-
- priv = backend->priv;
-
- if (weak_unref)
- g_object_weak_unref (G_OBJECT (cal), cal_destroy_cb, backend);
-
- /* Disconnect */
- g_mutex_lock (priv->clients_mutex);
- priv->clients = g_list_remove (priv->clients, cal);
- g_mutex_unlock (priv->clients_mutex);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
- /* When all clients go away, notify the parent factory about it so that
- * it may decide whether to kill the backend or not.
- */
- if (!priv->clients)
- g_signal_emit (backend, signals[LAST_CLIENT_GONE], 0);
+ return backend->priv->readonly;
}
/**
- * e_cal_backend_remove_client:
+ * e_cal_backend_is_removed:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
*
- * Removes a client from the list of connected clients to the given backend.
- */
-void
-e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal)
+ * Checks if @backend has been removed from its physical storage.
+ *
+ * Returns: %TRUE if @backend has been removed, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_is_removed (ECalBackend *backend)
{
- e_cal_backend_remove_client_private (backend, cal, TRUE);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->removed;
}
/**
- * e_cal_backend_add_query:
+ * e_cal_backend_set_is_removed:
* @backend: an #ECalBackend
- * @query: An #EDataCalView object.
+ * @is_removed: A flag indicating whether the backend's storage was removed
*
- * Adds a query to the list of live queries being run by the given backend.
- * Doing so means that any listener on the query will get notified of any
- * change that affect the live query.
- */
+ * Sets the flag indicating whether @backend was removed to @is_removed.
+ * Meant to be used by backend implementations.
+ *
+ * Since: 3.2
+ **/
void
-e_cal_backend_add_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_set_is_removed (ECalBackend *backend,
+ gboolean is_removed)
{
- g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_mutex_lock (backend->priv->queries_mutex);
-
- e_list_append (backend->priv->queries, query);
-
- g_mutex_unlock (backend->priv->queries_mutex);
+ backend->priv->removed = is_removed;
}
/**
- * e_cal_backend_get_queries:
+ * e_cal_backend_get_cache_dir:
* @backend: an #ECalBackend
*
- * Gets the list of live queries being run on the given backend.
+ * Returns the cache directory for the given backend.
+ *
+ * Returns: the cache directory for the backend
*
- * Returns: The list of live queries.
- */
-EList *
-e_cal_backend_get_queries (ECalBackend *backend)
+ * Since: 2.32
+ **/
+const gchar *
+e_cal_backend_get_cache_dir (ECalBackend *backend)
{
- g_return_val_if_fail (backend != NULL, NULL);
g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- return backend->priv->queries;
+ return backend->priv->cache_dir;
}
/**
- * e_cal_backend_remove_query
+ * e_cal_backend_set_cache_dir:
* @backend: an #ECalBackend
- * @query: An #EDataCalView object, previously added with @ref e_cal_backend_add_query.
+ * @cache_dir: a local cache directory
*
- * Removes query from the list of live queries for the backend.
+ * Sets the cache directory for the given backend.
+ *
+ * Note that #ECalBackend is initialized with a usable default based on
+ * #ECalBackend:source and #ECalBackend:kind properties. Backends should
+ * not override the default without good reason.
*
- * Since: 2.24
+ * Since: 2.32
**/
void
-e_cal_backend_remove_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_set_cache_dir (ECalBackend *backend,
+ const gchar *cache_dir)
{
- g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cache_dir != NULL);
- g_mutex_lock (backend->priv->queries_mutex);
+ if (g_strcmp0 (backend->priv->cache_dir, cache_dir) == 0)
+ return;
- e_list_remove (backend->priv->queries, query);
+ g_free (backend->priv->cache_dir);
+ backend->priv->cache_dir = g_strdup (cache_dir);
- g_mutex_unlock (backend->priv->queries_mutex);
+ g_object_notify (G_OBJECT (backend), "cache-dir");
}
/**
- * e_cal_backend_get_cal_address:
+ * e_cal_backend_create_cache_filename:
* @backend: an #ECalBackend
+ * @uid: a component UID
+ * @filename: a filename to use; can be NULL
+ * @fileindex: index of a file; used only when @filename is NULL
*
- * Queries the cal address associated with a calendar backend, which
- * must already have an open calendar.
+ * Returns: a filename for an attachment in a local cache dir. Free returned
+ * pointer with a g_free().
+ *
+ * Since: 3.4
**/
-void
-e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->get_cal_address != NULL);
- (* CLASS (backend)->get_cal_address) (backend, cal, context);
-}
-
-void
-e_cal_backend_notify_readonly (ECalBackend *backend, gboolean read_only)
-{
- ECalBackendPrivate *priv;
- GList *l;
-
- priv = backend->priv;
-
- if (priv->notification_proxy) {
- e_cal_backend_notify_readonly (priv->notification_proxy, read_only);
- return;
- }
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_read_only (l->data, NULL /* Success */, read_only);
-}
-
-void
-e_cal_backend_notify_cal_address (ECalBackend *backend, EServerMethodContext context, gchar *address)
+gchar *
+e_cal_backend_create_cache_filename (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *filename,
+ gint fileindex)
{
- ECalBackendPrivate *priv;
- GList *l;
-
- priv = backend->priv;
+ g_return_val_if_fail (backend != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_cal_address (l->data, context, NULL /* Success */, address);
+ return e_filename_mkdir_encoded (e_cal_backend_get_cache_dir (backend), uid, filename, fileindex);
}
/**
- * e_cal_backend_get_alarm_email_address:
+ * e_cal_backend_get_backend_property:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- *
- * Calls the get_alarm_email_address method on the given backend.
- */
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to get value of; cannot be NULL
+ *
+ * Calls the get_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_get_backend_property().
+ * Default implementation takes care of common properties and returns
+ * an 'unsupported' error for any unknown properties. The subclass may
+ * always call this default implementation for properties which fetching
+ * it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
void
-e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_get_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property != NULL);
- g_assert (CLASS (backend)->get_alarm_email_address != NULL);
- (* CLASS (backend)->get_alarm_email_address) (backend, cal, context);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
}
/**
- *e_cal_backend_get_alarm_email_address:
+ * e_cal_backend_set_backend_property:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- *
- * Calls the get_ldap_attribute method of the given backend.
- */
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to change; cannot be NULL
+ * @prop_value: value to set to @prop_name; cannot be NULL
+ *
+ * Calls the set_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_set_backend_property().
+ * Default implementation simply returns an 'unsupported' error.
+ * The subclass may always call this default implementation for properties
+ * which fetching it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
void
-e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_set_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name,
+ const gchar *prop_value)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (prop_value != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
- g_assert (CLASS (backend)->get_ldap_attribute != NULL);
- (* CLASS (backend)->get_ldap_attribute) (backend, cal, context);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
+}
+
+static void
+cal_destroy_cb (gpointer data,
+ GObject *where_cal_was)
+{
+ e_cal_backend_remove_client_private (
+ E_CAL_BACKEND (data),
+ (EDataCal *) where_cal_was, FALSE);
}
/**
- * e_cal_backend_get_alarm_email_address:
+ * e_cal_backend_add_client:
* @backend: an #ECalBackend
* @cal: an #EDataCal
*
- * Calls the get_static_capabilities method on the given backend.
+ * Adds a new client to the given backend. For any event, the backend will
+ * notify all clients added via this function.
*/
void
-e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_add_client (ECalBackend *backend,
+ EDataCal *cal)
{
+ ECalBackendPrivate *priv;
+
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (E_IS_DATA_CAL (cal));
+
+ priv = backend->priv;
+
+ g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
+
+ g_mutex_lock (&priv->clients_mutex);
+ priv->clients = g_list_append (priv->clients, cal);
+ g_mutex_unlock (&priv->clients_mutex);
+}
+
+static void
+e_cal_backend_remove_client_private (ECalBackend *backend,
+ EDataCal *cal,
+ gboolean weak_unref)
+{
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_IS_DATA_CAL (cal));
+
+ if (weak_unref)
+ g_object_weak_unref (G_OBJECT (cal), cal_destroy_cb, backend);
+
+ /* Make sure the backend stays alive while holding the mutex. */
+ g_object_ref (backend);
- g_assert (CLASS (backend)->get_static_capabilities != NULL);
- (* CLASS (backend)->get_static_capabilities) (backend, cal, context);
+ /* Disconnect */
+ g_mutex_lock (&backend->priv->clients_mutex);
+ backend->priv->clients = g_list_remove (backend->priv->clients, cal);
+
+ if (backend->priv->clients == NULL)
+ backend->priv->opening = FALSE;
+
+ g_mutex_unlock (&backend->priv->clients_mutex);
+
+ g_object_unref (backend);
}
/**
- * e_cal_backend_open:
+ * e_cal_backend_remove_client:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @only_if_exists: Whether the calendar should be opened only if it already
- * exists. If FALSE, a new calendar will be created when the specified @uri
- * does not exist.
- * @username: User name to use for authentication (if needed).
- * @password: Password for @username.
*
- * Opens a calendar backend with data from a calendar stored at the specified
- * URI.
+ * Removes a client from the list of connected clients to the given backend.
*/
void
-e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists,
- const gchar *username, const gchar *password)
+e_cal_backend_remove_client (ECalBackend *backend,
+ EDataCal *cal)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->open != NULL);
- (* CLASS (backend)->open) (backend, cal, context, only_if_exists, username, password);
+ e_cal_backend_remove_client_private (backend, cal, TRUE);
}
/**
- * e_cal_backend_refresh:
+ * e_cal_backend_add_view:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
+ * @view: An #EDataCalView object.
*
- * Refreshes the calendar being accessed by the given backend.
+ * Adds a view to the list of live views being run by the given backend.
+ * Doing so means that any listener on the view will get notified of any
+ * change that affect the live view.
*
- * Since: 2.30
+ * Since: 3.2
*/
void
-e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_add_view (ECalBackend *backend,
+ EDataCalView *view)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->refresh != NULL);
- (* CLASS (backend)->refresh) (backend, cal, context);
+ g_mutex_lock (&backend->priv->views_mutex);
+
+ backend->priv->views = g_list_append (backend->priv->views, view);
+
+ g_mutex_unlock (&backend->priv->views_mutex);
}
/**
- * e_cal_backend_remove:
+ * e_cal_backend_remove_view
* @backend: an #ECalBackend
- * @cal: an #EDataCal
+ * @view: An #EDataCalView object, previously added with @ref e_cal_backend_add_view.
*
- * Removes the calendar being accessed by the given backend.
- */
+ * Removes view from the list of live views for the backend.
+ *
+ * Since: 3.2
+ **/
void
-e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_remove_view (ECalBackend *backend,
+ EDataCalView *view)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->remove != NULL);
- (* CLASS (backend)->remove) (backend, cal, context);
+ g_mutex_lock (&backend->priv->views_mutex);
+
+ backend->priv->views = g_list_remove (backend->priv->views, view);
+
+ g_mutex_unlock (&backend->priv->views_mutex);
}
/**
- * e_cal_backend_is_loaded:
+ * e_cal_backend_list_views:
* @backend: an #ECalBackend
*
- * Queries whether a calendar backend has been loaded yet.
+ * Returns a list of #ECalBookView instances added with
+ * e_cal_backend_add_view().
*
- * Returns: TRUE if the backend has been loaded with data, FALSE
- * otherwise.
- */
-gboolean
-e_cal_backend_is_loaded (ECalBackend *backend)
+ * The views returned in the list are referenced for thread-safety.
+ * They must each be unreferenced with g_object_unref() when finished
+ * with them. Free the returned list itself with g_list_free().
+ *
+ * An easy way to free the list properly in one step is as follows:
+ *
+ * |[
+ * g_list_free_full (list, g_object_unref);
+ * ]|
+ *
+ * Returns: a list of cal views
+ *
+ * Since: 3.8
+ **/
+GList *
+e_cal_backend_list_views (ECalBackend *backend)
{
- gboolean result;
+ GList *list;
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+
+ g_mutex_lock (&backend->priv->views_mutex);
- g_assert (CLASS (backend)->is_loaded != NULL);
- result = (* CLASS (backend)->is_loaded) (backend);
+ /* XXX Use g_list_copy_deep() once we require GLib >= 2.34. */
+ list = g_list_copy (backend->priv->views);
+ g_list_foreach (list, (GFunc) g_object_ref, NULL);
- return result;
+ g_mutex_unlock (&backend->priv->views_mutex);
+
+ return list;
}
/**
- * e_cal_backend_is_read_only
+ * e_cal_backend_foreach_view:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
+ * @callback: callback to call
+ * @user_data: user_data passed into the @callback
*
- * Queries whether a calendar backend is read only or not.
+ * Calls @callback for each known calendar view of this @backend.
+ * @callback returns %FALSE to stop further processing.
*
- */
+ * Since: 3.2
+ *
+ * Deprecated: 3.8: Use e_cal_backend_list_views() instead.
+ **/
void
-e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal)
+e_cal_backend_foreach_view (ECalBackend *backend,
+ gboolean (*callback) (EDataCalView *view,
+ gpointer user_data),
+ gpointer user_data)
{
- g_return_if_fail (backend != NULL);
+ GList *list, *link;
+
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (callback != NULL);
+
+ list = e_cal_backend_list_views (backend);
- g_assert (CLASS (backend)->is_read_only != NULL);
- (* CLASS (backend)->is_read_only) (backend, cal);
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ if (!callback (E_DATA_CAL_VIEW (link->data), user_data))
+ break;
+ }
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
/**
- * e_cal_backend_start_query:
+ * e_cal_backend_set_notification_proxy:
* @backend: an #ECalBackend
- * @query: The query to be started.
+ * @proxy: The calendar backend to act as notification proxy.
*
- * Starts a new live query on the given backend.
+ * Sets the backend that will act as notification proxy for the given backend.
+ *
+ * Since: 3.2
*/
void
-e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_set_notification_proxy (ECalBackend *backend,
+ ECalBackend *proxy)
{
- g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->start_query != NULL);
- (* CLASS (backend)->start_query) (backend, query);
+ backend->priv->notification_proxy = proxy;
}
/**
- * e_cal_backend_get_mode:
+ * e_cal_backend_open:
* @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @only_if_exists: Whether the calendar should be opened only if it already
+ * exists. If FALSE, a new calendar will be created when the specified @uri
+ * does not exist.
*
- * Queries whether a calendar backend is connected remotely.
- *
- * Returns: The current mode the calendar is in
+ * Opens a calendar backend with data from a calendar stored at the specified URI.
+ * This might be finished with e_data_cal_respond_open() or e_cal_backend_respond_opened(),
+ * though the overall opening phase finishes only after call
+ * of e_cal_backend_notify_opened() after which call the backend
+ * is either fully opened (including authentication against (remote)
+ * server/storage) or an error was encountered during this opening phase.
+ * 'opened' and 'opening' properties are updated automatically.
+ * The backend refuses all other operations until the opening phase is finished.
+ *
+ * The e_cal_backend_notify_opened() is called either from this function
+ * or from e_cal_backend_authenticate_user(), or after necessary steps
+ * initiated by these two functions.
+ *
+ * The opening phase usually works like this:
+ * 1) client requests open for the backend
+ * 2) server receives this request and calls e_cal_backend_open() - the opening phase begun
+ * 3) either the backend is opened during this call, and notifies client
+ * with e_cal_backend_notify_opened() about that. This is usually
+ * for local backends; their opening phase is finished
+ * 4) or the backend requires authentication, thus it notifies client
+ * about that with e_cal_backend_notify_auth_required() and is
+ * waiting for credentials, which will be received from client
+ * by e_cal_backend_authenticate_user() call. Backend's opening
+ * phase is still running in this case, thus it doesn't call
+ * e_cal_backend_notify_opened() within e_cal_backend_open() call.
+ * 5) when backend receives credentials in e_cal_backend_authenticate_user()
+ * then it tries to authenticate against a server/storage with them
+ * and only after it knows result of the authentication, whether user
+ * was or wasn't authenticated, it notifies client with the result
+ * by e_cal_backend_notify_opened() and it's opening phase is
+ * finished now. If there was no error returned then the backend is
+ * considered opened, otherwise it's considered closed. Use AuthenticationFailed
+ * error when the given credentials were rejected by the server/store, which
+ * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
+ * if there was anything wrong with the given credentials. Set error's
+ * message to a reason for a re-prompt, it'll be shown to a user.
+ * 6) client checks error returned from e_cal_backend_notify_opened() and
+ * reprompts for a password if it was AuthenticationFailed. Otherwise
+ * considers backend opened based on the error presence (no error means success).
+ *
+ * In any case, the call of e_cal_backend_open() should be always finished
+ * with e_data_cal_respond_open(), which has no influence on the opening phase,
+ * or alternatively with e_cal_backend_respond_opened(). Never use authentication
+ * errors in e_data_cal_respond_open() to notify the client the authentication is
+ * required, there is e_cal_backend_notify_auth_required() for this.
**/
-CalMode
-e_cal_backend_get_mode (ECalBackend *backend)
-{
- CalMode result;
-
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
-
- g_assert (CLASS (backend)->get_mode != NULL);
- result = (* CLASS (backend)->get_mode) (backend);
-
- return result;
-}
-
-/**
- * e_cal_backend_set_mode:
- * @backend: A calendar backend
- * @mode: Mode to change to
- *
- * Sets the mode of the calendar
- */
void
-e_cal_backend_set_mode (ECalBackend *backend, CalMode mode)
+e_cal_backend_open (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ gboolean only_if_exists)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->open != NULL);
+
+ g_mutex_lock (&backend->priv->clients_mutex);
+
+ if (e_cal_backend_is_opened (backend)) {
+ gboolean online;
- g_assert (CLASS (backend)->set_mode != NULL);
- (* CLASS (backend)->set_mode) (backend, mode);
+ g_mutex_unlock (&backend->priv->clients_mutex);
+
+ e_data_cal_report_readonly (cal, backend->priv->readonly);
+
+ online = e_backend_get_online (E_BACKEND (backend));
+ e_data_cal_report_online (cal, online);
+
+ e_cal_backend_respond_opened (backend, cal, opid, NULL);
+ } else if (e_cal_backend_is_opening (backend)) {
+ g_mutex_unlock (&backend->priv->clients_mutex);
+
+ e_data_cal_respond_open (cal, opid, EDC_OPENING_ERROR);
+ } else {
+ backend->priv->opening = TRUE;
+ g_mutex_unlock (&backend->priv->clients_mutex);
+
+ (* E_CAL_BACKEND_GET_CLASS (backend)->open) (backend, cal, opid, cancellable, only_if_exists);
+ }
}
/**
- * e_cal_backend_get_default_object:
+ * e_cal_backend_refresh:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
*
- * Calls the get_default_object method on the given backend.
- */
+ * Refreshes the calendar being accessed by the given backend.
+ * This might be finished with e_data_cal_respond_refresh(),
+ * and it might be called as soon as possible; it doesn't mean
+ * that the refreshing is done after calling that, the backend
+ * is only notifying client whether it started the refresh process
+ * or not.
+ *
+ * Since: 2.30
+ **/
void
-e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_refresh (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->get_default_object != NULL);
- (* CLASS (backend)->get_default_object) (backend, cal, context);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_refresh (cal, opid, EDC_OPENING_ERROR);
+ else if (!E_CAL_BACKEND_GET_CLASS (backend)->refresh)
+ e_data_cal_respond_refresh (cal, opid, EDC_ERROR (UnsupportedMethod));
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_refresh (cal, opid, EDC_NOT_OPENED_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->refresh) (backend, cal, opid, cancellable);
}
/**
* e_cal_backend_get_object:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @uid: Unique identifier for a calendar object.
* @rid: ID for the object's recurrence to get.
*
* Queries a calendar backend for a calendar object based on its unique
* identifier and its recurrence ID (if a recurrent appointment).
- */
+ * This might be finished with e_data_cal_respond_get_object().
+ **/
void
-e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+e_cal_backend_get_object (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *uid,
+ const gchar *rid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object != NULL);
- g_assert (CLASS (backend)->get_object != NULL);
- (* CLASS (backend)->get_object) (backend, cal, context, uid, rid);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_object (cal, opid, EDC_OPENING_ERROR, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_get_object (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_object) (backend, cal, opid, cancellable, uid, rid);
}
/**
* e_cal_backend_get_object_list:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @sexp: Expression to search for.
*
* Calls the get_object_list method on the given backend.
- */
-void
-e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->get_object_list != NULL);
- (* CLASS (backend)->get_object_list) (backend, cal, context, sexp);
-}
-
-/**
- * e_cal_backend_get_attachment_list:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @uid: Unique identifier for a calendar object.
- * @rid: ID for the object's recurrence to get.
- *
- * Queries a calendar backend for attachments present in a calendar object based
- * on its unique identifier and its recurrence ID (if a recurrent appointment).
- */
+ * This might be finished with e_data_cal_respond_get_object_list().
+ **/
void
-e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+e_cal_backend_get_object_list (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *sexp)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object_list != NULL);
- g_assert (CLASS (backend)->get_object != NULL);
- (* CLASS (backend)->get_attachment_list) (backend, cal, context, uid, rid);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_object_list (cal, opid, EDC_OPENING_ERROR, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_get_object_list (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_object_list) (backend, cal, opid, cancellable, sexp);
}
/**
* e_cal_backend_get_free_busy:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @users: List of users to get free/busy information for.
* @start: Start time for query.
* @end: End time for query.
*
- * Gets a free/busy object for the given time interval
- */
+ * Gets a free/busy object for the given time interval. Client side is
+ * notified about free/busy objects throug e_data_cal_report_free_busy_data().
+ * This might be finished with e_data_cal_respond_get_free_busy().
+ **/
void
-e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end)
+e_cal_backend_get_free_busy (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const GSList *users,
+ time_t start,
+ time_t end)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (start != -1 && end != -1);
g_return_if_fail (start <= end);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy != NULL);
- g_assert (CLASS (backend)->get_free_busy != NULL);
- (* CLASS (backend)->get_free_busy) (backend, cal, context, users, start, end);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_free_busy (cal, opid, EDC_OPENING_ERROR);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_get_free_busy (cal, opid, EDC_NOT_OPENED_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy) (backend, cal, opid, cancellable, users, start, end);
}
/**
- * e_cal_backend_get_changes:
+ * e_cal_backend_create_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @change_id: A unique uid for the callers change list
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @calobjs: The objects to create (list of gchar *).
*
- * Builds a sequence of objects and the type of change that occurred on them since
- * the last time the give change_id was seen
- */
+ * Calls the create_object method on the given backend.
+ * This might be finished with e_data_cal_respond_create_objects().
+ *
+ * Since: 3.6
+ **/
void
-e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id)
+e_cal_backend_create_objects (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const GSList *calobjs)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (change_id != NULL);
-
- g_assert (CLASS (backend)->get_changes != NULL);
- (* CLASS (backend)->get_changes) (backend, cal, context, change_id);
+ g_return_if_fail (calobjs != NULL);
+
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_create_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else if (!E_CAL_BACKEND_GET_CLASS (backend)->create_objects)
+ e_data_cal_respond_create_objects (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_create_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->create_objects) (backend, cal, opid, cancellable, calobjs);
}
/**
- * e_cal_backend_discard_alarm
+ * e_cal_backend_modify_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @uid: UID of the component to discard the alarm from.
- * @auid: Alarm ID.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @calobjs: Objects to be modified (list of gchar *).
+ * @mod: Type of modification.
*
- * Discards an alarm from the given component. This allows the specific backend
- * to do whatever is needed to really discard the alarm.
- */
+ * Calls the modify_objects method on the given backend.
+ * This might be finished with e_data_cal_respond_modify_objects().
+ *
+ * Since: 3.6
+ **/
void
-e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid)
+e_cal_backend_modify_objects (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const GSList *calobjs,
+ CalObjModType mod)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
- g_return_if_fail (auid != NULL);
-
- g_assert (CLASS (backend)->discard_alarm != NULL);
- (* CLASS (backend)->discard_alarm) (backend, cal, context, uid, auid);
+ g_return_if_fail (calobjs != NULL);
+
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_modify_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else if (!E_CAL_BACKEND_GET_CLASS (backend)->modify_objects)
+ e_data_cal_respond_modify_objects (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_modify_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->modify_objects) (backend, cal, opid, cancellable, calobjs, mod);
}
/**
- * e_cal_backend_create_object:
+ * e_cal_backend_remove_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @calobj: The object to create.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @ids: List of #ECalComponentId objects identifying the objects to remove
+ * @mod: Type of removal.
*
- * Calls the create_object method on the given backend.
- */
+ * Removes objects in a calendar backend. The backend will notify all of its
+ * clients about the change.
+ * This might be finished with e_data_cal_respond_remove_objects().
+ *
+ * Since: 3.6
+ **/
void
-e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_remove_objects (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const GSList *ids,
+ CalObjModType mod)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobj != NULL);
+ g_return_if_fail (ids != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove_objects != NULL);
- if (CLASS (backend)->create_object)
- (* CLASS (backend)->create_object) (backend, cal, context, calobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_remove_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_remove_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL, NULL);
else
- e_data_cal_notify_object_created (cal, context, EDC_ERROR (UnsupportedMethod), NULL, NULL);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->remove_objects) (backend, cal, opid, cancellable, ids, mod);
}
/**
- * e_cal_backend_modify_object:
+ * e_cal_backend_receive_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @calobj: Object to be modified.
- * @mod: Type of modification.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @calobj: iCalendar object.
*
- * Calls the modify_object method on the given backend.
- */
+ * Calls the receive_objects method on the given backend.
+ * This might be finished with e_data_cal_respond_receive_objects().
+ **/
void
-e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod)
+e_cal_backend_receive_objects (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (calobj != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->receive_objects != NULL);
- if (CLASS (backend)->modify_object)
- (* CLASS (backend)->modify_object) (backend, cal, context, calobj, mod);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_receive_objects (cal, opid, EDC_OPENING_ERROR);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_receive_objects (cal, opid, EDC_NOT_OPENED_ERROR);
else
- e_data_cal_notify_object_removed (cal, context, EDC_ERROR (UnsupportedMethod), NULL, NULL, NULL);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->receive_objects) (backend, cal, opid, cancellable, calobj);
}
/**
- * e_cal_backend_remove_object:
+ * e_cal_backend_send_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @uid: Unique identifier of the object to remove.
- * @rid: A recurrence ID.
- * @mod: Type of removal.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @calobj: iCalendar object to be sent.
*
- * Removes an object in a calendar backend. The backend will notify all of its
- * clients about the change.
- */
+ * Calls the send_objects method on the given backend.
+ * This might be finished with e_data_cal_respond_send_objects().
+ **/
void
-e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod)
+e_cal_backend_send_objects (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
+ g_return_if_fail (calobj != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->send_objects != NULL);
- g_assert (CLASS (backend)->remove_object != NULL);
- (* CLASS (backend)->remove_object) (backend, cal, context, uid, rid, mod);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_send_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_send_objects (cal, opid, EDC_NOT_OPENED_ERROR, NULL, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->send_objects) (backend, cal, opid, cancellable, calobj);
}
/**
- * e_cal_backend_receive_objects:
+ * e_cal_backend_get_attachment_uris:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @calobj: iCalendar object.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @uid: Unique identifier for a calendar object.
+ * @rid: ID for the object's recurrence to get.
*
- * Calls the receive_objects method on the given backend.
- */
+ * Queries a calendar backend for attachments present in a calendar object based
+ * on its unique identifier and its recurrence ID (if a recurrent appointment).
+ * This might be finished with e_data_cal_respond_get_attachment_uris().
+ *
+ * Since: 3.2
+ **/
void
-e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_get_attachment_uris (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *uid,
+ const gchar *rid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobj != NULL);
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris != NULL);
- g_assert (CLASS (backend)->receive_objects != NULL);
- (* CLASS (backend)->receive_objects) (backend, cal, context, calobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_attachment_uris (cal, opid, EDC_OPENING_ERROR, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_get_attachment_uris (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris) (backend, cal, opid, cancellable, uid, rid);
}
/**
- * e_cal_backend_send_objects:
+ * e_cal_backend_discard_alarm:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @calobj: iCalendar object to be sent.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @uid: Unique identifier for a calendar object.
+ * @rid: ID for the object's recurrence to discard alarm in.
+ * @auid: Unique identifier of the alarm itself.
*
- * Calls the send_objects method on the given backend.
- */
+ * Discards alarm @auid from the object identified by @uid and @rid.
+ * This might be finished with e_data_cal_respond_discard_alarm().
+ * Default implementation of this method returns Not Supported error.
+ **/
void
-e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_discard_alarm (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *uid,
+ const gchar *rid,
+ const gchar *auid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (calobj != NULL);
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (auid != NULL);
- g_assert (CLASS (backend)->send_objects != NULL);
- (* CLASS (backend)->send_objects) (backend, cal, context, calobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_discard_alarm (cal, opid, EDC_OPENING_ERROR);
+ else if (!E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm)
+ e_data_cal_respond_discard_alarm (cal, opid, e_data_cal_create_error (NotSupported, NULL));
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_discard_alarm (cal, opid, EDC_NOT_OPENED_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm) (backend, cal, opid, cancellable, uid, rid, auid);
}
/**
* e_cal_backend_get_timezone:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
* NULL.
*
* Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
* can't be found.
- */
+ * This might be finished with e_data_cal_respond_get_timezone().
+ **/
void
-e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
+e_cal_backend_get_timezone (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *tzid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (tzid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_timezone != NULL);
- g_assert (CLASS (backend)->get_timezone != NULL);
- (* CLASS (backend)->get_timezone) (backend, cal, context, tzid);
-}
-
-/**
- * e_cal_backend_set_default_zone:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @tzobj: The timezone object, in a string.
- *
- * Sets the default timezone for the calendar, which is used to resolve
- * DATE and floating DATE-TIME values.
- */
-void
-e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzobj != NULL);
-
- (* CLASS (backend)->set_default_zone) (backend, cal, context, tzobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_timezone (cal, opid, EDC_OPENING_ERROR, NULL);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_get_timezone (cal, opid, EDC_NOT_OPENED_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_timezone) (backend, cal, opid, cancellable, tzid);
}
/**
* e_cal_backend_add_timezone
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @tzobj: The timezone object, in a string.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @tzobject: The timezone object, in a string.
*
* Add a timezone object to the given backend.
- */
+ * This might be finished with e_data_cal_respond_add_timezone().
+ **/
void
-e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
+e_cal_backend_add_timezone (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *tzobject)
{
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzobj != NULL);
- g_return_if_fail (CLASS (backend)->add_timezone != NULL);
+ g_return_if_fail (tzobject != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->add_timezone != NULL);
- (* CLASS (backend)->add_timezone) (backend, cal, context, tzobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_add_timezone (cal, opid, EDC_OPENING_ERROR);
+ else if (!e_cal_backend_is_opened (backend))
+ e_data_cal_respond_add_timezone (cal, opid, EDC_NOT_OPENED_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->add_timezone) (backend, cal, opid, cancellable, tzobject);
}
/**
- * e_cal_backend_internal_get_default_timezone:
+ * e_cal_backend_start_view:
* @backend: an #ECalBackend
+ * @view: The view to be started.
*
- * Calls the internal_get_default_timezone method on the given backend.
- */
-icaltimezone *
-e_cal_backend_internal_get_default_timezone (ECalBackend *backend)
-{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (CLASS (backend)->internal_get_default_timezone != NULL, NULL);
-
- return (* CLASS (backend)->internal_get_default_timezone) (backend);
-}
-
-/**
- * e_cal_backend_internal_get_timezone:
- * @backend: an #ECalBackend
- * @tzid: ID of the timezone to get.
+ * Starts a new live view on the given backend.
*
- * Calls the internal_get_timezone method on the given backend.
+ * Since: 3.2
*/
-icaltimezone *
-e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
+void
+e_cal_backend_start_view (ECalBackend *backend,
+ EDataCalView *view)
{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (tzid != NULL, NULL);
- g_return_val_if_fail (CLASS (backend)->internal_get_timezone != NULL, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->start_view != NULL);
- return (* CLASS (backend)->internal_get_timezone) (backend, tzid);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->start_view) (backend, view);
}
/**
- * e_cal_backend_set_notification_proxy:
+ * e_cal_backend_stop_view:
* @backend: an #ECalBackend
- * @proxy: The calendar backend to act as notification proxy.
+ * @view: The view to be stopped.
*
- * Sets the backend that will act as notification proxy for the given backend.
+ * Stops a previously started live view on the given backend.
+ *
+ * Since: 3.2
*/
void
-e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy)
+e_cal_backend_stop_view (ECalBackend *backend,
+ EDataCalView *view)
{
- ECalBackendPrivate *priv;
-
+ g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- priv = backend->priv;
+ /* backward compatibility, do not force each backend define this function */
+ if (!E_CAL_BACKEND_GET_CLASS (backend)->stop_view)
+ return;
- priv->notification_proxy = proxy;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->stop_view) (backend, view);
}
/**
- * e_cal_backend_notify_object_created:
+ * e_cal_backend_notify_component_created:
* @backend: an #ECalBackend
- * @calobj: iCalendar representation of new object
+ * @component: the newly created #ECalComponent
*
* Notifies each of the backend's listeners about a new object.
*
- * #e_data_cal_notify_object_created() calls this for you. You only need to
- * call e_cal_backend_notify_object_created() yourself to report objects
- * created by non-EDS clients.
+ * Like e_cal_backend_notify_object_created() except takes an #ECalComponent
+ * instead of an ical string representation and uses the #EDataCalView's
+ * fields-of-interest to filter out unwanted information from ical strings
+ * sent over the bus.
+ *
+ * Since: 3.4
**/
void
-e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj)
+e_cal_backend_notify_component_created (ECalBackend *backend,
+ ECalComponent *component)
{
- ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ GList *list, *link;
- priv = backend->priv;
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_IS_CAL_COMPONENT (component));
- if (priv->notification_proxy) {
- e_cal_backend_notify_object_created (priv->notification_proxy, calobj);
+ if (backend->priv->notification_proxy != NULL) {
+ e_cal_backend_notify_component_created (
+ backend->priv->notification_proxy, component);
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
+ list = e_cal_backend_list_views (backend);
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EDataCalView *view = E_DATA_CAL_VIEW (link->data);
- g_object_ref (query);
- if (e_data_cal_view_object_matches (query, calobj))
- e_data_cal_view_notify_objects_added_1 (query, calobj);
- g_object_unref (query);
-
- e_iterator_next (iter);
+ if (e_data_cal_view_component_matches (view, component))
+ e_data_cal_view_notify_components_added_1 (view, component);
}
- g_object_unref (iter);
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
static void
-match_query_and_notify (EDataCalView *query, const gchar *old_object, const gchar *object)
+match_view_and_notify_component (EDataCalView *view,
+ ECalComponent *old_component,
+ ECalComponent *new_component)
{
gboolean old_match = FALSE, new_match = FALSE;
- if (old_object)
- old_match = e_data_cal_view_object_matches (query, old_object);
+ if (old_component)
+ old_match = e_data_cal_view_component_matches (view, old_component);
+
+ new_match = e_data_cal_view_component_matches (view, new_component);
- new_match = e_data_cal_view_object_matches (query, object);
if (old_match && new_match)
- e_data_cal_view_notify_objects_modified_1 (query, object);
+ e_data_cal_view_notify_components_modified_1 (view, new_component);
else if (new_match)
- e_data_cal_view_notify_objects_added_1 (query, object);
+ e_data_cal_view_notify_components_added_1 (view, new_component);
else if (old_match) {
- ECalComponent *comp = NULL;
- comp = e_cal_component_new_from_string (old_object);
- if (comp) {
- ECalComponentId *id = e_cal_component_get_id (comp);
+ ECalComponentId *id = e_cal_component_get_id (old_component);
- e_data_cal_view_notify_objects_removed_1 (query, id);
+ e_data_cal_view_notify_objects_removed_1 (view, id);
- e_cal_component_free_id (id);
- g_object_unref (comp);
- }
+ e_cal_component_free_id (id);
}
}
/**
- * e_cal_backend_notify_view_progress_start
+ * e_cal_backend_notify_component_modified:
* @backend: an #ECalBackend
+ * @old_component: the #ECalComponent before the modification
+ * @new_component: the #ECalComponent after the modification
+ *
+ * Notifies each of the backend's listeners about a modified object.
*
- * This methods has to be used before e_cal_backend_notify_view_progress.
- * Sets last notified percent value to 0.
+ * Like e_cal_backend_notify_object_modified() except takes an #ECalComponent
+ * instead of an ical string representation and uses the #EDataCalView's
+ * fields-of-interest to filter out unwanted information from ical strings
+ * sent over the bus.
*
- * Since: 2.24
+ * Since: 3.4
**/
void
-e_cal_backend_notify_view_progress_start (ECalBackend *backend)
+e_cal_backend_notify_component_modified (ECalBackend *backend,
+ ECalComponent *old_component,
+ ECalComponent *new_component)
{
- ECalBackendPrivate *priv;
+ GList *list, *link;
- priv = backend->priv;
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_IS_CAL_COMPONENT (old_component));
+ g_return_if_fail (E_IS_CAL_COMPONENT (new_component));
+
+ if (backend->priv->notification_proxy != NULL) {
+ e_cal_backend_notify_component_modified (
+ backend->priv->notification_proxy,
+ old_component, new_component);
+ return;
+ }
+
+ list = e_cal_backend_list_views (backend);
- priv->last_percent_notified = 0;
+ for (link = list; link != NULL; link = g_list_next (link))
+ match_view_and_notify_component (
+ E_DATA_CAL_VIEW (link->data),
+ old_component, new_component);
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
/**
- * e_cal_backend_notify_view_progress:
+ * e_cal_backend_notify_component_removed:
* @backend: an #ECalBackend
- * @message: the UID of the removed object
- * @percent: percentage of the objects loaded in the view
+ * @id: the Id of the removed object
+ * @old_component: the removed component
+ * @new_component: the component after the removal. This only applies to recurrent
+ * appointments that had an instance removed. In that case, this function
+ * notifies a modification instead of a removal.
*
- * Notifies each of the backend's listeners about the view_progress in downloading the items.
+ * Notifies each of the backend's listeners about a removed object.
+ *
+ * Like e_cal_backend_notify_object_removed() except takes an #ECalComponent
+ * instead of an ical string representation and uses the #EDataCalView's
+ * fields-of-interest to filter out unwanted information from ical strings
+ * sent over the bus.
+ *
+ * Since: 3.4
**/
void
-e_cal_backend_notify_view_progress (ECalBackend *backend, const gchar *message, gint percent)
+e_cal_backend_notify_component_removed (ECalBackend *backend,
+ const ECalComponentId *id,
+ ECalComponent *old_component,
+ ECalComponent *new_component)
{
- ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ GList *list, *link;
- priv = backend->priv;
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (id != NULL);
- if (percent <= priv->last_percent_notified)
- return;
+ if (old_component != NULL)
+ g_return_if_fail (E_IS_CAL_COMPONENT (old_component));
- priv->last_percent_notified = percent;
+ if (new_component != NULL)
+ g_return_if_fail (E_IS_CAL_COMPONENT (new_component));
- if (priv->notification_proxy) {
- e_cal_backend_notify_view_progress (priv->notification_proxy, message, percent);
+ if (backend->priv->notification_proxy != NULL) {
+ e_cal_backend_notify_component_removed (
+ backend->priv->notification_proxy,
+ id, old_component, new_component);
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
+ list = e_cal_backend_list_views (backend);
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EDataCalView *view = E_DATA_CAL_VIEW (link->data);
- g_object_ref (query);
+ if (new_component != NULL)
+ match_view_and_notify_component (
+ view, old_component, new_component);
- e_data_cal_view_notify_progress (query, message, percent);
+ else if (old_component == NULL)
+ e_data_cal_view_notify_objects_removed_1 (view, id);
- g_object_unref (query);
-
- e_iterator_next (iter);
+ else if (e_data_cal_view_component_matches (view, old_component))
+ e_data_cal_view_notify_objects_removed_1 (view, id);
}
- g_object_unref (iter);
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
/**
- * e_cal_backend_notify_view_done:
+ * e_cal_backend_notify_error:
* @backend: an #ECalBackend
- * @error: returns the error, if any, once the view is fully populated.
+ * @message: Error message
*
- * Notifies each of the backend's listeners about the view_done in downloading the items.
+ * Notifies each of the backend's listeners about an error
**/
void
-e_cal_backend_notify_view_done (ECalBackend *backend, const GError *error)
+e_cal_backend_notify_error (ECalBackend *backend,
+ const gchar *message)
{
- ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
-
- priv = backend->priv;
+ ECalBackendPrivate *priv = backend->priv;
+ GList *l;
if (priv->notification_proxy) {
- e_cal_backend_notify_view_done (priv->notification_proxy, error);
+ e_cal_backend_notify_error (priv->notification_proxy, message);
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ g_mutex_lock (&priv->clients_mutex);
- g_object_ref (query);
-
- e_data_cal_view_notify_done (query, error);
-
- g_object_unref (query);
+ for (l = priv->clients; l; l = l->next)
+ e_data_cal_report_error (l->data, message);
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+ g_mutex_unlock (&priv->clients_mutex);
}
/**
- * e_cal_backend_notify_object_modified:
+ * e_cal_backend_notify_readonly:
* @backend: an #ECalBackend
- * @old_object: iCalendar representation of the original form of the object
- * @object: iCalendar representation of the new form of the object
+ * @is_readonly: flag indicating readonly status
*
- * Notifies each of the backend's listeners about a modified object.
- *
- * #e_data_cal_notify_object_modified() calls this for you. You only need to
- * call e_cal_backend_notify_object_modified() yourself to report objects
- * modified by non-EDS clients.
+ * Notifies all backend's clients about the current readonly state.
+ * Meant to be used by backend implementations.
**/
void
-e_cal_backend_notify_object_modified (ECalBackend *backend,
- const gchar *old_object, const gchar *object)
+e_cal_backend_notify_readonly (ECalBackend *backend,
+ gboolean is_readonly)
{
ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ GList *l;
priv = backend->priv;
+ priv->readonly = is_readonly;
if (priv->notification_proxy) {
- e_cal_backend_notify_object_modified (priv->notification_proxy, old_object, object);
+ e_cal_backend_notify_readonly (priv->notification_proxy, is_readonly);
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ g_mutex_lock (&priv->clients_mutex);
- g_object_ref (query);
- match_query_and_notify (query, old_object, object);
- g_object_unref (query);
+ for (l = priv->clients; l; l = l->next)
+ e_data_cal_report_readonly (l->data, is_readonly);
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+ g_mutex_unlock (&priv->clients_mutex);
}
/**
- * e_cal_backend_notify_object_removed:
+ * e_cal_backend_notify_online:
* @backend: an #ECalBackend
- * @id: the Id of the removed object
- * @old_object: iCalendar representation of the removed object
- * @new_object: iCalendar representation of the object after the removal. This
- * only applies to recurrent appointments that had an instance removed. In that
- * case, this function notifies a modification instead of a removal.
+ * @is_online: flag indicating whether @backend is connected and online
*
- * Notifies each of the backend's listeners about a removed object.
+ * Notifies clients of @backend's connection status indicated by @is_online.
+ * Meant to be used by backend implementations.
*
- * e_data_cal_notify_object_removed() calls this for you. You only need to
- * call e_cal_backend_notify_object_removed() yourself to report objects
- * removed by non-EDS clients.
+ * Since: 3.2
**/
void
-e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId *id,
- const gchar *old_object, const gchar *object)
+e_cal_backend_notify_online (ECalBackend *backend,
+ gboolean is_online)
{
ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ GList *clients;
priv = backend->priv;
if (priv->notification_proxy) {
- e_cal_backend_notify_object_removed (priv->notification_proxy, id, old_object, object);
+ e_cal_backend_notify_online (priv->notification_proxy, is_online);
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
-
- g_object_ref (query);
-
- if (object == NULL) {
- /* if object == NULL, it means the object has been completely
- removed from the backend */
- if (!old_object || e_data_cal_view_object_matches (query, old_object))
- e_data_cal_view_notify_objects_removed_1 (query, id);
- } else
- match_query_and_notify (query, old_object, object);
+ g_mutex_lock (&priv->clients_mutex);
- g_object_unref (query);
+ for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
+ e_data_cal_report_online (E_DATA_CAL (clients->data), is_online);
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+ g_mutex_unlock (&priv->clients_mutex);
}
/**
- * e_cal_backend_notify_objects_added:
+ * e_cal_backend_notify_opened:
+ * @backend: an #ECalBackend
+ * @error: a #GError corresponding to the error encountered during
+ * the opening phase. Use %NULL for success. The @error is freed
+ * automatically if not %NULL.
*
- * Since: 2.24
- **/
-void
-e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects)
-{
- e_data_cal_view_notify_objects_added (query, objects);
-}
-
-/**
- * e_cal_backend_notify_objects_removed:
+ * Notifies clients that @backend finished its opening phase.
+ * See e_cal_backend_open() for more information how the opening
+ * phase works. Calling this function changes 'opening' property,
+ * same as 'opened'. 'opening' is set to %FALSE and the backend
+ * is considered 'opened' only if the @error is %NULL.
*
- * Since: 2.24
- **/
-void
-e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids)
-{
- e_data_cal_view_notify_objects_removed (query, ids);
-}
-
-/**
- * e_cal_backend_notify_objects_modified:
+ * See also: e_cal_backend_respond_opened()
+ *
+ * Note: The @error is freed automatically if not %NULL.
+ *
+ * Meant to be used by backend implementations.
*
- * Since: 2.24
+ * Since: 3.2
**/
void
-e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects)
+e_cal_backend_notify_opened (ECalBackend *backend,
+ GError *error)
{
- e_data_cal_view_notify_objects_modified (query, objects);
+ ECalBackendPrivate *priv;
+ GList *clients;
+
+ priv = backend->priv;
+ g_mutex_lock (&priv->clients_mutex);
+
+ priv->opening = FALSE;
+ priv->opened = error == NULL;
+
+ for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
+ e_data_cal_report_opened (E_DATA_CAL (clients->data), error);
+
+ g_mutex_unlock (&priv->clients_mutex);
+
+ if (error)
+ g_error_free (error);
}
/**
- * e_cal_backend_notify_mode:
+ * e_cal_backend_notify_property_changed:
* @backend: an #ECalBackend
- * @status: Status of the mode set
- * @mode: the current mode
+ * @prop_name: property name, which changed
+ * @prop_value: new property value
*
- * Notifies each of the backend's listeners about the results of a
- * setMode call.
+ * Notifies client about property value change.
+ *
+ * Since: 3.2
**/
void
-e_cal_backend_notify_mode (ECalBackend *backend,
- EDataCalViewListenerSetModeStatus status,
- EDataCalMode mode)
+e_cal_backend_notify_property_changed (ECalBackend *backend,
+ const gchar *prop_name,
+ const gchar *prop_value)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ ECalBackendPrivate *priv;
+ GList *clients;
- if (priv->notification_proxy) {
- e_cal_backend_notify_mode (priv->notification_proxy, status, mode);
- return;
- }
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (*prop_name != '\0');
+ g_return_if_fail (prop_value != NULL);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_mode (l->data, status, mode);
-}
+ priv = backend->priv;
+ g_mutex_lock (&priv->clients_mutex);
-/**
- * e_cal_backend_notify_auth_required:
- * @backend: an #ECalBackend
- *
- * Notifies each of the backend's listeners that authentication is required to
- * open the calendar.
- */
-void
-e_cal_backend_notify_auth_required (ECalBackend *backend)
-{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
+ e_data_cal_report_backend_property_changed (E_DATA_CAL (clients->data), prop_name, prop_value);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_auth_required (l->data);
+ g_mutex_unlock (&priv->clients_mutex);
}
/**
- * e_cal_backend_notify_error:
+ * e_cal_backend_respond_opened:
* @backend: an #ECalBackend
- * @message: Error message
+ * @cal: an #EDataCal
+ * @opid: an operation ID
+ * @error: result error; can be %NULL, if it isn't then it's automatically freed
*
- * Notifies each of the backend's listeners about an error
+ * This is a replacement for e_data_cal_respond_open() for cases where
+ * the finish of 'open' method call also finishes backend opening phase.
+ * This function covers calling of both e_cal_backend_notify_opened() and
+ * e_data_cal_respond_open() with the same @error.
+ *
+ * See e_cal_backend_open() for more details how the opening phase works.
+ *
+ * Since: 3.2
**/
void
-e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
+e_cal_backend_respond_opened (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GError *error)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ GError *copy = NULL;
- if (priv->notification_proxy) {
- e_cal_backend_notify_error (priv->notification_proxy, message);
- return;
- }
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (opid != 0);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_error (l->data, message);
+ if (error)
+ copy = g_error_copy (error);
+
+ e_cal_backend_notify_opened (backend, copy);
+ e_data_cal_respond_open (cal, opid, error);
}
/**
* Since: 2.28
**/
void
-e_cal_backend_empty_cache (ECalBackend *backend, ECalBackendCache *cache)
+e_cal_backend_empty_cache (ECalBackend *backend,
+ ECalBackendCache *cache)
{
GList *comps_in_cache;
for (comps_in_cache = e_cal_backend_cache_get_components (cache);
comps_in_cache;
comps_in_cache = comps_in_cache->next) {
- gchar *comp_str;
ECalComponentId *id;
ECalComponent *comp = comps_in_cache->data;
id = e_cal_component_get_id (comp);
- comp_str = e_cal_component_get_as_string (comp);
e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
- e_cal_backend_notify_object_removed (backend, id, comp_str, NULL);
- g_free (comp_str);
+ e_cal_backend_notify_component_removed (backend, id, comp, NULL);
+
e_cal_component_free_id (id);
g_object_unref (comp);
}