Hook up some magic to (basically) cardify an entry on focus-out. (What we

2001-08-09  Jon Trowbridge  <trow@ximian.com>

	* gui/component/select-names/e-select-names-manager.c
	(e_select_names_manager_create_entry): Hook up some magic to
	(basically) cardify an entry on focus-out.  (What we do is actually
	more complicated than that.)

	* gui/component/select-names/e-select-names-bonobo.c
	(entry_set_property_fn): After we set an entry's text, try to
	cardify it.  We need to do this so that (for example) reply
	e-mails get properly cardified.

	* gui/component/select-names/e-select-names-model.c
	(e_select_names_model_duplicate): Use e_select_names_model_append,
	rather than manipulating lists directly.
	(e_select_names_model_insert): Connect "changed" signal proxy for
	added EDestination.
	(e_select_names_model_append): Ditto.
	(e_select_names_model_replace): Ditto, and disconnect signals for
	replaced EDestination.
	(e_select_names_model_delete): Ditto on the disconnection.
	(e_select_names_model_delete_all): Ditto.
	(e_select_names_model_cardify): Added.  Try to cardify a specified
	EDestination.
	(e_select_names_model_cancel_cardify): Added.  Cancel the pending
	cardification of a single EDestination.
	(e_select_names_model_cardify_all): Added.  Cardify all of the
	EDestinations in the model.
	(e_select_names_model_cancel_cardify_all): Added.  Cancel's any
	and all pending cardifications.

	* backend/ebook/e-destination.c (e_destination_class_init): Added
	"changed" and "cardified" signals.
	(e_destination_freeze): Added (static).
	(e_destination_thaw): Added (static).
	(e_destination_clear_card): Reset allow_cardify and
	cannot_cardify, cancel any pending cardifications, and emit the
	"changed" signal.
	(e_destination_clear_strings): Emit the "changed" signal.
	(e_destination_clear): Do freeze/thaw to prevent multiple signal
	emissions.
	(e_destination_set_card): Check that the card we are setting is
	not equal to the current card, and emit the "changed" signal if we
	are actually changing.
	(e_destination_set_card_uri): Emit "changed" signal, if necessary.
	(e_destination_set_name): Emit "changed" signal, if necessary.
	(e_destination_set_email): Emit "changed" signal, if necessary.
	(e_destination_set_html_mail_pref): Emit "changed" signal, if
	necessary.
	(use_card_cb): If we've just loaded/set the ECard, emit the
	"changed" signal.
	(e_destination_set_raw): Emit "changed" signal, if necessary.
	(e_destination_allow_cardification): Added.
	(e_destination_set_allow_cardification): Added.
	(e_destination_cardify): Added.  Tries to automatically convert
	a string-based EDestination to one based on an ECard.
	(e_destination_cardify_delayed): Added.  Cardifies in a timeout.
	(e_destination_cancel_cardify): Added.  Cancels any pending
	cardifications.
	(e_destination_xml_decode): Added freeze/thaw.

	* backend/ebook/e-book-util.c (e_book_nickname_query): Added.  A
	canned simple query for nicknames.

	* backend/ebook/e-card.c (e_card_email_find_number): Added.  Given
	a card and an string containing an email address, return the index
	number of the address inside of the card, or -1 if the address is
	not found.

svn path=/trunk/; revision=11837
This commit is contained in:
Jon Trowbridge
2001-08-09 18:07:35 +00:00
committed by Jon Trowbridge
parent 1844cac7c1
commit 07fbf1a035
12 changed files with 682 additions and 33 deletions

View File

@ -1,3 +1,72 @@
2001-08-09 Jon Trowbridge <trow@ximian.com>
* gui/component/select-names/e-select-names-manager.c
(e_select_names_manager_create_entry): Hook up some magic to
(basically) cardify an entry on focus-out. (What we do is actually
more complicated than that.)
* gui/component/select-names/e-select-names-bonobo.c
(entry_set_property_fn): After we set an entry's text, try to
cardify it. We need to do this so that (for example) reply
e-mails get properly cardified.
* gui/component/select-names/e-select-names-model.c
(e_select_names_model_duplicate): Use e_select_names_model_append,
rather than manipulating lists directly.
(e_select_names_model_insert): Connect "changed" signal proxy for
added EDestination.
(e_select_names_model_append): Ditto.
(e_select_names_model_replace): Ditto, and disconnect signals for
replaced EDestination.
(e_select_names_model_delete): Ditto on the disconnection.
(e_select_names_model_delete_all): Ditto.
(e_select_names_model_cardify): Added. Try to cardify a specified
EDestination.
(e_select_names_model_cancel_cardify): Added. Cancel the pending
cardification of a single EDestination.
(e_select_names_model_cardify_all): Added. Cardify all of the
EDestinations in the model.
(e_select_names_model_cancel_cardify_all): Added. Cancel's any
and all pending cardifications.
* backend/ebook/e-destination.c (e_destination_class_init): Added
"changed" and "cardified" signals.
(e_destination_freeze): Added (static).
(e_destination_thaw): Added (static).
(e_destination_clear_card): Reset allow_cardify and
cannot_cardify, cancel any pending cardifications, and emit the
"changed" signal.
(e_destination_clear_strings): Emit the "changed" signal.
(e_destination_clear): Do freeze/thaw to prevent multiple signal
emissions.
(e_destination_set_card): Check that the card we are setting is
not equal to the current card, and emit the "changed" signal if we
are actually changing.
(e_destination_set_card_uri): Emit "changed" signal, if necessary.
(e_destination_set_name): Emit "changed" signal, if necessary.
(e_destination_set_email): Emit "changed" signal, if necessary.
(e_destination_set_html_mail_pref): Emit "changed" signal, if
necessary.
(use_card_cb): If we've just loaded/set the ECard, emit the
"changed" signal.
(e_destination_set_raw): Emit "changed" signal, if necessary.
(e_destination_allow_cardification): Added.
(e_destination_set_allow_cardification): Added.
(e_destination_cardify): Added. Tries to automatically convert
a string-based EDestination to one based on an ECard.
(e_destination_cardify_delayed): Added. Cardifies in a timeout.
(e_destination_cancel_cardify): Added. Cancels any pending
cardifications.
(e_destination_xml_decode): Added freeze/thaw.
* backend/ebook/e-book-util.c (e_book_nickname_query): Added. A
canned simple query for nicknames.
* backend/ebook/e-card.c (e_card_email_find_number): Added. Given
a card and an string containing an email address, return the index
number of the address inside of the card, or -1 if the address is
not found.
2001-08-09 Chris Toshok <toshok@ximian.com>
[ Fixes ximian bugs #5080, #6021, #6704, #6705 ]

View File

@ -507,6 +507,56 @@ e_book_name_and_email_query (EBook *book,
return tag;
}
/*
* Simple nickname query
*/
typedef struct _NicknameQueryInfo NicknameQueryInfo;
struct _NicknameQueryInfo {
gchar *nickname;
EBookSimpleQueryCallback cb;
gpointer closure;
};
static void
nickname_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
{
NicknameQueryInfo *info = closure;
if (info->cb)
info->cb (book, status, cards, info->closure);
g_free (info->nickname);
g_free (info);
}
guint
e_book_nickname_query (EBook *book,
const char *nickname,
EBookSimpleQueryCallback cb,
gpointer closure)
{
NicknameQueryInfo *info;
gchar *query;
guint retval;
g_return_val_if_fail (E_IS_BOOK (book), 0);
g_return_val_if_fail (nickname && *nickname, 0);
info = g_new0 (NicknameQueryInfo, 1);
info->nickname = g_strdup (nickname);
info->cb = cb;
info->closure = closure;
query = g_strdup_printf ("(is \"nickname\" \"%s\")", info->nickname);
retval = e_book_simple_query (book, query, nickname_cb, info);
g_free (query);
return retval;
}
/*
* Convenience routine to check for addresses in the local address book.
*/

View File

@ -61,6 +61,11 @@ guint e_book_name_and_email_query (EBook *book,
EBookSimpleQueryCallback cb,
gpointer closure);
guint e_book_nickname_query (EBook *book,
const char *nickname,
EBookSimpleQueryCallback cb,
gpointer closure);
/* Returns the ECard associated to email in the callback,
or NULL if no match is found in the local address book. */
void e_book_query_address_locally (const gchar *email,

View File

@ -1813,6 +1813,29 @@ e_card_email_match_string (const ECard *card, const gchar *str)
return FALSE;
}
gint
e_card_email_find_number (const ECard *card, const gchar *email)
{
EIterator *iter;
gint count = 0;
g_return_val_if_fail (E_IS_CARD (card), -1);
g_return_val_if_fail (email != NULL, -1);
iter = e_list_get_iterator (card->email);
for (e_iterator_reset (iter); e_iterator_is_valid (iter); e_iterator_next (iter)) {
if (!strcmp (e_iterator_get (iter), email))
goto finished;
++count;
}
count = -1;
finished:
gtk_object_unref (GTK_OBJECT (iter));
return count;
}
/*
* ECard lifecycle management and vCard loading/saving.
*/

View File

@ -174,6 +174,8 @@ void e_card_arbitrary_free (ECardArbitrary
/* ECard email manipulation */
gboolean e_card_email_match_string (const ECard *card,
const gchar *str);
gint e_card_email_find_number (const ECard *card,
const gchar *email);
/* Specialized functionality */
GList *e_card_load_cards_from_file (const char *filename);

View File

@ -32,6 +32,7 @@
#include <ctype.h>
#include <string.h>
#include <gtk/gtkobject.h>
#include <gtk/gtkmain.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include "e-book.h"
@ -41,6 +42,14 @@
#include <gnome-xml/xmlmemory.h>
#include <camel/camel-internet-address.h>
enum {
CHANGED,
CARDIFIED,
LAST_SIGNAL
};
guint e_destination_signals[LAST_SIGNAL] = { 0 };
struct _EDestinationPrivate {
gchar *raw;
@ -57,6 +66,15 @@ struct _EDestinationPrivate {
gboolean wants_html_mail;
GList *list_dests;
gboolean has_been_cardified;
gboolean allow_cardify;
gboolean cannot_cardify;
guint pending_cardification;
EBook *cardify_book;
gint freeze_count;
gboolean pending_change;
};
static void e_destination_clear_card (EDestination *);
@ -70,6 +88,10 @@ e_destination_destroy (GtkObject *obj)
EDestination *dest = E_DESTINATION (obj);
e_destination_clear (dest);
if (dest->priv->cardify_book)
gtk_object_unref (GTK_OBJECT (dest->priv->cardify_book));
g_free (dest->priv);
if (parent_class->destroy)
@ -84,12 +106,34 @@ e_destination_class_init (EDestinationClass *klass)
parent_class = GTK_OBJECT_CLASS (gtk_type_class (GTK_TYPE_OBJECT));
object_class->destroy = e_destination_destroy;
e_destination_signals[CHANGED] =
gtk_signal_new ("changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (EDestinationClass, changed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
e_destination_signals[CARDIFIED] =
gtk_signal_new ("cardified",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (EDestinationClass, cardified),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, e_destination_signals, LAST_SIGNAL);
}
static void
e_destination_init (EDestination *dest)
{
dest->priv = g_new0 (struct _EDestinationPrivate, 1);
dest->priv->allow_cardify = TRUE;
dest->priv->cannot_cardify = FALSE;
dest->priv->pending_cardification = 0;
}
GtkType
@ -120,6 +164,38 @@ e_destination_new (void)
return E_DESTINATION (gtk_type_new (E_TYPE_DESTINATION));
}
static void
e_destination_freeze (EDestination *dest)
{
g_return_if_fail (E_IS_DESTINATION (dest));
g_return_if_fail (dest->priv->freeze_count >= 0);
++dest->priv->freeze_count;
}
static void
e_destination_thaw (EDestination *dest)
{
g_return_if_fail (E_IS_DESTINATION (dest));
g_return_if_fail (dest->priv->freeze_count > 0);
--dest->priv->freeze_count;
if (dest->priv->freeze_count == 0 && dest->priv->pending_change)
e_destination_changed (dest);
}
void
e_destination_changed (EDestination *dest)
{
if (dest->priv->freeze_count == 0) {
gtk_signal_emit (GTK_OBJECT (dest), e_destination_signals[CHANGED]);
dest->priv->pending_change = FALSE;
dest->priv->cannot_cardify = FALSE;
} else {
dest->priv->pending_change = TRUE;
}
}
EDestination *
e_destination_copy (const EDestination *dest)
{
@ -166,6 +242,13 @@ e_destination_clear_card (EDestination *dest)
g_list_foreach (dest->priv->list_dests, (GFunc) gtk_object_unref, NULL);
g_list_free (dest->priv->list_dests);
dest->priv->list_dests = NULL;
dest->priv->allow_cardify = TRUE;
dest->priv->cannot_cardify = FALSE;
e_destination_cancel_cardify (dest);
e_destination_changed (dest);
}
static void
@ -182,6 +265,8 @@ e_destination_clear_strings (EDestination *dest)
g_free (dest->priv->addr);
dest->priv->addr = NULL;
e_destination_changed (dest);
}
void
@ -189,8 +274,12 @@ e_destination_clear (EDestination *dest)
{
g_return_if_fail (dest && E_IS_DESTINATION (dest));
e_destination_freeze (dest);
e_destination_clear_card (dest);
e_destination_clear_strings (dest);
e_destination_thaw (dest);
}
gboolean
@ -215,12 +304,17 @@ 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));
e_destination_clear (dest);
if (dest->priv->card != card || dest->priv->card_email_num != email_num) {
dest->priv->card = card;
gtk_object_ref (GTK_OBJECT (dest->priv->card));
e_destination_clear (dest);
dest->priv->card_email_num = email_num;
dest->priv->card = card;
gtk_object_ref (GTK_OBJECT (dest->priv->card));
dest->priv->card_email_num = email_num;
e_destination_changed (dest);
}
}
void
@ -228,16 +322,23 @@ e_destination_set_card_uri (EDestination *dest, const gchar *uri, gint email_num
{
g_return_if_fail (dest && E_IS_DESTINATION (dest));
g_return_if_fail (uri != NULL);
g_free (dest->priv->card_uri);
dest->priv->card_uri = g_strdup (uri);
dest->priv->card_email_num = email_num;
/* If we already have a card, remove it unless it's uri matches the one
we just set. */
if (dest->priv->card && strcmp (uri, e_card_get_uri (dest->priv->card))) {
gtk_object_unref (GTK_OBJECT (dest->priv->card));
dest->priv->card = NULL;
if (dest->priv->card_uri == NULL
|| strcmp (dest->priv->card_uri, uri)
|| dest->priv->card_email_num != email_num) {
g_free (dest->priv->card_uri);
dest->priv->card_uri = g_strdup (uri);
dest->priv->card_email_num = email_num;
/* If we already have a card, remove it unless it's uri matches the one
we just set. */
if (dest->priv->card && strcmp (uri, e_card_get_uri (dest->priv->card))) {
gtk_object_unref (GTK_OBJECT (dest->priv->card));
dest->priv->card = NULL;
}
e_destination_changed (dest);
}
}
@ -247,12 +348,17 @@ e_destination_set_name (EDestination *dest, const gchar *name)
g_return_if_fail (dest && E_IS_DESTINATION (dest));
g_return_if_fail (name != NULL);
g_free (dest->priv->name);
dest->priv->name = g_strdup (name);
if (dest->priv->name == NULL || strcmp (dest->priv->name, name)) {
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
g_free (dest->priv->name);
dest->priv->name = g_strdup (name);
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
}
e_destination_changed (dest);
}
}
@ -262,12 +368,17 @@ e_destination_set_email (EDestination *dest, const gchar *email)
g_return_if_fail (dest && E_IS_DESTINATION (dest));
g_return_if_fail (email != NULL);
g_free (dest->priv->email);
dest->priv->email = g_strdup (email);
if (dest->priv->email == NULL || strcmp (dest->priv->email, email)) {
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
g_free (dest->priv->email);
dest->priv->email = g_strdup (email);
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
}
e_destination_changed (dest);
}
}
@ -275,9 +386,12 @@ void
e_destination_set_html_mail_pref (EDestination *dest, gboolean x)
{
g_return_if_fail (dest && E_IS_DESTINATION (dest));
dest->priv->html_mail_override = TRUE;
dest->priv->wants_html_mail = x;
if (dest->priv->wants_html_mail != x) {
dest->priv->wants_html_mail = x;
e_destination_changed (dest);
}
}
gboolean
@ -311,6 +425,7 @@ use_card_cb (ECard *card, gpointer closure)
uc->dest->priv->card = card;
gtk_object_ref (GTK_OBJECT (uc->dest->priv->card));
e_destination_changed (uc->dest);
}
@ -520,10 +635,16 @@ e_destination_set_raw (EDestination *dest, const gchar *raw)
g_return_if_fail (E_IS_DESTINATION (dest));
g_return_if_fail (raw != NULL);
e_destination_clear (dest);
if (dest->priv->raw == NULL || strcmp (dest->priv->raw, raw)) {
dest->priv->raw = g_strdup (raw);
e_destination_freeze (dest);
e_destination_clear (dest);
dest->priv->raw = g_strdup (raw);
e_destination_changed (dest);
e_destination_thaw (dest);
}
}
const gchar *
@ -582,6 +703,202 @@ e_destination_get_html_mail_pref (const EDestination *dest)
return dest->priv->card->wants_html;
}
gboolean
e_destination_allow_cardification (const EDestination *dest)
{
g_return_val_if_fail (E_IS_DESTINATION (dest), FALSE);
return dest->priv->allow_cardify;
}
void
e_destination_set_allow_cardification (EDestination *dest, gboolean x)
{
g_return_if_fail (E_IS_DESTINATION (dest));
dest->priv->allow_cardify = x;
}
static void
set_cardify_book (EDestination *dest, EBook *book)
{
if (dest->priv->cardify_book && dest->priv->cardify_book != book) {
gtk_object_unref (GTK_OBJECT (dest->priv->cardify_book));
}
dest->priv->cardify_book = book;
if (book)
gtk_object_ref (GTK_OBJECT (book));
}
static void
name_and_email_simple_query_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
{
EDestination *dest = E_DESTINATION (closure);
if (status == E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS && g_list_length ((GList *) cards) == 1) {
ECard *card = E_CARD (cards->data);
gint email_num = e_card_email_find_number (card, e_destination_get_email (dest));
if (email_num >= 0) {
dest->priv->has_been_cardified = TRUE;
e_destination_set_card (dest, E_CARD (cards->data), email_num);
gtk_signal_emit (GTK_OBJECT (dest), e_destination_signals[CARDIFIED]);
}
}
if (!dest->priv->has_been_cardified) {
dest->priv->cannot_cardify = TRUE;
}
gtk_object_unref (GTK_OBJECT (dest));
}
static void
nickname_simple_query_cb (EBook *book, EBookSimpleQueryStatus status, const GList *cards, gpointer closure)
{
EDestination *dest = E_DESTINATION (closure);
if (status == E_BOOK_SIMPLE_QUERY_STATUS_SUCCESS && g_list_length ((GList *) cards) == 1) {
dest->priv->has_been_cardified = TRUE;
e_destination_set_card (dest, E_CARD (cards->data), 0); /* Uses primary e-mail by default. */
gtk_signal_emit (GTK_OBJECT (dest), e_destination_signals[CARDIFIED]);
gtk_object_unref (GTK_OBJECT (dest));
} else {
e_book_name_and_email_query (book,
e_destination_get_name (dest),
e_destination_get_email (dest),
name_and_email_simple_query_cb,
dest);
}
}
static void
launch_cardify_query (EDestination *dest)
{
if (strchr (e_destination_get_textrep (dest), '@') == NULL) {
/* If it doesn't look like an e-mail address, see if it is a nickname. */
e_book_nickname_query (dest->priv->cardify_book,
e_destination_get_textrep (dest),
nickname_simple_query_cb,
dest);
} else {
e_book_name_and_email_query (dest->priv->cardify_book,
e_destination_get_name (dest),
e_destination_get_email (dest),
name_and_email_simple_query_cb,
dest);
}
}
static void
use_local_book_cb (EBook *book, gpointer closure)
{
EDestination *dest = E_DESTINATION (closure);
if (dest->priv->cardify_book == NULL) {
dest->priv->cardify_book = book;
gtk_object_ref (GTK_OBJECT (book));
}
launch_cardify_query (dest);
}
void
e_destination_cardify (EDestination *dest, EBook *book)
{
g_return_if_fail (E_IS_DESTINATION (dest));
g_return_if_fail (book == NULL || E_IS_BOOK (book));
if (e_destination_is_evolution_list (dest))
return;
if (e_destination_contains_card (dest))
return;
if (!dest->priv->allow_cardify)
return;
if (dest->priv->cannot_cardify)
return;
e_destination_cancel_cardify (dest);
set_cardify_book (dest, book);
/* Handle the case of an EDestination containing a card URL */
if (e_destination_contains_card (dest)) {
e_destination_use_card (dest, NULL, NULL);
return;
}
/* If we have a book ready, proceed. We hold a reference to ourselves
until our query is complete. */
gtk_object_ref (GTK_OBJECT (dest));
if (dest->priv->cardify_book != NULL) {
launch_cardify_query (dest);
} else {
e_book_use_local_address_book (use_local_book_cb, dest);
}
}
static gint
do_cardify_delayed (gpointer ptr)
{
EDestination *dest = E_DESTINATION (ptr);
e_destination_cardify (dest, dest->priv->cardify_book);
return FALSE;
}
void
e_destination_cardify_delayed (EDestination *dest, EBook *book, gint delay)
{
g_return_if_fail (E_IS_DESTINATION (dest));
g_return_if_fail (book == NULL || E_IS_BOOK (book));
if (delay < 0)
delay = 500;
e_destination_cancel_cardify (dest);
set_cardify_book (dest, book);
dest->priv->pending_cardification = gtk_timeout_add (delay, do_cardify_delayed, dest);
}
void
e_destination_cancel_cardify (EDestination *dest)
{
g_return_if_fail (E_IS_DESTINATION (dest));
if (dest->priv->pending_cardification) {
gtk_timeout_remove (dest->priv->pending_cardification);
dest->priv->pending_cardification = 0;
}
}
#if 0
void
e_destination_uncardify (EDestination *dest)
{
g_return_if_fail (E_IS_DESTINATION (dest));
g_assert_not_reached ();
}
#endif
/*
* Destination import/export
*/
gchar *
e_destination_get_address_textv (EDestination **destv)
{
@ -754,6 +1071,8 @@ e_destination_xml_decode (EDestination *dest, xmlNodePtr node)
node = node->next;
}
e_destination_freeze (dest);
e_destination_clear (dest);
@ -765,6 +1084,8 @@ e_destination_xml_decode (EDestination *dest, xmlNodePtr node)
e_destination_set_card_uri (dest, card_uri, email_num);
if (list_dests)
dest->priv->list_dests = list_dests;
e_destination_thaw (dest);
return TRUE;
}

View File

@ -54,12 +54,16 @@ struct _EDestination {
struct _EDestinationClass {
GtkObjectClass parent_class;
void (*changed) (EDestination *dest);
void (*cardified) (EDestination *dest);
};
GtkType e_destination_get_type (void);
EDestination *e_destination_new (void);
void e_destination_changed (EDestination *);
EDestination *e_destination_copy (const EDestination *);
void e_destination_clear (EDestination *);
@ -94,6 +98,16 @@ gboolean e_destination_is_evolution_list (const EDestination *);
/* If true, they want HTML mail. */
gboolean e_destination_get_html_mail_pref (const EDestination *);
gboolean e_destination_allow_cardification (const EDestination *);
void e_destination_set_allow_cardification (EDestination *, gboolean);
void e_destination_cardify (EDestination *, EBook *);
void e_destination_cardify_delayed (EDestination *, EBook *, gint delay); /* delay < 0: "default" */
void e_destination_cancel_cardify (EDestination *);
#if 0
void e_destination_uncardify (EDestination *);
#endif
gchar *e_destination_get_address_textv (EDestination **);
xmlNodePtr e_destination_xml_encode (const EDestination *dest);

View File

@ -132,8 +132,15 @@ entry_set_property_fn (BonoboPropertyBag *bag,
switch (arg_id) {
case ENTRY_PROPERTY_ID_TEXT:
e_entry_set_text (E_ENTRY (w), BONOBO_ARG_GET_STRING (arg));
break;
{
ESelectNamesModel *model;
model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (w), "select_names_model"));
g_assert (model != NULL);
e_entry_set_text (E_ENTRY (w), BONOBO_ARG_GET_STRING (arg));
e_select_names_model_cardify_all (model, NULL, 0);
break;
}
case ENTRY_PROPERTY_ID_DESTINATIONS:
{

View File

@ -368,6 +368,38 @@ popup_cb (EEntry *entry, GdkEventButton *ev, gint pos, ESelectNamesModel *model)
e_select_names_popup (model, ev, pos);
}
static gint
focus_in_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
EEntry *entry = E_ENTRY (user_data);
ESelectNamesModel *model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
e_select_names_model_cancel_cardify_all (model);
return FALSE;
}
static gint
focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
EEntry *entry = E_ENTRY (user_data);
ESelectNamesModel *model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
if (!e_entry_completion_popup_is_visible (entry))
e_select_names_model_cardify_all (model, NULL, 0);
return FALSE;
}
static void
completion_popup_cb (EEntry *entry, gint visible, gpointer user_data)
{
ESelectNamesModel *model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
if (!visible && !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->canvas)))
e_select_names_model_cardify_all (model, NULL, 0);
}
GtkWidget *
e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *id)
{
@ -389,6 +421,19 @@ e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *i
GTK_SIGNAL_FUNC (popup_cb),
section->model);
gtk_signal_connect (GTK_OBJECT (eentry->canvas),
"focus_in_event",
GTK_SIGNAL_FUNC (focus_in_cb),
eentry);
gtk_signal_connect (GTK_OBJECT (eentry->canvas),
"focus_out_event",
GTK_SIGNAL_FUNC (focus_out_cb),
eentry);
gtk_signal_connect (GTK_OBJECT (eentry),
"completion_popup",
GTK_SIGNAL_FUNC (completion_popup_cb),
NULL);
entry = g_new (ESelectNamesManagerEntry, 1);
entry->entry = eentry;
entry->id = (char *)id;

View File

@ -219,6 +219,12 @@ e_select_names_model_changed (ESelectNamesModel *model)
gtk_signal_emit (GTK_OBJECT(model), e_select_names_model_signals[E_SELECT_NAMES_MODEL_CHANGED]);
}
static void
destination_changed_proxy (EDestination *dest, gpointer closure)
{
e_select_names_model_changed (E_SELECT_NAMES_MODEL (closure));
}
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
ESelectNamesModel *
@ -240,7 +246,7 @@ e_select_names_model_duplicate (ESelectNamesModel *old)
for (iter = old->priv->data; iter != NULL; iter = g_list_next (iter)) {
EDestination *dup = e_destination_copy (E_DESTINATION (iter->data));
model->priv->data = g_list_append (model->priv->data, dup);
e_select_names_model_append (model, dup);
}
model->priv->limit = old->priv->limit;
@ -444,6 +450,21 @@ e_select_names_model_get_string (ESelectNamesModel *model, gint index)
return dest ? e_destination_get_textrep (dest) : "";
}
static void
connect_destination (ESelectNamesModel *model, EDestination *dest)
{
gtk_signal_connect (GTK_OBJECT (dest),
"changed",
destination_changed_proxy,
model);
}
static void
disconnect_destination (ESelectNamesModel *model, EDestination *dest)
{
gtk_signal_disconnect_by_func (GTK_OBJECT (dest), destination_changed_proxy, model);
}
void
e_select_names_model_insert (ESelectNamesModel *model, gint index, EDestination *dest)
{
@ -458,6 +479,8 @@ e_select_names_model_insert (ESelectNamesModel *model, gint index, EDestination
return;
}
connect_destination (model, dest);
model->priv->data = g_list_insert (model->priv->data, dest, index);
gtk_object_ref (GTK_OBJECT (dest));
@ -478,6 +501,8 @@ e_select_names_model_append (ESelectNamesModel *model, EDestination *dest)
return;
}
connect_destination (model, dest);
model->priv->data = g_list_append (model->priv->data, dest);
gtk_object_ref (GTK_OBJECT (dest));
@ -503,6 +528,8 @@ e_select_names_model_replace (ESelectNamesModel *model, gint index, EDestination
if (model->priv->data == NULL) {
connect_destination (model, dest);
model->priv->data = g_list_append (model->priv->data, dest);
gtk_object_ref (GTK_OBJECT (dest));
gtk_object_sink (GTK_OBJECT (dest));
@ -513,6 +540,9 @@ e_select_names_model_replace (ESelectNamesModel *model, gint index, EDestination
if (node->data != dest) {
disconnect_destination (model, E_DESTINATION (node->data));
connect_destination (model, dest);
old_str = e_destination_get_textrep (E_DESTINATION (node->data));
old_strlen = old_str ? strlen (old_str) : 0;
@ -540,6 +570,7 @@ e_select_names_model_delete (ESelectNamesModel *model, gint index)
g_return_if_fail (0 <= index && index < g_list_length (model->priv->data));
node = g_list_nth (model->priv->data, index);
disconnect_destination (model, E_DESTINATION (node->data));
gtk_object_unref (GTK_OBJECT (node->data));
model->priv->data = g_list_remove_link (model->priv->data, node);
@ -565,8 +596,10 @@ e_select_names_model_clean (ESelectNamesModel *model)
dest = iter->data ? E_DESTINATION (iter->data) : NULL;
if (dest == NULL || e_destination_is_empty (dest)) {
if (dest)
if (dest) {
disconnect_destination (model, dest);
gtk_object_unref (GTK_OBJECT (dest));
}
model->priv->data = g_list_remove_link (model->priv->data, iter);
g_list_free_1 (iter);
changed = TRUE;
@ -579,12 +612,19 @@ e_select_names_model_clean (ESelectNamesModel *model)
e_select_names_model_changed (model);
}
static void
delete_all_iter (gpointer data, gpointer closure)
{
disconnect_destination (E_SELECT_NAMES_MODEL (closure), E_DESTINATION (data));
gtk_object_unref (GTK_OBJECT (data));
}
void
e_select_names_model_delete_all (ESelectNamesModel *model)
{
g_return_if_fail (model != NULL && E_IS_SELECT_NAMES_MODEL (model));
g_list_foreach (model->priv->data, (GFunc) gtk_object_unref, NULL);
g_list_foreach (model->priv->data, delete_all_iter, model);
g_list_free (model->priv->data);
model->priv->data = NULL;
@ -692,3 +732,70 @@ e_select_names_model_text_pos (ESelectNamesModel *model, gint pos, gint *index,
if (length)
*length = len;
}
void
e_select_names_model_cardify (ESelectNamesModel *model, EBook *book, gint index, gint delay)
{
EDestination *dest;
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (book == NULL || E_IS_BOOK (book));
g_return_if_fail (0 <= index && index < g_list_length (model->priv->data));
dest = E_DESTINATION (g_list_nth_data (model->priv->data, index));
if (!e_destination_is_empty (dest)) {
if (delay > 0)
e_destination_cardify_delayed (dest, book, delay);
else
e_destination_cardify (dest, book);
}
}
void
e_select_names_model_cancel_cardify (ESelectNamesModel *model, gint index)
{
EDestination *dest;
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (0 <= index && index < g_list_length (model->priv->data));
dest = E_DESTINATION (g_list_nth_data (model->priv->data, index));
e_destination_cancel_cardify (dest);
}
void
e_select_names_model_cardify_all (ESelectNamesModel *model, EBook *book, gint delay)
{
GList *iter;
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
g_return_if_fail (book == NULL || E_IS_BOOK (book));
for (iter = model->priv->data; iter != NULL; iter = g_list_next (iter)) {
EDestination *dest = E_DESTINATION (iter->data);
if (!e_destination_is_empty (dest)) {
if (delay > 0)
e_destination_cardify_delayed (dest, book, delay);
else
e_destination_cardify (dest, book);
}
}
}
void
e_select_names_model_cancel_cardify_all (ESelectNamesModel *model)
{
GList *iter;
g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model));
for (iter = model->priv->data; iter != NULL; iter = g_list_next (iter)) {
EDestination *dest = E_DESTINATION (iter->data);
e_destination_cancel_cardify (dest);
}
}

View File

@ -73,4 +73,10 @@ void e_select_names_model_clean (ESelectNamesModel *model);
void e_select_names_model_name_pos (ESelectNamesModel *model, gint index, gint *pos, gint *length);
void e_select_names_model_text_pos (ESelectNamesModel *model, gint pos, gint *index, gint *start_pos, gint *length);
void e_select_names_model_cardify (ESelectNamesModel *model, EBook *book, gint index, gint delay);
void e_select_names_model_cancel_cardify (ESelectNamesModel *model, gint index);
void e_select_names_model_cardify_all (ESelectNamesModel *model, EBook *book, gint delay);
void e_select_names_model_cancel_cardify_all (ESelectNamesModel *model);
#endif /* ! __E_SELECT_NAMES_MODEL_H__ */

View File

@ -423,7 +423,7 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
EDestination *dest = e_destination_new ();
e_destination_set_raw (dest, new_str);
e_select_names_model_replace (source, index, dest);
if (this_length > 0) {