Make the standard for considering two cards to be match stricter.

2001-06-30  Jon Trowbridge  <trow@ximian.com>

        * 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
This commit is contained in:
Jon Trowbridge
2001-06-30 05:23:09 +00:00
committed by Jon Trowbridge
parent c187a911c8
commit 7c5dd95cd7
9 changed files with 429 additions and 64 deletions

View File

@ -1,3 +1,58 @@
2001-06-30 Jon Trowbridge <trow@ximian.com>
* 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.
2001-06-29 Christopher James Lahey <clahey@ximian.com>
* gui/component/select-names/e-select-names.c (update_query):

View File

@ -105,6 +105,7 @@ e_card_compare_name (ECard *card1, ECard *card2)
{
ECardName *a, *b;
gint matches=0, possible=0;
gboolean given_match = FALSE, additional_match = FALSE, family_match = FALSE;
g_return_val_if_fail (card1 && E_IS_CARD (card1), E_CARD_MATCH_NOT_APPLICABLE);
g_return_val_if_fail (card2 && E_IS_CARD (card2), E_CARD_MATCH_NOT_APPLICABLE);
@ -117,36 +118,45 @@ e_card_compare_name (ECard *card1, ECard *card2)
if (a->given && b->given) {
++possible;
if (name_fragment_match (a->given, b->given))
if (name_fragment_match (a->given, b->given)) {
++matches;
given_match = TRUE;
}
}
if (a->additional && b->additional) {
++possible;
if (name_fragment_match (a->additional, b->additional))
if (name_fragment_match (a->additional, b->additional)) {
++matches;
additional_match = TRUE;
}
}
if (a->family && b->family) {
++possible;
if (name_fragment_match (a->family, b->family))
if (name_fragment_match (a->family, b->family)) {
++matches;
family_match = TRUE;
}
}
/* Now look at the # of matches and try to intelligently map
an E_CARD_MATCH_* type to it. */
an E_CARD_MATCH_* type to it. Special consideration is given
to family-name matches. */
if (possible == 0)
return E_CARD_MATCH_NOT_APPLICABLE;
if (matches == 0)
return E_CARD_MATCH_NONE;
if (matches == possible) {
return possible > 1 ? E_CARD_MATCH_EXACT : E_CARD_MATCH_PARTIAL;
} else if (matches == possible-1)
return E_CARD_MATCH_PARTIAL;
else
return E_CARD_MATCH_VAGUE;
if (possible == 1)
return family_match ? E_CARD_MATCH_VAGUE : E_CARD_MATCH_NONE;
if (possible == matches)
return family_match ? E_CARD_MATCH_EXACT : E_CARD_MATCH_PARTIAL;
if (possible == matches+1)
return family_match ? E_CARD_MATCH_PARTIAL : E_CARD_MATCH_VAGUE;
return E_CARD_MATCH_NONE;
}

View File

@ -18,6 +18,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <gtk/gtkobject.h>
#include <bonobo/bonobo-object-client.h>
@ -69,6 +71,8 @@ enum {
ARG_EVOLUTION_LIST_SHOW_ADDRESSES,
ARG_ARBITRARY,
ARG_ID,
ARG_LAST_USE,
ARG_USE_SCORE,
};
#if 0
@ -114,6 +118,8 @@ static void parse_list(ECard *card, VObject *object);
static void parse_list_show_addresses(ECard *card, VObject *object);
static void parse_arbitrary(ECard *card, VObject *object);
static void parse_id(ECard *card, VObject *object);
static void parse_last_use(ECard *card, VObject *object);
static void parse_use_score(ECard *card, VObject *object);
static ECardPhoneFlags get_phone_flags (VObject *vobj);
static void set_phone_flags (VObject *vobj, ECardPhoneFlags flags);
@ -151,6 +157,9 @@ struct {
{ "CATEGORIES", parse_categories },
{ XEV_WANTS_HTML, parse_wants_html },
{ XEV_ARBITRARY, parse_arbitrary },
{ VCUniqueStringProp, parse_id },
{ "X-EVOLUTION-LAST-USE", parse_last_use },
{ "X-EVOLUTION-USE-SCORE", parse_use_score },
{ XEV_LIST, parse_list },
{ XEV_LIST_SHOW_ADDRESSES, parse_list_show_addresses },
{ VCUniqueStringProp, parse_id }
@ -215,7 +224,8 @@ e_card_new (char *vcard)
return card;
}
ECard *e_card_duplicate(ECard *card)
ECard *
e_card_duplicate(ECard *card)
{
char *vcard = e_card_get_vcard(card);
ECard *new_card = e_card_new(vcard);
@ -223,6 +233,65 @@ ECard *e_card_duplicate(ECard *card)
return new_card;
}
static void
e_card_get_today (GDate *dt)
{
time_t now;
struct tm *now_tm;
if (dt == NULL)
return;
time (&now);
now_tm = localtime (&now);
g_date_set_dmy (dt, now_tm->tm_mday, now_tm->tm_mon + 1, now_tm->tm_year + 1900);
}
float
e_card_get_use_score(ECard *card)
{
GDate today, last_use;
gint days_since_last_use;
g_return_val_if_fail (card != NULL && E_IS_CARD (card), 0);
if (card->last_use == NULL)
return 0.0;
e_card_get_today (&today);
g_date_set_dmy (&last_use, card->last_use->day, card->last_use->month, card->last_use->year);
days_since_last_use = g_date_julian (&today) - g_date_julian (&last_use);
/* Apply a seven-day "grace period" to the use score decay. */
days_since_last_use -= 7;
if (days_since_last_use < 0)
days_since_last_use = 0;
return MAX (card->raw_use_score, 0) * exp (- days_since_last_use / 30.0);
}
void
e_card_touch(ECard *card)
{
GDate today;
double use_score;
g_return_if_fail (card != NULL && E_IS_CARD (card));
e_card_get_today (&today);
use_score = e_card_get_use_score (card);
if (card->last_use == NULL)
card->last_use = g_new (ECardDate, 1);
card->last_use->day = g_date_day (&today);
card->last_use->month = g_date_month (&today);
card->last_use->year = g_date_year (&today);
card->raw_use_score = use_score + 1.0;
}
/**
* e_card_get_id:
* @card: an #ECard
@ -252,6 +321,18 @@ e_card_set_id (ECard *card, const char *id)
card->id = g_strdup(id);
}
static gchar *
e_card_date_to_string (ECardDate *dt)
{
if (dt)
return g_strdup_printf ("%04d-%02d-%02d",
CLAMP(dt->year, 1000, 9999),
CLAMP(dt->month, 1, 12),
CLAMP(dt->day, 1, 31));
else
return NULL;
}
static VObject *
e_card_get_vobject (ECard *card)
{
@ -353,13 +434,8 @@ e_card_get_vobject (ECard *card)
}
if ( card->bday ) {
ECardDate date;
char *value;
date = *card->bday;
date.year = MIN(date.year, 9999);
date.month = MIN(date.month, 12);
date.day = MIN(date.day, 31);
value = g_strdup_printf("%04d-%02d-%02d", date.year, date.month, date.day);
value = e_card_date_to_string (card->bday);
addPropValue(vobj, VCBirthDateProp, value);
g_free(value);
}
@ -399,13 +475,8 @@ e_card_get_vobject (ECard *card)
addPropValue(vobj, "X-EVOLUTION-SPOUSE", card->spouse);
if ( card->anniversary ) {
ECardDate date;
char *value;
date = *card->anniversary;
date.year = MIN(date.year, 9999);
date.month = MIN(date.month, 12);
date.day = MIN(date.day, 31);
value = g_strdup_printf("%04d-%02d-%02d", date.year, date.month, date.day);
value = e_card_date_to_string (card->anniversary);
addPropValue(vobj, "X-EVOLUTION-ANNIVERSARY", value);
g_free(value);
}
@ -424,6 +495,20 @@ e_card_get_vobject (ECard *card)
addProp(noteprop, VCQuotedPrintableProp);
}
if (card->last_use) {
char *value;
value = e_card_date_to_string (card->last_use);
addPropValue (vobj, "X-EVOLUTION-LAST-USE", value);
g_free (value);
}
if (card->raw_use_score > 0) {
char *value;
value = g_strdup_printf ("%f", card->raw_use_score);
addPropValue (vobj, "X-EVOLUTION-USE-SCORE", value);
g_free (value);
}
if (card->categories) {
EIterator *iterator;
int length = 0;
@ -988,6 +1073,31 @@ parse_id(ECard *card, VObject *vobj)
assign_string(vobj, &(card->id));
}
static void
parse_last_use(ECard *card, VObject *vobj)
{
if ( vObjectValueType (vobj) ) {
char *str = fakeCString (vObjectUStringZValue (vobj));
if ( card->last_use )
g_free(card->last_use);
card->last_use = g_new(ECardDate, 1);
*(card->last_use) = e_card_date_from_string(str);
free(str);
}
}
static void
parse_use_score(ECard *card, VObject *vobj)
{
card->raw_use_score = 0;
if ( vObjectValueType (vobj) ) {
char *str = fakeCString (vObjectUStringZValue (vobj));
card->raw_use_score = MAX(0, atof (str));
free (str);
}
}
static void
parse_attribute(ECard *card, VObject *vobj)
{
@ -1099,6 +1209,10 @@ e_card_class_init (ECardClass *klass)
GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_ARBITRARY);
gtk_object_add_arg_type ("ECard::id",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ID);
gtk_object_add_arg_type ("ECard::last_use",
GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_LAST_USE);
gtk_object_add_arg_type ("ECard::use_score",
GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_USE_SCORE);
object_class->destroy = e_card_destroy;
@ -1818,6 +1932,18 @@ e_card_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
g_free(card->id);
card->id = g_strdup(GTK_VALUE_STRING(*arg));
break;
case ARG_LAST_USE:
g_free(card->last_use);
if (GTK_VALUE_POINTER (*arg)) {
card->last_use = g_new (ECardDate, 1);
memcpy (card->last_use, GTK_VALUE_POINTER (*arg), sizeof (ECardDate));
} else {
card->last_use = NULL;
}
break;
case ARG_USE_SCORE:
card->raw_use_score = GTK_VALUE_FLOAT(*arg);
break;
case ARG_EVOLUTION_LIST:
card->list = GTK_VALUE_BOOL(*arg);
break;
@ -1964,6 +2090,13 @@ e_card_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
case ARG_ID:
GTK_VALUE_STRING(*arg) = card->id;
break;
case ARG_LAST_USE:
GTK_VALUE_POINTER(*arg) = card->last_use;
break;
case ARG_USE_SCORE:
GTK_VALUE_FLOAT(*arg) = e_card_get_use_score (card);
break;
case ARG_EVOLUTION_LIST:
GTK_VALUE_BOOL(*arg) = card->list;
break;
@ -2013,6 +2146,8 @@ e_card_init (ECard *card)
card->list = FALSE;
card->list_show_addresses = FALSE;
card->arbitrary = NULL;
card->last_use = NULL;
card->raw_use_score = 0;
#if 0
c = g_new0 (ECard, 1);

View File

@ -34,12 +34,12 @@ struct _ECard {
char *file_as; /* The File As field. */
char *fname; /* The full name. */
ECardName *name; /* The structured name. */
EList *address; /* Delivery addresses (ECardDeliveryAddress *) */
EList *address_label; /* Delivery address labels
EList *address; /* Delivery addresses (ECardDeliveryAddress *) */
EList *address_label; /* Delivery address labels
* (ECardAddrLabel *) */
EList *phone; /* Phone numbers (ECardPhone *) */
EList *email; /* Email addresses (char *) */
EList *phone; /* Phone numbers (ECardPhone *) */
EList *email; /* Email addresses (char *) */
char *url; /* The person's web page. */
ECardDate *bday; /* The person's birthday. */
@ -67,13 +67,17 @@ struct _ECard {
gint timezone; /* number of minutes from UTC as an int */
EList *categories; /* Categories. */
ECardDate *last_use;
float raw_use_score;
EList *arbitrary; /* Arbitrary fields. */
EList *categories; /* Categories. */
guint32 wants_html : 1; /* Wants html mail. */
EList *arbitrary; /* Arbitrary fields. */
guint32 wants_html : 1; /* Wants html mail. */
guint32 wants_html_set : 1; /* Wants html mail. */
guint32 list : 1; /* If the card corresponds to a contact list */
guint32 list_show_addresses : 1; /* Whether to show the addresses
in the To: or Bcc: field */
@ -119,6 +123,9 @@ char *e_card_get_vcard (ECard
char *e_card_list_get_vcard (GList *list);
ECard *e_card_duplicate (ECard *card);
float e_card_get_use_score (ECard *card);
void e_card_touch (ECard *card);
/* Evolution List convenience functions */
gboolean e_card_evolution_list (ECard *card);
gboolean e_card_evolution_list_show_addresses(ECard *card);

View File

@ -26,13 +26,20 @@
*/
#include <config.h>
#include "e-destination.h"
#include <string.h>
#include <gtk/gtkobject.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#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);
}
}

View File

@ -30,6 +30,7 @@
#include <gtk/gtkobject.h>
#include <addressbook/backend/ebook/e-card.h>
#include <addressbook/backend/ebook/e-book.h>
#define E_TYPE_DESTINATION (e_destination_get_type ())
#define E_DESTINATION(o) (GTK_CHECK_CAST ((o), E_TYPE_DESTINATION, EDestination))
@ -40,6 +41,8 @@
typedef struct _EDestination EDestination;
typedef struct _EDestinationClass EDestinationClass;
typedef void (*EDestinationCardCallback) (EDestination *dest, ECard *card, gpointer closure);
struct _EDestinationPrivate;
struct _EDestination {
@ -64,6 +67,11 @@ void e_destination_set_card (EDestination *, ECard *card, gi
void e_destination_set_string (EDestination *, const gchar *string);
void e_destination_set_html_mail_pref (EDestination *, gboolean);
gboolean e_destination_has_card (const EDestination *);
gboolean e_destination_has_pending_card (const EDestination *);
void e_destination_use_card (EDestination *, EDestinationCardCallback cb, gpointer closure);
ECard *e_destination_get_card (const EDestination *);
gint e_destination_get_email_num (const EDestination *);
const gchar *e_destination_get_string (const EDestination *);
@ -79,16 +87,13 @@ gboolean e_destination_get_html_mail_pref (const EDestination *);
gchar *e_destination_get_address_textv (EDestination **);
gchar *e_destination_export (const EDestination *);
EDestination *e_destination_import (const gchar *str);
gchar *e_destination_exportv (EDestination **);
EDestination **e_destination_importv (const gchar *str);
void e_destination_touch (EDestination *);
#endif /* __E_DESTINATION_H__ */

View File

@ -26,9 +26,12 @@
*/
#include <config.h>
#include "e-select-names-completion.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gtk/gtksignal.h>
#include <libgnome/gnome-defs.h>
@ -39,7 +42,7 @@
#include <addressbook/backend/ebook/e-book-util.h>
#include <addressbook/backend/ebook/e-destination.h>
#include <addressbook/backend/ebook/e-card-simple.h>
#include "e-select-names-completion.h"
struct _ESelectNamesCompletionPrivate {
@ -99,9 +102,12 @@ static ECompletionMatch *
make_match (EDestination *dest, const gchar *menu_form, double score)
{
ECompletionMatch *match = g_new0 (ECompletionMatch, 1);
ECard *card = e_destination_get_card (dest);
e_completion_match_construct (match);
e_completion_match_set_text (match, e_destination_get_name (dest), menu_form);
match->sort_major = card ? floor (e_card_get_use_score (card)) : 0;
match->score = score;
match->sort_minor = e_destination_get_email_num (dest);
@ -357,20 +363,6 @@ match_name (ESelectNamesCompletion *comp, EDestination *dest)
score *= 100;
}
#if 0
/* This leads to some pretty counter-intuitive results, so I'm disabling it. */
email = e_destination_get_email (dest);
if (email) {
/* Do the same for the email address. */
gchar *at = strchr (email, '@');
len = at ? at-email : strlen (email);
if ((card->name->given && !g_utf8_strncasecmp (card->name->given, email, MIN (strlen (card->name->given), len)))
|| (card->name->family && !g_utf8_strncasecmp (card->name->family, email, MIN (strlen (card->name->family), len)))
|| (card->name->additional && !g_utf8_strncasecmp (card->name->additional, email, MIN (strlen (card->name->additional), len))))
score *= 100;
}
#endif
have_given = card->name->given && *card->name->given;
have_additional = card->name->additional && *card->name->additional;
have_family = card->name->family && *card->name->family;
@ -1048,7 +1040,7 @@ e_select_names_completion_begin (ECompletion *comp, const gchar *text, gint pos,
ECompletionMatch *match = g_new (ECompletionMatch, 1);
e_completion_match_construct (match);
e_completion_match_set_text (match, text, override[j].text[k]);
match->score = 1 / (k + 1);
match->score = 1 / (double) (k + 1);
e_completion_found_match (comp, match);
}

View File

@ -330,7 +330,10 @@ e_select_names_model_export_destinationv (ESelectNamesModel *model)
destv = g_new0 (EDestination *, len+1);
for (i=0, j = model->priv->data; j != NULL; j = g_list_next (j)) {
destv[i++] = E_DESTINATION (j->data);
EDestination *dest = E_DESTINATION (j->data);
if (dest)
destv[i++] = dest;
}
str = e_destination_exportv (destv);

View File

@ -71,7 +71,7 @@ static void
match_query_callback (ECard *card, ECard *match, ECardMatchType type, gpointer closure)
{
ECardMergingLookup *lookup = closure;
if (type == E_CARD_MATCH_NONE) {
if ((gint) type <= (gint) E_CARD_MATCH_VAGUE) {
doit (lookup);
g_free (lookup);
} else {