Added addressbook querying and "cardification" functions, which are turned
2001-03-15 Jon Trowbridge <trow@ximian.com> * gui/component/e-address-widget.c: Added addressbook querying and "cardification" functions, which are turned off by default for now because of addressbook bugs. Added a popup menu option to turn queries on, so that others can enjoy the thrill of massive flaming death. * gui/component/addressbook-factory.c (main): Made warnings always be fatal. * backend/pas/pas-book-view.c: Added some debugging spew. * backend/pas/pas-backend-file.c (pas_backend_file_search): Added a little experimental code to try to make file searches scale better. #if 0/#endif-ed out for now. * contact-editor/e-contact-quick-add.c: #included e-book-util.h. * backend/ebook/e-card.c (e_card_name_match_string): Added. Looser name-matching function. (e_card_email_match_string): Added. Loose e-mail matching. * backend/ebook/e-book-view-listener.c (e_book_view_listener_check_queue): Added code to cause us to abort rather than get trapped in a 100%-CPU-consuming loop in certain situations. Now we just need to figure out how to avoid these situations altogether. * backend/ebook/e-book-util.c: Added. Now contains the simple query stuff and the open local addressbook functions. * backend/ebook/e-book.c: Moved simple query stuff and open local addressbook functions into e-book-util.c. 2001-03-15 Jon Trowbridge <trow@ximian.com> * wombat.c (main): If we can't initialize a service on startup, tell us which one before terminating. svn path=/trunk/; revision=8754
This commit is contained in:
committed by
Jon Trowbridge
parent
403205b15e
commit
57de6972c8
@ -1,3 +1,38 @@
|
||||
2001-03-15 Jon Trowbridge <trow@ximian.com>
|
||||
|
||||
* gui/component/e-address-widget.c: Added addressbook querying and
|
||||
"cardification" functions, which are turned off by default for now
|
||||
because of addressbook bugs. Added a popup menu option to turn
|
||||
queries on, so that others can enjoy the thrill of massive flaming
|
||||
death.
|
||||
|
||||
* gui/component/addressbook-factory.c (main): Made warnings always
|
||||
be fatal.
|
||||
|
||||
* backend/pas/pas-book-view.c: Added some debugging spew.
|
||||
|
||||
* backend/pas/pas-backend-file.c (pas_backend_file_search): Added
|
||||
a little experimental code to try to make file searches scale
|
||||
better. #if 0/#endif-ed out for now.
|
||||
|
||||
* contact-editor/e-contact-quick-add.c: #included e-book-util.h.
|
||||
|
||||
* backend/ebook/e-card.c (e_card_name_match_string): Added.
|
||||
Looser name-matching function.
|
||||
(e_card_email_match_string): Added. Loose e-mail matching.
|
||||
|
||||
* backend/ebook/e-book-view-listener.c
|
||||
(e_book_view_listener_check_queue): Added code to cause us to
|
||||
abort rather than get trapped in a 100%-CPU-consuming loop in
|
||||
certain situations. Now we just need to figure out how to avoid
|
||||
these situations altogether.
|
||||
|
||||
* backend/ebook/e-book-util.c: Added. Now contains the simple
|
||||
query stuff and the open local addressbook functions.
|
||||
|
||||
* backend/ebook/e-book.c: Moved simple query stuff and open local
|
||||
addressbook functions into e-book-util.c.
|
||||
|
||||
2001-03-15 Dan Winship <danw@ximian.com>
|
||||
|
||||
* gui/widgets/e-minicard-label.c (e_minicard_label_set_arg):
|
||||
|
||||
@ -43,6 +43,7 @@ libebook_la_SOURCES = \
|
||||
e-book-view-listener.c \
|
||||
e-book-view.c \
|
||||
e-book.c \
|
||||
e-book-util.c \
|
||||
e-card-cursor.c \
|
||||
e-card-simple.c \
|
||||
e-card.c \
|
||||
@ -56,6 +57,7 @@ libebookinclude_HEADERS = \
|
||||
e-book-view-listener.h \
|
||||
e-book-view.h \
|
||||
e-book.h \
|
||||
e-book-util.h \
|
||||
e-card-cursor.h \
|
||||
e-card-pairs.h \
|
||||
e-card-simple.h \
|
||||
|
||||
444
addressbook/backend/ebook/e-book-util.c
Normal file
444
addressbook/backend/ebook/e-book-util.c
Normal file
@ -0,0 +1,444 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
|
||||
/*
|
||||
* e-book-util.c
|
||||
*
|
||||
* Copyright (C) 2001 Ximian, Inc.
|
||||
*
|
||||
* Developed by Jon Trowbridge <trow@ximian.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <libgnome/gnome-defs.h>
|
||||
#include <libgnome/gnome-util.h>
|
||||
#include "e-book-util.h"
|
||||
|
||||
gboolean
|
||||
e_book_load_local_address_book (EBook *book, EBookCallback open_response, gpointer closure)
|
||||
{
|
||||
gchar *filename;
|
||||
gchar *uri;
|
||||
gboolean rv;
|
||||
|
||||
g_return_val_if_fail (book != NULL, FALSE);
|
||||
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
|
||||
g_return_val_if_fail (open_response != NULL, FALSE);
|
||||
|
||||
filename = gnome_util_prepend_user_home ("evolution/local/Contacts/addressbook.db");
|
||||
uri = g_strdup_printf ("file://%s", filename);
|
||||
|
||||
rv = e_book_load_uri (book, uri, open_response, closure);
|
||||
|
||||
g_free (filename);
|
||||
g_free (uri);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Simple Query Stuff
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct _SimpleQueryInfo SimpleQueryInfo;
|
||||
struct _SimpleQueryInfo {
|
||||
guint tag;
|
||||
EBook *book;
|
||||
gchar *query;
|
||||
EBookSimpleQueryCallback cb;
|
||||
gpointer closure;
|
||||
EBookView *view;
|
||||
guint add_tag;
|
||||
guint seq_complete_tag;
|
||||
GList *cards;
|
||||
};
|
||||
|
||||
static void
|
||||
book_add_simple_query (EBook *book, SimpleQueryInfo *info)
|
||||
{
|
||||
GList *pending = gtk_object_get_data (GTK_OBJECT (book), "sq_pending");
|
||||
pending = g_list_prepend (pending, info);
|
||||
gtk_object_set_data (GTK_OBJECT (book), "sq_pending", pending);
|
||||
}
|
||||
|
||||
static SimpleQueryInfo *
|
||||
book_lookup_simple_query (EBook *book, guint tag)
|
||||
{
|
||||
GList *pending = gtk_object_get_data (GTK_OBJECT (book), "sq_pending");
|
||||
while (pending) {
|
||||
SimpleQueryInfo *sq = pending->data;
|
||||
if (sq->tag == tag)
|
||||
return sq;
|
||||
pending = g_list_next (pending);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
book_remove_simple_query (EBook *book, SimpleQueryInfo *info)
|
||||
{
|
||||
GList *pending = gtk_object_get_data (GTK_OBJECT (book), "sq_pending");
|
||||
GList *i;
|
||||
|
||||
for (i=pending; i != NULL; i = g_list_next (i)) {
|
||||
if (i->data == info) {
|
||||
pending = g_list_remove_link (pending, i);
|
||||
g_list_free_1 (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gtk_object_set_data (GTK_OBJECT (book), "sq_pending", pending);
|
||||
}
|
||||
|
||||
static guint
|
||||
book_issue_tag (EBook *book)
|
||||
{
|
||||
gpointer ptr = gtk_object_get_data (GTK_OBJECT (book), "sq_tag");
|
||||
guint tag = GPOINTER_TO_UINT (ptr);
|
||||
if (tag == 0)
|
||||
tag = 1;
|
||||
gtk_object_set_data (GTK_OBJECT (book), "sq_tag", GUINT_TO_POINTER (tag+1));
|
||||
return tag;
|
||||
}
|
||||
|
||||
#ifdef USE_WORKAROUND
|
||||
static GList *WORKAROUND_sq_queue = NULL;
|
||||
static gboolean WORKAROUND_running_query = FALSE;
|
||||
#endif
|
||||
|
||||
static SimpleQueryInfo *
|
||||
simple_query_new (EBook *book, const char *query, EBookSimpleQueryCallback cb, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = g_new0 (SimpleQueryInfo, 1);
|
||||
|
||||
sq->tag = book_issue_tag (book);
|
||||
sq->book = book;
|
||||
gtk_object_ref (GTK_OBJECT (book));
|
||||
sq->query = g_strdup_printf (query);
|
||||
sq->cb = cb;
|
||||
sq->closure = closure;
|
||||
|
||||
/* Automatically add ourselves to the EBook's pending list. */
|
||||
book_add_simple_query (book, sq);
|
||||
|
||||
#ifdef USE_WORKAROUND
|
||||
/* Add ourselves to the queue. */
|
||||
WORKAROUND_sq_queue = g_list_append (WORKAROUND_sq_queue, sq);
|
||||
#endif
|
||||
|
||||
return sq;
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_free (SimpleQueryInfo *sq)
|
||||
{
|
||||
GList *i;
|
||||
|
||||
/* Remove ourselves from the EBook's pending list. */
|
||||
book_remove_simple_query (sq->book, sq);
|
||||
|
||||
#ifdef USE_WORKAROUND
|
||||
/* If we are still in the queue, remove ourselves. */
|
||||
for (i = WORKAROUND_sq_queue; i != NULL; i = g_list_next (i)) {
|
||||
if (i->data == sq) {
|
||||
WORKAROUND_sq_queue = g_list_remove_link (WORKAROUND_sq_queue, i);
|
||||
g_list_free_1 (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free (sq->query);
|
||||
|
||||
if (sq->add_tag)
|
||||
gtk_signal_disconnect (GTK_OBJECT (sq->view), sq->add_tag);
|
||||
if (sq->seq_complete_tag)
|
||||
gtk_signal_disconnect (GTK_OBJECT (sq->view), sq->seq_complete_tag);
|
||||
|
||||
#ifdef USE_WORKAROUND
|
||||
if (sq->view)
|
||||
WORKAROUND_running_query = FALSE;
|
||||
#endif
|
||||
|
||||
if (sq->view)
|
||||
gtk_object_unref (GTK_OBJECT (sq->view));
|
||||
|
||||
if (sq->book)
|
||||
gtk_object_unref (GTK_OBJECT (sq->book));
|
||||
|
||||
g_list_foreach (sq->cards, (GFunc) gtk_object_unref, NULL);
|
||||
g_list_free (sq->cards);
|
||||
|
||||
g_free (sq);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_card_added_cb (EBookView *view, const GList *cards, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
sq->cards = g_list_concat (sq->cards, g_list_copy ((GList *) cards));
|
||||
g_list_foreach ((GList *) cards, (GFunc) gtk_object_ref, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_sequence_complete_cb (EBookView *view, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS, sq->cards, sq->closure);
|
||||
simple_query_free (sq);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_book_view_cb (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
if (status != E_BOOK_STATUS_SUCCESS) {
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_OTHER_ERROR, NULL, sq->closure);
|
||||
simple_query_free (sq);
|
||||
return;
|
||||
}
|
||||
|
||||
sq->view = book_view;
|
||||
gtk_object_ref (GTK_OBJECT (book_view));
|
||||
|
||||
sq->add_tag = gtk_signal_connect (GTK_OBJECT (sq->view),
|
||||
"card_added",
|
||||
GTK_SIGNAL_FUNC (simple_query_card_added_cb),
|
||||
sq);
|
||||
sq->seq_complete_tag = gtk_signal_connect (GTK_OBJECT (sq->view),
|
||||
"sequence_complete",
|
||||
GTK_SIGNAL_FUNC (simple_query_sequence_complete_cb),
|
||||
sq);
|
||||
}
|
||||
|
||||
#ifdef USE_WORKAROUND
|
||||
static gint
|
||||
WORKAROUND_try_queue (gpointer foo)
|
||||
{
|
||||
if (WORKAROUND_sq_queue) {
|
||||
SimpleQueryInfo *sq;
|
||||
GList *i;
|
||||
|
||||
if (WORKAROUND_running_query)
|
||||
return TRUE;
|
||||
|
||||
WORKAROUND_running_query = TRUE;
|
||||
sq = WORKAROUND_sq_queue->data;
|
||||
|
||||
i = WORKAROUND_sq_queue;
|
||||
WORKAROUND_sq_queue = g_list_remove_link (WORKAROUND_sq_queue, WORKAROUND_sq_queue);
|
||||
g_list_free_1 (i);
|
||||
|
||||
e_book_get_book_view (sq->book, sq->query, simple_query_book_view_cb, sq);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
guint
|
||||
e_book_simple_query (EBook *book, const char *query, EBookSimpleQueryCallback cb, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq;
|
||||
|
||||
g_return_val_if_fail (book && E_IS_BOOK (book), 0);
|
||||
g_return_val_if_fail (query, 0);
|
||||
g_return_val_if_fail (cb, 0);
|
||||
|
||||
sq = simple_query_new (book, query, cb, closure);
|
||||
#ifdef USE_WORKAROUND
|
||||
gtk_timeout_add (50, WORKAROUND_try_queue, NULL);
|
||||
#else
|
||||
e_book_get_book_view (book, query, simple_query_book_view_cb, sq);
|
||||
#endif
|
||||
|
||||
return sq->tag;
|
||||
}
|
||||
|
||||
void
|
||||
e_book_simple_query_cancel (EBook *book, guint tag)
|
||||
{
|
||||
SimpleQueryInfo *sq;
|
||||
|
||||
g_return_if_fail (book && E_IS_BOOK (book));
|
||||
|
||||
sq = book_lookup_simple_query (book, tag);
|
||||
|
||||
if (sq) {
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_CANCELLED, NULL, sq->closure);
|
||||
simple_query_free (sq);
|
||||
} else {
|
||||
g_warning ("Simple query tag %d is unknown", tag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Specialized Queries
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct _NameEmailQueryInfo NameEmailQueryInfo;
|
||||
struct _NameEmailQueryInfo {
|
||||
gchar *name;
|
||||
gchar *email;
|
||||
EBookSimpleQueryCallback cb;
|
||||
gpointer closure;
|
||||
};
|
||||
|
||||
static void
|
||||
name_email_query_info_free (NameEmailQueryInfo *info)
|
||||
{
|
||||
if (info) {
|
||||
g_free (info->name);
|
||||
g_free (info->email);
|
||||
g_free (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
name_and_email_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
|
||||
{
|
||||
NameEmailQueryInfo *info = closure;
|
||||
GList *filtered_cards = NULL;
|
||||
|
||||
while (cards) {
|
||||
ECard *card = E_CARD (cards->data);
|
||||
if ((info->name == NULL || e_card_name_match_string (card->name, info->name))
|
||||
&& (info->email == NULL || e_card_email_match_string (card, info->email)))
|
||||
filtered_cards = g_list_append (filtered_cards, card);
|
||||
cards = g_list_next (cards);
|
||||
}
|
||||
|
||||
info->cb (book, status, filtered_cards, info->closure);
|
||||
|
||||
g_list_free (filtered_cards);
|
||||
|
||||
name_email_query_info_free (info);
|
||||
}
|
||||
|
||||
guint
|
||||
e_book_name_and_email_query (EBook *book,
|
||||
const gchar *name,
|
||||
const gchar *email,
|
||||
EBookSimpleQueryCallback cb,
|
||||
gpointer closure)
|
||||
{
|
||||
NameEmailQueryInfo *info;
|
||||
gchar *email_query=NULL, *name_query=NULL, *query;
|
||||
guint tag;
|
||||
|
||||
g_return_val_if_fail (book && E_IS_BOOK (book), 0);
|
||||
g_return_val_if_fail (cb != NULL, 0);
|
||||
|
||||
if (name && !*name)
|
||||
name = NULL;
|
||||
if (email && !*email)
|
||||
email = NULL;
|
||||
|
||||
if (name == NULL && email == NULL)
|
||||
return 0;
|
||||
|
||||
/* Build our e-mail query.
|
||||
* We only query against the username part of the address, to avoid not matching
|
||||
* fred@foo.com and fred@mail.foo.com. While their may be namespace collisions
|
||||
* in the usernames of everyone out there, it shouldn't be that bad. (Famous last words.)
|
||||
*/
|
||||
if (email) {
|
||||
const gchar *t=email;
|
||||
while (*t && *t != '@')
|
||||
++t;
|
||||
if (*t == '@') {
|
||||
email_query = g_strdup_printf ("(beginswith \"email\" \"%.*s@\")", t-email, email);
|
||||
|
||||
} else {
|
||||
email_query = g_strdup_printf ("(beginswith \"email\" \"%s\")", email);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build our name query.
|
||||
* We only do name-query stuff if we don't have an e-mail address. Our basic assumption
|
||||
* is that the username part of the email is good enough to keep the amount of stuff returned
|
||||
* in the query relatively small.
|
||||
*/
|
||||
if (name && !email) {
|
||||
gchar *name_cpy = g_strdup (name), *qjoined;
|
||||
gchar **namev;
|
||||
gint i, count=0;
|
||||
|
||||
g_strstrip (name_cpy);
|
||||
namev = g_strsplit (" ", name_cpy, 0);
|
||||
for (i=0; namev[i]; ++i) {
|
||||
if (*namev[i]) {
|
||||
namev[i] = g_strdup_printf ("(contains \"file_as\" \"%s\")", namev[i]);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
qjoined = g_strjoinv (" ", namev);
|
||||
if (count > 1) {
|
||||
name_query = g_strdup_printf ("(or %s)", qjoined);
|
||||
} else {
|
||||
name_query = qjoined;
|
||||
qjoined = NULL;
|
||||
}
|
||||
|
||||
|
||||
g_free (name_cpy);
|
||||
for (i=0; namev[i]; ++i)
|
||||
if (*namev[i])
|
||||
g_free (namev[i]);
|
||||
g_free (namev);
|
||||
g_free (qjoined);
|
||||
}
|
||||
|
||||
/* Assemble our e-mail & name queries */
|
||||
if (email_query && name_query) {
|
||||
query = g_strdup_printf ("(and %s %s)", email_query, name_query);
|
||||
} else if (email_query) {
|
||||
query = email_query;
|
||||
email_query = NULL;
|
||||
} else if (name_query) {
|
||||
query = name_query;
|
||||
name_query = NULL;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
g_message ("query: %s", query);
|
||||
|
||||
info = g_new0 (NameEmailQueryInfo, 1);
|
||||
info->name = g_strdup (name);
|
||||
info->email = g_strdup (email);
|
||||
info->cb = cb;
|
||||
info->closure = closure;
|
||||
|
||||
tag = e_book_simple_query (book, query, name_and_email_cb, info);
|
||||
|
||||
g_free (email_query);
|
||||
g_free (name_query);
|
||||
g_free (query);
|
||||
|
||||
return tag;
|
||||
}
|
||||
64
addressbook/backend/ebook/e-book-util.h
Normal file
64
addressbook/backend/ebook/e-book-util.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
|
||||
/*
|
||||
* e-book-util.h
|
||||
*
|
||||
* Copyright (C) 2001 Ximian, Inc.
|
||||
*
|
||||
* Developed by Jon Trowbridge <trow@ximian.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef __E_BOOK_UTIL_H__
|
||||
#define __E_BOOK_UTIL_H__
|
||||
|
||||
#include <libgnome/gnome-defs.h>
|
||||
#include "e-book.h"
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
|
||||
/* Callbacks for asynchronous functions. */
|
||||
typedef void (*EBookSimpleQueryCallback) (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure);
|
||||
|
||||
gboolean e_book_load_local_address_book (EBook *book,
|
||||
EBookCallback open_response,
|
||||
gpointer closure);
|
||||
|
||||
/* Simple Query Interface. */
|
||||
|
||||
guint e_book_simple_query (EBook *book,
|
||||
const char *query,
|
||||
EBookSimpleQueryCallback cb,
|
||||
gpointer closure);
|
||||
void e_book_simple_query_cancel (EBook *book,
|
||||
guint tag);
|
||||
|
||||
/* Specialized Name/Email Queries */
|
||||
|
||||
guint e_book_name_and_email_query (EBook *book,
|
||||
const char *name,
|
||||
const char *email,
|
||||
EBookSimpleQueryCallback cb,
|
||||
gpointer closure);
|
||||
|
||||
END_GNOME_DECLS
|
||||
|
||||
|
||||
#endif /* __E_BOOK_UTIL_H__ */
|
||||
|
||||
@ -33,12 +33,31 @@ struct _EBookViewListenerPrivate {
|
||||
static gboolean
|
||||
e_book_view_listener_check_queue (EBookViewListener *listener)
|
||||
{
|
||||
static gint thrash = 0;
|
||||
gint queue_len;
|
||||
|
||||
queue_len = g_list_length (listener->priv->response_queue);
|
||||
|
||||
bonobo_object_ref (BONOBO_OBJECT (listener));
|
||||
if (listener->priv->response_queue != NULL) {
|
||||
gtk_signal_emit (GTK_OBJECT (listener),
|
||||
e_book_view_listener_signals [RESPONSES_QUEUED]);
|
||||
}
|
||||
|
||||
/* This means we didn't make any progress in dealing with what is on our
|
||||
response queue. */
|
||||
if (queue_len == g_list_length (listener->priv->response_queue))
|
||||
++thrash;
|
||||
else
|
||||
thrash = 0;
|
||||
|
||||
if (thrash > 20) {
|
||||
g_error ("e_book_view_listener_check_queue thrashing!");
|
||||
thrash = 0;
|
||||
listener->priv->idle_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (listener->priv->response_queue == NULL) {
|
||||
listener->priv->idle_id = 0;
|
||||
bonobo_object_unref (BONOBO_OBJECT (listener));
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#include <gtk/gtksignal.h>
|
||||
#include <gtk/gtkmarshal.h>
|
||||
#include <libgnome/gnome-defs.h>
|
||||
#include <libgnome/gnome-util.h>
|
||||
#include <liboaf/liboaf.h>
|
||||
|
||||
#include "addressbook.h"
|
||||
@ -517,28 +516,6 @@ e_book_unload_uri (EBook *book)
|
||||
book->priv->load_state = URINotLoaded;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_book_load_local_address_book (EBook *book, EBookCallback open_response, gpointer closure)
|
||||
{
|
||||
gchar *filename;
|
||||
gchar *uri;
|
||||
gboolean rv;
|
||||
|
||||
g_return_val_if_fail (book != NULL, FALSE);
|
||||
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
|
||||
g_return_val_if_fail (open_response != NULL, FALSE);
|
||||
|
||||
filename = gnome_util_prepend_user_home ("evolution/local/Contacts/addressbook.db");
|
||||
uri = g_strdup_printf ("file://%s", filename);
|
||||
|
||||
rv = e_book_load_uri (book, uri, open_response, closure);
|
||||
|
||||
g_free (filename);
|
||||
g_free (uri);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *
|
||||
e_book_get_static_capabilities (EBook *book)
|
||||
{
|
||||
@ -1119,157 +1096,6 @@ e_book_get_changes (EBook *book,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Simple Query Stuff
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct _SimpleQueryInfo SimpleQueryInfo;
|
||||
struct _SimpleQueryInfo {
|
||||
guint tag;
|
||||
EBook *book;
|
||||
gchar *query;
|
||||
EBookSimpleQueryCallback cb;
|
||||
gpointer closure;
|
||||
EBookView *view;
|
||||
guint add_tag;
|
||||
guint seq_complete_tag;
|
||||
GList *cards;
|
||||
};
|
||||
|
||||
static SimpleQueryInfo *
|
||||
simple_query_new (EBook *book, char *query, EBookSimpleQueryCallback cb, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = g_new0 (SimpleQueryInfo, 1);
|
||||
|
||||
sq->tag = ++book->priv->sq_tag;
|
||||
sq->book = book;
|
||||
gtk_object_ref (GTK_OBJECT (book));
|
||||
sq->query = g_strdup_printf (query);
|
||||
sq->cb = cb;
|
||||
sq->closure = closure;
|
||||
|
||||
/* Automatically add ourselves to the EBook's pending list. */
|
||||
book->priv->sq_pending = g_list_prepend (book->priv->sq_pending, sq);
|
||||
|
||||
return sq;
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_free (SimpleQueryInfo *sq)
|
||||
{
|
||||
GList *i;
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* Find & remove ourselves from the EBook's pending list. */
|
||||
for (i = sq->book->priv->sq_pending; i != NULL; i = g_list_next (i)) {
|
||||
if (i->data == sq) {
|
||||
sq->book->priv->sq_pending = g_list_remove_link (sq->book->priv->sq_pending, i);
|
||||
g_list_free_1 (i);
|
||||
i = NULL;
|
||||
found = TRUE;
|
||||
} else
|
||||
i = g_list_next (i);
|
||||
}
|
||||
|
||||
g_assert (found);
|
||||
|
||||
g_free (sq->query);
|
||||
|
||||
if (sq->add_tag)
|
||||
gtk_signal_disconnect (GTK_OBJECT (sq->view), sq->add_tag);
|
||||
if (sq->seq_complete_tag)
|
||||
gtk_signal_disconnect (GTK_OBJECT (sq->view), sq->seq_complete_tag);
|
||||
|
||||
if (sq->view)
|
||||
gtk_object_unref (GTK_OBJECT (sq->view));
|
||||
|
||||
if (sq->book)
|
||||
gtk_object_unref (GTK_OBJECT (sq->book));
|
||||
|
||||
g_list_foreach (sq->cards, (GFunc) gtk_object_unref, NULL);
|
||||
g_list_free (sq->cards);
|
||||
|
||||
g_free (sq);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_card_added_cb (EBookView *view, const GList *cards, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
sq->cards = g_list_concat (sq->cards, g_list_copy ((GList *) cards));
|
||||
g_list_foreach ((GList *) cards, (GFunc) gtk_object_ref, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_sequence_complete_cb (EBookView *view, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS, sq->cards, sq->closure);
|
||||
simple_query_free (sq);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_query_book_view_cb (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq = closure;
|
||||
|
||||
if (status != E_BOOK_STATUS_SUCCESS) {
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_OTHER_ERROR, NULL, sq->closure);
|
||||
simple_query_free (sq);
|
||||
return;
|
||||
}
|
||||
|
||||
sq->view = book_view;
|
||||
gtk_object_ref (GTK_OBJECT (book_view));
|
||||
|
||||
sq->add_tag = gtk_signal_connect (GTK_OBJECT (sq->view),
|
||||
"card_added",
|
||||
GTK_SIGNAL_FUNC (simple_query_card_added_cb),
|
||||
sq);
|
||||
sq->seq_complete_tag = gtk_signal_connect (GTK_OBJECT (sq->view),
|
||||
"sequence_complete",
|
||||
GTK_SIGNAL_FUNC (simple_query_sequence_complete_cb),
|
||||
sq);
|
||||
}
|
||||
|
||||
guint
|
||||
e_book_simple_query (EBook *book, char *query, EBookSimpleQueryCallback cb, gpointer closure)
|
||||
{
|
||||
SimpleQueryInfo *sq;
|
||||
|
||||
g_return_val_if_fail (book && E_IS_BOOK (book), 0);
|
||||
g_return_val_if_fail (query, 0);
|
||||
g_return_val_if_fail (cb, 0);
|
||||
|
||||
sq = simple_query_new (book, query, cb, closure);
|
||||
e_book_get_book_view (book, query, simple_query_book_view_cb, sq);
|
||||
|
||||
return sq->tag;
|
||||
}
|
||||
|
||||
void
|
||||
e_book_simple_query_cancel (EBook *book, guint tag)
|
||||
{
|
||||
GList *i;
|
||||
|
||||
g_return_if_fail (book && E_IS_BOOK (book));
|
||||
|
||||
for (i=book->priv->sq_pending; i != NULL; i=g_list_next (i)) {
|
||||
SimpleQueryInfo *sq = i->data;
|
||||
|
||||
if (sq->tag == tag) {
|
||||
sq->cb (sq->book, E_BOOK_SIMPLE_QUERY_STATUS_CANCELLED, NULL, sq->closure);
|
||||
simple_query_free (sq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_warning ("Simple query tag %d is unknown", tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* e_book_get_name:
|
||||
*/
|
||||
|
||||
@ -50,9 +50,6 @@ typedef void (*EBookCursorCallback) (EBook *book, EBookStatus status, ECardCurso
|
||||
typedef void (*EBookBookViewCallback) (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure);
|
||||
typedef void (*EBookFieldsCallback) (EBook *book, EBookStatus status, EList *fields, gpointer closure);
|
||||
|
||||
typedef void (*EBookSimpleQueryCallback) (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure);
|
||||
|
||||
|
||||
/* Creating a new addressbook. */
|
||||
EBook *e_book_new (void);
|
||||
|
||||
@ -62,10 +59,6 @@ gboolean e_book_load_uri (EBook *book,
|
||||
gpointer closure);
|
||||
void e_book_unload_uri (EBook *book);
|
||||
|
||||
gboolean e_book_load_local_address_book (EBook *book,
|
||||
EBookCallback open_response,
|
||||
gpointer closure);
|
||||
|
||||
char *e_book_get_static_capabilities (EBook *book);
|
||||
|
||||
gboolean e_book_get_supported_fields (EBook *book,
|
||||
@ -133,15 +126,6 @@ gboolean e_book_get_changes (EBook *book,
|
||||
EBookBookViewCallback cb,
|
||||
gpointer closure);
|
||||
|
||||
/* Simple Query Interface. */
|
||||
|
||||
guint e_book_simple_query (EBook *book,
|
||||
char *query,
|
||||
EBookSimpleQueryCallback cb,
|
||||
gpointer closure);
|
||||
void e_book_simple_query_cancel (EBook *book,
|
||||
guint tag);
|
||||
|
||||
/* Getting the name of the repository. */
|
||||
char *e_book_get_name (EBook *book);
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -1348,6 +1349,154 @@ e_card_name_from_string(const char *full_name)
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/* This *so* doesn't belong here... at least not implemented in a
|
||||
sucky way like this. But by getting it in here now, I can fix it
|
||||
up w/o adding a new feature when we are in feature freeze. :-) */
|
||||
|
||||
/* This is very Anglocentric. Maybe it should be by locale? */
|
||||
static gchar *name_synonyms[][2] = {
|
||||
{ "Jon", "John" }, /* Ah, the hacker's perogative */
|
||||
{ "Jon", "Jonathan" },
|
||||
{ "Daniel", "Dan" },
|
||||
{ "Joseph", "Joe" },
|
||||
{ "Robert", "Rob" },
|
||||
{ "Robert", "Bob" },
|
||||
{ "Richard", "Rich" },
|
||||
{ "Richard", "Dick" },
|
||||
{ "William", "Will" },
|
||||
{ "William", "Bill" },
|
||||
{ "Anthony", "Tony" },
|
||||
{ "Steven", "Steve" },
|
||||
{ "Michael", "Mike" },
|
||||
{ "Douglas", "Doug" },
|
||||
{ "Sidney", "Sid" },
|
||||
{ "Eric", "Erik" },
|
||||
{ "Chris", "Christopher" },
|
||||
{ "Chris", "Christine" },
|
||||
{ "Chris", "Christy" },
|
||||
{ "Elizabeth", "Liz" },
|
||||
{ "Jeff", "Geoff" },
|
||||
{ "Jeff", "Jeffrey" },
|
||||
{ "Jeff", "Geoffrey" },
|
||||
{ "Jim", "James" },
|
||||
{ "Abigal", "Abby" },
|
||||
{ "Amanda", "Amy" },
|
||||
{ "Amanda", "Manda" },
|
||||
{ "Di", "Diana" },
|
||||
{ "Di", "Diane" },
|
||||
{ "Maxine", "Max" },
|
||||
{ "Rebecca", "Becca" },
|
||||
{ "Rebecca", "Becky" },
|
||||
{ "Jennifer", "Jen" },
|
||||
{ "Jennifer", "Jenny" },
|
||||
/* We could go on and on... */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static gboolean
|
||||
name_fragment_match (const gchar *a, const gchar *b)
|
||||
{
|
||||
gint i;
|
||||
gboolean nickname_match = FALSE;
|
||||
|
||||
if (!g_strcasecmp (a, b))
|
||||
return TRUE;
|
||||
|
||||
/* Check for nicknames. Yes, the linear search blows. */
|
||||
for (i=0; name_synonyms[i][0]; ++i) {
|
||||
if (!g_strcasecmp (name_synonyms[i][1], a)) {
|
||||
a = name_synonyms[i][0];
|
||||
nickname_match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; name_synonyms[i][0]; ++i) {
|
||||
if (!g_strcasecmp (name_synonyms[i][1], b)) {
|
||||
b = name_synonyms[i][0];
|
||||
nickname_match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nickname_match && !g_strcasecmp (a, b);
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_card_name_match_string (const ECardName *name, const gchar *str)
|
||||
{
|
||||
gchar *cpy, *name_str;
|
||||
gchar **strv, **namev;
|
||||
gint i, j, match_count;
|
||||
gboolean matched = FALSE;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
cpy = g_strdup (str);
|
||||
strv = g_strsplit (cpy, " ", 0);
|
||||
for (i=0; strv[i]; ++i)
|
||||
g_strstrip (strv[i]);
|
||||
|
||||
name_str = e_card_name_to_string (name);
|
||||
namev = g_strsplit (name_str, " ", 0);
|
||||
for (i=0; namev[i]; ++i)
|
||||
g_strstrip (namev[i]);
|
||||
|
||||
match_count = 0;
|
||||
i = j = 0;
|
||||
while (strv[i] && namev[j]) {
|
||||
gint k1, k2;
|
||||
|
||||
for (k1=0; strv[i+k1]; ++k1) {
|
||||
if (name_fragment_match (strv[i+k1], namev[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
for (k2=0; namev[j+k2]; ++k2) {
|
||||
if (name_fragment_match (strv[i], namev[j+k2]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (strv[i+k1] == NULL && namev[j+k2] == NULL) {
|
||||
matched = FALSE;
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
|
||||
++match_count;
|
||||
|
||||
if (k1 < k2) {
|
||||
i += k1+1;
|
||||
++j;
|
||||
} else if (k2 < k1) {
|
||||
++i;
|
||||
j += k2+1;
|
||||
} else if (k1 == k2) {
|
||||
i += k1+1;
|
||||
j += k2+1;
|
||||
}
|
||||
}
|
||||
|
||||
/* This rule could be made more precise.
|
||||
As it is, it will say that "Joe Smith" will match the name
|
||||
"Joe Allen Smith" (which is good), but "de Icaza" will match
|
||||
either "Miguel de Icaza" as well as Miguel's shiftless
|
||||
brother "Roger de Icaza". In this sort of a case, the match
|
||||
threshold should go up to 3. */
|
||||
if (match_count >= 2)
|
||||
matched = TRUE;
|
||||
|
||||
|
||||
cleanup_and_return:
|
||||
g_free (strv);
|
||||
g_free (cpy);
|
||||
g_free (namev);
|
||||
g_free (name_str);
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
ECardArbitrary *
|
||||
e_card_arbitrary_new(void)
|
||||
{
|
||||
@ -1382,6 +1531,59 @@ e_card_arbitrary_free(ECardArbitrary *arbitrary)
|
||||
g_free(arbitrary);
|
||||
}
|
||||
|
||||
/* EMail matching */
|
||||
static gboolean
|
||||
e_card_email_match_single_string (const gchar *a, const gchar *b)
|
||||
{
|
||||
const gchar *xa = NULL, *xb = NULL;
|
||||
gboolean match = TRUE;
|
||||
|
||||
for (xa=a; *xa && *xa != '@'; ++xa);
|
||||
for (xb=b; *xb && *xb != '@'; ++xb);
|
||||
|
||||
if (xa-a != xb-b || *xa != *xb || g_strncasecmp (a, b, xa-a))
|
||||
return FALSE;
|
||||
|
||||
if (*xa == '\0')
|
||||
return TRUE;
|
||||
|
||||
/* Find the end of the string, then walk through backwards comparing.
|
||||
This is so that we'll match joe@foobar.com and joe@mail.foobar.com.
|
||||
*/
|
||||
while (*xa)
|
||||
++xa;
|
||||
while (*xb)
|
||||
++xb;
|
||||
|
||||
while (match && *xa != '@' && *xb != '@') {
|
||||
match = (*xa == *xb);
|
||||
--xa;
|
||||
--xb;
|
||||
}
|
||||
|
||||
match = match && ((*xa == *xb) || (*xa == '.') || (*xb == '.'));
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_card_email_match_string (const ECard *card, const gchar *str)
|
||||
{
|
||||
EIterator *iter;
|
||||
|
||||
g_return_val_if_fail (card && E_IS_CARD (card), FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
iter = e_list_get_iterator (card->email);
|
||||
for (e_iterator_reset (iter); e_iterator_is_valid (iter); e_iterator_next (iter)) {
|
||||
if (e_card_email_match_single_string (e_iterator_get (iter), str))
|
||||
return TRUE;
|
||||
}
|
||||
gtk_object_unref (GTK_OBJECT (iter));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ECard lifecycle management and vCard loading/saving.
|
||||
*/
|
||||
|
||||
@ -140,12 +140,18 @@ ECardName *e_card_name_copy (const ECardName
|
||||
void e_card_name_free (ECardName *name);
|
||||
char *e_card_name_to_string (const ECardName *name);
|
||||
ECardName *e_card_name_from_string (const char *full_name);
|
||||
gboolean e_card_name_match_string (const ECardName *name,
|
||||
const gchar *str);
|
||||
|
||||
/* ECardArbitrary manipulation */
|
||||
ECardArbitrary *e_card_arbitrary_new (void);
|
||||
ECardArbitrary *e_card_arbitrary_copy (const ECardArbitrary *arbitrary);
|
||||
void e_card_arbitrary_free (ECardArbitrary *arbitrary);
|
||||
|
||||
/* ECard email manipulation */
|
||||
gboolean e_card_email_match_string (const ECard *card,
|
||||
const gchar *str);
|
||||
|
||||
/* Specialized functionality */
|
||||
GList *e_card_load_cards_from_file (const char *filename);
|
||||
|
||||
|
||||
@ -475,6 +475,7 @@ pas_backend_file_search (PASBackendFile *bf,
|
||||
{
|
||||
int db_error = 0;
|
||||
GList *cards = NULL;
|
||||
gint card_count = 0;
|
||||
DB *db = bf->priv->file_db;
|
||||
DBT id_dbt, vcard_dbt;
|
||||
int i;
|
||||
@ -518,6 +519,18 @@ pas_backend_file_search (PASBackendFile *bf,
|
||||
/* check if the vcard matches the search sexp */
|
||||
if (vcard_matches_search (view, vcard_string)) {
|
||||
cards = g_list_append (cards, g_strdup (vcard_string));
|
||||
++card_count;
|
||||
#if 0
|
||||
/* If we've accumulated a number of matches, pass them off to the client. */
|
||||
if (card_count > 50) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -528,7 +541,9 @@ pas_backend_file_search (PASBackendFile *bf,
|
||||
g_warning ("pas_backend_file_search: error building list\n");
|
||||
}
|
||||
|
||||
pas_book_view_notify_add (view->book_view, cards);
|
||||
// if (card_count)
|
||||
pas_book_view_notify_add (view->book_view, cards);
|
||||
|
||||
pas_book_view_notify_complete (view->book_view);
|
||||
|
||||
/*
|
||||
|
||||
@ -154,7 +154,7 @@ pas_book_view_notify_status_message (PASBookView *book_view,
|
||||
book_view->priv->listener, message, &ev);
|
||||
|
||||
if (ev._major != CORBA_NO_EXCEPTION) {
|
||||
g_warning ("pas_book_view_notify_complete: Exception signaling BookViewListener!\n");
|
||||
g_warning ("pas_book_view_notify_status_message: Exception signaling BookViewListener!\n");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
@ -248,7 +248,6 @@ pas_book_view_destroy (GtkObject *object)
|
||||
|
||||
GNOME_Evolution_Addressbook_BookViewListener_unref (book_view->priv->listener, &ev);
|
||||
if (ev._major != CORBA_NO_EXCEPTION) {
|
||||
g_warning("Unable to unref listener object in pas-book-view.c\n");
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
return;
|
||||
@ -256,7 +255,6 @@ pas_book_view_destroy (GtkObject *object)
|
||||
|
||||
CORBA_Object_release (book_view->priv->listener, &ev);
|
||||
if (ev._major != CORBA_NO_EXCEPTION) {
|
||||
g_warning("Unable to release listener object in pas-book-view.c\n");
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
return;
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <ctype.h>
|
||||
#include <gnome.h>
|
||||
#include <addressbook/backend/ebook/e-book.h>
|
||||
#include <addressbook/backend/ebook/e-book-util.h>
|
||||
#include <addressbook/backend/ebook/e-card.h>
|
||||
#include "e-contact-editor.h"
|
||||
#include "e-contact-quick-add.h"
|
||||
|
||||
@ -70,6 +70,8 @@ main (int argc, char **argv)
|
||||
|
||||
unicode_init();
|
||||
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
|
||||
|
||||
bonobo_main ();
|
||||
|
||||
return 0;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <ctype.h>
|
||||
#include <bonobo/bonobo-control.h>
|
||||
#include <bonobo/bonobo-property-bag.h>
|
||||
#include <bonobo/bonobo-generic-factory.h>
|
||||
@ -38,9 +39,14 @@ static void e_address_widget_destroy (GtkObject *obj);
|
||||
|
||||
static gint e_address_widget_button_press_handler (GtkWidget *w, GdkEventButton *ev);
|
||||
static void e_address_widget_popup (EAddressWidget *, GdkEventButton *ev);
|
||||
static void e_address_widget_schedule_query (EAddressWidget *);
|
||||
|
||||
static GtkObjectClass *parent_class;
|
||||
|
||||
static EBook *common_book = NULL; /* sort of lame */
|
||||
|
||||
static gboolean doing_queries = FALSE;
|
||||
|
||||
static void
|
||||
e_address_widget_class_init (EAddressWidgetClass *klass)
|
||||
{
|
||||
@ -67,8 +73,12 @@ e_address_widget_destroy (GtkObject *obj)
|
||||
|
||||
g_free (addr->name);
|
||||
g_free (addr->email);
|
||||
if (addr->card)
|
||||
gtk_object_unref (GTK_OBJECT (addr->card));
|
||||
|
||||
if (addr->query_tag)
|
||||
e_book_simple_query_cancel (common_book, addr->query_tag);
|
||||
|
||||
if (addr->query_idle_tag)
|
||||
gtk_idle_remove (addr->query_idle_tag);
|
||||
}
|
||||
|
||||
static gint
|
||||
@ -123,10 +133,21 @@ e_address_widget_refresh (EAddressWidget *addr)
|
||||
g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
|
||||
|
||||
have_name = addr->name && *addr->name;
|
||||
have_email = addr->email && *addr->email;
|
||||
have_email = addr->email && *addr->email && (addr->card == NULL || !addr->known_email);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (addr->name_widget), have_name ? addr->name : "");
|
||||
gtk_widget_visible (addr->name_widget, have_name);
|
||||
if (addr->card) {
|
||||
gint i, N = strlen (addr->name);
|
||||
gchar *pattern = g_malloc (N+1);
|
||||
for (i=0; i<N; ++i)
|
||||
pattern[i] = '_';
|
||||
pattern[i] = '\0';
|
||||
gtk_label_set_pattern (GTK_LABEL (addr->name_widget), pattern);
|
||||
g_free (pattern);
|
||||
} else {
|
||||
gtk_label_set_pattern (GTK_LABEL (addr->name_widget), "");
|
||||
}
|
||||
|
||||
if (have_email) {
|
||||
str = g_strdup_printf (have_name ? "<%s>" : "%s", addr->email);
|
||||
@ -140,7 +161,8 @@ e_address_widget_refresh (EAddressWidget *addr)
|
||||
gtk_widget_visible (addr->spacer, have_name && have_email);
|
||||
|
||||
/* Launch a query to find the appropriate card, if necessary. */
|
||||
addr->querying = TRUE;
|
||||
if (addr->card == NULL)
|
||||
e_address_widget_schedule_query (addr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -207,6 +229,92 @@ e_address_widget_new (void)
|
||||
return GTK_WIDGET (addr);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Cardification
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
e_address_widget_cardify (EAddressWidget *addr, ECard *card, gboolean known_email)
|
||||
{
|
||||
if (addr->card != card || addr->known_email != known_email) {
|
||||
|
||||
if (addr->card != card) {
|
||||
if (addr->card)
|
||||
gtk_object_unref (GTK_OBJECT (addr->card));
|
||||
addr->card = card;
|
||||
gtk_object_ref (GTK_OBJECT (addr->card));
|
||||
}
|
||||
|
||||
addr->known_email = known_email;
|
||||
|
||||
if (!(addr->name && *addr->name)) {
|
||||
gchar *s = e_card_name_to_string (card->name);
|
||||
e_address_widget_set_name (addr, s);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
e_address_widget_refresh (addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
query_results_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer user_data)
|
||||
{
|
||||
EAddressWidget *addr = user_data;
|
||||
|
||||
if (g_list_length ((GList *) cards) == 1) {
|
||||
ECard *card = E_CARD (cards->data);
|
||||
e_address_widget_cardify (addr, card, TRUE);
|
||||
}
|
||||
|
||||
addr->query_tag = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
e_address_widget_do_query (EAddressWidget *addr)
|
||||
{
|
||||
e_book_name_and_email_query (common_book, addr->name, addr->email, query_results_cb, addr);
|
||||
}
|
||||
|
||||
static void
|
||||
book_ready_cb (EBook *book, EBookStatus status, gpointer user_data)
|
||||
{
|
||||
EAddressWidget *addr = E_ADDRESS_WIDGET (user_data);
|
||||
|
||||
if (common_book == NULL) {
|
||||
common_book = book;
|
||||
gtk_object_ref (GTK_OBJECT (common_book));
|
||||
} else
|
||||
gtk_object_unref (GTK_OBJECT (book));
|
||||
|
||||
e_address_widget_do_query (addr);
|
||||
}
|
||||
|
||||
static gint
|
||||
query_idle_fn (gpointer ptr)
|
||||
{
|
||||
EAddressWidget *addr = E_ADDRESS_WIDGET (ptr);
|
||||
|
||||
if (common_book) {
|
||||
e_address_widget_do_query (addr);
|
||||
} else {
|
||||
e_book_load_local_address_book (e_book_new (), book_ready_cb, addr);
|
||||
}
|
||||
|
||||
addr->query_idle_tag = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
e_address_widget_schedule_query (EAddressWidget *addr)
|
||||
{
|
||||
if (addr->query_idle_tag || !doing_queries)
|
||||
return;
|
||||
addr->query_idle_tag = gtk_idle_add (query_idle_fn, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Popup Menu
|
||||
@ -214,13 +322,84 @@ e_address_widget_new (void)
|
||||
*/
|
||||
|
||||
#define ARBITRARY_UIINFO_LIMIT 64
|
||||
|
||||
static gint
|
||||
popup_add_name_and_address (EAddressWidget *addr, GnomeUIInfo *uiinfo, gint i)
|
||||
{
|
||||
gboolean flag = FALSE;
|
||||
|
||||
if (addr->name && *addr->name) {
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = addr->name;
|
||||
++i;
|
||||
flag = TRUE;
|
||||
}
|
||||
|
||||
if (addr->email && *addr->email) {
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = addr->email;
|
||||
++i;
|
||||
flag = TRUE;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
uiinfo[i].type = GNOME_APP_UI_SEPARATOR;
|
||||
++i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
flip_queries_flag_cb (GtkWidget *w, gpointer user_data)
|
||||
{
|
||||
doing_queries = !doing_queries;
|
||||
}
|
||||
|
||||
static gint
|
||||
popup_add_query_change (EAddressWidget *addr, GnomeUIInfo *uiinfo, gint i)
|
||||
{
|
||||
uiinfo[i].type = GNOME_APP_UI_SEPARATOR;
|
||||
++i;
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = doing_queries ? _("Disable Queries") : _("Enable Queries (Dangerous!)");
|
||||
uiinfo[i].moreinfo = flip_queries_flag_cb;
|
||||
++i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static GtkWidget *
|
||||
popup_menu_card (EAddressWidget *addr)
|
||||
{
|
||||
GnomeUIInfo uiinfo[ARBITRARY_UIINFO_LIMIT];
|
||||
GtkWidget *pop;
|
||||
gint i=0;
|
||||
ECard *card = E_CARD (addr->card);
|
||||
|
||||
g_return_val_if_fail (card != NULL, NULL);
|
||||
|
||||
return NULL;
|
||||
memset (uiinfo, 0, sizeof (uiinfo));
|
||||
|
||||
i = popup_add_name_and_address (addr, uiinfo, i);
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = _("Edit Contact Info");
|
||||
++i;
|
||||
|
||||
i = popup_add_query_change (addr, uiinfo, i);
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_ENDOFINFO;
|
||||
pop = gnome_popup_menu_new (uiinfo);
|
||||
return pop;
|
||||
}
|
||||
|
||||
static void
|
||||
post_quick_add_cb (ECard *card, gpointer user_data)
|
||||
{
|
||||
e_address_widget_cardify (E_ADDRESS_WIDGET (user_data), card, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -228,7 +407,7 @@ add_contacts_cb (GtkWidget *w, gpointer user_data)
|
||||
{
|
||||
EAddressWidget *addr = E_ADDRESS_WIDGET (user_data);
|
||||
|
||||
e_contact_quick_add (addr->name, addr->email, NULL, NULL);
|
||||
e_contact_quick_add (addr->name, addr->email, post_quick_add_cb, addr);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@ -240,30 +419,17 @@ popup_menu_nocard (EAddressWidget *addr)
|
||||
|
||||
memset (uiinfo, 0, sizeof (uiinfo));
|
||||
|
||||
if (addr->name) {
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = addr->name;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (addr->email) {
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = addr->email;
|
||||
++i;
|
||||
}
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_SEPARATOR;
|
||||
++i;
|
||||
i = popup_add_name_and_address (addr, uiinfo, i);
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_ITEM;
|
||||
uiinfo[i].label = N_("Add to Contacts");
|
||||
uiinfo[i].label = _("Add to Contacts");
|
||||
uiinfo[i].moreinfo = add_contacts_cb;
|
||||
++i;
|
||||
|
||||
i = popup_add_query_change (addr, uiinfo, i);
|
||||
|
||||
uiinfo[i].type = GNOME_APP_UI_ENDOFINFO;
|
||||
|
||||
pop = gnome_popup_menu_new (uiinfo);
|
||||
|
||||
return pop;
|
||||
}
|
||||
|
||||
@ -409,3 +575,4 @@ e_address_widget_factory_init (void)
|
||||
if (factory == NULL)
|
||||
g_error ("I could not register an AddressWidget factory.");
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <libgnome/gnome-defs.h>
|
||||
#include <addressbook/backend/ebook/e-book.h>
|
||||
#include <addressbook/backend/ebook/e-book-util.h>
|
||||
#include <addressbook/backend/ebook/e-card.h>
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
@ -53,8 +55,11 @@ struct _EAddressWidget {
|
||||
GtkWidget *email_widget;
|
||||
GtkWidget *spacer;
|
||||
|
||||
gboolean querying;
|
||||
guint query_idle_tag;
|
||||
guint query_tag;
|
||||
|
||||
ECard *card;
|
||||
gboolean known_email;
|
||||
};
|
||||
|
||||
struct _EAddressWidgetClass {
|
||||
@ -71,7 +76,7 @@ void e_address_widget_construct (EAddressWidget *);
|
||||
GtkWidget *e_address_widget_new (void);
|
||||
|
||||
|
||||
void e_address_widget_factory_init (void);
|
||||
void e_address_widget_factory_init (void);
|
||||
|
||||
|
||||
|
||||
@ -79,3 +84,17 @@ END_GNOME_DECLS
|
||||
|
||||
#endif /* __E_ADDRESS_WIDGET_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <ctype.h>
|
||||
#include <gnome.h>
|
||||
#include <addressbook/backend/ebook/e-book.h>
|
||||
#include <addressbook/backend/ebook/e-book-util.h>
|
||||
#include <addressbook/backend/ebook/e-card.h>
|
||||
#include "e-contact-editor.h"
|
||||
#include "e-contact-quick-add.h"
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
2001-03-15 Jon Trowbridge <trow@ximian.com>
|
||||
|
||||
* wombat.c (main): If we can't initialize a service on startup,
|
||||
tell us which one before terminating.
|
||||
|
||||
2001-02-27 Federico Mena Quintero <federico@ximian.com>
|
||||
|
||||
* wombat.c (init_corba): Use VERSION and the Wombat description
|
||||
|
||||
@ -183,9 +183,13 @@ init_bonobo (int *argc, char **argv)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gboolean did_pas=FALSE, did_pcs=FALSE, did_config=FALSE;
|
||||
|
||||
bindtextdomain (PACKAGE, EVOLUTION_LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
g_message ("Starting wombat");
|
||||
|
||||
init_bonobo (&argc, argv);
|
||||
setup_vfs (argc, argv);
|
||||
|
||||
@ -193,10 +197,20 @@ main (int argc, char **argv)
|
||||
G_LOG_LEVEL_CRITICAL |
|
||||
G_LOG_LEVEL_WARNING);*/
|
||||
|
||||
if (!(setup_pas (argc, argv)
|
||||
&& setup_pcs (argc, argv)
|
||||
&& setup_config (argc, argv))) {
|
||||
g_message ("main(): could not initialize all of the Wombat services; terminating");
|
||||
if (!( (did_pas = setup_pas (argc, argv))
|
||||
&& (did_pcs = setup_pcs (argc, argv))
|
||||
&& (did_config = setup_config (argc, argv)))) {
|
||||
|
||||
const gchar *failed = NULL;
|
||||
|
||||
if (!did_pas)
|
||||
failed = "PAS";
|
||||
else if (!did_pcs)
|
||||
failed = "PCS";
|
||||
else if (!did_config)
|
||||
failed = "Config";
|
||||
|
||||
g_message ("main(): could not initialize Wombat service \"%s\"; terminating", failed);
|
||||
|
||||
if (pas_book_factory) {
|
||||
bonobo_object_unref (BONOBO_OBJECT (pas_book_factory));
|
||||
|
||||
Reference in New Issue
Block a user