diff options
Diffstat (limited to 'addressbook/backend/pas/pas-backend-file.c')
-rw-r--r-- | addressbook/backend/pas/pas-backend-file.c | 598 |
1 files changed, 342 insertions, 256 deletions
diff --git a/addressbook/backend/pas/pas-backend-file.c b/addressbook/backend/pas/pas-backend-file.c index 06eb84cc4e..ddef2a568b 100644 --- a/addressbook/backend/pas/pas-backend-file.c +++ b/addressbook/backend/pas/pas-backend-file.c @@ -10,13 +10,15 @@ #include "pas-backend-file.h" #include <stdio.h> -#include <string.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <db.h> #include <sys/stat.h> +#include <libgnome/gnome-defs.h> +#include <libgnome/gnome-i18n.h> + #include <e-util/e-db3-utils.h> #if DB_VERSION_MAJOR != 3 || \ @@ -25,14 +27,15 @@ #error Including wrong DB3. Need libdb 3.1.17. #endif +#include <gtk/gtksignal.h> +#include <libgnome/gnome-defs.h> +#include <libgnome/gnome-util.h> #include <gal/util/e-util.h> #include <gal/widgets/e-unicode.h> #include <ebook/e-card-simple.h> #include <e-util/e-dbhash.h> #include <e-util/e-db3-utils.h> -#include <libgnome/gnome-i18n.h> - #include "pas-book.h" #include "pas-card-cursor.h" #include "pas-backend-card-sexp.h" @@ -51,10 +54,13 @@ typedef struct _PASBackendFileSearchContext PASBackendFileSearchContext; typedef struct _PasBackendFileChangeContext PASBackendFileChangeContext; struct _PASBackendFilePrivate { + GList *clients; + gboolean loaded; char *uri; char *filename; DB *file_db; EList *book_views; + gboolean writable; GHashTable *address_lists; PASBackendSummary *summary; }; @@ -208,7 +214,7 @@ pas_backend_file_book_view_copy(const PASBackendFileBookView *book_view, void *c new_book_view->search = g_strdup(book_view->search); new_book_view->card_sexp = book_view->card_sexp; if (new_book_view->card_sexp) - g_object_ref(new_book_view->card_sexp); + gtk_object_ref(GTK_OBJECT(new_book_view->card_sexp)); new_book_view->change_id = g_strdup(book_view->change_id); if (book_view->change_context) { @@ -230,7 +236,7 @@ pas_backend_file_book_view_free(PASBackendFileBookView *book_view, void *closure { g_free(book_view->search); if (book_view->card_sexp) - g_object_unref (book_view->card_sexp); + gtk_object_unref (GTK_OBJECT(book_view->card_sexp)); g_free(book_view->change_id); if (book_view->change_context) { @@ -268,7 +274,7 @@ get_nth(PASCardCursor *cursor, long n, gpointer data) } static void -cursor_destroy(gpointer data, GObject *where_object_was) +cursor_destroy(GtkObject *object, gpointer data) { CORBA_Environment ev; GNOME_Evolution_Addressbook_Book corba_book; @@ -294,7 +300,7 @@ cursor_destroy(gpointer data, GObject *where_object_was) } static void -view_destroy(gpointer data, GObject *where_object_was) +view_destroy(GtkObject *object, gpointer data) { PASBook *book = (PASBook *)data; PASBackendFile *bf; @@ -304,7 +310,7 @@ view_destroy(gpointer data, GObject *where_object_was) bf = PAS_BACKEND_FILE(pas_book_get_backend(book)); for (iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { const PASBackendFileBookView *view = e_iterator_get(iterator); - if (view->book_view == (PASBookView*)where_object_was) { + if (view->book_view == PAS_BOOK_VIEW(object)) { e_iterator_delete(iterator); success = TRUE; break; @@ -312,7 +318,7 @@ view_destroy(gpointer data, GObject *where_object_was) } if (!success) g_warning ("Failed to remove from book_views list"); - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); bonobo_object_unref(BONOBO_OBJECT(book)); } @@ -337,116 +343,6 @@ vcard_matches_search (const PASBackendFileBookView *view, char *vcard_string) return pas_backend_card_sexp_match_vcard (view->card_sexp, vcard_string); } -static gboolean -ecard_matches_search (const PASBackendFileBookView *view, ECard *card) -{ - /* If this is not a search context view, it doesn't match be default */ - if (view->card_sexp == NULL) - return FALSE; - - return pas_backend_card_sexp_match_ecard (view->card_sexp, card); -} - -typedef struct { - PASBackendFile *bf; - PASBook *book; - const PASBackendFileBookView *view; - DBC *dbc; - - int card_count; - int card_threshold; - int card_threshold_max; - GList *cards; - - gboolean done_first; - gboolean search_needed; -} FileBackendSearchClosure; - -static void -free_search_closure (FileBackendSearchClosure *closure) -{ - g_list_foreach (closure->cards, (GFunc)g_free, NULL); - g_list_free (closure->cards); - g_free (closure); -} - -static gboolean -pas_backend_file_search_timeout (gpointer data) -{ - FileBackendSearchClosure *closure = data; - int db_error = 0; - DBT id_dbt, vcard_dbt; - int file_version_name_len; - DBC *dbc = closure->dbc; - - file_version_name_len = strlen (PAS_BACKEND_FILE_VERSION_NAME); - - memset (&id_dbt, 0, sizeof (id_dbt)); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - - if (closure->done_first) { - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); - } - else { - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); - closure->done_first = TRUE; - } - - while (db_error == 0) { - - /* don't include the version in the list of cards */ - if (id_dbt.size != file_version_name_len+1 - || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { - char *vcard_string = vcard_dbt.data; - - /* check if the vcard matches the search sexp */ - if ((!closure->search_needed) || vcard_matches_search (closure->view, vcard_string)) { - closure->cards = g_list_prepend (closure->cards, g_strdup (vcard_string)); - closure->card_count ++; - } - - /* If we've accumulated a number of checks, pass them off to the client. */ - if (closure->card_count >= closure->card_threshold) { - pas_book_view_notify_add (closure->view->book_view, closure->cards); - /* Clean up the handed-off data. */ - g_list_foreach (closure->cards, (GFunc)g_free, NULL); - g_list_free (closure->cards); - closure->cards = NULL; - closure->card_count = 0; - - /* Yeah, this scheme is overly complicated. But I like it. */ - if (closure->card_threshold < closure->card_threshold_max) { - closure->card_threshold = MIN (2*closure->card_threshold, closure->card_threshold_max); - } - - /* return here, we'll do the next lump in the next callback */ - g_timeout_add (200, pas_backend_file_search_timeout, closure); - - return FALSE; - } - } - - db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); - } - - dbc->c_close (dbc); - - if (db_error != DB_NOTFOUND) { - g_warning ("pas_backend_file_search: error building list\n"); - free_search_closure (closure); - } - - if (closure->card_count) - pas_book_view_notify_add (closure->view->book_view, closure->cards); - - pas_book_view_notify_complete (closure->view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); - - free_search_closure (closure); - - return FALSE; -} - - static void pas_backend_file_search (PASBackendFile *bf, PASBook *book, @@ -456,6 +352,9 @@ pas_backend_file_search (PASBackendFile *bf, PASBackendFileBookView *view = (PASBackendFileBookView *)cnstview; gboolean search_needed; + if (!bf->priv->loaded) + return; + search_needed = TRUE; if ( ! strcmp (view->search, "(contains \"x-evolution-any-field\" \"\")")) @@ -467,7 +366,7 @@ pas_backend_file_search (PASBackendFile *bf, pas_book_view_notify_status_message (view->book_view, _("Loading...")); if (view->card_sexp) { - g_object_unref (view->card_sexp); + gtk_object_unref (GTK_OBJECT(view->card_sexp)); view->card_sexp = NULL; } @@ -482,24 +381,74 @@ pas_backend_file_search (PASBackendFile *bf, do_summary_query (bf, view, completion_search); } else { - FileBackendSearchClosure *closure = g_new0 (FileBackendSearchClosure, 1); - DB *db = bf->priv->file_db; - int db_error; + gint card_count = 0, card_threshold = 20, card_threshold_max = 3000; + int db_error = 0; + GList *cards = NULL; + DB *db = bf->priv->file_db; + DBC *dbc; + DBT id_dbt, vcard_dbt; + int file_version_name_len; + + file_version_name_len = strlen (PAS_BACKEND_FILE_VERSION_NAME); - closure->card_threshold = 20; - closure->card_threshold_max = 3000; - closure->search_needed = search_needed; - closure->view = view; - closure->bf = bf; - closure->book = book; + db_error = db->cursor (db, NULL, &dbc, 0); - db_error = db->cursor (db, NULL, &closure->dbc, 0); + memset (&id_dbt, 0, sizeof (id_dbt)); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); if (db_error != 0) { g_warning ("pas_backend_file_search: error building list\n"); } else { - g_idle_add (pas_backend_file_search_timeout, closure); + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_FIRST); + + while (db_error == 0) { + + /* don't include the version in the list of cards */ + if (id_dbt.size != file_version_name_len+1 + || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { + char *vcard_string = vcard_dbt.data; + + /* check if the vcard matches the search sexp */ + if ((!search_needed) || vcard_matches_search (view, vcard_string)) { + cards = g_list_prepend (cards, g_strdup (vcard_string)); + card_count ++; + } + + /* If we've accumulated a number of checks, pass them off to the client. */ + if (card_count >= card_threshold) { + pas_book_view_notify_add (view->book_view, cards); + /* Clean up the handed-off data. */ + g_list_foreach (cards, (GFunc)g_free, NULL); + g_list_free (cards); + cards = NULL; + card_count = 0; + + /* Yeah, this scheme is overly complicated. But I like it. */ + if (card_threshold < card_threshold_max) { + card_threshold = MIN (2*card_threshold, card_threshold_max); + } + } + } + + db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); + } + dbc->c_close (dbc); + + if (db_error != DB_NOTFOUND) { + g_warning ("pas_backend_file_search: error building list\n"); + } } + + if (card_count) + pas_book_view_notify_add (view->book_view, cards); + + pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); + + /* + ** It's fine to do this now since the data has been handed off. + */ + g_list_foreach (cards, (GFunc)g_free, NULL); + g_list_free (cards); } } @@ -541,6 +490,9 @@ pas_backend_file_changes (PASBackendFile *bf, memset (&id_dbt, 0, sizeof (id_dbt)); memset (&vcard_dbt, 0, sizeof (vcard_dbt)); + if (!bf->priv->loaded) + return; + /* Find the changed ids */ dirname = g_strdup (bf->priv->filename); slash = strrchr (dirname, '/'); @@ -572,9 +524,9 @@ pas_backend_file_changes (PASBackendFile *bf, * card changing */ card = e_card_new (vcard_dbt.data); - g_object_set (card, "last_use", NULL, "use_score", 0.0, NULL); + gtk_object_set (GTK_OBJECT (card), "last_use", NULL, "use_score", 0.0, NULL); vcard_string = e_card_get_vcard_assume_utf8 (card); - g_object_unref (card); + gtk_object_unref (GTK_OBJECT (card)); /* check what type of change has occurred, if any */ switch (e_dbhash_compare (ehash, id, vcard_string)) { @@ -612,7 +564,7 @@ pas_backend_file_changes (PASBackendFile *bf, for (v = ctx->del_ids; v != NULL; v = v->next){ char *id = v->data; - pas_book_view_notify_remove_1 (view->book_view, id); + pas_book_view_notify_remove (view->book_view, id); } pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); @@ -684,7 +636,7 @@ do_create(PASBackend *backend, ret_val = NULL; } - g_object_unref(card); + gtk_object_unref(GTK_OBJECT(card)); card = NULL; if (vcard_ptr && ret_val) @@ -716,7 +668,7 @@ pas_backend_file_process_create_card (PASBackend *backend, bonobo_object_unref (BONOBO_OBJECT (view->book_view)); } } - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); pas_book_respond_create ( book, @@ -739,76 +691,59 @@ pas_backend_file_process_create_card (PASBackend *backend, } static void -pas_backend_file_process_remove_cards (PASBackend *backend, - PASBook *book, - PASRemoveCardsRequest *req) +pas_backend_file_process_remove_card (PASBackend *backend, + PASBook *book, + PASRemoveCardRequest *req) { PASBackendFile *bf = PAS_BACKEND_FILE (backend); DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; int db_error; EIterator *iterator; + char *vcard_string; const char *id; - GList *l; - GList *removed_cards = NULL; - GNOME_Evolution_Addressbook_BookListener_CallStatus rv = GNOME_Evolution_Addressbook_BookListener_Success; - - for (l = req->ids; l; l = l->next) { - id = l->data; - string_to_dbt (id, &id_dbt); - memset (&vcard_dbt, 0, sizeof (vcard_dbt)); + id = req->id; + string_to_dbt (id, &id_dbt); + memset (&vcard_dbt, 0, sizeof (vcard_dbt)); - db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); - if (0 != db_error) { - rv = GNOME_Evolution_Addressbook_BookListener_CardNotFound; - continue; - } + db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0); + if (0 != db_error) { + pas_book_respond_remove ( + book, + GNOME_Evolution_Addressbook_BookListener_CardNotFound); + return; + } - db_error = db->del (db, NULL, &id_dbt, 0); - if (0 != db_error) { - rv = GNOME_Evolution_Addressbook_BookListener_CardNotFound; - continue; - } - - removed_cards = g_list_prepend (removed_cards, e_card_new (vcard_dbt.data)); + db_error = db->del (db, NULL, &id_dbt, 0); + if (0 != db_error) { + pas_book_respond_remove ( + book, + GNOME_Evolution_Addressbook_BookListener_CardNotFound); + return; } - /* if we actually removed some, try to sync */ - if (removed_cards) { - db_error = db->sync (db, 0); - if (db_error != 0) - g_warning ("db->sync failed.\n"); - } + db_error = db->sync (db, 0); + if (db_error != 0) + g_warning ("db->sync failed.\n"); + + vcard_string = vcard_dbt.data; for (iterator = e_list_get_iterator (bf->priv->book_views); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { const PASBackendFileBookView *view = e_iterator_get(iterator); - GList *view_removed = NULL; - for (l = removed_cards; l; l = l->next) { - ECard *removed_card = l->data; - if (ecard_matches_search (view, removed_card)) { - view_removed = g_list_prepend (view_removed, (char*)e_card_get_id (removed_card)); - } - } - if (view_removed) { + if (vcard_matches_search (view, vcard_string)) { bonobo_object_ref (BONOBO_OBJECT (view->book_view)); - pas_book_view_notify_remove (view->book_view, view_removed); + pas_book_view_notify_remove (view->book_view, req->id); pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); bonobo_object_unref (BONOBO_OBJECT (view->book_view)); - g_list_free (view_removed); } } - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); - pas_book_respond_remove (book, rv); - - for (l = removed_cards; l; l = l->next) { - ECard *c = l->data; - pas_backend_summary_remove_card (bf->priv->summary, e_card_get_id (c)); - g_object_unref (c); - } - - g_list_free (removed_cards); + pas_book_respond_remove ( + book, + GNOME_Evolution_Addressbook_BookListener_Success); + pas_backend_summary_remove_card (bf->priv->summary, id); } static void @@ -878,7 +813,7 @@ pas_backend_file_process_modify_card (PASBackend *backend, else if (new_match) pas_book_view_notify_add_1 (view->book_view, req->vcard); else /* if (old_match) */ - pas_book_view_notify_remove_1 (view->book_view, id); + pas_book_view_notify_remove (view->book_view, id); pas_book_view_notify_complete (view->book_view, GNOME_Evolution_Addressbook_BookViewListener_Success); @@ -887,7 +822,7 @@ pas_backend_file_process_modify_card (PASBackend *backend, CORBA_exception_free (&ev); } - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); pas_book_respond_modify ( book, @@ -904,7 +839,7 @@ pas_backend_file_process_modify_card (PASBackend *backend, g_free(old_vcard_string); - g_object_unref(card); + gtk_object_unref(GTK_OBJECT(card)); } static void @@ -1038,8 +973,8 @@ pas_backend_file_process_get_cursor (PASBackend *backend, get_nth, cursor_data); - g_object_weak_ref (G_OBJECT (cursor), - cursor_destroy, cursor_data); + gtk_signal_connect(GTK_OBJECT(cursor), "destroy", + GTK_SIGNAL_FUNC(cursor_destroy), cursor_data); pas_book_respond_get_cursor ( book, @@ -1059,11 +994,14 @@ pas_backend_file_process_get_book_view (PASBackend *backend, PASBackendFileBookView view; EIterator *iterator; + g_return_if_fail (req->listener != NULL); + bonobo_object_ref(BONOBO_OBJECT(book)); book_view = pas_book_view_new (req->listener); - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); + gtk_signal_connect(GTK_OBJECT(book_view), "destroy", + GTK_SIGNAL_FUNC(view_destroy), book); view.book_view = book_view; view.search = g_strdup (req->search); @@ -1079,13 +1017,10 @@ pas_backend_file_process_get_book_view (PASBackend *backend, : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), book_view); - if (!pas_backend_is_loaded (backend)) - return; - iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_last(iterator); pas_backend_file_search (bf, book, e_iterator_get(iterator), FALSE); - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); } static void @@ -1098,11 +1033,14 @@ pas_backend_file_process_get_completion_view (PASBackend *backend, PASBackendFileBookView view; EIterator *iterator; + g_return_if_fail (req->listener != NULL); + bonobo_object_ref(BONOBO_OBJECT(book)); book_view = pas_book_view_new (req->listener); - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); + gtk_signal_connect(GTK_OBJECT(book_view), "destroy", + GTK_SIGNAL_FUNC(view_destroy), book); view.book_view = book_view; view.search = g_strdup (req->search); @@ -1118,13 +1056,10 @@ pas_backend_file_process_get_completion_view (PASBackend *backend, : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */), book_view); - if (!pas_backend_is_loaded (backend)) - return; - iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_last(iterator); pas_backend_file_search (bf, book, e_iterator_get(iterator), TRUE); - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); } static void @@ -1138,11 +1073,14 @@ pas_backend_file_process_get_changes (PASBackend *backend, PASBackendFileChangeContext ctx; EIterator *iterator; + g_return_if_fail (req->listener != NULL); + bonobo_object_ref(BONOBO_OBJECT(book)); book_view = pas_book_view_new (req->listener); - g_object_weak_ref (G_OBJECT (book_view), view_destroy, book); + gtk_signal_connect(GTK_OBJECT(book_view), "destroy", + GTK_SIGNAL_FUNC(view_destroy), book); pas_book_respond_get_changes (book, (book_view != NULL @@ -1164,13 +1102,10 @@ pas_backend_file_process_get_changes (PASBackend *backend, e_list_append(bf->priv->book_views, &view); - if (!pas_backend_is_loaded (backend)) - return; - iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_last(iterator); pas_backend_file_changes (bf, book, e_iterator_get(iterator)); - g_object_unref(iterator); + gtk_object_unref(GTK_OBJECT(iterator)); } static void @@ -1219,14 +1154,85 @@ pas_backend_file_process_get_supported_fields (PASBackend *backend, for (i = 0; i < E_CARD_SIMPLE_FIELD_LAST; i ++) e_list_append (fields, e_card_simple_get_ecard_field (simple, i)); - g_object_unref (card); - g_object_unref (simple); + gtk_object_unref (GTK_OBJECT (card)); + gtk_object_unref (GTK_OBJECT (simple)); pas_book_respond_get_supported_fields (book, GNOME_Evolution_Addressbook_BookListener_Success, fields); } +static void +pas_backend_file_process_client_requests (PASBook *book) +{ + PASBackend *backend; + PASRequest *req; + + backend = pas_book_get_backend (book); + + req = pas_book_pop_request (book); + if (req == NULL) + return; + + switch (req->op) { + case CreateCard: + pas_backend_file_process_create_card (backend, book, (PASCreateCardRequest*)req); + break; + + case RemoveCard: + pas_backend_file_process_remove_card (backend, book, (PASRemoveCardRequest*)req); + break; + + case ModifyCard: + pas_backend_file_process_modify_card (backend, book, (PASModifyCardRequest*)req); + break; + + case CheckConnection: + pas_backend_file_process_check_connection (backend, book, (PASCheckConnectionRequest*)req); + break; + + case GetVCard: + pas_backend_file_process_get_vcard (backend, book, (PASGetVCardRequest*)req); + break; + + case GetCursor: + pas_backend_file_process_get_cursor (backend, book, (PASGetCursorRequest*)req); + break; + + case GetBookView: + pas_backend_file_process_get_book_view (backend, book, (PASGetBookViewRequest*)req); + break; + + case GetCompletionView: + pas_backend_file_process_get_completion_view (backend, book, (PASGetCompletionViewRequest*)req); + break; + + case GetChanges: + pas_backend_file_process_get_changes (backend, book, (PASGetChangesRequest*)req); + break; + + case AuthenticateUser: + pas_backend_file_process_authenticate_user (backend, book, (PASAuthenticateUserRequest*)req); + break; + + case GetSupportedFields: + pas_backend_file_process_get_supported_fields (backend, book, (PASGetSupportedFieldsRequest*)req); + break; + } + + pas_book_free_request (req); +} + +static void +pas_backend_file_book_destroy_cb (PASBook *book, gpointer data) +{ + PASBackendFile *backend; + + backend = PAS_BACKEND_FILE (data); + + pas_backend_remove_client (PAS_BACKEND (backend), book); +} + /* ** versions: ** @@ -1301,7 +1307,7 @@ pas_backend_file_upgrade_db (PASBackendFile *bf, char *old_version) card_failed++; } - g_object_unref (card); + gtk_object_unref (GTK_OBJECT(card)); } db_error = dbc->c_get(dbc, &id_dbt, &vcard_dbt, DB_NEXT); @@ -1353,10 +1359,11 @@ pas_backend_file_maybe_upgrade_db (PASBackendFile *bf) return ret_val; } + #define INITIAL_VCARD "BEGIN:VCARD\n\ X-EVOLUTION-FILE-AS:Ximian, Inc.\n\ LABEL;WORK;QUOTED-PRINTABLE:401 Park Drive 3 West=0ABoston, MA 02215=0AUSA\n\ -TEL;WORK;VOICE:(617) 375-3800\n\ +TEL;WORK;VOICE:(617) 236-0442\n\ TEL;WORK;FAX:(617) 236-8630\n\ EMAIL;INTERNET:hello@ximian.com\n\ URL:www.ximian.com/\n\ @@ -1378,6 +1385,8 @@ pas_backend_file_load_uri (PASBackend *backend, struct stat sb; char *summary_filename; + g_assert (bf->priv->loaded == FALSE); + db_version (&major, &minor, &patch); if (major != 3 || @@ -1422,10 +1431,10 @@ pas_backend_file_load_uri (PASBackend *backend, char *create_initial_file; char *dir; - dir = g_path_get_dirname(filename); - create_initial_file = g_build_filename (dir, "create-initial", NULL); + dir = g_dirname(filename); + create_initial_file = g_concat_dir_and_file(dir, "create-initial"); - if (g_file_test(create_initial_file, G_FILE_TEST_EXISTS)) { + if (g_file_exists(create_initial_file)) { char *id; id = do_create(backend, INITIAL_VCARD, NULL); g_free (id); @@ -1444,9 +1453,14 @@ pas_backend_file_load_uri (PASBackend *backend, return GNOME_Evolution_Addressbook_BookListener_OtherError; } - if (!pas_backend_file_maybe_upgrade_db (bf)) { + bf->priv->writable = writable; + + if (pas_backend_file_maybe_upgrade_db (bf)) + bf->priv->loaded = TRUE; + else { db->close (db, 0); bf->priv->file_db = NULL; + bf->priv->writable = FALSE; return GNOME_Evolution_Addressbook_BookListener_OtherError; } @@ -1459,6 +1473,7 @@ pas_backend_file_load_uri (PASBackend *backend, if (stat (bf->priv->filename, &sb) == -1) { db->close (db, 0); bf->priv->file_db = NULL; + bf->priv->writable = FALSE; return GNOME_Evolution_Addressbook_BookListener_OtherError; } db_mtime = sb.st_mtime; @@ -1472,8 +1487,6 @@ pas_backend_file_load_uri (PASBackend *backend, build_summary (bf->priv); } - pas_backend_set_is_loaded (backend, TRUE); - pas_backend_set_is_writable (backend, writable); return GNOME_Evolution_Addressbook_BookListener_Success; } @@ -1485,15 +1498,99 @@ pas_backend_file_get_uri (PASBackend *backend) bf = PAS_BACKEND_FILE (backend); + g_return_val_if_fail (bf->priv->loaded, NULL); g_assert (bf->priv->uri != NULL); return bf->priv->uri; } +static gboolean +pas_backend_file_add_client (PASBackend *backend, + GNOME_Evolution_Addressbook_BookListener listener) +{ + PASBackendFile *bf; + PASBook *book; + + g_assert (backend != NULL); + g_assert (PAS_IS_BACKEND_FILE (backend)); + + bf = PAS_BACKEND_FILE (backend); + + book = pas_book_new (backend, listener); + + if (!book) { + if (!bf->priv->clients) + pas_backend_last_client_gone (backend); + + return FALSE; + } + + gtk_signal_connect (GTK_OBJECT (book), "destroy", + pas_backend_file_book_destroy_cb, backend); + + gtk_signal_connect (GTK_OBJECT (book), "requests_queued", + pas_backend_file_process_client_requests, NULL); + + bf->priv->clients = g_list_prepend ( + bf->priv->clients, book); + + if (bf->priv->loaded) { + pas_book_respond_open ( + book, GNOME_Evolution_Addressbook_BookListener_Success); + if (bf->priv->writable) + pas_book_report_writable (book, bf->priv->writable); + } else { + pas_book_respond_open ( + book, GNOME_Evolution_Addressbook_BookListener_OtherError); + } + + bonobo_object_unref (BONOBO_OBJECT (book)); + + return TRUE; +} + +static void +pas_backend_file_remove_client (PASBackend *backend, + PASBook *book) +{ + PASBackendFile *bf; + GList *l; + PASBook *lbook; + + g_return_if_fail (backend != NULL); + g_return_if_fail (PAS_IS_BACKEND_FILE (backend)); + g_return_if_fail (book != NULL); + g_return_if_fail (PAS_IS_BOOK (book)); + + bf = PAS_BACKEND_FILE (backend); + + /* Find the book in the list of clients */ + + for (l = bf->priv->clients; l; l = l->next) { + lbook = PAS_BOOK (l->data); + + if (lbook == book) + break; + } + + g_assert (l != NULL); + + /* Disconnect */ + + bf->priv->clients = g_list_remove_link (bf->priv->clients, l); + g_list_free_1 (l); + + /* When all clients go away, notify the parent factory about it so that + * it may decide whether to kill the backend or not. + */ + if (!bf->priv->clients) + pas_backend_last_client_gone (backend); +} + static char * -pas_backend_file_get_static_capabilities (PASBackend *backend) +pas_backend_file_get_static_capabilities (PASBackend *backend) { - return g_strdup("local,do-initial-query,bulk-removes"); + return g_strdup("local,do-initial-query,cache-completions"); } static gboolean @@ -1516,10 +1613,10 @@ pas_backend_file_new (void) { PASBackendFile *backend; - backend = g_object_new (PAS_TYPE_BACKEND_FILE, NULL); + backend = gtk_type_new (pas_backend_file_get_type ()); if (! pas_backend_file_construct (backend)) { - g_object_unref (backend); + gtk_object_unref (GTK_OBJECT (backend)); return NULL; } @@ -1528,53 +1625,40 @@ pas_backend_file_new (void) } static void -pas_backend_file_dispose (GObject *object) +pas_backend_file_destroy (GtkObject *object) { PASBackendFile *bf; bf = PAS_BACKEND_FILE (object); - if (bf->priv) { - g_object_unref(bf->priv->book_views); - g_object_unref(bf->priv->summary); - g_free (bf->priv->uri); - g_free (bf->priv->filename); + gtk_object_unref(GTK_OBJECT(bf->priv->book_views)); + gtk_object_unref(GTK_OBJECT(bf->priv->summary)); + g_free (bf->priv->uri); + g_free (bf->priv->filename); - g_free (bf->priv); - bf->priv = NULL; - } + g_free (bf->priv); - G_OBJECT_CLASS (pas_backend_file_parent_class)->dispose (object); + GTK_OBJECT_CLASS (pas_backend_file_parent_class)->destroy (object); } static void pas_backend_file_class_init (PASBackendFileClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkObjectClass *object_class = (GtkObjectClass *) klass; PASBackendClass *parent_class; - pas_backend_file_parent_class = g_type_class_peek_parent (klass); + pas_backend_file_parent_class = gtk_type_class (pas_backend_get_type ()); parent_class = PAS_BACKEND_CLASS (klass); /* Set the virtual methods. */ parent_class->load_uri = pas_backend_file_load_uri; parent_class->get_uri = pas_backend_file_get_uri; + parent_class->add_client = pas_backend_file_add_client; + parent_class->remove_client = pas_backend_file_remove_client; parent_class->get_static_capabilities = pas_backend_file_get_static_capabilities; - parent_class->create_card = pas_backend_file_process_create_card; - parent_class->remove_cards = pas_backend_file_process_remove_cards; - parent_class->modify_card = pas_backend_file_process_modify_card; - parent_class->check_connection = pas_backend_file_process_check_connection; - parent_class->get_vcard = pas_backend_file_process_get_vcard; - parent_class->get_cursor = pas_backend_file_process_get_cursor; - parent_class->get_book_view = pas_backend_file_process_get_book_view; - parent_class->get_completion_view = pas_backend_file_process_get_completion_view; - parent_class->get_changes = pas_backend_file_process_get_changes; - parent_class->authenticate_user = pas_backend_file_process_authenticate_user; - parent_class->get_supported_fields = pas_backend_file_process_get_supported_fields; - - object_class->dispose = pas_backend_file_dispose; + object_class->destroy = pas_backend_file_destroy; } static void @@ -1583,8 +1667,11 @@ pas_backend_file_init (PASBackendFile *backend) PASBackendFilePrivate *priv; priv = g_new0 (PASBackendFilePrivate, 1); + priv->loaded = FALSE; + priv->clients = NULL; priv->book_views = e_list_new((EListCopyFunc) pas_backend_file_book_view_copy, (EListFreeFunc) pas_backend_file_book_view_free, NULL); priv->uri = NULL; + priv->writable = FALSE; backend->priv = priv; } @@ -1592,25 +1679,24 @@ pas_backend_file_init (PASBackendFile *backend) /** * pas_backend_file_get_type: */ -GType +GtkType pas_backend_file_get_type (void) { - static GType type = 0; + static GtkType type = 0; if (! type) { - GTypeInfo info = { - sizeof (PASBackendFileClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) pas_backend_file_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ + GtkTypeInfo info = { + "PASBackendFile", sizeof (PASBackendFile), - 0, /* n_preallocs */ - (GInstanceInitFunc) pas_backend_file_init + sizeof (PASBackendFileClass), + (GtkClassInitFunc) pas_backend_file_class_init, + (GtkObjectInitFunc) pas_backend_file_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL }; - type = g_type_register_static (PAS_TYPE_BACKEND, "PASBackendFile", &info, 0); + type = gtk_type_unique (pas_backend_get_type (), &info); } return type; |