calendar: include rid in "objects-removed" ECalView signal
authorPatrick Ohly <patrick.ohly@intel.com>
Tue, 17 May 2011 07:45:24 +0000 (09:45 +0200)
committerPatrick Ohly <patrick.ohly@intel.com>
Tue, 7 Jun 2011 09:35:45 +0000 (11:35 +0200)
Since migration to D-Bus for libecal<->EDS communication, the
RECURRENCE-ID (rid) has not been sent in the "objects-removed" signal.
As a result, a backend could not communicate the removal of specific
recurrences.

This patch adds the rid after a newline to the string stored
internally and transferred via D-Bus. Because the newline is only
added when needed, traditional uid-only removals look the same as
before and continue to work with older versions of libecal. A uid+rid
combination will look like an unknown uid to an older libecal which
does not know how to split them. Therefore the D-Bus API is considered
unchanged and the interface number is not increased.

Whether clients really interpret "objects-removed" with empty rid (=
parent removed) or valid rid (= child removed) correctly is outside
the scope of this patch.

calendar/libecal/e-cal-view.c
calendar/libedata-cal/e-data-cal-view.c

index 0ca1437..988aa65 100644 (file)
@@ -91,9 +91,18 @@ build_id_list (const gchar * const *seq)
        list = NULL;
        for (i = 0; seq[i]; i++) {
                ECalComponentId *id;
+               const gchar * eol;
+
                id = g_new (ECalComponentId, 1);
-               id->uid = g_strdup (seq[i]);
-               id->rid = NULL; /* TODO */
+               /* match encoding as in notify_remove() in e-data-cal-view.c: <uid>[\n<rid>] */
+               eol = strchr (seq[i], '\n');
+               if (eol) {
+                       id->uid = g_strndup (seq[i], eol - seq[i]);
+                       id->rid = g_strdup (eol + 1);
+               } else {
+                       id->uid = g_strdup (seq[i]);
+                       id->rid = NULL;
+               }
                list = g_list_prepend (list, id);
        }
 
@@ -137,14 +146,14 @@ objects_modified_cb (EGdbusCalView *gdbus_calview, const gchar * const *objects,
 }
 
 static void
-objects_removed_cb (EGdbusCalView *gdbus_calview, const gchar * const *uids, ECalView *view)
+objects_removed_cb (EGdbusCalView *gdbus_calview, const gchar * const *seq, ECalView *view)
 {
        GList *list;
 
        g_return_if_fail (E_IS_CAL_VIEW (view));
        g_object_ref (view);
 
-       list = build_id_list (uids);
+       list = build_id_list (seq);
 
        g_signal_emit (G_OBJECT (view), signals[OBJECTS_REMOVED], 0, list);
 
index 22e0d27..e272ba3 100644 (file)
@@ -227,7 +227,7 @@ send_pending_removes (EDataCalView *view)
        if (priv->removes->len == 0)
                return;
 
-       /* TODO: send ECalComponentIds as a list of pairs */
+       /* send ECalComponentIds as <uid>[\n<rid>], as encoded in notify_remove() */
        e_gdbus_cal_view_emit_objects_removed (view->priv->gdbus_object, (const gchar * const *) priv->removes->data);
        reset_array (priv->removes);
 }
@@ -306,7 +306,9 @@ static void
 notify_remove (EDataCalView *view, ECalComponentId *id)
 {
        EDataCalViewPrivate *priv = view->priv;
-       gchar *uid;
+       gchar *ids;
+       gchar *uid, *rid;
+       size_t uid_len, rid_len;
 
        send_pending_adds (view);
        send_pending_changes (view);
@@ -315,9 +317,38 @@ notify_remove (EDataCalView *view, ECalComponentId *id)
                send_pending_removes (view);
        }
 
-       /* TODO: store ECalComponentId instead of just uid*/
-       uid = e_util_utf8_make_valid (id->uid);
-       g_array_append_val (priv->removes, uid);
+       /* store ECalComponentId as <uid>[\n<rid>] (matches D-Bus API) */
+       if (id->uid) {
+               uid = e_util_utf8_make_valid (id->uid);
+               uid_len = strlen (uid);
+       } else {
+               uid = NULL;
+               uid_len = 0;
+       }
+       if (id->rid) {
+               rid = e_util_utf8_make_valid (id->rid);
+               rid_len = strlen (rid);
+       } else {
+               rid = NULL;
+               rid_len = 0;
+       }
+       if (uid_len && !rid_len) {
+               /* shortcut */
+               ids = uid;
+               uid = NULL;
+       } else {
+               /* concatenate */
+               ids = g_malloc (uid_len + rid_len + (rid_len ? 2 : 1));
+               if (uid_len)
+                       strcpy (ids, uid);
+               if (rid_len) {
+                       ids[uid_len] = '\n';
+                       strcpy (ids + uid_len + 1, rid);
+               }
+       }
+       g_array_append_val (priv->removes, ids);
+       g_free (uid);
+       g_free (rid);
 
        g_hash_table_remove (priv->ids, id);