diff options
author | Jon Trowbridge <trow@ximian.com> | 2001-09-09 11:48:20 +0800 |
---|---|---|
committer | Jon Trowbridge <trow@src.gnome.org> | 2001-09-09 11:48:20 +0800 |
commit | 91a2ff89c4ffe82aa07be175fb623b329d3d6a61 (patch) | |
tree | 2ff4e51eb0964fc60e691eb4434b73c17e5c726d | |
parent | 2e3a7b37fe4bb3adffd998d005e39fd4758e2c1e (diff) | |
download | gsoc2013-evolution-91a2ff89c4ffe82aa07be175fb623b329d3d6a61.tar.gz gsoc2013-evolution-91a2ff89c4ffe82aa07be175fb623b329d3d6a61.tar.zst gsoc2013-evolution-91a2ff89c4ffe82aa07be175fb623b329d3d6a61.zip |
(Apologies if you are seeing this multiple times. CVS is being annoying.)
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=12710
8 files changed, 153 insertions, 81 deletions
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 b853dbe835..c5d1727300 100644 --- a/addressbook/gui/component/select-names/e-select-names-completion.c +++ b/addressbook/gui/component/select-names/e-select-names-completion.c @@ -821,6 +821,8 @@ clean_query_text (const gchar *s) } *t = '\0'; + g_strstrip (q); + return q; } 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 3212242fbd..3b49497f42 100644 --- a/addressbook/gui/component/select-names/e-select-names-manager.c +++ b/addressbook/gui/component/select-names/e-select-names-manager.c @@ -40,6 +40,7 @@ typedef struct { char *id; char *title; ESelectNamesModel *model; + ESelectNamesModel *original_model; ESelectNamesManager *manager; guint changed_handler; } ESelectNamesManagerSection; @@ -188,6 +189,7 @@ section_copy(const void *sec, void *data) newsec->id = g_strdup(section->id); newsec->title = g_strdup(section->title); newsec->model = section->model; + newsec->original_model = section->original_model; newsec->manager = section->manager; newsec->changed_handler = gtk_signal_connect (GTK_OBJECT (newsec->model), "changed", @@ -196,6 +198,9 @@ section_copy(const void *sec, void *data) if (newsec->model) gtk_object_ref(GTK_OBJECT(newsec->model)); + if (newsec->original_model) + gtk_object_ref(GTK_OBJECT(newsec->original_model)); + return newsec; } @@ -209,7 +214,10 @@ section_free(void *sec, void *data) g_free(section->id); g_free(section->title); if (section->model) - gtk_object_unref(GTK_OBJECT(section->model)); + gtk_object_unref (GTK_OBJECT(section->model)); + if (section->original_model) + gtk_object_unref (GTK_OBJECT (section->original_model)); + g_free(section); } @@ -290,6 +298,8 @@ e_select_names_manager_add_section_with_limit (ESelectNamesManager *manager, section->model = e_select_names_model_new(); e_select_names_model_set_limit (section->model, limit); + section->original_model = NULL; + section->manager = manager; section->changed_handler = gtk_signal_connect (GTK_OBJECT (section->model), @@ -420,7 +430,7 @@ e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *i "popup", GTK_SIGNAL_FUNC (popup_cb), section->model); - + gtk_signal_connect (GTK_OBJECT (eentry->canvas), "focus_in_event", GTK_SIGNAL_FUNC (focus_in_cb), @@ -465,42 +475,26 @@ e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *i static void e_select_names_clicked(ESelectNames *dialog, gint button, ESelectNamesManager *manager) { + gnome_dialog_close(GNOME_DIALOG(dialog)); + switch(button) { - case 0: { + case 0: + /* We don't need to do anything if they click on OK */ + break; + + case 1: { EList *list = manager->sections; EIterator *iterator = e_list_get_iterator(list); - for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - ESelectNamesManagerSection *section = (void *) e_iterator_get(iterator); - ESelectNamesModel *source = e_select_names_get_source(dialog, section->id); - e_select_names_model_merge (section->model, source); - gtk_object_unref (GTK_OBJECT (source)); - - } - gtk_object_unref(GTK_OBJECT(iterator)); -#if 0 - list = manager->entries; - iterator = e_list_get_iterator(list); for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - ESelectNamesManagerEntry *entry = (void *) e_iterator_get(iterator); - ESelectNamesModel *source = e_select_names_get_source(dialog, entry->id); - if (source) { - ETextModel *model = e_select_names_text_model_new(source); - if (model) { - gtk_object_set(GTK_OBJECT(entry->entry), - "model", model, - NULL); - gtk_object_unref(GTK_OBJECT(source)); - } - gtk_object_unref(GTK_OBJECT(model)); - } + ESelectNamesManagerSection *section = (void *) e_iterator_get(iterator); + e_select_names_model_overwrite_copy (section->model, section->original_model); } + gtk_object_unref(GTK_OBJECT(iterator)); -#endif break; } } - gnome_dialog_close(GNOME_DIALOG(dialog)); } void @@ -519,14 +513,15 @@ e_select_names_manager_activate_dialog (ESelectNamesManager *manager, iterator = e_list_get_iterator(manager->sections); for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - const ESelectNamesManagerSection *section = e_iterator_get(iterator); - ESelectNamesModel *newmodel = e_select_names_model_duplicate(section->model); - e_select_names_add_section(manager->names, section->id, section->title, newmodel); - gtk_signal_connect (GTK_OBJECT (newmodel), + ESelectNamesManagerSection *section = (ESelectNamesManagerSection *) e_iterator_get(iterator); + if (section->original_model != NULL) + gtk_object_unref (GTK_OBJECT (section->original_model)); + section->original_model = e_select_names_model_duplicate (section->model); + e_select_names_add_section (manager->names, section->id, section->title, section->model); + gtk_signal_connect (GTK_OBJECT (section->model), "changed", GTK_SIGNAL_FUNC (section_model_working_copy_changed_cb), (gpointer)section); /* casting out const to avoid compiler warning */ - gtk_object_unref(GTK_OBJECT(newmodel)); } e_select_names_set_default(manager->names, id); gtk_signal_connect(GTK_OBJECT(manager->names), "clicked", @@ -538,20 +533,3 @@ e_select_names_manager_activate_dialog (ESelectNamesManager *manager, } } -#if 0 -/* Of type ECard */ -EList * -e_select_names_manager_get_cards (ESelectNamesManager *manager, - const char *id) -{ - EIterator *iterator; - iterator = e_list_get_iterator(manager->sections); - for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { - const ESelectNamesManagerSection *section = e_iterator_get(iterator); - if (!strcmp(section->id, id)) { - return e_select_names_model_get_cards(section->model); - } - } - return NULL; -} -#endif diff --git a/addressbook/gui/component/select-names/e-select-names-manager.h b/addressbook/gui/component/select-names/e-select-names-manager.h index 61779fb56a..dccc3fd7c2 100644 --- a/addressbook/gui/component/select-names/e-select-names-manager.h +++ b/addressbook/gui/component/select-names/e-select-names-manager.h @@ -54,12 +54,6 @@ GtkWidget *e_select_names_manager_create_entry (ESelectNames void e_select_names_manager_activate_dialog (ESelectNamesManager *manager, const char *id); -#if 0 -/* Of type ECard */ -EList *e_select_names_manager_get_cards (ESelectNamesManager *manager, - const char *id); -#endif - /* Standard Gtk function */ GtkType e_select_names_manager_get_type (void); diff --git a/addressbook/gui/component/select-names/e-select-names-model.c b/addressbook/gui/component/select-names/e-select-names-model.c index 0f43464507..89838f9b82 100644 --- a/addressbook/gui/component/select-names/e-select-names-model.c +++ b/addressbook/gui/component/select-names/e-select-names-model.c @@ -58,6 +58,9 @@ struct _ESelectNamesModelPrivate { gchar *addr_text; gint limit; + + gint freeze_count; + gboolean pending_changed; }; @@ -216,7 +219,12 @@ e_select_names_model_changed (ESelectNamesModel *model) g_free (model->priv->addr_text); model->priv->addr_text = NULL; - gtk_signal_emit (GTK_OBJECT(model), e_select_names_model_signals[E_SELECT_NAMES_MODEL_CHANGED]); + if (model->priv->freeze_count > 0) { + model->priv->pending_changed = TRUE; + } else { + gtk_signal_emit (GTK_OBJECT(model), e_select_names_model_signals[E_SELECT_NAMES_MODEL_CHANGED]); + model->priv->pending_changed = FALSE; + } } static void @@ -580,14 +588,17 @@ void e_select_names_model_delete (ESelectNamesModel *model, gint index) { GList *node; + EDestination *dest; g_return_if_fail (model != NULL); g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model)); 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)); + dest = E_DESTINATION (node->data); + + disconnect_destination (model, dest); + gtk_object_unref (GTK_OBJECT (dest)); model->priv->data = g_list_remove_link (model->priv->data, node); g_list_free_1 (node); @@ -788,6 +799,31 @@ e_select_names_model_cardify (ESelectNamesModel *model, EBook *book, gint index, } } +gboolean +e_select_names_model_uncardify (ESelectNamesModel *model, gint index) +{ + EDestination *dest; + gboolean rv = FALSE; + + g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), FALSE); + g_return_val_if_fail (0 <= index && index < g_list_length (model->priv->data), FALSE); + + dest = E_DESTINATION (g_list_nth_data (model->priv->data, index)); + + if (!e_destination_is_empty (dest)) { + EDestination *cpy_dest = e_destination_copy (dest); + + rv = e_destination_uncardify (cpy_dest); + + if (rv) { + e_select_names_model_replace (model, index, cpy_dest); + } + + } + + return rv; +} + void e_select_names_model_cancel_cardify (ESelectNamesModel *model, gint index) { @@ -834,3 +870,21 @@ e_select_names_model_cancel_cardify_all (ESelectNamesModel *model) } } +void +e_select_names_model_freeze (ESelectNamesModel *model) +{ + g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model)); + + ++model->priv->freeze_count; +} + +void +e_select_names_model_thaw (ESelectNamesModel *model) +{ + g_return_if_fail (E_IS_SELECT_NAMES_MODEL (model)); + g_return_if_fail (model->priv->freeze_count > 0); + + --model->priv->freeze_count; + if (model->priv->pending_changed) + e_select_names_model_changed (model); +} diff --git a/addressbook/gui/component/select-names/e-select-names-model.h b/addressbook/gui/component/select-names/e-select-names-model.h index c10b6ccf2a..b7fa04d6cd 100644 --- a/addressbook/gui/component/select-names/e-select-names-model.h +++ b/addressbook/gui/component/select-names/e-select-names-model.h @@ -77,9 +77,15 @@ void e_select_names_model_name_pos (ESelectNamesModel *model, gint inde 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); +gboolean e_select_names_model_uncardify (ESelectNamesModel *model, gint index); 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); +/* This is a mildly annoying freeze/thaw pair, in that it only applies to the 'changed' + signal and not to 'resized'. This could cause unexpected results in some cases. */ +void e_select_names_model_freeze (ESelectNamesModel *model); +void e_select_names_model_thaw (ESelectNamesModel *model); + #endif /* ! __E_SELECT_NAMES_MODEL_H__ */ diff --git a/addressbook/gui/component/select-names/e-select-names-table-model.c b/addressbook/gui/component/select-names/e-select-names-table-model.c index fee84ce071..84c7754020 100644 --- a/addressbook/gui/component/select-names/e-select-names-table-model.c +++ b/addressbook/gui/component/select-names/e-select-names-table-model.c @@ -129,8 +129,11 @@ fill_in_info (ESelectNamesTableModel *model) model->data[i].email = g_strdup(""); gtk_object_unref(GTK_OBJECT(simple)); } else { - model->data[i].name = g_strdup (e_destination_get_name (dest)); - model->data[i].email = g_strdup (e_destination_get_email (dest)); + const gchar *name = e_destination_get_name (dest); + const gchar *email = e_destination_get_email (dest); + + model->data[i].name = g_strdup (name && *name ? name : email); + model->data[i].email = g_strdup (email); } } } else { diff --git a/addressbook/gui/component/select-names/e-select-names-text-model.c b/addressbook/gui/component/select-names/e-select-names-text-model.c index c6f2b7856b..782b7ebb90 100644 --- a/addressbook/gui/component/select-names/e-select-names-text-model.c +++ b/addressbook/gui/component/select-names/e-select-names-text-model.c @@ -426,10 +426,12 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha if (new_str) { - EDestination *dest = e_destination_new (); + EDestination *dest; + dest = index >= 0 ? e_destination_copy (e_select_names_model_get_destination (source, index)) : e_destination_new (); e_destination_set_raw (dest, new_str); - e_select_names_model_replace (source, index, dest); + + /* e_select_names_model_replace (source, index, dest); */ if (this_length > 0) { repos.model = model; @@ -616,7 +618,7 @@ e_select_names_text_model_delete (ETextModel *model, gint pos, gint length) EReposDeleteShift repos; EDestination *dest; - dest = e_destination_new (); + dest = index >= 0 ? e_destination_copy (e_select_names_model_get_destination (source, index)) : e_destination_new (); e_destination_set_raw (dest, new_str); e_select_names_model_replace (source, index, dest); diff --git a/addressbook/gui/component/select-names/e-select-names.c b/addressbook/gui/component/select-names/e-select-names.c index 7316458630..eda6dbd301 100644 --- a/addressbook/gui/component/select-names/e-select-names.c +++ b/addressbook/gui/component/select-names/e-select-names.c @@ -146,13 +146,48 @@ addressbook_model_set_uri(EAddressbookModel *model, char *uri) static void * card_key (ECard *card) { - EBook *book = e_card_get_book (card); - const gchar *book_uri = book ? e_book_get_uri (book) : "NoBook"; + EBook *book; + const gchar *book_uri; + if (card == NULL) + return NULL; + + g_assert (E_IS_CARD (card)); + + book = e_card_get_book (card); + book_uri = book ? e_book_get_uri (book) : "NoBook"; return g_strdup_printf ("%s|%s", book_uri ? book_uri : "NoURI", e_card_get_id (card)); } static void +sync_one_model (gpointer k, gpointer val, gpointer closure) +{ + ETableWithout *etw = E_TABLE_WITHOUT (closure); + ESelectNamesChild *child = val; + ESelectNamesModel *model = child->source; + gint i, count; + ECard *card; + void *key; + + count = e_select_names_model_count (model); + for (i = 0; i < count; ++i) { + card = e_select_names_model_get_card (model, i); + if (card) { + key = card_key (card); + e_table_without_hide (etw, key); + g_free (key); + } + } +} + +static void +sync_table_and_models (ESelectNamesModel *triggering_model, ESelectNames *esl) +{ + e_table_without_show_all (E_TABLE_WITHOUT (esl->without)); + g_hash_table_foreach (esl->children, sync_one_model, esl->without); +} + +static void real_add_address_cb (int model_row, gpointer closure) { ESelectNamesChild *child = closure; @@ -160,14 +195,11 @@ real_add_address_cb (int model_row, gpointer closure) ECard *card; EDestination *dest = e_destination_new (); gint mapped_row; - void *key; mapped_row = e_table_subset_view_to_model_row (E_TABLE_SUBSET (names->without), model_row); card = e_addressbook_model_get_card(E_ADDRESSBOOK_MODEL(names->model), mapped_row); - key = card_key (card); - e_table_without_hide (E_TABLE_WITHOUT (names->without), key); - g_free (key); + e_destination_set_card (dest, card, 0); @@ -180,8 +212,10 @@ real_add_address_cb (int model_row, gpointer closure) static void real_add_address(ESelectNames *names, ESelectNamesChild *child) { + e_select_names_model_freeze (child->source); e_table_selected_row_foreach(e_table_scrolled_get_table(names->table), real_add_address_cb, child); + e_select_names_model_thaw (child->source); } static void @@ -597,6 +631,7 @@ e_select_names_init (ESelectNames *e_select_names) static void e_select_names_child_free(char *key, ESelectNamesChild *child, ESelectNames *e_select_names) { + gtk_signal_disconnect_by_func (GTK_OBJECT (child->source), GTK_SIGNAL_FUNC (sync_table_and_models), e_select_names); g_free(child->title); gtk_object_unref(GTK_OBJECT(child->model)); gtk_object_unref(GTK_OBJECT(child->source)); @@ -607,7 +642,7 @@ static void e_select_names_destroy (GtkObject *object) { ESelectNames *e_select_names = E_SELECT_NAMES(object); - + gtk_signal_disconnect_by_data(GTK_OBJECT(e_select_names->local_listener), e_select_names); gtk_object_unref(GTK_OBJECT(e_select_names->local_listener)); gtk_signal_disconnect_by_data(GTK_OBJECT(e_select_names->other_contacts_listener), e_select_names); @@ -663,16 +698,7 @@ button_clicked(GtkWidget *button, ESelectNamesChild *child) static void remove_address(ETable *table, int row, int col, GdkEvent *event, ESelectNamesChild *child) { - const EDestination *dest; - ECard *card; - void *key; - dest = e_select_names_model_get_destination (child->source, row); - card = e_destination_get_card (dest); - key = card_key (card); - e_select_names_model_delete (child->source, row); - e_table_without_show (E_TABLE_WITHOUT (child->names->without), key); - g_free (key); } struct _RightClickData { @@ -698,7 +724,7 @@ selected_rows_foreach_cb (void *row, void *data) { ESelectNamesChild *child = data; - e_select_names_model_delete (child->source, GPOINTER_TO_INT (row)); + remove_address (NULL, GPOINTER_TO_INT (row), 0, NULL, child); } static void @@ -798,6 +824,11 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E child->source = source; gtk_object_ref(GTK_OBJECT(child->model)); gtk_object_ref(GTK_OBJECT(child->source)); + + gtk_signal_connect (GTK_OBJECT (child->source), + "changed", + GTK_SIGNAL_FUNC (sync_table_and_models), + e_select_names); gtk_widget_show(etable); @@ -809,6 +840,8 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E 0, 0); g_hash_table_insert(e_select_names->children, g_strdup(id), child); + + sync_table_and_models (child->source, e_select_names); } static void * |