aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/pas/pas-backend-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'addressbook/backend/pas/pas-backend-file.c')
-rw-r--r--addressbook/backend/pas/pas-backend-file.c598
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;