aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook
diff options
context:
space:
mode:
authorJon Trowbridge <trow@ximian.com>2001-06-06 01:53:04 +0800
committerJon Trowbridge <trow@src.gnome.org>2001-06-06 01:53:04 +0800
commit7b226f961c3340d85cff72b2b4485677ddfddb1d (patch)
tree4bde4031b9ed17473088a4dae76deb0f6af1d6bf /addressbook
parentf90d524db34db50df1baad3410162d4301de34c9 (diff)
downloadgsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar.gz
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar.bz2
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar.lz
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar.xz
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.tar.zst
gsoc2013-evolution-7b226f961c3340d85cff72b2b4485677ddfddb1d.zip
Change the completion handler to use the ECompletionMatch.
2001-06-05 Jon Trowbridge <trow@ximian.com> * gui/component/select-names/e-select-names-manager.c (completion_handler): Change the completion handler to use the ECompletionMatch. * gui/component/select-names/e-select-names-completion.c General changes to convert for ECompletionMatch use. (emailify_match): Use extra sort keys in ECompletionMatch to let us ensure that the primary email address is always the first option, the secondary comes second, etc. There was no nice way to do this previously. (match_name): Removed code that adjusted score based on similarities between the "real name" and the e-mail address. It seemed like a good idea at the time, but produced unexpected and confusing results. svn path=/trunk/; revision=10120
Diffstat (limited to 'addressbook')
-rw-r--r--addressbook/ChangeLog17
-rw-r--r--addressbook/gui/component/select-names/e-select-names-completion.c295
-rw-r--r--addressbook/gui/component/select-names/e-select-names-manager.c7
3 files changed, 163 insertions, 156 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog
index 00816b50b8..1ecae91348 100644
--- a/addressbook/ChangeLog
+++ b/addressbook/ChangeLog
@@ -1,3 +1,20 @@
+2001-06-05 Jon Trowbridge <trow@ximian.com>
+
+ * gui/component/select-names/e-select-names-manager.c
+ (completion_handler): Change the completion handler to use the
+ ECompletionMatch.
+
+ * gui/component/select-names/e-select-names-completion.c
+ General changes to convert for ECompletionMatch use.
+ (emailify_match): Use extra sort keys in ECompletionMatch to let
+ us ensure that the primary email address is always the first
+ option, the secondary comes second, etc. There was no nice way to
+ do this previously.
+ (match_name): Removed code that adjusted score based on
+ similarities between the "real name" and the e-mail address. It
+ seemed like a good idea at the time, but produced unexpected and
+ confusing results.
+
2001-06-04 Jon Trowbridge <trow@ximian.com>
* backend/ebook/e-card-compare.c: Added. Code for testing
diff --git a/addressbook/gui/component/select-names/e-select-names-completion.c b/addressbook/gui/component/select-names/e-select-names-completion.c
index dbe54e8a6b..8639ca5871 100644
--- a/addressbook/gui/component/select-names/e-select-names-completion.c
+++ b/addressbook/gui/component/select-names/e-select-names-completion.c
@@ -87,86 +87,88 @@ static FILE *out;
*/
typedef gchar *(*BookQuerySExp) (ESelectNamesCompletion *);
-typedef gchar *(*BookQueryMatchTester) (ESelectNamesCompletion *, EDestination *, double *score);
+typedef ECompletionMatch *(*BookQueryMatchTester) (ESelectNamesCompletion *, EDestination *);
-/*
- * Nickname query
- */
-
-static gchar *
-sexp_nickname (ESelectNamesCompletion *comp)
+static void
+our_match_destroy (ECompletionMatch *match)
{
- return g_strdup_printf ("(beginswith \"nickname\" \"%s\")", comp->priv->query_text);
-
+ gtk_object_unref (GTK_OBJECT (match->user_data));
}
-static gint
-e_utf8_strncasecmp (const gchar *p, const gchar *q, gint len)
+static ECompletionMatch *
+make_match (EDestination *dest, const gchar *menu_form, double score)
{
- if (p == NULL || q == NULL) {
- if (p) return +1;
- if (q) return -1;
- return 0;
- }
+ ECompletionMatch *match = g_new0 (ECompletionMatch, 1);
+ e_completion_match_construct (match);
- if (len < 0)
- len = G_MAXINT;
-
- while (*p && *q && len > 0) {
- gunichar cp = g_utf8_get_char (p);
- gunichar cq = g_utf8_get_char (q);
+ e_completion_match_set_text (match, e_destination_get_name (dest), menu_form);
+ match->score = score;
+ match->sort_minor = e_destination_get_email_num (dest);
- if (!(g_unichar_validate (cp)
- && g_unichar_validate (cq)))
- break;
+ match->user_data = dest;
+ gtk_object_ref (GTK_OBJECT (dest));
+
+ match->destroy = our_match_destroy;
- cp = g_unichar_tolower (cp);
- cq = g_unichar_tolower (cq);
+ return match;
+}
- if (cp != cq)
- return (cp < cq) - (cp > cq);
+static void
+emailify_match (ECompletionMatch *match)
+{
+ EDestination *dest = E_DESTINATION (match->user_data);
+ ECard *card = e_destination_get_card (dest);
+ const gchar *email = e_destination_get_email (dest);
+ const gchar *menu_txt = e_completion_match_get_menu_text (match);
+
+ if (card && card->email && e_list_length (card->email) > 1) {
- p = g_utf8_next_char (p);
- q = g_utf8_next_char (q);
- --len;
- }
+ if (email && strstr (menu_txt, email) == NULL) {
+ gchar *tmp = g_strdup_printf ("%s <%s>", menu_txt, email);
+ e_completion_match_set_text (match,
+ e_completion_match_get_match_text (match),
+ tmp);
+ g_free (tmp);
+ }
- if (len) {
- if (*p)
- return +1;
- else if (*q)
- return -1;
+ match->sort_minor = e_destination_get_email_num (dest);
}
-
- return 0;
}
-static gint
-e_utf8_strcasecmp (const gchar *p, const gchar *q)
+/*
+ * Nickname query
+ */
+
+static gchar *
+sexp_nickname (ESelectNamesCompletion *comp)
{
- return e_utf8_strncasecmp (p, q, -1);
-}
+ return g_strdup_printf ("(beginswith \"nickname\" \"%s\")", comp->priv->query_text);
+}
-static gchar *
-match_nickname (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_nickname (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *match = NULL;
gint len = strlen (comp->priv->query_text);
ECard *card = e_destination_get_card (dest);
+ double score;
if (card->nickname
- && !e_utf8_strncasecmp (comp->priv->query_text, card->nickname, len)) {
+ && !g_utf8_strncasecmp (comp->priv->query_text, card->nickname, len)) {
+ ECompletionMatch *match = g_new0 (ECompletionMatch, 1);
gchar *name = e_card_name_to_string (card->name);
gchar *str;
- *score = len * 10; /* nickname gives 10 points per matching character */
-
+ score = len * 10; /* nickname gives 10 points per matching character */
str = g_strdup_printf ("(%s) %s", card->nickname, name);
+
+ match = make_match (dest, str, score);
g_free (name);
- return str;
+ g_free (str);
}
- return NULL;
+ return match;
}
/*
@@ -179,23 +181,33 @@ sexp_email (ESelectNamesCompletion *comp)
return g_strdup_printf ("(beginswith \"email\" \"%s\")", comp->priv->query_text);
}
-static gchar *
-match_email (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_email (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *match;
gint len = strlen (comp->priv->query_text);
ECard *card = e_destination_get_card (dest);
const gchar *email = e_destination_get_email (dest);
+ double score;
- if (email && !e_utf8_strncasecmp (comp->priv->query_text, email, len)) {
+ if (email && !g_utf8_strncasecmp (comp->priv->query_text, email, len)) {
+
gchar *name, *str;
- *score = len * 2; /* 2 points for each matching character */
+
+ score = len * 2; /* 2 points for each matching character */
+
name = e_card_name_to_string (card->name);
if (name && *name)
str = g_strdup_printf ("<%s> %s", email, name);
else
str = g_strdup (email);
+
+ match = make_match (dest, str, score);
+
g_free (name);
- return str;
+ g_free (str);
+
+ return match;
}
return NULL;
@@ -235,6 +247,7 @@ sexp_name (ESelectNamesCompletion *comp)
g_free (cpy);
g_free (strv);
+
return query;
}
@@ -258,7 +271,7 @@ match_name_fragment (const gchar *fragment, const gchar *txt)
gint len = strlen (txt);
while (*fragment) {
- if (!e_utf8_strncasecmp (fragment, txt, len))
+ if (!g_utf8_strncasecmp (fragment, txt, len))
return TRUE;
while (*fragment && !isspace ((gint) *fragment))
@@ -270,14 +283,17 @@ match_name_fragment (const gchar *fragment, const gchar *txt)
return FALSE;
}
-static gchar *
-match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_name (ESelectNamesCompletion *comp, EDestination *dest)
{
+ ECompletionMatch *final_match = NULL;
+ gchar *menu_text = NULL;
ECard *card;
gchar *cpy, **strv;
const gchar *email;
gint len, i, match_len = 0;
gint match = 0, first_match = 0;
+ double score = 0;
gboolean have_given, have_additional, have_family;
card = e_destination_get_card (dest);
@@ -330,28 +346,31 @@ match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
}
- *score = match_len * 3; /* three points per match character */
+ score = match_len * 3; /* three points per match character */
if (card->nickname) {
/* We massively boost the score if the nickname exists and is the same as one of the "real" names. This keeps the
nickname from matching ahead of the real name for this card. */
len = strlen (card->nickname);
- if ((card->name->given && !e_utf8_strncasecmp (card->name->given, card->nickname, MIN (strlen (card->name->given), len)))
- || (card->name->family && !e_utf8_strncasecmp (card->name->family, card->nickname, MIN (strlen (card->name->family), len)))
- || (card->name->additional && !e_utf8_strncasecmp (card->name->additional, card->nickname, MIN (strlen (card->name->additional), len))))
- *score *= 100;
+ if ((card->name->given && !g_utf8_strncasecmp (card->name->given, card->nickname, MIN (strlen (card->name->given), len)))
+ || (card->name->family && !g_utf8_strncasecmp (card->name->family, card->nickname, MIN (strlen (card->name->family), len)))
+ || (card->name->additional && !g_utf8_strncasecmp (card->name->additional, card->nickname, MIN (strlen (card->name->additional), len))))
+ 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 && !e_utf8_strncasecmp (card->name->given, email, MIN (strlen (card->name->given), len)))
- || (card->name->family && !e_utf8_strncasecmp (card->name->family, email, MIN (strlen (card->name->family), len)))
- || (card->name->additional && !e_utf8_strncasecmp (card->name->additional, email, MIN (strlen (card->name->additional), len))))
- *score *= 100;
+ 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;
@@ -360,41 +379,46 @@ match_name (ESelectNamesCompletion *comp, EDestination *dest, double *score)
if (first_match == MATCHED_GIVEN_NAME) {
if (have_family)
- return g_strdup_printf ("%s %s", card->name->given, card->name->family);
+ menu_text = g_strdup_printf ("%s %s", card->name->given, card->name->family);
else
- return g_strdup_printf (card->name->given);
+ menu_text = g_strdup_printf (card->name->given);
} else if (first_match == MATCHED_ADDITIONAL_NAME) {
if (have_family) {
- return g_strdup_printf ("%s, %s%s%s",
- card->name->family,
- have_given ? card->name->given : "",
- have_given ? " " : "",
- card->name->additional);
+ menu_text = g_strdup_printf ("%s, %s%s%s",
+ card->name->family,
+ have_given ? card->name->given : "",
+ have_given ? " " : "",
+ card->name->additional);
} else {
- return g_strdup_printf ("%s%s%s",
- have_given ? card->name->given : "",
- have_given ? " " : "",
- card->name->additional);
+ menu_text = g_strdup_printf ("%s%s%s",
+ have_given ? card->name->given : "",
+ have_given ? " " : "",
+ card->name->additional);
}
} else if (first_match == MATCHED_FAMILY_NAME) {
if (have_given)
- return g_strdup_printf ("%s, %s %s",
- card->name->family,
- card->name->given,
- have_additional ? card->name->additional : "");
+ menu_text = g_strdup_printf ("%s, %s %s",
+ card->name->family,
+ card->name->given,
+ have_additional ? card->name->additional : "");
else
- return g_strdup_printf (card->name->family);
+ menu_text = g_strdup_printf (card->name->family);
+ }
+
+ if (menu_text) {
+ final_match = make_match (dest, menu_text, score);
+ g_free (menu_text);
}
- return NULL;
+ return final_match;
}
/*
@@ -407,8 +431,8 @@ sexp_initials (ESelectNamesCompletion *comp)
return NULL;
}
-static gchar *
-match_initials (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+match_initials (ESelectNamesCompletion *comp, EDestination *dest)
{
return NULL;
}
@@ -480,72 +504,38 @@ book_query_sexp (ESelectNamesCompletion *comp)
* Sweep across all of our query rules and find the best score/match
* string that applies to a given destination.
*/
-static gchar *
-book_query_score (ESelectNamesCompletion *comp, EDestination *dest, double *score)
+static ECompletionMatch *
+book_query_score (ESelectNamesCompletion *comp, EDestination *dest)
{
- double best_score = -1;
- gchar *best_string = NULL;
+ ECompletionMatch *best_match = NULL;
gint i;
- g_return_val_if_fail (score, NULL);
- *score = -1;
-
g_return_val_if_fail (comp && E_IS_SELECT_NAMES_COMPLETION (comp), NULL);
g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL);
for (i=0; i<book_query_count; ++i) {
- double this_score = -1;
- gchar *this_string = NULL;
+
+ ECompletionMatch *this_match = NULL;
if (book_queries[i].primary || !comp->priv->primary_only) {
if (book_queries[i].tester && e_destination_get_card (dest))
- this_string = book_queries[i].tester (comp, dest, &this_score);
- if (this_string) {
- if (this_score > best_score) {
- g_free (best_string);
- best_string = this_string;
- best_score = this_score;
+ this_match = book_queries[i].tester (comp, dest);
+
+ if (this_match) {
+ if (best_match == NULL || this_match->score > best_match->score) {
+ e_completion_match_unref (best_match);
+ best_match = this_match;
} else {
- g_free (this_string);
+ e_completion_match_unref (this_match);
}
}
}
}
- /* If this destination corresponds to a card w/ multiple addresses, and if the
- address isn't already in the string, append it. */
- if (best_string) {
- ECard *card = e_destination_get_card (dest);
- if (e_list_length (card->email) > 1) {
- ECardSimple *simp;
- const gchar *email = e_destination_get_email (dest);
- const gchar *simp_email;
-
- if (email && strstr (best_string, email) == NULL) {
- gchar *tmp = g_strdup_printf ("%s <%s>", best_string, email);
- g_free (best_string);
- best_string = tmp;
- }
+ if (best_match)
+ emailify_match (best_match);
- /* Give a small bonus to the primary/secondary e-mail address, so that they will
- always come in the correct order in the listing. */
- if (email) {
- simp = e_card_simple_new (card);
- simp_email = e_card_simple_get_email (simp, E_CARD_SIMPLE_EMAIL_ID_EMAIL);
- if (simp_email && !e_utf8_strcasecmp (simp_email, email)) {
- best_score += 0.2;
- }
- simp_email = e_card_simple_get_email (simp, E_CARD_SIMPLE_EMAIL_ID_EMAIL_2);
- if (simp_email && !e_utf8_strcasecmp (simp_email, email)) {
- best_score += 0.1;
- }
- gtk_object_unref (GTK_OBJECT (simp));
- }
- }
- }
-
- *score = best_score;
- return best_string;
+ return best_match;
}
static void
@@ -559,24 +549,20 @@ book_query_process_card_list (ESelectNamesCompletion *comp, const GList *cards)
for (i=0; i<e_list_length (card->email); ++i) {
EDestination *dest = e_destination_new ();
const gchar *email;
- gchar *match_text;
- double score = -1;
+ ECompletionMatch *match;
e_destination_set_card (dest, card, i);
email = e_destination_get_email (dest);
if (email && *email) {
- match_text = book_query_score (comp, dest, &score);
- if (match_text && score > 0) {
-
- e_completion_found_match_full (E_COMPLETION (comp), match_text, score, dest,
- (GtkDestroyNotify) gtk_object_unref);
+ match = book_query_score (comp, dest);
+ if (match && match->score > 0) {
+ e_completion_found_match (E_COMPLETION (comp), match);
} else {
- gtk_object_unref (GTK_OBJECT (dest));
+ e_completion_match_unref (match);
}
- g_free (match_text);
- } else {
+
gtk_object_unref (GTK_OBJECT (dest));
}
}
@@ -956,7 +942,7 @@ e_select_names_completion_do_query (ESelectNamesCompletion *comp, const gchar *q
can_reuse_cached_cards = (comp->priv->cached_query_text
&& (strlen (comp->priv->cached_query_text) <= strlen (clean))
- && !e_utf8_strncasecmp (comp->priv->cached_query_text, clean, strlen (comp->priv->cached_query_text)));
+ && !g_utf8_strncasecmp (comp->priv->cached_query_text, clean, strlen (comp->priv->cached_query_text)));
if (can_reuse_cached_cards) {
@@ -1012,7 +998,7 @@ search_override_check (SearchOverride *over, const gchar *text)
if (over == NULL || text == NULL)
return FALSE;
- return !e_utf8_strcasecmp (over->trigger, text);
+ return !g_utf8_strcasecmp (over->trigger, text);
}
@@ -1055,11 +1041,14 @@ e_select_names_completion_begin (ECompletion *comp, const gchar *text, gint pos,
if (search_override_check (&(override[j]), str)) {
gint k;
- for (k=0; override[j].text[k]; ++k)
- e_completion_found_match (comp, override[j].text[k]);
-
- if (out)
- fprintf (out, "aborting on override \"%s\"\n", override[j].trigger);
+ for (k=0; override[j].text[k]; ++k) {
+ 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;
+ e_completion_found_match (comp, match);
+ }
+
e_completion_end_search (comp);
return;
}
diff --git a/addressbook/gui/component/select-names/e-select-names-manager.c b/addressbook/gui/component/select-names/e-select-names-manager.c
index 6c06624918..9361cfa836 100644
--- a/addressbook/gui/component/select-names/e-select-names-manager.c
+++ b/addressbook/gui/component/select-names/e-select-names-manager.c
@@ -267,17 +267,18 @@ entry_destroyed(EEntry *entry, ESelectNamesManager *manager)
}
static void
-completion_handler (EEntry *entry, const gchar *text, gpointer user_data)
+completion_handler (EEntry *entry, ECompletionMatch *match)
{
ESelectNamesModel *snm;
EDestination *dest;
gint i, pos, start_pos, len;
- if (user_data == NULL)
+ if (match == NULL || match->user_data == NULL)
return;
+
snm = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
- dest = E_DESTINATION (user_data);
+ dest = E_DESTINATION (match->user_data);
/* Sometimes I really long for garbage collection. Reference
counting makes you feel 31337, but sometimes it is just a