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:
committed by
Jon Trowbridge
parent
c187a911c8
commit
7c5dd95cd7
@ -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):
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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__ */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user