From 7c5dd95cd7aefa8243edac3c67bf1910fc905c4e Mon Sep 17 00:00:00 2001 From: Jon Trowbridge Date: Sat, 30 Jun 2001 05:23:09 +0000 Subject: Make the standard for considering two cards to be match stricter. 2001-06-30 Jon Trowbridge * gui/merging/e-card-merging.c (match_query_callback): Make the standard for considering two cards to be match stricter. * gui/component/select-names/e-select-names-completion.c (make_match): Use the card's use-score to set the match's sort_major value. (match_name): Removed obsolete code. (e_select_names_completion_begin): Added (double) cast to make match->score calculation come out properly. * backend/ebook/e-card.c: Added X-EVOLUTION-LAST-USE and X-EVOLUTION-USE-SCORE to attribute_jump_array. (e_card_get_today): Added. A convenience routine for getting today's date and putting it in a GDate. (e_card_get_use_score): Added. Compute the current, time-decayed, use-score for the card. (e_card_touch): Increment the use-score by one; update the last used date. (e_card_date_to_string): Added as a convenience routine, getting rid of some code duplication. (e_card_get_vobject): Add handlers for X-EVOLUTION-USE-SCORE and X-EVOLUTION-LAST-USE. (parse_last_use): Added. (parse_use_score): Added. (e_card_class_init): Added args for last-use and use-score. (e_card_get_arg): Added handlers for last-use and use-score. o (e_card_set_arg): Added handlers for last-use and use-score. * backend/ebook/e-destination.c: Added pending_card_id to EDestinationPrivate struct. (e_destination_copy): Copy the pending_card_id. (e_destination_is_empty): Check for a pending_card_id. We are non-empty if we have one. (e_destination_clear_card): Clear pending_card_id. (e_destination_set_card): Clear pending_card_id. (e_destination_has_pending_card): Added. (e_destination_use_card): Added. An asynchronous way to load a pending card and then apply a callback to it. (build_field): Be paranoid, map our special characters to '_'. (e_destination_export): Use EXPORT_MAX_FIELDS symbol rather than a hard-wired array size. Added the "card" entry. (e_destination_import): Fix bug in handling of the "name" field. Process the "card" field. (e_destination_touch): "Touch" and commit the ECard corresponding to the e-mail address in the destination. (A query against the local addressbook is actually performed, in case the destination isn't cardified. * backend/ebook/e-card-compare.c (e_card_compare_name): Revamp the way E_CARD_MATCH_FOO results are mapped to comparison results. Report better matches when the family name is matched. svn path=/trunk/; revision=10626 --- addressbook/backend/ebook/e-destination.c | 176 ++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 9 deletions(-) (limited to 'addressbook/backend/ebook/e-destination.c') diff --git a/addressbook/backend/ebook/e-destination.c b/addressbook/backend/ebook/e-destination.c index 83bd96a7d1..513f934cdf 100644 --- a/addressbook/backend/ebook/e-destination.c +++ b/addressbook/backend/ebook/e-destination.c @@ -26,13 +26,20 @@ */ #include +#include "e-destination.h" + #include #include #include #include -#include "e-destination.h" +#include "e-book.h" +#include "e-book-util.h" + struct _EDestinationPrivate { + + gchar *pending_card_id; + ECard *card; gint card_email_num; @@ -117,6 +124,8 @@ e_destination_copy (EDestination *dest) new_dest = e_destination_new (); + new_dest->priv->pending_card_id = g_strdup (new_dest->priv->pending_card_id); + new_dest->priv->card = dest->priv->card; if (new_dest->priv->card) gtk_object_ref (GTK_OBJECT (new_dest->priv->card)); @@ -135,12 +144,15 @@ e_destination_is_empty (EDestination *dest) { g_return_val_if_fail (dest && E_IS_DESTINATION (dest), TRUE); - return !(dest->priv->card || (dest->priv->string && *dest->priv->string)); + return !(dest->priv->card || dest->priv->pending_card_id || (dest->priv->string && *dest->priv->string)); } static void e_destination_clear_card (EDestination *dest) { + g_free (dest->priv->pending_card_id); + dest->priv->pending_card_id = NULL; + if (dest->priv->card) gtk_object_unref (GTK_OBJECT (dest->priv->card)); dest->priv->card = NULL; @@ -168,6 +180,11 @@ e_destination_set_card (EDestination *dest, ECard *card, gint email_num) g_return_if_fail (dest && E_IS_DESTINATION (dest)); g_return_if_fail (card && E_IS_CARD (card)); + if (dest->priv->pending_card_id) { + g_free (dest->priv->pending_card_id); + dest->priv->pending_card_id = NULL; + } + if (dest->priv->card != card) { if (dest->priv->card) gtk_object_unref (GTK_OBJECT (dest->priv->card)); @@ -199,6 +216,83 @@ e_destination_set_html_mail_pref (EDestination *dest, gboolean x) dest->priv->wants_html_mail = x; } +gboolean +e_destination_has_card (const EDestination *dest) +{ + g_return_val_if_fail (dest && E_IS_DESTINATION (dest), FALSE); + return dest->priv->card != NULL; +} + +gboolean +e_destination_has_pending_card (const EDestination *dest) +{ + g_return_val_if_fail (dest && E_IS_DESTINATION (dest), FALSE); + return dest->priv->pending_card_id != NULL; +} + + +typedef struct _UseCard UseCard; +struct _UseCard { + EDestination *dest; + EDestinationCardCallback cb; + gpointer closure; +}; + +static void +use_card_cb (EBook *book, gpointer closure) +{ + UseCard *uc = (UseCard *) closure; + ECard *card; + + if (book != NULL && uc->dest->priv->card == NULL) { + + if (uc->dest->priv->pending_card_id) { + + card = e_book_get_card (book, uc->dest->priv->pending_card_id); + + if (card) { + ECard *old = uc->dest->priv->card; + uc->dest->priv->card = card; + gtk_object_ref (GTK_OBJECT (card)); + if (old) + gtk_object_unref (GTK_OBJECT (old)); + } + + g_free (uc->dest->priv->pending_card_id); + uc->dest->priv->pending_card_id = NULL; + + } + + } + + if (uc->cb) + uc->cb (uc->dest, uc->dest->priv->card, uc->closure); + + gtk_object_unref (GTK_OBJECT (uc->dest)); + g_free (uc); +} + +void +e_destination_use_card (EDestination *dest, EDestinationCardCallback cb, gpointer closure) +{ + g_return_if_fail (dest && E_IS_DESTINATION (dest)); + + if (dest->priv->card) { + + if (cb) { + cb (dest, dest->priv->card, closure); + } + + } else { + UseCard *uc = g_new (UseCard, 1); + uc->dest = dest; + gtk_object_ref (GTK_OBJECT (uc->dest)); + uc->cb = cb; + uc->closure = closure; + e_book_use_local_address_book (use_card_cb, uc); + } +} + ECard * e_destination_get_card (const EDestination *dest) { @@ -393,11 +487,13 @@ e_destination_get_address_textv (EDestination **destv) #define DESTINATION_TAG "DEST" #define DESTINATION_SEPARATOR "|" +#define VEC_SEPARATOR "\1" static gchar * join_strings (gchar **strv) { /* FIXME: Should also quote any |'s that occur in any of the strings. */ + /* (We fake it by mapping | to _ when building our fields below) */ return g_strjoinv (DESTINATION_SEPARATOR, strv); } @@ -405,13 +501,37 @@ static gchar ** unjoin_string (const gchar *str) { /* FIXME: Should properly handle quoteded |'s in the string. */ + /* (We fake it by mapping | to _ when building our fields below) */ return g_strsplit (str, DESTINATION_SEPARATOR, 0); } static gchar * build_field (const gchar *key, const gchar *value) { - return g_strdup_printf ("%s=%s", key, value); + gchar *field; + gchar *c; + + g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + + field = g_strdup_printf ("%s=%s", key, value); + + /* Paranoia: Convert any '=' in the key to '_' */ + c = field; + while (*key) { + if (*c == '=') + *c = '_'; + ++key; + ++c; + } + + /* Paranoia: Convert any '\1' or '|' in the key or value to '_' */ + for (c=field; *c; ++c) { + if (*c == VEC_SEPARATOR || *c == DESTINATION_SEPARATOR) + *c = '_'; + } + + return field; } /* Modifies string in place, \0-terminates after the key, returns pointer to "value", @@ -426,17 +546,18 @@ extract_field (gchar *field) return s+1; } - +#define EXPORT_MAX_FIELDS 10 gchar * e_destination_export (const EDestination *dest) { + ECard *card; gchar **fields; gchar *str; gint i; g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL); - fields = g_new (gchar *, 5); + fields = g_new (gchar *, EXPORT_MAX_FIELDS); fields[0] = g_strdup (DESTINATION_TAG); fields[1] = build_field ("addr", e_destination_get_email (dest)); @@ -448,6 +569,10 @@ e_destination_export (const EDestination *dest) fields[i++] = build_field ("html", e_destination_get_html_mail_pref (dest) ? "Y" : "N"); + card = e_destination_get_card (dest); + if (card) + fields[i++] = build_field ("card", e_card_get_id (card)); + fields[i] = NULL; @@ -464,7 +589,7 @@ e_destination_import (const gchar *str) gchar **fields; gint i; - gchar *addr = NULL, *name = NULL; + gchar *addr = NULL, *name = NULL, *card = NULL; gboolean want_html = FALSE; g_return_val_if_fail (str, NULL); @@ -493,12 +618,20 @@ e_destination_import (const gchar *str) g_warning ("name redefined: \"%s\" => \"%s\"", name, value); } - name = g_strdup (name); + name = g_strdup (value); } else if (!strcmp ("html", key)) { want_html = (*value == 'Y'); + } else if (!strcmp ("card", key)) { + + if (card) { + g_warning ("card redefined: \"%s\" => \"%s\"", card, value); + } + + card = g_strdup (value); + } } @@ -510,6 +643,9 @@ e_destination_import (const gchar *str) /* We construct this part of the object in a rather abusive way. */ dest->priv->string_email = addr; dest->priv->name = name; + dest->priv->pending_card_id = card; + + g_message ("name:[%s] addr:[%s]", name, addr); e_destination_set_html_mail_pref (dest, want_html); @@ -518,8 +654,6 @@ e_destination_import (const gchar *str) return dest; } -#define VEC_SEPARATOR "\1" - gchar * e_destination_exportv (EDestination **destv) { @@ -574,3 +708,27 @@ e_destination_importv (const gchar *str) g_strfreev (strv); return destv; } + +static void +touch_cb (EBook *book, const gchar *addr, ECard *card, gpointer closure) +{ + if (book != NULL && card != NULL) { + e_card_touch (card); + g_message ("Use score for \"%s\" is now %f", addr, e_card_get_use_score (card)); + e_book_commit_card (book, card, NULL, NULL); + } +} + +void +e_destination_touch (EDestination *dest) +{ + const gchar *email; + + g_return_if_fail (dest && E_IS_DESTINATION (dest)); + + email = e_destination_get_email (dest); + + if (email) { + e_book_query_address_locally (email, touch_cb, NULL); + } +} -- cgit