aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook
diff options
context:
space:
mode:
Diffstat (limited to 'addressbook')
-rw-r--r--addressbook/ChangeLog73
-rw-r--r--addressbook/backend/ebook/e-book.c41
-rw-r--r--addressbook/backend/ebook/e-book.h5
-rw-r--r--addressbook/backend/idl/addressbook.idl10
-rw-r--r--addressbook/backend/pas/pas-backend-file.c97
-rw-r--r--addressbook/backend/pas/pas-backend-ldap.c5
-rw-r--r--addressbook/backend/pas/pas-backend-summary.c223
-rw-r--r--addressbook/backend/pas/pas-backend-summary.h21
-rw-r--r--addressbook/backend/pas/pas-book.c73
-rw-r--r--addressbook/backend/pas/pas-book.h33
10 files changed, 471 insertions, 110 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog
index 343c9a394b..001132267e 100644
--- a/addressbook/ChangeLog
+++ b/addressbook/ChangeLog
@@ -1,3 +1,76 @@
+2002-07-10 Chris Toshok <toshok@ximian.com>
+
+ * backend/idl/addressbook.idl: add Book.getCompletionView.
+
+ * backend/ebook/e-book.c (e_book_get_completion_view): new
+ function, basically c&p of e_book_get_book_view, but call
+ getCompletionView.
+
+ * backend/ebook/e-book.h: add prototype for
+ e_book_get_completion_view.
+
+ * backend/pas/pas-backend-ldap.c
+ (pas_backend_ldap_process_client_requests): add a
+ GetCompletionView case here that just calls the same code as
+ GetBookView (since we don't build summaries for the ldap backend.)
+
+ * backend/pas/pas-backend-file.c (do_summary_query): add
+ @completion_search. If it's TRUE, just create the vcards from the
+ summary using pas_backend_summary_get_summary_vcard instead of
+ looking them up from the db.
+ (pas_backend_file_search): add @completion_search and pass it on
+ to do_summary_query.
+ (pas_backend_file_process_get_book_view): pass FALSE to
+ pas_backend_file_search.
+ (pas_backend_file_process_get_completion_view): new function,
+ basically c&p pas_backend_file_process_get_book_view, but pass
+ TRUE to pas_backend_file_search.
+ (pas_backend_file_process_client_requests): add a case for
+ GetCompletionView.
+ (pas_backend_file_load_uri): track the change to the summary api -
+ create the summary filename
+
+ * backend/pas/pas-book.c (pas_book_queue_get_completion_view): new
+ function, queue a GetCompletionView request to our queue.
+ (impl_GNOME_Evolution_Addressbook_Book_getCompletionView): new
+ function, call pas_book_queue_get_completion_view.
+ (pas_book_respond_get_completion_view): new function, just call
+ notifyViewRequested.
+ (pas_book_free_request): add a case for GetCompletionView.
+ (pas_book_get_epv): fill in epv->getCompletionView.
+
+ * backend/pas/pas-book.h: add a GetCompletionView PASOperation,
+ and a new structure (PASGetCompletionViewRequest). Also, add
+ get_completion_view to PASRequest.
+
+ * backend/pas/pas-backend-summary.c (clear_items): remove the
+ items from the hash table.
+ (pas_backend_summary_new): db_path -> summary_path.
+ (pas_backend_summary_destroy): db_.path -> summary_path, and
+ destroy the hash table.
+ (pas_backend_summary_init): db_path = summary_path, and initialize
+ the id_to_item hashtable.
+ (pas_backend_summary_load_header): handle the upgrading from
+ version 1.0 to version 2.0 (the addition of an mtime field in the
+ header)
+ (pas_backend_summary_load_item): version 1.0 and 2.0 have the same
+ format for items.
+ (pas_backend_summary_open): new function. open the summary so we
+ can load the header (and get the mtime).
+ (pas_backend_summary_load): rework this a bit since the header has
+ already been loaded, and also add the items to the hashtable.
+ (pas_backend_summary_add_card): add the new item to the hashtable.
+ (pas_backend_summary_remove_card): remove the item from the hash
+ table.
+ (pas_backend_summary_is_up_to_date): new function, chekc @t
+ against the summary's mtime.
+ (pas_backend_summary_get_summary_vcard): create a vcard from the
+ fields we have in the summary.
+
+ * backend/pas/pas-backend-summary.h: add prorotypes for
+ pas_backend_summary_is_up_to_date and
+ pas_backend_summary_get_summary_vcard.
+
2002-07-09 Ettore Perazzoli <ettore@ximian.com>
* gui/component/addressbook-storage.c (load_source_data): Pass
diff --git a/addressbook/backend/ebook/e-book.c b/addressbook/backend/ebook/e-book.c
index ca9faff929..3fa0852dc4 100644
--- a/addressbook/backend/ebook/e-book.c
+++ b/addressbook/backend/ebook/e-book.c
@@ -1306,6 +1306,47 @@ e_book_get_book_view (EBook *book,
}
guint
+e_book_get_completion_view (EBook *book,
+ const gchar *query,
+ EBookBookViewCallback cb,
+ gpointer closure)
+{
+ CORBA_Environment ev;
+ EBookViewListener *listener;
+ guint tag;
+
+ g_return_val_if_fail (book != NULL, 0);
+ g_return_val_if_fail (E_IS_BOOK (book), 0);
+
+ if (book->priv->load_state != URILoaded) {
+ g_warning ("e_book_get_completion_view: No URI loaded!\n");
+ return 0;
+ }
+
+ listener = e_book_view_listener_new();
+
+ CORBA_exception_init (&ev);
+
+ tag = e_book_queue_op (book, cb, closure, listener);
+
+ GNOME_Evolution_Addressbook_Book_getCompletionView (book->priv->corba_book,
+ bonobo_object_corba_objref(BONOBO_OBJECT(listener)),
+ query, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("e_book_get_completion_view: Exception "
+ "getting completion_view!\n");
+ CORBA_exception_free (&ev);
+ e_book_unqueue_op (book);
+ return 0;
+ }
+
+ CORBA_exception_free (&ev);
+
+ return tag;
+}
+
+guint
e_book_get_changes (EBook *book,
gchar *changeid,
EBookBookViewCallback cb,
diff --git a/addressbook/backend/ebook/e-book.h b/addressbook/backend/ebook/e-book.h
index 1403a23f60..b1549f4f8e 100644
--- a/addressbook/backend/ebook/e-book.h
+++ b/addressbook/backend/ebook/e-book.h
@@ -126,6 +126,11 @@ guint e_book_get_book_view (EBook *book,
EBookBookViewCallback cb,
gpointer closure);
+guint e_book_get_completion_view (EBook *book,
+ const gchar *query,
+ EBookBookViewCallback cb,
+ gpointer closure);
+
guint e_book_get_changes (EBook *book,
char *changeid,
EBookBookViewCallback cb,
diff --git a/addressbook/backend/idl/addressbook.idl b/addressbook/backend/idl/addressbook.idl
index f708026424..1d597189c5 100644
--- a/addressbook/backend/idl/addressbook.idl
+++ b/addressbook/backend/idl/addressbook.idl
@@ -77,6 +77,16 @@ module Addressbook {
void getChanges (in BookViewListener listener, in string change_id);
+ /*
+ * This function returns a book view that is identical
+ * to a normal book view, except in one way - The only
+ * values reflected in the cards that are transfered
+ * back are: File As, family name, given name, email
+ * addresses, and nickname. It is intended for use in
+ * completion searches.
+ */
+ void getCompletionView (in BookViewListener listener, in string query);
+
void checkConnection ();
void getSupportedFields ();
diff --git a/addressbook/backend/pas/pas-backend-file.c b/addressbook/backend/pas/pas-backend-file.c
index a6216cf98e..329b919e7d 100644
--- a/addressbook/backend/pas/pas-backend-file.c
+++ b/addressbook/backend/pas/pas-backend-file.c
@@ -14,6 +14,7 @@
#include <fcntl.h>
#include <time.h>
#include <db.h>
+#include <sys/stat.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
@@ -131,8 +132,9 @@ build_summary (PASBackendFilePrivate *bfpriv)
}
static void
-do_summary_query (PASBackendFile *bf,
- PASBackendFileBookView *view)
+do_summary_query (PASBackendFile *bf,
+ PASBackendFileBookView *view,
+ gboolean completion_search)
{
GPtrArray *ids = pas_backend_summary_search (bf->priv->summary, view->search);
int db_error = 0;
@@ -144,14 +146,24 @@ do_summary_query (PASBackendFile *bf,
for (i = 0; i < ids->len; i ++) {
char *id = g_ptr_array_index (ids, i);
-
- string_to_dbt (id, &id_dbt);
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
+ char *vcard = NULL;
+
+ if (completion_search) {
+ vcard = pas_backend_summary_get_summary_vcard (bf->priv->summary,
+ id);
+ }
+ else {
+ string_to_dbt (id, &id_dbt);
+ memset (&vcard_dbt, 0, sizeof (vcard_dbt));
- db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
+ db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
- if (db_error == 0) {
- cards = g_list_prepend (cards, g_strdup (vcard_dbt.data));
+ if (db_error == 0)
+ vcard = g_strdup (vcard_dbt.data);
+ }
+
+ if (vcard) {
+ cards = g_list_prepend (cards, vcard);
card_count ++;
/* If we've accumulated a number of checks, pass them off to the client. */
@@ -326,7 +338,8 @@ vcard_matches_search (const PASBackendFileBookView *view, char *vcard_string)
static void
pas_backend_file_search (PASBackendFile *bf,
PASBook *book,
- const PASBackendFileBookView *cnstview)
+ const PASBackendFileBookView *cnstview,
+ gboolean completion_search)
{
PASBackendFileBookView *view = (PASBackendFileBookView *)cnstview;
gboolean search_needed;
@@ -350,7 +363,7 @@ pas_backend_file_search (PASBackendFile *bf,
}
if (pas_backend_summary_is_summary_query (bf->priv->summary, view->search)) {
- do_summary_query (bf, view);
+ do_summary_query (bf, view, completion_search);
}
else {
gint card_count = 0, card_threshold = 20, card_threshold_max = 3000;
@@ -1000,7 +1013,46 @@ pas_backend_file_process_get_book_view (PASBackend *backend,
iterator = e_list_get_iterator(bf->priv->book_views);
e_iterator_last(iterator);
- pas_backend_file_search (bf, book, e_iterator_get(iterator));
+ pas_backend_file_search (bf, book, e_iterator_get(iterator), FALSE);
+ gtk_object_unref(GTK_OBJECT(iterator));
+}
+
+static void
+pas_backend_file_process_get_completion_view (PASBackend *backend,
+ PASBook *book,
+ PASGetCompletionViewRequest *req)
+{
+ PASBackendFile *bf = PAS_BACKEND_FILE (backend);
+ PASBookView *book_view;
+ 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);
+
+ 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);
+ view.card_sexp = NULL;
+ view.change_id = NULL;
+ view.change_context = NULL;
+
+ e_list_append(bf->priv->book_views, &view);
+
+ pas_book_respond_get_completion_view (book,
+ (book_view != NULL
+ ? GNOME_Evolution_Addressbook_BookListener_Success
+ : GNOME_Evolution_Addressbook_BookListener_CardNotFound /* XXX */),
+ book_view);
+
+ iterator = e_list_get_iterator(bf->priv->book_views);
+ e_iterator_last(iterator);
+ pas_backend_file_search (bf, book, e_iterator_get(iterator), TRUE);
gtk_object_unref(GTK_OBJECT(iterator));
}
@@ -1145,6 +1197,10 @@ pas_backend_file_process_client_requests (PASBook *book)
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;
@@ -1319,6 +1375,9 @@ pas_backend_file_load_uri (PASBackend *backend,
int db_error;
DB *db;
int major, minor, patch;
+ time_t db_mtime;
+ struct stat sb;
+ char *summary_filename;
g_assert (bf->priv->loaded == FALSE);
@@ -1405,10 +1464,22 @@ pas_backend_file_load_uri (PASBackend *backend,
g_free (bf->priv->filename);
bf->priv->filename = filename;
- bf->priv->summary = pas_backend_summary_new (filename, SUMMARY_FLUSH_TIMEOUT);
+ 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;
+
+ summary_filename = g_strconcat (bf->priv->filename, ".summary", NULL);
+ bf->priv->summary = pas_backend_summary_new (summary_filename, SUMMARY_FLUSH_TIMEOUT);
+ g_free (summary_filename);
- if (!pas_backend_summary_load (bf->priv->summary))
+ if (pas_backend_summary_is_up_to_date (bf->priv->summary, db_mtime) == FALSE
+ || pas_backend_summary_load (bf->priv->summary) == FALSE ) {
build_summary (bf->priv);
+ }
return GNOME_Evolution_Addressbook_BookListener_Success;
}
diff --git a/addressbook/backend/pas/pas-backend-ldap.c b/addressbook/backend/pas/pas-backend-ldap.c
index ceedc1419f..e7a19c2d2c 100644
--- a/addressbook/backend/pas/pas-backend-ldap.c
+++ b/addressbook/backend/pas/pas-backend-ldap.c
@@ -2948,6 +2948,11 @@ pas_backend_ldap_process_client_requests (PASBook *book)
pas_backend_ldap_process_get_book_view (backend, book, req);
break;
+ case GetCompletionView:
+ /* we don't support summaries so completion view requests are the same as book view requests */
+ pas_backend_ldap_process_get_book_view (backend, book, req);
+ break;
+
case GetChanges:
/* FIXME: Code this. */
break;
diff --git a/addressbook/backend/pas/pas-backend-summary.c b/addressbook/backend/pas/pas-backend-summary.c
index 3972426367..23a24c879e 100644
--- a/addressbook/backend/pas/pas-backend-summary.c
+++ b/addressbook/backend/pas/pas-backend-summary.c
@@ -39,13 +39,16 @@
static GtkObjectClass *parent_class;
struct _PASBackendSummaryPrivate {
- char *db_path;
char *summary_path;
+ FILE *fp;
guint32 file_version;
+ time_t mtime;
gboolean dirty;
int flush_timeout_millis;
int flush_timeout;
GPtrArray *items;
+ GHashTable *id_to_item;
+ guint32 num_items; /* used only for loading */
#ifdef SUMMARY_STATS
int size;
#endif
@@ -73,19 +76,21 @@ typedef struct {
guint16 email_1_len;
guint16 email_2_len;
guint16 email_3_len;
-} PASBackendSummaryDiskItem_1_0;
+} PASBackendSummaryDiskItem;
typedef struct {
guint32 file_version;
guint32 num_items;
+ guint32 summary_mtime; /* version 2.0 field */
} PASBackendSummaryHeader;
#define PAS_SUMMARY_MAGIC "PAS-SUMMARY"
#define PAS_SUMMARY_MAGIC_LEN 11
#define PAS_SUMMARY_FILE_VERSION_1_0 1000
+#define PAS_SUMMARY_FILE_VERSION_2_0 2000
-#define PAS_SUMMARY_FILE_VERSION PAS_SUMMARY_FILE_VERSION_1_0
+#define PAS_SUMMARY_FILE_VERSION PAS_SUMMARY_FILE_VERSION_2_0
static void
free_summary_item (PASBackendSummaryItem *item)
@@ -106,17 +111,17 @@ clear_items (PASBackendSummary *summary)
int i;
for (i = 0; i < summary->priv->items->len; i++) {
PASBackendSummaryItem *item = g_ptr_array_index (summary->priv->items, i);
+ g_hash_table_remove (summary->priv->id_to_item, item->id);
free_summary_item (item);
}
}
PASBackendSummary*
-pas_backend_summary_new (const char *db_path, int flush_timeout_millis)
+pas_backend_summary_new (const char *summary_path, int flush_timeout_millis)
{
PASBackendSummary *summary = gtk_type_new (PAS_BACKEND_SUMMARY_TYPE);
- summary->priv->db_path = g_strdup (db_path);
- summary->priv->summary_path = g_strconcat (db_path, ".summary", NULL);
+ summary->priv->summary_path = g_strdup (summary_path);
summary->priv->flush_timeout_millis = flush_timeout_millis;
summary->priv->file_version = PAS_SUMMARY_FILE_VERSION_1_0;
@@ -136,11 +141,15 @@ pas_backend_summary_destroy (GtkObject *object)
summary->priv->flush_timeout = 0;
}
- g_free (summary->priv->db_path);
+ if (summary->priv->fp)
+ fclose (summary->priv->fp);
+
g_free (summary->priv->summary_path);
clear_items (summary);
g_ptr_array_free (summary->priv->items, TRUE);
+ g_hash_table_destroy (summary->priv->id_to_item);
+
g_free (summary->priv);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
@@ -167,10 +176,11 @@ pas_backend_summary_init (PASBackendSummary *summary)
summary->priv = priv;
- priv->db_path = NULL;
priv->summary_path = NULL;
+ priv->fp = NULL;
priv->dirty = FALSE;
priv->items = g_ptr_array_new();
+ priv->id_to_item = g_hash_table_new (g_str_hash, g_str_equal);
priv->flush_timeout_millis = 0;
priv->flush_timeout = 0;
#ifdef SUMMARY_STATS
@@ -233,10 +243,33 @@ pas_backend_summary_load_header (PASBackendSummary *summary, FILE *fp,
return FALSE;
header->file_version = ntohl (header->file_version);
- if (header->file_version != PAS_SUMMARY_FILE_VERSION) {
- /* XXX upgrade stuff in here, but since there's only 1
- version now return FALSE */
- return FALSE;
+
+ if (header->file_version == PAS_SUMMARY_FILE_VERSION) {
+ rv = fread (&header->summary_mtime, sizeof (header->summary_mtime), 1, fp);
+ if (rv != 1)
+ return FALSE;
+ header->summary_mtime = ntohl (header->summary_mtime);
+ }
+ else {
+ if (header->file_version == PAS_SUMMARY_FILE_VERSION_1_0) {
+ /* the header lacks the mtime of the file.
+ set it to the mtime of the on-disk file,
+ and we'll save it out properly next time */
+ int fd;
+ struct stat sb;
+
+ fd = fileno (fp);
+ if (fstat (fd, &sb) == -1) {
+ g_warning ("error fstat'ing summary file.");
+ /* just set the mtime to zero and hope for the best */
+ header->summary_mtime = 0;
+ }
+ header->summary_mtime = sb.st_mtime;
+ }
+ else {
+ /* unknown version */
+ return FALSE;
+ }
}
rv = fread (&header->num_items, sizeof (header->num_items), 1, fp);
@@ -266,14 +299,15 @@ read_string (FILE *fp, int len)
}
static gboolean
-pas_backend_summary_load_item (PASBackendSummary *summary, FILE *fp,
+pas_backend_summary_load_item (PASBackendSummary *summary,
PASBackendSummaryItem **new_item)
{
PASBackendSummaryItem *item;
char *buf;
+ FILE *fp = summary->priv->fp;
- if (summary->priv->file_version == PAS_SUMMARY_FILE_VERSION_1_0) {
- PASBackendSummaryDiskItem_1_0 disk_item;
+ if (summary->priv->file_version <= PAS_SUMMARY_FILE_VERSION_2_0) {
+ PASBackendSummaryDiskItem disk_item;
int rv = fread (&disk_item, sizeof (disk_item), 1, fp);
if (rv != 1)
return FALSE;
@@ -376,22 +410,13 @@ pas_backend_summary_load_item (PASBackendSummary *summary, FILE *fp,
return TRUE;
}
-gboolean
-pas_backend_summary_load (PASBackendSummary *summary)
+/* opens the file and loads the header */
+static void
+pas_backend_summary_open (PASBackendSummary *summary)
{
+ FILE *fp;
+ PASBackendSummaryHeader header;
struct stat sb;
- time_t db_mtime, summary_mtime;
-
- /* we don't have a way to determine what was added since we
- last updated the summary (without traversing the entire db
- anyway), so if the db is newer we just lose the on-disk
- summary */
-
- if (stat (summary->priv->db_path, &sb) == -1) {
- g_warning ("no db present for summary load");
- return FALSE;
- }
- db_mtime = sb.st_mtime;
if (stat (summary->priv->summary_path, &sb) == -1) {
/* if there's no summary present, look for the .new
@@ -401,61 +426,63 @@ pas_backend_summary_load (PASBackendSummary *summary)
if (stat (new_filename, &sb) == -1) {
g_warning ("no summary present");
g_free (new_filename);
- return FALSE;
+ return;
}
else {
rename (new_filename, summary->priv->summary_path);
- stat (summary->priv->summary_path, &sb);
g_free (new_filename);
}
-
}
- summary_mtime = sb.st_mtime;
- if (summary_mtime < db_mtime) {
- /* we need to regenerate the summary */
- return FALSE;
+ fp = fopen (summary->priv->summary_path, "r");
+ if (!fp) {
+ g_warning ("failed to open summary file");
+ return;
}
- else {
- /* the mtime is ok, load the summary */
- PASBackendSummaryHeader header;
- PASBackendSummaryItem *new_item;
- FILE *fp = fopen (summary->priv->summary_path, "r");
- int i;
- if (!fp) {
- g_warning ("failed to open summary file");
- return FALSE;
- }
+ if (!pas_backend_summary_check_magic (summary, fp)) {
+ g_warning ("file is not a valid summary file");
+ fclose (fp);
+ return;
+ }
- if (!pas_backend_summary_check_magic (summary, fp)) {
- g_warning ("file is not a valid summary file");
- fclose (fp);
- return FALSE;
- }
+ if (!pas_backend_summary_load_header (summary, fp, &header)) {
+ g_warning ("failed to read summary header");
+ fclose (fp);
+ return;
+ }
- if (!pas_backend_summary_load_header (summary, fp, &header)) {
- g_warning ("failed to read summary header");
- fclose (fp);
- return FALSE;
- }
+ summary->priv->num_items = header.num_items;
+ summary->priv->file_version = header.file_version;
+ summary->priv->mtime = header.summary_mtime;
+ summary->priv->fp = fp;
+}
- summary->priv->file_version = header.file_version;
+gboolean
+pas_backend_summary_load (PASBackendSummary *summary)
+{
+ PASBackendSummaryItem *new_item;
+ int i;
+
+ pas_backend_summary_open (summary);
- for (i = 0; i < header.num_items; i ++) {
- if (!pas_backend_summary_load_item (summary, fp, &new_item)) {
- g_warning ("error while reading summary item");
- clear_items (summary);
- fclose (fp);
- return FALSE;
- }
+ if (!summary->priv->fp)
+ return FALSE;
- g_ptr_array_add (summary->priv->items, new_item);
+ for (i = 0; i < summary->priv->num_items; i ++) {
+ if (!pas_backend_summary_load_item (summary, &new_item)) {
+ g_warning ("error while reading summary item");
+ clear_items (summary);
+ fclose (summary->priv->fp);
+ summary->priv->fp = NULL;
+ return FALSE;
}
- /* XXX for now return FALSE so we'll regenerate the summary */
- return TRUE;
+ g_ptr_array_add (summary->priv->items, new_item);
+ g_hash_table_insert (summary->priv->id_to_item, new_item->id, new_item);
}
+
+ return TRUE;
}
static gboolean
@@ -475,8 +502,9 @@ pas_backend_summary_save_header (PASBackendSummary *summary, FILE *fp)
PASBackendSummaryHeader header;
int rv;
- header.file_version = htonl (summary->priv->file_version);
+ header.file_version = htonl (PAS_SUMMARY_FILE_VERSION);
header.num_items = htonl (summary->priv->items->len);
+ header.summary_mtime = htonl (time (NULL));
rv = fwrite (&header, sizeof (header), 1, fp);
if (rv != 1)
@@ -500,7 +528,7 @@ save_string (const char *str, FILE *fp)
static gboolean
pas_backend_summary_save_item (PASBackendSummary *summary, FILE *fp, PASBackendSummaryItem *item)
{
- PASBackendSummaryDiskItem_1_0 disk_item;
+ PASBackendSummaryDiskItem disk_item;
int len;
int rv;
@@ -635,6 +663,7 @@ pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard)
new_item->email_3 = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_EMAIL_3);
g_ptr_array_add (summary->priv->items, new_item);
+ g_hash_table_insert (summary->priv->id_to_item, new_item->id, new_item);
gtk_object_unref (GTK_OBJECT (simple));
gtk_object_unref (GTK_OBJECT (card));
@@ -656,16 +685,14 @@ pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard)
void
pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id)
{
- int i;
+ PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id);
- for (i = 0; i < summary->priv->items->len; i ++) {
- PASBackendSummaryItem *item = g_ptr_array_index (summary->priv->items, i);
- if (!strcmp (item->id, id)) {
- g_ptr_array_remove_index (summary->priv->items, i);
- free_summary_item (item);
- pas_backend_summary_touch (summary);
- return;
- }
+ if (item) {
+ g_ptr_array_remove (summary->priv->items, item);
+ g_hash_table_remove (summary->priv->id_to_item, id);
+ free_summary_item (item);
+ pas_backend_summary_touch (summary);
+ return;
}
g_warning ("pas_backend_summary_remove_card: unable to locate id `%s'", id);
@@ -702,6 +729,12 @@ pas_backend_summary_touch (PASBackendSummary *summary)
summary_flush_func, summary);
}
+gboolean
+pas_backend_summary_is_up_to_date (PASBackendSummary *summary, time_t t)
+{
+ return summary->priv->mtime >= t;
+}
+
/* we only want to do summary queries if the query is over the set fields in the summary */
@@ -955,3 +988,37 @@ pas_backend_summary_search (PASBackendSummary *summary, const char *query)
return retval;
}
+
+char*
+pas_backend_summary_get_summary_vcard(PASBackendSummary *summary, const char *id)
+{
+ PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id);
+
+ if (item) {
+ ECard *card = e_card_new ("");
+ ECardSimple *simple = e_card_simple_new (card);
+ char *vcard;
+
+ e_card_simple_set_id (simple, item->id);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FILE_AS, item->file_as);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_GIVEN_NAME, item->given_name);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FAMILY_NAME, item->surname);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_NICKNAME, item->nickname);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL, item->email_1);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_2, item->email_2);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_3, item->email_3);
+
+ e_card_simple_sync_card (simple);
+
+ vcard = e_card_simple_get_vcard (simple);
+
+ gtk_object_unref (GTK_OBJECT (simple));
+ gtk_object_unref (GTK_OBJECT (card));
+
+ return vcard;
+ }
+ else {
+ g_warning ("in unable to locate card `%s' in summary", id);
+ }
+}
+
diff --git a/addressbook/backend/pas/pas-backend-summary.h b/addressbook/backend/pas/pas-backend-summary.h
index 8feac77339..fb989332fe 100644
--- a/addressbook/backend/pas/pas-backend-summary.h
+++ b/addressbook/backend/pas/pas-backend-summary.h
@@ -37,22 +37,27 @@ typedef struct {
GtkObjectClass parent_class;
} PASBackendSummaryClass;
-PASBackendSummary* pas_backend_summary_new (const char *db_path, int flush_timeout_millis);
+PASBackendSummary* pas_backend_summary_new (const char *summary_path,
+ int flush_timeout_millis);
GtkType pas_backend_summary_get_type (void);
/* returns FALSE if the load fails for any reason (including that the
summary is out of date), TRUE if it succeeds */
-gboolean pas_backend_summary_load (PASBackendSummary *summary);
+gboolean pas_backend_summary_load f (PASBackendSummary *summary);
/* returns FALSE if the save fails, TRUE if it succeeds (or isn't required due to no changes) */
-gboolean pas_backend_summary_save (PASBackendSummary *summary);
+gboolean pas_backend_summary_save (PASBackendSummary *summary);
-void pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard);
-void pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id);
+void pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard);
+void pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id);
-void pas_backend_summary_touch (PASBackendSummary *summary);
+void pas_backend_summary_touch (PASBackendSummary *summary);
-gboolean pas_backend_summary_is_summary_query (PASBackendSummary *summary, const char *query);
-GPtrArray* pas_backend_summary_search (PASBackendSummary *summary, const char *query);
+/* returns TRUE if the summary's mtime is >= @t. */
+gboolean pas_backend_summary_is_up_to_date (PASBackendSummary *summary, time_t t);
+
+gboolean pas_backend_summary_is_summary_query (PASBackendSummary *summary, const char *query);
+GPtrArray* pas_backend_summary_search (PASBackendSummary *summary, const char *query);
+char* pas_backend_summary_get_summary_vcard (PASBackendSummary *summary, const char *id);
#define PAS_BACKEND_SUMMARY_TYPE (pas_backend_summary_get_type ())
#define PAS_BACKEND_SUMMARY(o) (GTK_CHECK_CAST ((o), PAS_BACKEND_SUMMARY_TYPE, PASBackendSummary))
diff --git a/addressbook/backend/pas/pas-book.c b/addressbook/backend/pas/pas-book.c
index 9bb2cd348e..7a3ab55f92 100644
--- a/addressbook/backend/pas/pas-book.c
+++ b/addressbook/backend/pas/pas-book.c
@@ -179,6 +179,30 @@ pas_book_queue_get_book_view (PASBook *book, const GNOME_Evolution_Addressbook_B
}
static void
+pas_book_queue_get_completion_view (PASBook *book, const GNOME_Evolution_Addressbook_BookViewListener listener, const char *search)
+{
+ PASRequest *req;
+ CORBA_Environment ev;
+
+ req = g_new0 (PASRequest, 1);
+ req->op = GetCompletionView;
+ req->get_book_view.search = g_strdup(search);
+
+ CORBA_exception_init (&ev);
+
+ req->get_book_view.listener = bonobo_object_dup_ref(listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("pas_book_queue_get_completion_view: Exception "
+ "duplicating BookViewListener!\n");
+ }
+
+ CORBA_exception_free (&ev);
+
+ pas_book_queue_request (book, req);
+}
+
+static void
pas_book_queue_get_changes (PASBook *book, const GNOME_Evolution_Addressbook_BookViewListener listener, const char *change_id)
{
PASRequest *req;
@@ -286,6 +310,18 @@ impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servan
pas_book_queue_get_book_view (book, listener, search);
}
+
+static void
+impl_GNOME_Evolution_Addressbook_Book_getCompletionView (PortableServer_Servant servant,
+ const GNOME_Evolution_Addressbook_BookViewListener listener,
+ const CORBA_char *search,
+ CORBA_Environment *ev)
+{
+ PASBook *book = PAS_BOOK (bonobo_object_from_servant (servant));
+
+ pas_book_queue_get_completion_view (book, listener, search);
+}
+
static void
impl_GNOME_Evolution_Addressbook_Book_getChanges (PortableServer_Servant servant,
const GNOME_Evolution_Addressbook_BookViewListener listener,
@@ -601,6 +637,32 @@ pas_book_respond_get_book_view (PASBook *book,
}
/**
+ * pas_book_respond_get_book_view:
+ */
+void
+pas_book_respond_get_completion_view (PASBook *book,
+ GNOME_Evolution_Addressbook_BookListener_CallStatus status,
+ PASBookView *completion_view)
+{
+ CORBA_Environment ev;
+ CORBA_Object object;
+
+ CORBA_exception_init (&ev);
+
+ object = bonobo_object_corba_objref(BONOBO_OBJECT(completion_view));
+
+ GNOME_Evolution_Addressbook_BookListener_notifyViewRequested (
+ book->priv->listener, status, object, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("pas_book_respond_get_completion_view: Exception "
+ "responding to BookListener!\n");
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+/**
* pas_book_respond_get_changes:
*/
void
@@ -797,6 +859,16 @@ pas_book_free_request (PASRequest *req)
CORBA_exception_free (&ev);
break;
+ case GetCompletionView:
+ g_free (req->get_completion_view.search);
+ CORBA_exception_init (&ev);
+ bonobo_object_release_unref (req->get_completion_view.listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("pas_book_free_request(GetCompletionView): could not release the listener");
+
+ CORBA_exception_free (&ev);
+ break;
case GetChanges:
g_free (req->get_changes.change_id);
CORBA_exception_init (&ev);
@@ -875,6 +947,7 @@ pas_book_get_epv (void)
epv->getSupportedFields = impl_GNOME_Evolution_Addressbook_Book_getSupportedFields;
epv->getCursor = impl_GNOME_Evolution_Addressbook_Book_getCursor;
epv->getBookView = impl_GNOME_Evolution_Addressbook_Book_getBookView;
+ epv->getCompletionView = impl_GNOME_Evolution_Addressbook_Book_getCompletionView;
epv->getChanges = impl_GNOME_Evolution_Addressbook_Book_getChanges;
return epv;
diff --git a/addressbook/backend/pas/pas-book.h b/addressbook/backend/pas/pas-book.h
index a6f2fda3cc..4dcd1e205d 100644
--- a/addressbook/backend/pas/pas-book.h
+++ b/addressbook/backend/pas/pas-book.h
@@ -31,6 +31,7 @@ typedef enum {
GetVCard,
GetCursor,
GetBookView,
+ GetCompletionView,
GetChanges,
CheckConnection,
AuthenticateUser,
@@ -71,6 +72,12 @@ typedef struct {
typedef struct {
PASOperation op;
+ char *search;
+ GNOME_Evolution_Addressbook_BookViewListener listener;
+} PASGetCompletionViewRequest;
+
+typedef struct {
+ PASOperation op;
char *change_id;
GNOME_Evolution_Addressbook_BookViewListener listener;
} PASGetChangesRequest;
@@ -91,17 +98,18 @@ typedef struct {
} PASGetSupportedFieldsRequest;
typedef union {
- PASOperation op;
-
- PASCreateCardRequest create;
- PASRemoveCardRequest remove;
- PASModifyCardRequest modify;
- PASGetVCardRequest get_vcard;
- PASGetCursorRequest get_cursor;
- PASGetBookViewRequest get_book_view;
- PASGetChangesRequest get_changes;
- PASCheckConnectionRequest check_connection;
- PASAuthenticateUserRequest auth_user;
+ PASOperation op;
+
+ PASCreateCardRequest create;
+ PASRemoveCardRequest remove;
+ PASModifyCardRequest modify;
+ PASGetVCardRequest get_vcard;
+ PASGetCursorRequest get_cursor;
+ PASGetBookViewRequest get_book_view;
+ PASGetCompletionViewRequest get_completion_view;
+ PASGetChangesRequest get_changes;
+ PASCheckConnectionRequest check_connection;
+ PASAuthenticateUserRequest auth_user;
PASGetSupportedFieldsRequest get_supported_fields;
} PASRequest;
@@ -148,6 +156,9 @@ void pas_book_respond_get_cursor (PASBook
void pas_book_respond_get_book_view (PASBook *book,
GNOME_Evolution_Addressbook_BookListener_CallStatus status,
PASBookView *book_view);
+void pas_book_respond_get_completion_view (PASBook *book,
+ GNOME_Evolution_Addressbook_BookListener_CallStatus status,
+ PASBookView *completion_view);
void pas_book_respond_get_vcard (PASBook *book,
GNOME_Evolution_Addressbook_BookListener_CallStatus status,
char *vcard);