*/
#include <config.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xmlmemory.h>
+
+#include <glib/gi18n-lib.h>
#include "e-cal-backend.h"
+#include "e-cal-backend-cache.h"
+
+#define E_CAL_BACKEND_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_CAL_BACKEND, ECalBackendPrivate))
-\f
+#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;
-
- /* URI, from source. This is cached, since we return const. */
- char *uri;
+ 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 */
- int last_percent_notified;
};
/* Property IDs */
-enum props {
+enum {
PROP_0,
- PROP_SOURCE,
- PROP_URI,
- PROP_KIND
+ PROP_CACHE_DIR,
+ PROP_KIND,
+ PROP_REGISTRY
};
-/* Signal IDs */
-enum {
- LAST_CLIENT_GONE,
- OPENED,
- REMOVED,
- LAST_SIGNAL
-};
-static guint e_cal_backend_signals[LAST_SIGNAL];
+/* 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 e_cal_backend_class_init (ECalBackendClass *class);
-static void e_cal_backend_init (ECalBackend *backend);
-static void e_cal_backend_finalize (GObject *object);
+static void
+cal_backend_free_zone (icaltimezone *zone)
+{
+ icaltimezone_free (zone, 1);
+}
-#define CLASS(backend) (E_CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (backend)))
+static void
+cal_backend_set_default_cache_dir (ECalBackend *backend)
+{
+ ESource *source;
+ icalcomponent_kind kind;
+ const gchar *component_type;
+ const gchar *user_cache_dir;
+ const gchar *uid;
+ gchar *filename;
-static GObjectClass *parent_class;
+ user_cache_dir = e_get_user_cache_dir ();
-\f
+ kind = e_cal_backend_get_kind (backend);
+ source = e_backend_get_source (E_BACKEND (backend));
-/**
- * e_cal_backend_get_type:
- *
- * Registers the #ECalBackend class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #ECalBackend class.
- **/
-GType
-e_cal_backend_get_type (void)
-{
- static GType e_cal_backend_type = 0;
-
- if (!e_cal_backend_type) {
- static GTypeInfo info = {
- sizeof (ECalBackendClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) e_cal_backend_class_init,
- NULL, NULL,
- sizeof (ECalBackend),
- 0,
- (GInstanceInitFunc) e_cal_backend_init,
- };
- e_cal_backend_type = g_type_register_static (G_TYPE_OBJECT, "ECalBackend", &info, 0);
+ uid = e_source_get_uid (source);
+ g_return_if_fail (uid != NULL);
+
+ switch (kind) {
+ case ICAL_VEVENT_COMPONENT:
+ component_type = "calendar";
+ break;
+ case ICAL_VTODO_COMPONENT:
+ component_type = "tasks";
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ component_type = "memos";
+ break;
+ default:
+ g_return_if_reached ();
}
- return e_cal_backend_type;
+ filename = g_build_filename (
+ user_cache_dir, component_type, uid, NULL);
+ e_cal_backend_set_cache_dir (backend, filename);
+ g_free (filename);
}
static void
-e_cal_backend_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+cal_backend_get_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name)
{
- ECalBackend *backend;
- ECalBackendPrivate *priv;
-
- backend = E_CAL_BACKEND (object);
- priv = backend->priv;
-
- switch (property_id) {
- case PROP_SOURCE:
- {
- ESource *new_source;
-
- new_source = g_value_get_object (value);
- if (new_source)
- g_object_ref (new_source);
+ 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);
+ }
+}
- if (priv->source)
- g_object_unref (priv->source);
+static void
+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 (cal != NULL);
+ g_return_if_fail (prop_name != NULL);
- priv->source = new_source;
+ 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));
+}
- /* Cache the URI */
- if (new_source) {
- g_free (priv->uri);
- priv->uri = e_source_get_uri (priv->source);
- }
- }
- break;
- case PROP_URI:
- if (!priv->source) {
- g_free (priv->uri);
- priv->uri = g_value_dup_string (value);
- }
- break;
- case PROP_KIND:
- priv->kind = g_value_get_ulong (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
+static void
+cal_backend_set_kind (ECalBackend *backend,
+ icalcomponent_kind kind)
+{
+ backend->priv->kind = kind;
}
static void
-e_cal_backend_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+cal_backend_set_registry (ECalBackend *backend,
+ ESourceRegistry *registry)
{
- ECalBackend *backend;
- ECalBackendPrivate *priv;
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (backend->priv->registry == NULL);
- backend = E_CAL_BACKEND (object);
- priv = backend->priv;
+ backend->priv->registry = g_object_ref (registry);
+}
+static void
+cal_backend_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
switch (property_id) {
- case PROP_SOURCE:
- g_value_set_object (value, e_cal_backend_get_source (backend));
- break;
- case PROP_URI:
- g_value_set_string (value, e_cal_backend_get_uri (backend));
- break;
- case PROP_KIND:
- g_value_set_ulong (value, e_cal_backend_get_kind (backend));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
+ case PROP_CACHE_DIR:
+ e_cal_backend_set_cache_dir (
+ 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_REGISTRY:
+ cal_backend_set_registry (
+ E_CAL_BACKEND (object),
+ g_value_get_object (value));
+ return;
}
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
-/* Class initialization function for the calendar backend */
static void
-e_cal_backend_class_init (ECalBackendClass *class)
+cal_backend_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GObjectClass *object_class;
+ switch (property_id) {
+ case PROP_CACHE_DIR:
+ g_value_set_string (
+ 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_REGISTRY:
+ g_value_set_object (
+ value, e_cal_backend_get_registry (
+ E_CAL_BACKEND (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
- parent_class = (GObjectClass *) g_type_class_peek_parent (class);
-
- object_class = (GObjectClass *) class;
-
- object_class->set_property = e_cal_backend_set_property;
- object_class->get_property = e_cal_backend_get_property;
- object_class->finalize = e_cal_backend_finalize;
-
- g_object_class_install_property (object_class, PROP_SOURCE,
- g_param_spec_object ("source", NULL, NULL, E_TYPE_SOURCE,
- G_PARAM_READABLE | G_PARAM_WRITABLE
- | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class, PROP_URI,
- g_param_spec_string ("uri", NULL, NULL, "",
- G_PARAM_READABLE | G_PARAM_WRITABLE
- | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class, PROP_KIND,
- g_param_spec_ulong ("kind", NULL, NULL,
- ICAL_NO_COMPONENT, ICAL_XLICMIMEPART_COMPONENT,
- ICAL_NO_COMPONENT,
- G_PARAM_READABLE | G_PARAM_WRITABLE
- | G_PARAM_CONSTRUCT_ONLY));
- e_cal_backend_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);
- e_cal_backend_signals[OPENED] =
- g_signal_new ("opened",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECalBackendClass, opened),
- NULL, NULL,
- g_cclosure_marshal_VOID__ENUM,
- G_TYPE_NONE, 1,
- G_TYPE_INT);
- e_cal_backend_signals[REMOVED] =
- g_signal_new ("removed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECalBackendClass, removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__ENUM,
- G_TYPE_NONE, 1,
- G_TYPE_INT);
-
- class->last_client_gone = NULL;
- class->opened = NULL;
- class->obj_updated = NULL;
-
- class->get_cal_address = NULL;
- class->get_alarm_email_address = NULL;
- class->get_static_capabilities = NULL;
- class->open = NULL;
- class->is_loaded = NULL;
- class->is_read_only = NULL;
- class->start_query = NULL;
- class->get_mode = NULL;
- class->set_mode = NULL;
- class->get_object = NULL;
- class->get_default_object = NULL;
- class->get_object_list = NULL;
- class->get_free_busy = NULL;
- class->get_changes = NULL;
- class->discard_alarm = NULL;
- class->create_object = NULL;
- class->modify_object = NULL;
- class->remove_object = NULL;
- class->receive_objects = NULL;
- class->send_objects = NULL;
- class->get_timezone = NULL;
- class->add_timezone = NULL;
- class->set_default_timezone = NULL;
-}
-
-/* Object initialization func for the calendar backend */
static void
-e_cal_backend_init (ECalBackend *backend)
+cal_backend_dispose (GObject *object)
{
ECalBackendPrivate *priv;
- priv = g_new0 (ECalBackendPrivate, 1);
- backend->priv = priv;
+ priv = E_CAL_BACKEND_GET_PRIVATE (object);
- priv->clients = NULL;
- priv->clients_mutex = g_mutex_new ();
- priv->last_percent_notified = 0;
+ if (priv->registry != NULL) {
+ g_object_unref (priv->registry);
+ priv->registry = NULL;
+ }
- /* FIXME bonobo_object_ref/unref? */
- priv->queries = e_list_new ((EListCopyFunc) bonobo_object_ref, (EListFreeFunc) bonobo_object_unref, NULL);
- priv->queries_mutex = g_mutex_new ();
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_cal_backend_parent_class)->dispose (object);
}
static void
-e_cal_backend_finalize (GObject *object)
+cal_backend_finalize (GObject *object)
{
- ECalBackend *backend = (ECalBackend *)object;
ECalBackendPrivate *priv;
- priv = backend->priv;
+ priv = E_CAL_BACKEND_GET_PRIVATE (object);
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_list_free (priv->views);
+ g_mutex_clear (&priv->views_mutex);
- g_mutex_free (priv->clients_mutex);
- g_mutex_free (priv->queries_mutex);
+ g_hash_table_destroy (priv->zone_cache);
+ g_mutex_clear (&priv->zone_cache_lock);
- g_free (priv->uri);
- g_object_unref (priv->source);
- g_free (priv);
+ g_free (priv->cache_dir);
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
}
-\f
+static void
+cal_backend_constructed (GObject *object)
+{
+ cal_backend_set_default_cache_dir (E_CAL_BACKEND (object));
-/**
- * e_cal_backend_get_source:
- * @backend: An #ECalBackend object.
- *
- * Gets the #ESource associated with the given backend.
- *
- * Return value: The #ESource for the backend.
- */
-ESource *
-e_cal_backend_get_source (ECalBackend *backend)
+ 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;
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
- priv = backend->priv;
+ 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;
- return priv->source;
+ 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);
}
-/**
- * e_cal_backend_get_uri:
- * @backend: A calendar backend.
- *
- * Queries the URI of a calendar backend, which must already have an open
- * calendar.
- *
- * Return value: The URI where the calendar is stored.
- **/
-const char *
-e_cal_backend_get_uri (ECalBackend *backend)
+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;
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
- priv = backend->priv;
+ 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);
- return priv->uri;
+ 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;
}
-/**
- * e_cal_backend_get_kind:
- * @backend: An #ECalBackend object.
- *
- * Gets the kind of components the given backend stores.
- *
- * Return value: The kind of components for this backend.
- */
-icalcomponent_kind
-e_cal_backend_get_kind (ECalBackend *backend)
+static GList *
+cal_backend_list_cached_timezones (ETimezoneCache *cache)
{
ECalBackendPrivate *priv;
+ GList *list;
- g_return_val_if_fail (backend != NULL, ICAL_NO_COMPONENT);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
+ priv = E_CAL_BACKEND_GET_PRIVATE (cache);
- priv = backend->priv;
+ g_mutex_lock (&priv->zone_cache_lock);
+
+ list = g_hash_table_get_values (priv->zone_cache);
+
+ g_mutex_unlock (&priv->zone_cache_lock);
- return priv->kind;
+ return list;
}
static void
-cal_destroy_cb (gpointer data, GObject *where_cal_was)
+e_cal_backend_class_init (ECalBackendClass *class)
{
- ECalBackend *backend = E_CAL_BACKEND (data);
-
- e_cal_backend_remove_client (backend, (EDataCal *) where_cal_was);
+ 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,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_KIND,
+ g_param_spec_ulong (
+ "kind",
+ "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_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REGISTRY,
+ g_param_spec_object (
+ "registry",
+ "Registry",
+ "Data source registry",
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
}
static void
-listener_died_cb (gpointer cnx, gpointer data)
+e_cal_backend_timezone_cache_init (ETimezoneCacheInterface *interface)
{
- EDataCal *cal = E_DATA_CAL (data);
-
- if (ORBit_small_get_connection_status (e_data_cal_get_listener(cal)) == ORBIT_CONNECTION_DISCONNECTED)
- e_cal_backend_remove_client (e_data_cal_get_backend (cal), cal);
+ 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
-last_client_gone (ECalBackend *backend)
+e_cal_backend_init (ECalBackend *backend)
{
- g_signal_emit (backend, e_cal_backend_signals[LAST_CLIENT_GONE], 0);
+ GHashTable *zone_cache;
+
+ 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 = E_CAL_BACKEND_GET_PRIVATE (backend);
+
+ backend->priv->clients = NULL;
+ g_mutex_init (&backend->priv->clients_mutex);
+
+ backend->priv->views = NULL;
+ g_mutex_init (&backend->priv->views_mutex);
+
+ backend->priv->zone_cache = zone_cache;
+ g_mutex_init (&backend->priv->zone_cache_lock);
+
+ backend->priv->readonly = TRUE;
}
/**
- * e_cal_backend_add_client:
- * @backend: An ECalBackend object.
- * @cal: An EDataCal object.
+ * e_cal_backend_get_kind:
+ * @backend: an #ECalBackend
*
- * Adds a new client to the given backend. For any event, the backend will
- * notify all clients added via this function.
+ * Gets the kind of components the given backend stores.
+ *
+ * Returns: The kind of components for this backend.
*/
-void
-e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal)
+icalcomponent_kind
+e_cal_backend_get_kind (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));
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
- priv = backend->priv;
+ return backend->priv->kind;
+}
- bonobo_object_set_immortal (BONOBO_OBJECT (cal), TRUE);
+/**
+ * e_cal_backend_get_registry:
+ * @backend: an #ECalBackend
+ *
+ * Returns the data source registry to which #EBackend:source belongs.
+ *
+ * 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);
- g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
+ return backend->priv->registry;
+}
- ORBit_small_listen_for_broken (e_data_cal_get_listener (cal), G_CALLBACK (listener_died_cb), cal);
+/**
+ * e_cal_backend_is_opened:
+ * @backend: an #ECalBackend
+ *
+ * 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.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_is_opened (ECalBackend *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->opened;
}
/**
- * e_cal_backend_remove_client:
- * @backend: An #ECalBackend object.
- * @cal: An #EDataCal object.
+ * e_cal_backend_is_opening:
+ * @backend: an #ECalBackend
*
- * 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 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_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
- /* 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));
+ return backend->priv->opening;
+}
- priv = backend->priv;
+/**
+ * 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)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
- /* Disconnect */
- g_mutex_lock (priv->clients_mutex);
- priv->clients = g_list_remove (priv->clients, cal);
- g_mutex_unlock (priv->clients_mutex);
+ return backend->priv->readonly;
+}
+
+/**
+ * e_cal_backend_is_removed:
+ * @backend: an #ECalBackend
+ *
+ * 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)
+{
+ 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)
- last_client_gone (backend);
+ return backend->priv->removed;
}
/**
- * e_cal_backend_add_query:
- * @backend: An #ECalBackend object.
- * @query: An #EDataCalView object.
+ * e_cal_backend_set_is_removed:
+ * @backend: an #ECalBackend
+ * @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:
- * @backend: An #ECalBackend object.
+ * 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.
*
- * Return value: The list of live queries.
- */
-EList *
-e_cal_backend_get_queries (ECalBackend *backend)
+ * Returns: the cache directory for the 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
- * @backend: An #ECalBackend object.
- * @query: An #EDataCalView object, previously added with @ref e_cal_backend_add_query.
+ * e_cal_backend_set_cache_dir:
+ * @backend: an #ECalBackend
+ * @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.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:
- * @backend: A calendar backend.
+ * 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
+ *
+ * Returns: a filename for an attachment in a local cache dir. Free returned
+ * pointer with a g_free().
*
- * Queries the cal address associated with a calendar backend, which
- * must already have an open calendar.
+ * Since: 3.4
**/
-void
-e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal)
+gchar *
+e_cal_backend_create_cache_filename (ECalBackend *backend,
+ const gchar *uid,
+ const gchar *filename,
+ gint fileindex)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_val_if_fail (backend != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- g_assert (CLASS (backend)->get_cal_address != NULL);
- (* CLASS (backend)->get_cal_address) (backend, cal);
+ return e_filename_mkdir_encoded (e_cal_backend_get_cache_dir (backend), uid, filename, fileindex);
}
+/**
+ * e_cal_backend_get_backend_property:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @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_notify_readonly (ECalBackend *backend, gboolean read_only)
+e_cal_backend_get_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name)
{
- ECalBackendPrivate *priv;
- GList *l;
-
- priv = backend->priv;
+ 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);
- 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, GNOME_Evolution_Calendar_Success, read_only);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
}
+/**
+ * e_cal_backend_set_backend_property:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @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_notify_cal_address (ECalBackend *backend, char *address)
+e_cal_backend_set_backend_property (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *prop_name,
+ const gchar *prop_value)
{
- ECalBackendPrivate *priv;
- GList *l;
+ 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);
- priv = backend->priv;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
+}
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_cal_address (l->data, GNOME_Evolution_Calendar_Success, address);
+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:
- * @backend: An #ECalBackend object.
- * @cal: An #EDataCal object.
+ * e_cal_backend_add_client:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
*
- * Calls the get_alarm_email_address 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_alarm_email_address (ECalBackend *backend, EDataCal *cal)
+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));
- g_assert (CLASS (backend)->get_alarm_email_address != NULL);
- (* CLASS (backend)->get_alarm_email_address) (backend, 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);
}
-/**
- *e_cal_backend_get_alarm_email_address:
- * @backend: An #ECalBackend object.
- * @cal: An #EDataCal object.
- *
- * Calls the get_ldap_attribute method of the given backend.
- */
-void
-e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal)
+static void
+e_cal_backend_remove_client_private (ECalBackend *backend,
+ EDataCal *cal,
+ gboolean weak_unref)
{
- g_return_if_fail (backend != NULL);
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);
+
+ /* 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_assert (CLASS (backend)->get_ldap_attribute != NULL);
- (* CLASS (backend)->get_ldap_attribute) (backend, cal);
+ g_object_unref (backend);
}
/**
- * e_cal_backend_get_alarm_email_address:
- * @backend: An #ECalBackend object.
- * @cal: An #EDataCal object.
+ * e_cal_backend_remove_client:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
*
- * Calls the get_static_capabilities method on the given backend.
+ * Removes a client from the list of connected clients to the given backend.
*/
void
-e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal)
+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)->get_static_capabilities != NULL);
- (* CLASS (backend)->get_static_capabilities) (backend, cal);
+ e_cal_backend_remove_client_private (backend, cal, TRUE);
}
/**
- * e_cal_backend_open:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @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.
+ * e_cal_backend_add_view:
+ * @backend: an #ECalBackend
+ * @view: An #EDataCalView object.
+ *
+ * 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.
*
- * Opens a calendar backend with data from a calendar stored at the specified
- * URI.
+ * Since: 3.2
*/
void
-e_cal_backend_open (ECalBackend *backend, EDataCal *cal, gboolean only_if_exists,
- const char *username, const char *password)
+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)->open != NULL);
- (* CLASS (backend)->open) (backend, cal, only_if_exists, username, password);
+ 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:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
+ * e_cal_backend_remove_view
+ * @backend: an #ECalBackend
+ * @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)
+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);
+ 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:
- * @backend: A calendar backend.
+ * 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().
*
- * Return value: 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
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
+ * e_cal_backend_foreach_view:
+ * @backend: an #ECalBackend
+ * @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);
- g_assert (CLASS (backend)->is_read_only != NULL);
- (* CLASS (backend)->is_read_only) (backend, cal);
-}
+ list = e_cal_backend_list_views (backend);
-/**
- * e_cal_backend_start_query:
- * @backend: A calendar backend.
- * @query: The query to be started.
- *
- * Starts a new live query on the given backend.
- */
-void
-e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ if (!callback (E_DATA_CAL_VIEW (link->data), user_data))
+ break;
+ }
- g_assert (CLASS (backend)->start_query != NULL);
- (* CLASS (backend)->start_query) (backend, query);
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
/**
- * e_cal_backend_get_mode:
- * @backend: A calendar backend.
+ * e_cal_backend_set_notification_proxy:
+ * @backend: an #ECalBackend
+ * @proxy: The calendar backend to act as notification proxy.
*
- * Queries whether a calendar backend is connected remotely.
+ * Sets the backend that will act as notification proxy for the given backend.
*
- * Return value: The current mode the calendar is in
- **/
-CalMode
-e_cal_backend_get_mode (ECalBackend *backend)
+ * Since: 3.2
+ */
+void
+e_cal_backend_set_notification_proxy (ECalBackend *backend,
+ ECalBackend *proxy)
{
- 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);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
- return result;
+ backend->priv->notification_proxy = proxy;
}
-
/**
- * e_cal_backend_set_mode:
- * @backend: A calendar backend
- * @mode: Mode to change to
+ * 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.
*
- * Sets the mode of the calendar
- */
+ * 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.
+ **/
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);
- g_assert (CLASS (backend)->set_mode != NULL);
- (* CLASS (backend)->set_mode) (backend, mode);
+ if (e_cal_backend_is_opened (backend)) {
+ gboolean online;
+
+ 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:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- *
- * Calls the get_default_object method on the given backend.
- */
+ * e_cal_backend_refresh:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ *
+ * 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)
+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);
+ 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: A calendar backend.
- * @cal: An #EDataCal 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, const char *uid, const char *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, 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: A calendar backend.
- * @cal: An #EDataCal object.
+ * @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, const char *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, sexp);
-}
-
-/**
- * e_cal_backend_get_attachment_list:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @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, const char *uid, const char *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, 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: A calendar backend.
- * @cal: An #EDataCal object.
+ * @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, 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, users, start, end);
-}
-
-/**
- * e_cal_backend_get_changes:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @change_id: A unique uid for the callers change list
- *
- * Builds a sequence of objects and the type of change that occurred on them since
- * the last time the give change_id was seen
- */
-void
-e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, const char *change_id)
-{
- 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, change_id);
-}
-
-/**
- * e_cal_backend_discard_alarm
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @uid: UID of the component to discard the alarm from.
- * @auid: Alarm ID.
- *
- * Discards an alarm from the given component. This allows the specific backend
- * to do whatever is needed to really discard the alarm.
- */
-void
-e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, const char *uid, const char *auid)
-{
- 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, uid, auid);
+ 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_create_object:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @calobj: The object to create.
+ * e_cal_backend_create_objects:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @calobjs: The objects to create (list of gchar *).
*
* 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_create_object (ECalBackend *backend, EDataCal *cal, const char *calobj)
+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 (calobj != NULL);
-
- if (CLASS (backend)->create_object)
- (* CLASS (backend)->create_object) (backend, cal, calobj);
+ 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_data_cal_notify_object_created (cal, GNOME_Evolution_Calendar_PermissionDenied, NULL, NULL);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->create_objects) (backend, cal, opid, cancellable, calobjs);
}
/**
- * e_cal_backend_modify_object:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @calobj: Object to be modified.
+ * e_cal_backend_modify_objects:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @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.
*
- * Calls the modify_object method on the given backend.
- */
+ * 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_modify_object (ECalBackend *backend, EDataCal *cal, const char *calobj, CalObjModType mod)
+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 (calobj != NULL);
-
- if (CLASS (backend)->modify_object)
- (* CLASS (backend)->modify_object) (backend, cal, calobj, mod);
+ 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_data_cal_notify_object_removed (cal, GNOME_Evolution_Calendar_PermissionDenied, NULL, NULL, NULL);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->modify_objects) (backend, cal, opid, cancellable, calobjs, mod);
}
/**
- * e_cal_backend_remove_object:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @uid: Unique identifier of the object to remove.
- * @rid: A recurrence ID.
+ * e_cal_backend_remove_objects:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @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.
*
- * Removes an object in a calendar backend. The backend will notify all of its
+ * 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_remove_object (ECalBackend *backend, EDataCal *cal, const char *uid, const char *rid, CalObjModType mod)
+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 (uid != NULL);
+ g_return_if_fail (ids != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove_objects != NULL);
- g_assert (CLASS (backend)->remove_object != NULL);
- (* CLASS (backend)->remove_object) (backend, cal, uid, rid, mod);
+ 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_CAL_BACKEND_GET_CLASS (backend)->remove_objects) (backend, cal, opid, cancellable, ids, mod);
}
/**
* e_cal_backend_receive_objects:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: iCalendar object.
*
* Calls the receive_objects method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_receive_objects().
+ **/
void
-e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, const char *calobj)
+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);
- g_assert (CLASS (backend)->receive_objects != NULL);
- (* CLASS (backend)->receive_objects) (backend, cal, calobj);
+ 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_CAL_BACKEND_GET_CLASS (backend)->receive_objects) (backend, cal, opid, cancellable, calobj);
}
/**
* e_cal_backend_send_objects:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: iCalendar object to be sent.
*
* Calls the send_objects method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_send_objects().
+ **/
void
-e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, const char *calobj)
+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 (calobj != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->send_objects != NULL);
- g_assert (CLASS (backend)->send_objects != NULL);
- (* CLASS (backend)->send_objects) (backend, cal, calobj);
+ 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_get_timezone:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
- * NULL.
+ * e_cal_backend_get_attachment_uris:
+ * @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.
*
- * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
- * can't be found.
- */
+ * 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_get_timezone (ECalBackend *backend, EDataCal *cal, const char *tzid)
+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 (tzid != 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)->get_timezone != NULL);
- (* CLASS (backend)->get_timezone) (backend, cal, tzid);
+ 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_set_default_zone:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @tzobj: The timezone object, in a string.
+ * e_cal_backend_discard_alarm:
+ * @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 discard alarm in.
+ * @auid: Unique identifier of the alarm itself.
*
- * Sets the default timezone for the calendar, which is used to resolve
- * DATE and floating DATE-TIME values.
- */
+ * 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_set_default_zone (ECalBackend *backend, EDataCal *cal, const char *tzobj)
+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 (tzobj != NULL);
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (auid != NULL);
- (* CLASS (backend)->set_default_zone) (backend, cal, tzobj);
+ 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);
}
/**
- * @deprecated This virual function should not be used in the backends, use
- * e_cal_backend_set_zone instead. This function restricts the default timezone
- * to be libical builtin timezone.
- *
- * e_cal_backend_set_default_timezone:
- * @backend: A calendar backend.
- * @cal: An #EDataCal object.
- * @tzid: The TZID identifying the timezone.
- *
- * Sets the default timezone for the calendar, which is used to resolve
- * DATE and floating DATE-TIME values.
+ * 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_set_default_timezone (ECalBackend *backend, EDataCal *cal, const char *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);
- (* CLASS (backend)->set_default_timezone) (backend, cal, tzid);
+ 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: A calendar backend.
- * @cal: An #EDataCal object.
- * @tzobj: The timezone object, in a string.
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @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, const char *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, 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:
- * @backend: A calendar backend.
+ * 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: A calendar backend.
- * @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 char *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:
- * @backend: A calendar backend.
- * @proxy: The calendar backend to act as notification proxy.
+ * e_cal_backend_stop_view:
+ * @backend: an #ECalBackend
+ * @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:
- * @backend: A calendar backend.
- * @calobj: iCalendar representation of new object
+ * e_cal_backend_notify_component_created:
+ * @backend: an #ECalBackend
+ * @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 char *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);
- bonobo_object_ref (query);
- if (e_data_cal_view_object_matches (query, calobj))
- e_data_cal_view_notify_objects_added_1 (query, calobj);
- bonobo_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 char *old_object, const char *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
- * @backend: A calendar backend.
+ * e_cal_backend_notify_component_modified:
+ * @backend: an #ECalBackend
+ * @old_component: the #ECalComponent before the modification
+ * @new_component: the #ECalComponent after the modification
*
- * This methods has to be used before e_cal_backend_notify_view_progress.
- * Sets last notified percent value to 0.
+ * Notifies each of the backend's listeners about a modified object.
+ *
+ * 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: 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:
- * @backend: A calendar backend.
- * @message: the UID of the removed object
- * @percent: percentage of the objects loaded in the view
+ * e_cal_backend_notify_component_removed:
+ * @backend: an #ECalBackend
+ * @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 char *message, int 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);
- bonobo_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);
- bonobo_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:
- * @backend: A calendar backend.
- * @status: returns the status once the view is fully populated.
+ * e_cal_backend_notify_error:
+ * @backend: an #ECalBackend
+ * @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, GNOME_Evolution_Calendar_CallStatus status)
+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, status);
+ 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);
- bonobo_object_ref (query);
-
- e_data_cal_view_notify_done (query, status);
-
- bonobo_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:
- * @backend: A calendar backend.
- * @old_object: iCalendar representation of the original form of the object
- * @object: iCalendar representation of the new form of the object
+ * e_cal_backend_notify_readonly:
+ * @backend: an #ECalBackend
+ * @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 char *old_object, const char *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);
- bonobo_object_ref (query);
- match_query_and_notify (query, old_object, object);
- bonobo_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:
- * @backend: A calendar backend.
- * @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.
+ * e_cal_backend_notify_online:
+ * @backend: an #ECalBackend
+ * @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 char *old_object, const char *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_mutex_lock (&priv->clients_mutex);
- bonobo_object_ref (query);
+ for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
+ e_data_cal_report_online (E_DATA_CAL (clients->data), is_online);
- if (object == NULL) {
- /* if object == NULL, it means the object has been completely
- removed from the backend */
- if (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_unlock (&priv->clients_mutex);
+}
- bonobo_object_unref (query);
+/**
+ * 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.
+ *
+ * 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.
+ *
+ * See also: e_cal_backend_respond_opened()
+ *
+ * Note: The @error is freed automatically if not %NULL.
+ *
+ * Meant to be used by backend implementations.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_backend_notify_opened (ECalBackend *backend,
+ GError *error)
+{
+ ECalBackendPrivate *priv;
+ GList *clients;
- e_iterator_next (iter);
- }
- g_object_unref (iter);
-}
+ priv = backend->priv;
+ g_mutex_lock (&priv->clients_mutex);
+ priv->opening = FALSE;
+ priv->opened = error == NULL;
-void
-e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects)
-{
- e_data_cal_view_notify_objects_added (query, objects);
-}
+ for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
+ e_data_cal_report_opened (E_DATA_CAL (clients->data), error);
-void
-e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids)
-{
- e_data_cal_view_notify_objects_removed (query, ids);
-}
+ g_mutex_unlock (&priv->clients_mutex);
-void
-e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects)
-{
- e_data_cal_view_notify_objects_modified (query, objects);
+ if (error)
+ g_error_free (error);
}
/**
- * e_cal_backend_notify_mode:
- * @backend: A calendar backend.
- * @status: Status of the mode set
- * @mode: the current mode
+ * e_cal_backend_notify_property_changed:
+ * @backend: an #ECalBackend
+ * @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,
- GNOME_Evolution_Calendar_CalListener_SetModeStatus status,
- GNOME_Evolution_Calendar_CalMode 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);
+
+ 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);
+
+ g_mutex_unlock (&priv->clients_mutex);
}
/**
- * e_cal_backend_notify_auth_required:
- * @backend: A calendar backend.
+ * e_cal_backend_respond_opened:
+ * @backend: an #ECalBackend
+ * @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 that authentication is required to
- * open the calendar.
- */
+ * 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_auth_required (ECalBackend *backend)
+e_cal_backend_respond_opened (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GError *error)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ GError *copy = 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 (opid != 0);
+
+ if (error)
+ copy = g_error_copy (error);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_auth_required (l->data);
+ e_cal_backend_notify_opened (backend, copy);
+ e_data_cal_respond_open (cal, opid, error);
}
/**
- * e_cal_backend_notify_error:
- * @backend: A calendar backend.
- * @message: Error message
+ * e_cal_backend_empty_cache:
+ * @backend: an #ECalBackend
+ * @cache: Backend's cache to empty.
*
- * Notifies each of the backend's listeners about an error
+ * Empties backend's cache with all notifications and so on, thus all listening
+ * will know there is nothing in this backend.
+ *
+ * Since: 2.28
**/
void
-e_cal_backend_notify_error (ECalBackend *backend, const char *message)
+e_cal_backend_empty_cache (ECalBackend *backend,
+ ECalBackendCache *cache)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ GList *comps_in_cache;
- if (priv->notification_proxy) {
- e_cal_backend_notify_error (priv->notification_proxy, message);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+
+ if (!cache)
return;
+
+ g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
+
+ e_file_cache_freeze_changes (E_FILE_CACHE (cache));
+
+ for (comps_in_cache = e_cal_backend_cache_get_components (cache);
+ comps_in_cache;
+ comps_in_cache = comps_in_cache->next) {
+ ECalComponentId *id;
+ ECalComponent *comp = comps_in_cache->data;
+
+ id = e_cal_component_get_id (comp);
+
+ e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
+
+ e_cal_backend_notify_component_removed (backend, id, comp, NULL);
+
+ e_cal_component_free_id (id);
+ g_object_unref (comp);
}
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_error (l->data, message);
+ g_list_free (comps_in_cache);
+
+ e_file_cache_thaw_changes (E_FILE_CACHE (cache));
}