On Tue, Jul 5, 2011 at 10:45 AM, Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx> wrote: > Hi Bartosz, > > On Tue, Jul 5, 2011 at 12:51 AM, Bartosz Szatkowski <bulislaw@xxxxxxxxx> wrote: >> Until now only default ebook was used, this patch change this behaviour >> so each function is run on all available (active) ebooks and merging >> results from each of them. >> --- >> plugins/phonebook-ebook.c | 281 +++++++++++++++++++++++++++++---------------- >> 1 files changed, 182 insertions(+), 99 deletions(-) >> >> diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c >> index 82019da..f223965 100644 >> --- a/plugins/phonebook-ebook.c >> +++ b/plugins/phonebook-ebook.c >> @@ -45,17 +45,20 @@ >> #define QUERY_NAME "(contains \"given_name\" \"%s\")" >> #define QUERY_PHONE "(contains \"phone\" \"%s\")" >> >> - >> struct query_context { >> - gboolean completed; >> const struct apparam_field *params; >> phonebook_cb contacts_cb; >> phonebook_entry_cb entry_cb; >> phonebook_cache_ready_cb ready_cb; >> + EBookQuery *query; >> + int count; >> + GString *buf; >> + char *id; >> + unsigned queued_calls; >> void *user_data; >> }; >> >> -static EBook *ebook = NULL; >> +static GSList *ebooks = NULL; >> >> static char *attribute_mask[] = { >> /* 0 */ "VERSION", >> @@ -91,6 +94,19 @@ static char *attribute_mask[] = { >> >> }; >> >> +static void free_query_context(struct query_context *data) >> +{ >> + g_free(data->id); >> + >> + if (data->buf != NULL) >> + g_string_free(data->buf, TRUE); >> + >> + if (data->query != NULL) >> + e_book_query_unref(data->query); >> + >> + g_free(data); >> +} >> + >> static char *evcard_to_string(EVCard *evcard, unsigned int format, >> uint64_t filter) >> { >> @@ -99,7 +115,8 @@ static char *evcard_to_string(EVCard *evcard, unsigned int format, >> char *vcard; >> >> if (!filter) >> - return e_vcard_to_string(evcard, format); >> + return e_vcard_to_string(evcard, EVC_FORMAT_VCARD_30); >> + /* XXX There is no support for VCARD 2.1 at this time */ >> >> /* >> * Mandatory attributes for vCard 2.1 are VERSION ,N and TEL. >> @@ -136,24 +153,20 @@ static char *evcard_to_string(EVCard *evcard, unsigned int format, >> return vcard; >> } >> >> -static void ebookpull_cb(EBook *book, EBookStatus estatus, GList *contacts, >> +static void ebookpull_cb(EBook *book, const GError *gerr, GList *contacts, >> void *user_data) >> { >> struct query_context *data = user_data; >> - GString *string = g_string_new(""); >> - unsigned int count = 0, maxcount; >> GList *l; >> + unsigned int count = data->count, maxcount; >> >> - if (estatus == E_BOOK_ERROR_CANCELLED) { >> - error("E-Book operation was cancelled: status %d", estatus); >> - goto fail; >> - } >> - >> - if (estatus != E_BOOK_ERROR_OK) { >> - error("E-Book query failed: status %d", estatus); >> + if (gerr != NULL) { >> + error("E-Book query failed: %s", gerr->message); >> goto done; >> } >> >> + DBG(""); >> + >> /* >> * When MaxListCount is zero, PCE wants to know the number of used >> * indexes in the phonebook of interest. All other parameters that >> @@ -161,7 +174,7 @@ static void ebookpull_cb(EBook *book, EBookStatus estatus, GList *contacts, >> */ >> maxcount = data->params->maxlistcount; >> if (maxcount == 0) { >> - count = g_list_length(contacts); >> + count += g_list_length(contacts); >> goto done; >> } >> >> @@ -177,45 +190,36 @@ static void ebookpull_cb(EBook *book, EBookStatus estatus, GList *contacts, >> vcard = evcard_to_string(evcard, data->params->format, >> data->params->filter); >> >> - string = g_string_append(string, vcard); >> - string = g_string_append(string, "\r\n"); >> + data->buf = g_string_append(data->buf, vcard); >> + data->buf = g_string_append(data->buf, "\r\n"); >> g_free(vcard); >> } >> - DBG("collected %d vcards", count); >> - >> >> done: >> - data->completed = TRUE; >> - data->contacts_cb(string->str, string->len, count, 0, TRUE, >> - data->user_data); >> + g_list_free_full(contacts, g_object_unref); >> >> -fail: >> - g_string_free(string, TRUE); >> + DBG("collected %d vcards", count); >> >> - if (data->completed) >> - g_free(data); >> + data->queued_calls--; >> + if (data->queued_calls == 0) >> + data->contacts_cb(data->buf->str, data->buf->len, count, 0, >> + TRUE, data->user_data); >> } >> >> -static void ebook_entry_cb(EBook *book, EBookStatus estatus, >> - EContact *contact, void *user_data) >> +static void ebook_entry_cb(EBook *book, const GError *gerr, >> + EContact *contact, void *user_data) >> { >> struct query_context *data = user_data; >> EVCard *evcard; >> char *vcard; >> size_t len; >> >> - if (estatus == E_BOOK_ERROR_CANCELLED) { >> - error("E-Book operation was cancelled: status %d", estatus); >> - goto fail; >> + if (gerr != NULL) { >> + error("E-Book query failed: %s", gerr->message); >> + goto done; >> } >> >> - data->completed = TRUE; >> - >> - if (estatus != E_BOOK_ERROR_OK) { >> - error("E-Book query failed: status %d", estatus); >> - data->contacts_cb(NULL, 0, 1, 0, TRUE, data->user_data); >> - goto fail; >> - } >> + DBG(""); >> >> evcard = E_VCARD(contact); >> >> @@ -224,13 +228,21 @@ static void ebook_entry_cb(EBook *book, EBookStatus estatus, >> >> len = vcard ? strlen(vcard) : 0; >> >> + data->count++; >> data->contacts_cb(vcard, len, 1, 0, TRUE, data->user_data); >> >> g_free(vcard); >> + g_object_unref(contact); >> >> -fail: >> - if (data->completed) >> - g_free(data); >> +done: >> + data->queued_calls--; >> + if (data->queued_calls == 0) { >> + if (data->count == 0) >> + data->contacts_cb(NULL, 0, 1, 0, TRUE, >> + data->user_data); >> + >> + free_query_context(data); >> + } >> } >> >> static char *evcard_name_attribute_to_string(EVCard *evcard) >> @@ -263,24 +275,19 @@ static char *evcard_name_attribute_to_string(EVCard *evcard) >> return g_string_free(name, FALSE); >> } >> >> -static void cache_cb(EBook *book, EBookStatus estatus, GList *contacts, >> +static void cache_cb(EBook *book, const GError *gerr, GList *contacts, >> void *user_data) >> { >> struct query_context *data = user_data; >> GList *l; >> >> - if (estatus == E_BOOK_ERROR_CANCELLED) { >> - error("E-Book operation was cancelled: status %d", estatus); >> - goto fail; >> - } >> - >> - data->completed = TRUE; >> - >> - if (estatus != E_BOOK_ERROR_OK) { >> - error("E-Book query failed: status %d", estatus); >> + if (gerr != NULL) { >> + error("E-Book operation failed: %s", gerr->message); >> goto done; >> } >> >> + DBG(""); >> + >> for (l = contacts; l; l = g_list_next(l)) { >> EContact *contact = E_CONTACT(l->data); >> EVCard *evcard = E_VCARD(contact); >> @@ -295,61 +302,116 @@ static void cache_cb(EBook *book, EBookStatus estatus, GList *contacts, >> if (!attrib) >> continue; >> >> - uid = e_vcard_attribute_get_value(attrib); >> + uid = e_vcard_attribute_get_value(attrib); >> if (!uid) >> continue; >> >> attrib = e_vcard_get_attribute(evcard, EVC_TEL); >> if (!attrib) >> - continue; >> - >> - tel = e_vcard_attribute_get_value(attrib); >> + tel = e_vcard_attribute_get_value(attrib); >> + else >> + tel = g_strdup(""); >> >> data->entry_cb(uid, PHONEBOOK_INVALID_HANDLE, name, NULL, >> tel, data->user_data); >> + >> g_free(name); >> g_free(uid); >> g_free(tel); >> } >> + >> done: >> - data->ready_cb(data->user_data); >> + g_list_free_full(contacts, g_object_unref); >> >> -fail: >> - if (data->completed) >> - g_free(data); >> + data->queued_calls--; >> + if (data->queued_calls == 0) >> + data->ready_cb(data->user_data); >> } >> >> int phonebook_init(void) >> { >> - GError *gerr = NULL; >> + GError *gerr; >> + ESourceList *src_list; >> + GSList *list; >> + gchar *default_src = NULL; >> + int status = 0; >> >> - if (ebook) >> + if (ebooks) >> return 0; >> >> g_type_init(); >> >> - ebook = e_book_new_default_addressbook(&gerr); >> - if (!ebook) { >> - error("Can't create user's default address book: %s", >> - gerr->message); >> - g_error_free(gerr); >> - return -EIO; >> + if (e_book_get_addressbooks(&src_list, &gerr) == FALSE) { >> + error("Can't list user's address books: %s", gerr->message); >> + >> + status = -EIO; >> + goto fail; >> } >> >> - if (!e_book_open(ebook, FALSE, &gerr)) { >> - error("Can't open e-book address book: %s", gerr->message); >> - g_error_free(gerr); >> - return -EIO; > > Please consider splitting this function since it is becoming too big. OK, i may put iterating overt this ebooks in new function. > >> + list = e_source_list_peek_groups(src_list); >> + while (list) { >> + ESourceGroup *group = E_SOURCE_GROUP(list->data); >> + >> + GSList *sources = e_source_group_peek_sources(group); >> + while (sources != NULL) { >> + EBook *ebook = e_book_new(E_SOURCE(sources->data), >> + &gerr); >> + if (ebook == NULL) { >> + error("Can't create user's address book: %s", >> + gerr->message); >> + >> + status = -EIO; >> + goto fail; >> + } >> + >> + if (g_strcmp0(default_src, e_source_get_uri( >> + E_SOURCE(sources->data))) == 0) { >> + sources = sources->next; >> + >> + continue; >> + } >> + >> + if (e_book_open(ebook, FALSE, &gerr) == FALSE) { >> + error("Can't open e-book address book: %s", >> + gerr->message); >> + >> + status = -EIO; >> + goto fail; >> + } >> + >> + if (default_src == NULL) >> + default_src = e_source_get_uri( >> + E_SOURCE(sources->data)); >> + >> + DBG("%s address book opened", >> + e_source_peek_name(sources->data)); >> + >> + ebooks = g_slist_append(ebooks, ebook); >> + >> + sources = sources->next; >> + } >> + >> + list = list->next; >> } >> >> - return 0; >> + return status; >> + >> +fail: >> + g_error_free(gerr); >> + g_slist_free_full(ebooks, g_object_unref); >> + g_object_unref(src_list); >> + >> + return status; >> } >> >> void phonebook_exit(void) >> { >> - if (ebook) >> - g_object_unref(ebook); >> - ebook = NULL; >> + DBG(""); >> + >> + if (ebooks == NULL) >> + return; >> + >> + g_slist_free_full(ebooks, g_object_unref); >> } >> >> char *phonebook_set_folder(const char *current_folder, >> @@ -440,13 +502,10 @@ void phonebook_req_finalize(void *request) >> { >> struct query_context *data = request; >> >> - if (!data) >> - return; >> + DBG(""); >> >> - if (!data->completed) { >> - data->completed = TRUE; >> - e_book_cancel_async_op(ebook, NULL); >> - } >> + if (data != NULL && data->queued_calls == 0) >> + free_query_context(data); >> } >> >> void *phonebook_pull(const char *name, const struct apparam_field *params, >> @@ -458,6 +517,7 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, >> data->contacts_cb = cb; >> data->params = params; >> data->user_data = user_data; >> + data->buf = g_string_new(""); >> >> if (err) >> *err = 0; >> @@ -468,15 +528,26 @@ void *phonebook_pull(const char *name, const struct apparam_field *params, >> int phonebook_pull_read(void *request) >> { >> struct query_context *data = request; >> - EBookQuery *query; >> + gboolean ret; >> + GSList *ebook; >> >> if (!data) >> return -ENOENT; >> >> - query = e_book_query_any_field_contains(""); >> - e_book_async_get_contacts(ebook, query, ebookpull_cb, data); >> + data->query = e_book_query_any_field_contains(""); >> + >> + ebook = ebooks; >> + while (ebook != NULL) { >> + ret = e_book_get_contacts_async(ebook->data, data->query, >> + ebookpull_cb, data); >> + if (ret == TRUE) >> + data->queued_calls++; >> >> - e_book_query_unref(query); >> + ebook = ebook->next; >> + } >> + >> + if (data->queued_calls == 0) >> + return -ENOENT; >> >> return 0; >> } >> @@ -485,22 +556,28 @@ void *phonebook_get_entry(const char *folder, const char *id, >> const struct apparam_field *params, >> phonebook_cb cb, void *user_data, int *err) >> { >> + gboolean ret; >> struct query_context *data; >> + GSList *ebook; >> >> data = g_new0(struct query_context, 1); >> data->contacts_cb = cb; >> data->params = params; >> data->user_data = user_data; >> + data->id = g_strdup(id); >> >> - if (e_book_async_get_contact(ebook, id, ebook_entry_cb, data)) { >> - g_free(data); >> - if (err) >> - *err = -ENOENT; >> - return NULL; >> + ebook = ebooks; >> + while (ebook != NULL) { >> + ret = e_book_get_contact_async(ebook->data, data->id, >> + ebook_entry_cb, data); >> + if (ret == TRUE) >> + data->queued_calls++; >> + >> + ebook = ebook->next; >> } >> >> if (err) >> - *err = 0; >> + *err = (data->queued_calls == 0 ? -ENOENT : 0); >> >> return data; >> } >> @@ -511,31 +588,37 @@ void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb, >> struct query_context *data; >> EBookQuery *query; >> gboolean ret; >> + GSList *ebook; >> >> if (g_strcmp0("/telecom/pb", name) != 0) { >> if (err) >> *err = -ENOENT; >> + >> return NULL; >> } >> >> + DBG(""); >> + >> query = e_book_query_any_field_contains(""); >> >> data = g_new0(struct query_context, 1); >> data->entry_cb = entry_cb; >> data->ready_cb = ready_cb; >> data->user_data = user_data; >> + data->query = query; >> >> - ret = e_book_async_get_contacts(ebook, query, cache_cb, data); >> - e_book_query_unref(query); >> - if (ret != FALSE) { >> - g_free(data); >> - if (err) >> - *err = -EFAULT; >> - return NULL; >> + ebook = ebooks; >> + while (ebook != NULL) { >> + ret = e_book_get_contacts_async(ebook->data, query, >> + cache_cb, data); >> + if (ret == TRUE) >> + data->queued_calls++; >> + >> + ebook = ebook->next; >> } >> >> if (err) >> - *err = 0; >> + *err = (data->queued_calls == 0 ? -ENOENT : 0); >> >> return data; >> } >> -- >> 1.7.5.3 >> >> -- > > Btw, are we still using libebook? I though this breaks the integration > with gdbus, doesn't it? > > > > -- > Luiz Augusto von Dentz > Don't know anything about it, but is there really any other choice? -- Pozdrowienia, Bartosz Szatkowski ��.n��������+%������w��{.n�����{����^n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�