See e_book_listener_check_queue below.

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

	* backend/ebook/e-book-view-listener.c
	(e_book_view_listener_check_queue): See
	e_book_listener_check_queue below.
	(e_book_view_listener_queue_response): See
	e_book_listener_queue_response below.

	* backend/ebook/e-book-listener.c (e_book_listener_check_queue):
	Explicitly prohibit reentrancy.  Use gtk-unref rather than
	bobobo-unref.
	(e_book_listener_queue_response): Hold a gtk-ref to the listener
	while the idle function runs, not a bonobo-ref.  As far as I can
	tell, it is impossible to avoid a race condition here when we have
	to worry about bonobo reentrancy.

	* gui/component/select-names/e-select-names-text-model.c
	(e_select_names_text_model_insert_length): Alter a copy of the
	original EDestination, rather than just using a new one.  We need
	to do this to preserve prior-card information for possible
	reversion later.
	(e_select_names_text_model_delete): Ditto.

	* backend/ebook/e-destination.c (e_destination_clear_card): When
	clearing a destination where ->card != NULL, store it for possible
	reversion later.
	(e_destination_revert): If we have an old card stored, go back to
	using it for the destination.
	(e_destination_is_valid): Tries to detect obviously broken
	addresses.
	(e_destination_cardify): If our destination is invalid, first try
	to cardify simply by reverting to an older card.
	(e_destination_destroy): Unref any cached old card.
	(e_destination_copy): Copy the old card information.

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

	* gui/component/select-names/e-select-names.c
	(sync_table_and_models): Show all rows in the table, and then
	remove the rows that correspond to entries in the
	ESelectNamesModels in the children.
	(real_add_address): Freeze/thaw our ESelectNamesModel, so that we
	don't change our table while we are in the middle of iterating
	over the selection.
	(remove_address): Just delete the address from the
	ESelectNamesModel, the signal handler will do the rest.
	(selected_rows_foreach_cb): Call remove_address to do our dirty
	work.
	(e_select_names_add_section): Connect to the 'changed' signal from
	the ESelectNamesModel, and call sync_table_and_models explicitly to
	get our initial state correct.

	* gui/component/select-names/e-select-names-table-model.c
	(fill_in_info): Deal with EDestinations in our table that don't
	come from cards.

	* gui/component/select-names/e-select-names-manager.c: Added
	another ESelectNamesModel* to the ESelectNamesManagerSection
	struct.  Called 'original_model', this contains a copy of the
	model as it is when we begin using the SelectNames dialog.
	(section_copy): Copy the original model.
	(section_free): Free the original model.
	(e_select_names_manager_add_section_with_limit): Initialize the
	original model.
	(e_select_names_clicked): I've changed the semantics of this
	dialog quite a bit... no UI freeze can stop me!  If OK is clicked,
	we do nothing.  If Cancel is clicked, we revert to the
	'original_model' copy of our address entry state before we started
	editting.  Finally, we close the dialog before any of thing. Doing
	it last caused problems, because signals were being triggered
	which had dangling pointers as their closures.
	(e_select_names_manager_activate_dialog): Copy our current state
	to the original model, and share the same ESelectNamesModel
	between the dialog and the address entry in the composer..
	(e_select_names_manager_get_cards): Removed.  It had been
	#if 0/#endif-ed out for a while.

	* gui/component/select-names/e-select-names-model.c
	(e_select_names_model_freeze): Added.
	(e_select_names_model_thaw): Added.
	(e_select_names_model_uncardify): Added.  If possible,
	"uncardifies" a specific model entry.
	(e_select_names_model_changed): Changed to pay attention
	to the freeze count.

	* gui/component/select-names/e-select-names-completion.c
	(clean_query_text): Strip leading/trailing whitespace from
	queries.

	* backend/ebook/e-destination.c (e_destination_uncardify): Added.
	Converts a card-associated destination into a text-associated
	destination w/ the e-mail address.
	(e_destination_list_to_vector): Added.  A convenience routine.
	(e_destination_freev): Added.  A convenience routine.
	(e_destination_touchv): Added.  I'm lazy.

svn path=/trunk/; revision=12709
This commit is contained in:
Jon Trowbridge
2001-09-09 03:45:55 +00:00
committed by Jon Trowbridge
parent ba8ba2de6e
commit 2e3a7b37fe
5 changed files with 255 additions and 99 deletions

View File

@ -128,7 +128,6 @@
* gui/component/addressbook-component.c: Removed unused factory
variable.
>>>>>>> 1.757
2001-09-06 Chris Toshok <toshok@ximian.com>
* gui/component/addressbook-storage.c (notify_listener): new

View File

@ -26,8 +26,9 @@ static BonoboObjectClass *e_book_listener_parent_class;
POA_GNOME_Evolution_Addressbook_BookListener__vepv e_book_listener_vepv;
struct _EBookListenerPrivate {
GList *response_queue;
gint idle_id;
GList *response_queue;
gint idle_id;
gboolean idle_lock;
guint stopped : 1;
};
@ -35,32 +36,35 @@ struct _EBookListenerPrivate {
static gboolean
e_book_listener_check_queue (EBookListener *listener)
{
gboolean retval;
if (listener->priv->idle_lock)
return TRUE;
/* Hold a reference locally, so that we can't get blown away
during the signal emission. */
bonobo_object_ref (BONOBO_OBJECT (listener));
retval = TRUE;
listener->priv->idle_lock = TRUE;
if (listener->priv->stopped) {
listener->priv->idle_id = 0;
goto exit_gracefully;
}
if (listener->priv->response_queue != NULL) {
gtk_signal_emit (GTK_OBJECT (listener),
e_book_listener_signals [RESPONSES_QUEUED]);
gtk_signal_emit (GTK_OBJECT (listener), e_book_listener_signals [RESPONSES_QUEUED]);
}
/* Make sure that ->idle_id != 0, so that only the first reentrant call to
this function unrefs our "global" reference. */
if (listener->priv->response_queue == NULL && listener->priv->idle_id != 0) {
if (listener->priv->response_queue == NULL) {
listener->priv->idle_id = 0;
/* We only release our reference to the listener when the idle
function is totally finished. */
bonobo_object_unref (BONOBO_OBJECT (listener));
retval = FALSE;
}
bonobo_object_unref (BONOBO_OBJECT (listener));
exit_gracefully:
return retval;
listener->priv->idle_lock = FALSE;
/* Only drop the reference when we exit for the last time. */
if (listener->priv->idle_id == 0) {
gtk_object_unref (GTK_OBJECT (listener));
return FALSE;
}
return TRUE;
}
static void
@ -74,10 +78,9 @@ e_book_listener_queue_response (EBookListener *listener,
if (listener->priv->idle_id == 0) {
/* Hold a reference to the listener until the idle function is finished. */
bonobo_object_ref (BONOBO_OBJECT (listener));
gtk_object_ref (GTK_OBJECT (listener));
listener->priv->idle_id = g_idle_add (
(GSourceFunc) e_book_listener_check_queue, listener);
listener->priv->idle_id = g_idle_add ((GSourceFunc) e_book_listener_check_queue, listener);
}
}

View File

@ -26,8 +26,9 @@ static BonoboObjectClass *e_book_view_listener_parent_class;
POA_GNOME_Evolution_Addressbook_BookViewListener__vepv e_book_view_listener_vepv;
struct _EBookViewListenerPrivate {
GList *response_queue;
gint idle_id;
GList *response_queue;
gint idle_id;
gboolean idle_lock;
guint stopped : 1;
};
@ -36,56 +37,49 @@ struct _EBookViewListenerPrivate {
static gboolean
e_book_view_listener_check_queue (EBookViewListener *listener)
{
gboolean retval;
if (listener->priv->idle_lock)
return TRUE;
listener->priv->idle_lock = TRUE;
if (listener->priv->stopped) {
listener->priv->idle_id = 0;
bonobo_object_unref (BONOBO_OBJECT (listener));
goto exit_gracefully;
}
if (listener->priv->response_queue != NULL) {
gtk_signal_emit (GTK_OBJECT (listener), e_book_view_listener_signals [RESPONSES_QUEUED]);
}
if (listener->priv->response_queue == NULL) {
listener->priv->idle_id = 0;
}
exit_gracefully:
listener->priv->idle_lock = FALSE;
/* Only drop the reference when we exit for the last time. */
if (listener->priv->idle_id == 0) {
gtk_object_unref (GTK_OBJECT (listener));
return FALSE;
}
/* An extra ref to keep listener from being destroyed during the
signal emission. */
bonobo_object_ref (BONOBO_OBJECT (listener));
retval = TRUE;
if (listener->priv->response_queue != NULL) {
gtk_signal_emit (GTK_OBJECT (listener),
e_book_view_listener_signals [RESPONSES_QUEUED]);
}
/* this callback could be (and indeed is) called from signal emited above,
signal handler could call e_book_view_listener_stop, so we need to check
if idle is still set and if not we don't want to unref again */
if (listener->priv->response_queue == NULL && listener->priv->idle_id != 0) {
listener->priv->idle_id = 0;
bonobo_object_unref (BONOBO_OBJECT (listener));
retval = FALSE;
}
/* Drop our extra reference from above. */
bonobo_object_unref (BONOBO_OBJECT (listener));
return retval;
return TRUE;
}
static void
e_book_view_listener_queue_response (EBookViewListener *listener,
EBookViewListenerResponse *response)
{
listener->priv->response_queue =
g_list_append (listener->priv->response_queue,
response);
listener->priv->response_queue = g_list_append (listener->priv->response_queue, response);
if (listener->priv->idle_id == 0) {
/* Hold a reference to the listener while the idle is active. */
bonobo_object_ref (BONOBO_OBJECT (listener));
gtk_object_ref (GTK_OBJECT (listener));
listener->priv->idle_id = g_idle_add (
(GSourceFunc) e_book_view_listener_check_queue, listener);
listener->priv->idle_id = g_idle_add ((GSourceFunc) e_book_view_listener_check_queue, listener);
}
}

View File

@ -59,9 +59,13 @@ struct _EDestinationPrivate {
ECard *card;
gint card_email_num;
ECard *old_card;
gint old_card_email_num;
gchar *name;
gchar *email;
gchar *addr;
gchar *textrep;
gboolean html_mail_override;
gboolean wants_html_mail;
@ -90,6 +94,9 @@ e_destination_destroy (GtkObject *obj)
EDestination *dest = E_DESTINATION (obj);
e_destination_clear (dest);
if (dest->priv->old_card)
gtk_object_unref (GTK_OBJECT (dest->priv->old_card));
if (dest->priv->cardify_book)
gtk_object_unref (GTK_OBJECT (dest->priv->cardify_book));
@ -207,17 +214,22 @@ e_destination_copy (const EDestination *dest)
new_dest = e_destination_new ();
new_dest->priv->book_uri = g_strdup (dest->priv->book_uri);
new_dest->priv->card_uid = g_strdup (dest->priv->card_uid);
new_dest->priv->name = g_strdup (dest->priv->name);
new_dest->priv->email = g_strdup (dest->priv->email);
new_dest->priv->addr = g_strdup (dest->priv->addr);
new_dest->priv->card_email_num = dest->priv->card_email_num;
new_dest->priv->book_uri = g_strdup (dest->priv->book_uri);
new_dest->priv->card_uid = g_strdup (dest->priv->card_uid);
new_dest->priv->name = g_strdup (dest->priv->name);
new_dest->priv->email = g_strdup (dest->priv->email);
new_dest->priv->addr = g_strdup (dest->priv->addr);
new_dest->priv->card_email_num = dest->priv->card_email_num;
new_dest->priv->old_card_email_num = dest->priv->old_card_email_num;
new_dest->priv->card = dest->priv->card;
if (new_dest->priv->card)
gtk_object_ref (GTK_OBJECT (new_dest->priv->card));
new_dest->priv->old_card = dest->priv->old_card;
if (new_dest->priv->old_card)
gtk_object_ref (GTK_OBJECT (new_dest->priv->old_card));
new_dest->priv->html_mail_override = dest->priv->html_mail_override;
new_dest->priv->wants_html_mail = dest->priv->wants_html_mail;
@ -237,10 +249,16 @@ e_destination_clear_card (EDestination *dest)
g_free (dest->priv->card_uid);
dest->priv->card_uid = NULL;
if (dest->priv->card)
gtk_object_unref (GTK_OBJECT (dest->priv->card));
dest->priv->card = NULL;
if (dest->priv->card) {
if (dest->priv->old_card)
gtk_object_unref (GTK_OBJECT (dest->priv->old_card));
dest->priv->old_card = dest->priv->card;
dest->priv->old_card_email_num = dest->priv->card_email_num;
}
dest->priv->card = NULL;
dest->priv->card_email_num = -1;
g_list_foreach (dest->priv->list_dests, (GFunc) gtk_object_unref, NULL);
@ -270,6 +288,9 @@ e_destination_clear_strings (EDestination *dest)
g_free (dest->priv->addr);
dest->priv->addr = NULL;
g_free (dest->priv->textrep);
dest->priv->textrep = NULL;
e_destination_changed (dest);
}
@ -290,7 +311,7 @@ gboolean
e_destination_is_empty (const EDestination *dest)
{
struct _EDestinationPrivate *p;
g_return_val_if_fail (dest && E_IS_DESTINATION (dest), TRUE);
g_return_val_if_fail (E_IS_DESTINATION (dest), TRUE);
p = dest->priv;
return !(p->card != NULL
@ -303,6 +324,20 @@ e_destination_is_empty (const EDestination *dest)
|| (p->list_dests != NULL));
}
gboolean
e_destination_is_valid (const EDestination *dest)
{
const gchar *email;
g_return_val_if_fail (E_IS_DESTINATION (dest), FALSE);
if (dest->priv->card != NULL)
return TRUE;
email = e_destination_get_email (dest);
return email && *email && strchr (email, '@');
}
gboolean
e_destination_equal (const EDestination *a, const EDestination *b)
{
@ -419,19 +454,25 @@ e_destination_set_card_uid (EDestination *dest, const gchar *uid, gint email_num
void
e_destination_set_name (EDestination *dest, const gchar *name)
{
g_return_if_fail (dest && E_IS_DESTINATION (dest));
g_return_if_fail (name != NULL);
gboolean changed = FALSE;
if (dest->priv->name == NULL || strcmp (dest->priv->name, name)) {
g_return_if_fail (E_IS_DESTINATION (dest));
if (name == NULL) {
if (dest->priv->name != NULL) {
g_free (dest->priv->name);
dest->priv->name = NULL;
changed = TRUE;
}
} else if (dest->priv->name == NULL || strcmp (dest->priv->name, name)) {
g_free (dest->priv->name);
dest->priv->name = g_strdup (name);
changed = TRUE;
}
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
}
if (changed) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
e_destination_changed (dest);
}
}
@ -439,19 +480,27 @@ e_destination_set_name (EDestination *dest, const gchar *name)
void
e_destination_set_email (EDestination *dest, const gchar *email)
{
g_return_if_fail (dest && E_IS_DESTINATION (dest));
g_return_if_fail (email != NULL);
gboolean changed = FALSE;
if (dest->priv->email == NULL || strcmp (dest->priv->email, email)) {
g_return_if_fail (E_IS_DESTINATION (dest));
if (email == NULL) {
if (dest->priv->email != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
changed = TRUE;
}
} else if (dest->priv->email == NULL || strcmp (dest->priv->email, email)) {
g_free (dest->priv->email);
dest->priv->email = g_strdup (email);
changed = TRUE;
}
if (dest->priv->addr != NULL) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
}
if (changed) {
g_free (dest->priv->addr);
dest->priv->addr = NULL;
e_destination_changed (dest);
}
}
@ -750,20 +799,32 @@ e_destination_set_raw (EDestination *dest, const gchar *raw)
const gchar *
e_destination_get_textrep (const EDestination *dest)
{
const gchar *txt;
const gchar *name, *email;
g_return_val_if_fail (dest && E_IS_DESTINATION (dest), NULL);
if (dest->priv->raw)
return dest->priv->raw;
txt = e_destination_get_name (dest);
if (txt != NULL)
return txt;
name = e_destination_get_name (dest);
email = e_destination_get_email (dest);
txt = e_destination_get_email (dest);
if (txt != NULL)
return txt;
if (e_destination_from_card (dest) && name != NULL)
return name;
if (name && email) {
gchar *rep = g_strdup_printf ("%s <%s>", name, email);
if (dest->priv->textrep && !strcmp (rep, dest->priv->textrep)) {
g_free (rep);
} else {
g_free (dest->priv->textrep);
dest->priv->textrep = rep;
}
return dest->priv->textrep;
}
if (email)
return email;
return "";
}
@ -943,6 +1004,11 @@ e_destination_cardify (EDestination *dest, EBook *book)
e_destination_cancel_cardify (dest);
/* In some cases, we can revert to the previous card. */
if (!e_destination_is_valid (dest) && e_destination_revert (dest)) {
return;
}
set_cardify_book (dest, book);
/* Handle the case of an EDestination containing a card URL */
@ -996,15 +1062,54 @@ e_destination_cancel_cardify (EDestination *dest)
}
}
#if 0
void
gboolean
e_destination_uncardify (EDestination *dest)
{
g_return_if_fail (E_IS_DESTINATION (dest));
gchar *email;
g_assert_not_reached ();
g_return_val_if_fail (E_IS_DESTINATION (dest), FALSE);
if (! e_destination_contains_card (dest))
return FALSE;
email = g_strdup (e_destination_get_email (dest));
if (email == NULL)
return FALSE;
e_destination_freeze (dest);
e_destination_clear (dest);
e_destination_set_raw (dest, email);
g_free (email);
e_destination_thaw (dest);
return TRUE;
}
gboolean
e_destination_revert (EDestination *dest)
{
g_return_val_if_fail (E_IS_DESTINATION (dest), FALSE);
if (dest->priv->old_card) {
ECard *card;
gint card_email_num;
card = dest->priv->old_card;
card_email_num = dest->priv->old_card_email_num;
dest->priv->old_card = NULL;
e_destination_freeze (dest);
e_destination_clear (dest);
e_destination_set_card (dest, card, card_email_num);
e_destination_thaw (dest);
return TRUE;
}
return FALSE;
}
#endif
/*
* Destination import/export
@ -1216,6 +1321,9 @@ e_destination_xml_decode (EDestination *dest, xmlNodePtr node)
if (list_dests)
dest->priv->list_dests = list_dests;
dest->priv->html_mail_override = TRUE;
dest->priv->wants_html_mail = html_mail;
dest->priv->show_addresses = show_addr;
e_destination_thaw (dest);
@ -1390,6 +1498,42 @@ e_destination_importv (const gchar *str)
return destv;
}
EDestination **
e_destination_list_to_vector (GList *list)
{
gint N = g_list_length (list);
EDestination **destv;
gint i = 0;
if (N == 0)
return NULL;
destv = g_new (EDestination *, N+1);
while (list != NULL) {
destv[i] = E_DESTINATION (list->data);
list->data = NULL;
++i;
list = g_list_next (list);
}
destv[N] = NULL;
return destv;
}
void
e_destination_freev (EDestination **destv)
{
gint i;
if (destv) {
for (i = 0; destv[i] != NULL; ++i) {
gtk_object_unref (GTK_OBJECT (destv[i]));
}
g_free (destv);
}
}
static void
touch_cb (EBook *book, const gchar *addr, ECard *card, gpointer closure)
{
@ -1413,3 +1557,15 @@ e_destination_touch (EDestination *dest)
e_book_query_address_locally (email, touch_cb, NULL);
}
}
void
e_destination_touchv (EDestination **destv)
{
gint i;
g_return_if_fail (destv != NULL);
for (i = 0; destv[i] != NULL; ++i) {
e_destination_touch (destv[i]);
}
}

View File

@ -68,6 +68,7 @@ EDestination *e_destination_copy (const EDestination *);
void e_destination_clear (EDestination *);
gboolean e_destination_is_empty (const EDestination *);
gboolean e_destination_is_valid (const EDestination *);
gboolean e_destination_equal (const EDestination *a, const EDestination *b);
void e_destination_set_card (EDestination *, ECard *card, gint email_num);
@ -107,10 +108,9 @@ 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 *);
gboolean e_destination_uncardify (EDestination *);
#if 0
void e_destination_uncardify (EDestination *);
#endif
gboolean e_destination_revert (EDestination *);
gchar *e_destination_get_address_textv (EDestination **);
@ -123,7 +123,11 @@ EDestination *e_destination_import (const gchar *str);
gchar *e_destination_exportv (EDestination **);
EDestination **e_destination_importv (const gchar *str);
EDestination **e_destination_list_to_vector (GList *);
void e_destination_freev (EDestination **);
void e_destination_touch (EDestination *);
void e_destination_touchv (EDestination **);
#endif /* __E_DESTINATION_H__ */