diff options
This commit was manufactured by cvs2svn to create tagEVOLUTION_1_0_2
'EVOLUTION_1_0_2'.
svn path=/tags/EVOLUTION_1_0_2/; revision=15455
Diffstat (limited to 'addressbook/gui/component/select-names')
4 files changed, 483 insertions, 521 deletions
diff --git a/addressbook/gui/component/select-names/e-select-names-bonobo.c b/addressbook/gui/component/select-names/e-select-names-bonobo.c index b2c791f259..3398882181 100644 --- a/addressbook/gui/component/select-names/e-select-names-bonobo.c +++ b/addressbook/gui/component/select-names/e-select-names-bonobo.c @@ -48,6 +48,8 @@ static BonoboObjectClass *parent_class = NULL; struct _ESelectNamesBonoboPrivate { ESelectNamesManager *manager; BonoboEventSource *event_source; + guint manager_changed_tag; + guint manager_ok_tag; }; enum _EntryPropertyID { @@ -75,11 +77,11 @@ entry_get_property_fn (BonoboPropertyBag *bag, switch (arg_id) { case ENTRY_PROPERTY_ID_TEXT: { - ETextModel *text_model; - text_model = E_TEXT_MODEL (gtk_object_get_data (GTK_OBJECT (w), "select_names_text_model")); - g_assert (text_model != NULL); + ESelectNamesModel *model; + model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (w), "select_names_model")); + g_assert (model != NULL); - BONOBO_ARG_SET_STRING (arg, e_text_model_get_text (text_model)); + BONOBO_ARG_SET_STRING (arg, e_select_names_model_get_textification (model)); break; } @@ -348,21 +350,41 @@ impl_SelectNames_activate_dialog (PortableServer_Servant servant, /* GtkObject methods. */ +/* ACK! */ +typedef struct { + char *id; + EEntry *entry; +} ESelectNamesManagerEntry; + static void impl_destroy (GtkObject *object) { ESelectNamesBonobo *select_names; ESelectNamesBonoboPrivate *priv; + EIterator *iterator; select_names = E_SELECT_NAMES_BONOBO (object); priv = select_names->priv; + gtk_signal_disconnect (GTK_OBJECT (priv->manager), priv->manager_changed_tag); + gtk_signal_disconnect (GTK_OBJECT (priv->manager), priv->manager_ok_tag); + if (priv->manager->names) { gtk_widget_destroy (GTK_WIDGET (priv->manager->names)); priv->manager->names = NULL; } - gtk_object_unref (GTK_OBJECT (priv->manager)); + /* More suckage */ + iterator = e_list_get_iterator (priv->manager->entries); + for (e_iterator_reset (iterator); e_iterator_is_valid (iterator); e_iterator_next (iterator)) { + ESelectNamesManagerEntry *entry = (ESelectNamesManagerEntry *)e_iterator_get (iterator); + if (entry && entry->entry) + gtk_widget_destroy (GTK_WIDGET (entry->entry)); + } + gtk_object_unref (GTK_OBJECT (iterator)); + + /* FIXME: We leak on purpose. This sucks. */ + /* gtk_object_unref (GTK_OBJECT (priv->manager)); */ g_free (priv); } @@ -414,15 +436,17 @@ init (ESelectNamesBonobo *select_names) priv->manager = e_select_names_manager_new (); priv->event_source = NULL; - gtk_signal_connect (GTK_OBJECT (priv->manager), - "changed", - GTK_SIGNAL_FUNC (manager_changed_cb), - select_names); - - gtk_signal_connect (GTK_OBJECT (priv->manager), - "ok", - GTK_SIGNAL_FUNC (manager_ok_cb), - select_names); + priv->manager_changed_tag = + gtk_signal_connect (GTK_OBJECT (priv->manager), + "changed", + GTK_SIGNAL_FUNC (manager_changed_cb), + select_names); + + priv->manager_ok_tag = + gtk_signal_connect (GTK_OBJECT (priv->manager), + "ok", + GTK_SIGNAL_FUNC (manager_ok_cb), + select_names); select_names->priv = priv; } 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 cbfc1d56c6..eb15c4f232 100644 --- a/addressbook/gui/component/select-names/e-select-names-completion.c +++ b/addressbook/gui/component/select-names/e-select-names-completion.c @@ -55,7 +55,7 @@ typedef struct { struct _ESelectNamesCompletionPrivate { - ESelectNamesTextModel *text_model; + ESelectNamesModel *model; GList *book_data; gint books_not_ready; @@ -739,8 +739,8 @@ e_select_names_completion_destroy (GtkObject *object) ESelectNamesCompletion *comp = E_SELECT_NAMES_COMPLETION (object); GList *l; - if (comp->priv->text_model) - gtk_object_unref (GTK_OBJECT (comp->priv->text_model)); + if (comp->priv->model) + gtk_object_unref (GTK_OBJECT (comp->priv->model)); for (l = comp->priv->book_data; l; l = l->next) { ESelectNamesCompletionBookData *book_data = l->data; @@ -1142,10 +1142,8 @@ e_select_names_completion_handle_request (ECompletion *comp, const gchar *text, fprintf (out, "text=\"%s\" pos=%d limit=%d\n", text, pos, limit); } - e_select_names_model_text_pos (selcomp->priv->text_model->source, - selcomp->priv->text_model->seplen, - pos, &index, NULL, NULL); - str = index >= 0 ? e_select_names_model_get_string (selcomp->priv->text_model->source, index) : NULL; + e_select_names_model_text_pos (selcomp->priv->model, pos, &index, NULL, NULL); + str = index >= 0 ? e_select_names_model_get_string (selcomp->priv->model, index) : NULL; if (out) fprintf (out, "index=%d str=\"%s\"\n", index, str); @@ -1227,12 +1225,13 @@ e_select_names_completion_book_ready (EBook *book, EBookStatus status, ESelectNa */ ECompletion * -e_select_names_completion_new (EBook *book, ESelectNamesTextModel *text_model) +e_select_names_completion_new (EBook *book, ESelectNamesModel *model) { ESelectNamesCompletion *comp; g_return_val_if_fail (book == NULL || E_IS_BOOK (book), NULL); - g_return_val_if_fail (E_IS_SELECT_NAMES_TEXT_MODEL (text_model), NULL); + g_return_val_if_fail (model, NULL); + g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL); comp = (ESelectNamesCompletion *) gtk_type_new (e_select_names_completion_get_type ()); @@ -1254,8 +1253,8 @@ e_select_names_completion_new (EBook *book, ESelectNamesTextModel *text_model) e_select_names_completion_add_book (comp, book); } - comp->priv->text_model = text_model; - gtk_object_ref (GTK_OBJECT (text_model)); + comp->priv->model = model; + gtk_object_ref (GTK_OBJECT (model)); return E_COMPLETION (comp); } 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 53978ac502..e2b0238123 100644 --- a/addressbook/gui/component/select-names/e-select-names-manager.c +++ b/addressbook/gui/component/select-names/e-select-names-manager.c @@ -2,9 +2,8 @@ /* * Authors: * Chris Lahey <clahey@ximian.com> - * Jon Trowbridge <trow@ximian.com. * - * Copyright (C) 2000, 2001 Ximian, Inc. + * Copyright (C) 2000 Ximian, Inc. */ #include <config.h> @@ -27,10 +26,15 @@ #include <bonobo/bonobo-object.h> #include <bonobo/bonobo-moniker-util.h> +/* Object argument IDs */ +enum { + ARG_0, + ARG_CARD, +}; + enum { CHANGED, OK, - CANCEL, LAST_SIGNAL }; @@ -43,442 +47,489 @@ typedef struct { ESelectNamesModel *model; ESelectNamesModel *original_model; ESelectNamesManager *manager; - guint changed_tag; + guint changed_handler; } ESelectNamesManagerSection; typedef struct { char *id; EEntry *entry; - ESelectNamesManager *manager; - ESelectNamesModel *model; - guint cleaning_tag; } ESelectNamesManagerEntry; static void e_select_names_manager_init (ESelectNamesManager *manager); static void e_select_names_manager_class_init (ESelectNamesManagerClass *klass); static void e_select_names_manager_destroy (GtkObject *object); +static void e_select_names_manager_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void e_select_names_manager_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ +/** + * e_select_names_manager_get_type: + * @void: + * + * Registers the &ESelectNamesManager class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &ESelectNamesManager class. + **/ +GtkType +e_select_names_manager_get_type (void) +{ + static GtkType manager_type = 0; -/* ESelectNamesManagerSection routines */ + if (!manager_type) { + GtkTypeInfo manager_info = { + "ESelectNamesManager", + sizeof (ESelectNamesManager), + sizeof (ESelectNamesManagerClass), + (GtkClassInitFunc) e_select_names_manager_class_init, + (GtkObjectInitFunc) e_select_names_manager_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + manager_type = gtk_type_unique (gtk_object_get_type (), &manager_info); + } + + return manager_type; +} static void -section_model_changed_cb (ESelectNamesModel *model, gpointer closure) +open_book_cb (EBook *book, EBookStatus status, ESelectNamesManager *manager) { - ESelectNamesManagerSection *section = closure; - gtk_signal_emit (GTK_OBJECT (section->manager), - e_select_names_manager_signals[CHANGED], - section->id, - FALSE); + if (status != E_BOOK_STATUS_SUCCESS) { + gtk_object_unref (GTK_OBJECT (book)); + manager->completion_book = NULL; + } + + gtk_object_unref (GTK_OBJECT (manager)); /* unref ourself (matches ref before the load_uri call below) */ } -static ESelectNamesManagerSection * -e_select_names_manager_section_new (ESelectNamesManager *manager, - const gchar *id, - const gchar *title, - ESelectNamesModel *model) +/** + * e_select_names_manager_new: + * @VCard: a string in vCard format + * + * Returns: a new #ESelectNamesManager that wraps the @VCard. + */ +ESelectNamesManager * +e_select_names_manager_new (void) { - ESelectNamesManagerSection *section; + ESelectNamesManager *manager = E_SELECT_NAMES_MANAGER(gtk_type_new(e_select_names_manager_get_type())); + Bonobo_ConfigDatabase db; + CORBA_Environment ev; + char *val; - g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL); - g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL); + CORBA_exception_init (&ev); - section = g_new0 (ESelectNamesManagerSection, 1); + db = addressbook_config_database (&ev); - section->id = g_strdup (id); - section->title = g_strdup (title); + val = bonobo_config_get_string (db, "/Addressbook/Completion/uri", &ev); - section->manager = manager; + CORBA_exception_free (&ev); - section->model = model; - gtk_object_ref (GTK_OBJECT (section->model)); - section->changed_tag = - gtk_signal_connect (GTK_OBJECT (section->model), - "changed", - GTK_SIGNAL_FUNC (section_model_changed_cb), - section); + if (val) { + manager->completion_book = e_book_new (); + gtk_object_ref (GTK_OBJECT (manager)); /* ref ourself before our async call */ + addressbook_load_uri (manager->completion_book, val, (EBookCallback)open_book_cb, manager); + g_free (val); + } + else + manager->completion_book = NULL; - return section; + return manager; } static void -e_select_names_manager_section_free (ESelectNamesManagerSection *section) +e_select_names_manager_class_init (ESelectNamesManagerClass *klass) { - if (section == NULL) - return; - - g_free (section->id); - g_free (section->title); + GtkObjectClass *object_class; - if (section->model) { - gtk_signal_disconnect (GTK_OBJECT (section->model), section->changed_tag); - gtk_object_unref (GTK_OBJECT (section->model)); - } + object_class = GTK_OBJECT_CLASS(klass); - if (section->original_model) { - gtk_object_unref (GTK_OBJECT (section->original_model)); - } + gtk_object_add_arg_type ("ESelectNamesManager::card", + GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_CARD); - g_free (section); -} + object_class->destroy = e_select_names_manager_destroy; + object_class->get_arg = e_select_names_manager_get_arg; + object_class->set_arg = e_select_names_manager_set_arg; -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + e_select_names_manager_signals[CHANGED] = + gtk_signal_new ("changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ESelectNamesManagerClass, changed), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, + GTK_TYPE_INT); -/* ESelectNamesManagerEntry routines */ + e_select_names_manager_signals[OK] = + gtk_signal_new ("ok", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ESelectNamesManagerClass, ok), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); -static ESelectNamesManagerEntry * -get_entry_info (EEntry *entry) -{ - g_return_val_if_fail (E_IS_ENTRY (entry), NULL); - return (ESelectNamesManagerEntry *) gtk_object_get_data (GTK_OBJECT (entry), "entry_info"); + gtk_object_class_add_signals (object_class, e_select_names_manager_signals, LAST_SIGNAL); } +/* + * ESelectNamesManager lifecycle management and vcard loading/saving. + */ + static void -popup_cb (EEntry *eentry, GdkEventButton *ev, gint pos, gpointer user_data) +e_select_names_manager_destroy (GtkObject *object) { - ESelectNamesTextModel *text_model; + ESelectNamesManager *manager; + + manager = E_SELECT_NAMES_MANAGER (object); - gtk_object_get (GTK_OBJECT (eentry), - "model", &text_model, - NULL); - g_assert (E_IS_SELECT_NAMES_TEXT_MODEL (text_model)); + gtk_object_unref(GTK_OBJECT(manager->sections)); + gtk_object_unref(GTK_OBJECT(manager->entries)); - e_select_names_popup (text_model, ev, pos); + if (manager->names) { + gtk_widget_destroy (GTK_WIDGET (manager->names)); + manager->names = NULL; + } } -static gboolean -clean_cb (gpointer ptr) -{ - ESelectNamesManagerEntry *entry = ptr; - - e_select_names_model_clean (entry->model, TRUE); - entry->cleaning_tag = 0; - return FALSE; -} -static gint -focus_in_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data) +/* Set_arg handler for the manager */ +static void +e_select_names_manager_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) { - ESelectNamesManagerEntry *entry = user_data; + ESelectNamesManager *manager; + + manager = E_SELECT_NAMES_MANAGER (object); - if (entry->cleaning_tag) { - gtk_timeout_remove (entry->cleaning_tag); - entry->cleaning_tag = 0; + switch (arg_id) { + case ARG_CARD: + break; + default: + return; } - - e_select_names_model_cancel_cardify_all (entry->model); - - return FALSE; } -static gint -focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data) +/* Get_arg handler for the manager */ +static void +e_select_names_manager_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) { - ESelectNamesManagerEntry *entry = user_data; - gboolean visible = e_entry_completion_popup_is_visible (entry->entry); + ESelectNamesManager *manager; - if (! visible) { - e_select_names_model_cardify_all (entry->model, entry->manager->completion_book, 100); - if (entry->cleaning_tag == 0) - entry->cleaning_tag = gtk_timeout_add (100, clean_cb, entry); - } + manager = E_SELECT_NAMES_MANAGER (object); - return FALSE; + switch (arg_id) { + case ARG_CARD: + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } } -static void -completion_popup_cb (EEntry *w, gint visible, gpointer user_data) +static void * +section_copy(const void *sec, void *data) { - ESelectNamesManagerEntry *entry = user_data; - - if (!visible && !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->entry->canvas))) - e_select_names_model_cardify_all (entry->model, entry->manager->completion_book, 0); + const ESelectNamesManagerSection *section = sec; + ESelectNamesManagerSection *newsec; + + static void section_model_changed_cb (ESelectNamesModel *, gpointer); + + newsec = g_new(ESelectNamesManagerSection, 1); + 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", + GTK_SIGNAL_FUNC (section_model_changed_cb), + newsec); + + if (newsec->model) + gtk_object_ref(GTK_OBJECT(newsec->model)); + if (newsec->original_model) + gtk_object_ref(GTK_OBJECT(newsec->original_model)); + + return newsec; } static void -completion_handler (EEntry *entry, ECompletionMatch *match) +section_free(void *sec, void *data) { - ESelectNamesManagerEntry *mgr_entry; - ESelectNamesTextModel *text_model; - EDestination *dest; - gint i, pos, start_pos, len; - - if (match == NULL || match->user_data == NULL) - return; - - mgr_entry = get_entry_info (entry); - 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 - bitch. */ - gtk_object_ref (GTK_OBJECT (dest)); - - gtk_object_get (GTK_OBJECT (entry), - "model", &text_model, - NULL); - g_assert (E_IS_SELECT_NAMES_TEXT_MODEL (text_model)); + ESelectNamesManagerSection *section = sec; + if (section->manager && section->changed_handler) { + gtk_signal_disconnect (GTK_OBJECT (section->model), section->changed_handler); + } + g_free(section->id); + g_free(section->title); + if (section->model) + gtk_object_unref (GTK_OBJECT(section->model)); + if (section->original_model) + gtk_object_unref (GTK_OBJECT (section->original_model)); - pos = e_entry_get_position (entry); - e_select_names_model_text_pos (mgr_entry->model, text_model->seplen, pos, &i, NULL, NULL); - e_select_names_model_replace (mgr_entry->model, i, dest); - e_select_names_model_name_pos (mgr_entry->model, text_model->seplen, i, &start_pos, &len); - e_entry_set_position (entry, start_pos+len); + g_free(section); } -static ESelectNamesManagerEntry * -e_select_names_manager_entry_new (ESelectNamesManager *manager, ESelectNamesModel *model, const gchar *id) +static void * +entry_copy(const void *ent, void *data) { - ESelectNamesManagerEntry *entry; - ETextModel *text_model; - ECompletion *comp; - - g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL); - g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL); - - entry = g_new0 (ESelectNamesManagerEntry, 1); - - entry->id = g_strdup (id); - - entry->entry = E_ENTRY (e_entry_new ()); - text_model = e_select_names_text_model_new (model); - gtk_object_set(GTK_OBJECT(entry->entry), - "model", text_model, /* The entry takes ownership of the text model */ - "editable", TRUE, - "use_ellipsis", TRUE, - "allow_newlines", FALSE, - NULL); - - gtk_object_ref (GTK_OBJECT (entry->entry)); - - comp = e_select_names_completion_new (NULL, E_SELECT_NAMES_TEXT_MODEL (text_model)); - if (manager->completion_book) - e_select_names_completion_add_book (E_SELECT_NAMES_COMPLETION (comp), - manager->completion_book); - - e_entry_enable_completion_full (entry->entry, comp, 50, completion_handler); - - entry->manager = manager; - - entry->model = model; - gtk_object_ref (GTK_OBJECT (model)); - - gtk_signal_connect (GTK_OBJECT (entry->entry), - "popup", - GTK_SIGNAL_FUNC (popup_cb), - entry); - - gtk_signal_connect (GTK_OBJECT (entry->entry->canvas), - "focus_in_event", - GTK_SIGNAL_FUNC (focus_in_cb), - entry); + const ESelectNamesManagerEntry *entry = ent; + ESelectNamesManagerEntry *newent; - gtk_signal_connect (GTK_OBJECT (entry->entry->canvas), - "focus_out_event", - GTK_SIGNAL_FUNC (focus_out_cb), - entry); - - gtk_signal_connect (GTK_OBJECT (entry->entry), - "completion_popup", - GTK_SIGNAL_FUNC (completion_popup_cb), - entry); - - gtk_object_set_data (GTK_OBJECT (entry->entry), "entry_info", entry); - gtk_object_set_data (GTK_OBJECT (entry->entry), "select_names_model", model); - gtk_object_set_data (GTK_OBJECT (entry->entry), "select_names_text_model", text_model); - gtk_object_set_data (GTK_OBJECT (entry->entry), "completion_handler", comp); - - return entry; + newent = g_new(ESelectNamesManagerEntry, 1); + newent->id = g_strdup(entry->id); + newent->entry = entry->entry; + if (newent->entry) + gtk_object_ref(GTK_OBJECT(newent->entry)); + return newent; } static void -e_select_names_manager_entry_free (ESelectNamesManagerEntry *entry) +entry_free(void *ent, void *data) { - if (entry == NULL) - return; + ESelectNamesManagerEntry *entry = ent; + g_free(entry->id); + if (entry->entry) + gtk_object_unref(GTK_OBJECT(entry->entry)); + g_free(entry); +} - g_free (entry->id); - gtk_object_unref (GTK_OBJECT (entry->model)); - gtk_object_unref (GTK_OBJECT (entry->entry)); +/** + * e_select_names_manager_init: + */ +static void +e_select_names_manager_init (ESelectNamesManager *manager) +{ + manager->sections = e_list_new(section_copy, section_free, manager); + manager->entries = e_list_new(entry_copy, entry_free, manager); +} - if (entry->cleaning_tag) - gtk_timeout_remove (entry->cleaning_tag); +static void +section_model_changed_cb (ESelectNamesModel *model, gpointer closure) +{ + ESelectNamesManagerSection *section = closure; + gtk_signal_emit (GTK_OBJECT (section->manager), + e_select_names_manager_signals[CHANGED], + section->id, + FALSE); +} - g_free (entry); +static void +section_model_working_copy_changed_cb (ESelectNamesModel *model, gpointer closure) +{ + ESelectNamesManagerSection *section = closure; + gtk_signal_emit (GTK_OBJECT (section->manager), + e_select_names_manager_signals[CHANGED], + section->id, + TRUE); } -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ +void +e_select_names_manager_add_section (ESelectNamesManager *manager, + const char *id, + const char *title) +{ + e_select_names_manager_add_section_with_limit (manager, id, title, -1); +} -static void -e_select_names_manager_save_models (ESelectNamesManager *manager) +void +e_select_names_manager_add_section_with_limit (ESelectNamesManager *manager, + const char *id, + const char *title, + gint limit) { - GList *iter; + ESelectNamesManagerSection *section; - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; + section = g_new(ESelectNamesManagerSection, 1); + section->id = g_strdup(id); + section->title = g_strdup(title); - if (section->original_model == NULL && section->model != NULL) - section->original_model = e_select_names_model_duplicate (section->model); + section->model = e_select_names_model_new(); + e_select_names_model_set_limit (section->model, limit); - } -} + section->original_model = NULL; -static void -e_select_names_manager_revert_to_saved_models (ESelectNamesManager *manager) -{ - GList *iter; + section->manager = manager; - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; - if (section->model && section->original_model) { - e_select_names_model_overwrite_copy (section->model, section->original_model); - gtk_object_unref (GTK_OBJECT (section->original_model)); - section->original_model = NULL; - } - } + section->changed_handler = gtk_signal_connect (GTK_OBJECT (section->model), + "changed", + GTK_SIGNAL_FUNC (section_model_changed_cb), + section); + + e_list_append(manager->sections, section); + section_free(section, manager); } -static void -e_select_names_manager_discard_saved_models (ESelectNamesManager *manager) +ESelectNamesModel * +e_select_names_manager_get_source (ESelectNamesManager *manager, const char *id) { - GList *iter; + EIterator *iterator; - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; - if (section->original_model) { - gtk_object_unref (GTK_OBJECT (section->original_model)); - section->original_model = NULL; + g_return_val_if_fail (manager && E_IS_SELECT_NAMES_MANAGER (manager), NULL); + g_return_val_if_fail (id, NULL); + + 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 section->model; } } -} - -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + return NULL; +} static void -open_book_cb (EBook *book, EBookStatus status, ESelectNamesManager *manager) +entry_destroyed(EEntry *entry, ESelectNamesManager *manager) { - if (status != E_BOOK_STATUS_SUCCESS) { - gtk_object_unref (GTK_OBJECT (book)); - manager->completion_book = NULL; + if(!GTK_OBJECT_DESTROYED(manager)) { + EIterator *iterator = e_list_get_iterator(manager->entries); + for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { + const ESelectNamesManagerEntry *this_entry = e_iterator_get(iterator); + if(entry == this_entry->entry) { + e_iterator_delete(iterator); + break; + } + } } - - gtk_object_unref (GTK_OBJECT (manager)); /* unref ourself (matches ref before the load_uri call below) */ } -/** - * e_select_names_manager_new: - * @VCard: a string in vCard format - * - * Returns: a new #ESelectNamesManager that wraps the @VCard. - */ -ESelectNamesManager * -e_select_names_manager_new (void) +static void +completion_handler (EEntry *entry, ECompletionMatch *match) { - ESelectNamesManager *manager = E_SELECT_NAMES_MANAGER(gtk_type_new(e_select_names_manager_get_type())); - Bonobo_ConfigDatabase db; - CORBA_Environment ev; - char *val; - - CORBA_exception_init (&ev); + ESelectNamesModel *snm; + EDestination *dest; + gint i, pos, start_pos, len; - db = addressbook_config_database (&ev); + if (match == NULL || match->user_data == NULL) + return; - val = bonobo_config_get_string (db, "/Addressbook/Completion/uri", &ev); - CORBA_exception_free (&ev); + snm = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model")); + dest = E_DESTINATION (match->user_data); - if (val) { - manager->completion_book = e_book_new (); - gtk_object_ref (GTK_OBJECT (manager)); /* ref ourself before our async call */ - addressbook_load_uri (manager->completion_book, val, (EBookCallback)open_book_cb, manager); - g_free (val); - } - else - manager->completion_book = NULL; + /* Sometimes I really long for garbage collection. Reference + counting makes you feel 31337, but sometimes it is just a + bitch. */ + gtk_object_ref (GTK_OBJECT (dest)); - return manager; + pos = e_entry_get_position (entry); + e_select_names_model_text_pos (snm, pos, &i, NULL, NULL); + e_select_names_model_replace (snm, i, dest); + e_select_names_model_name_pos (snm, i, &start_pos, &len); + e_entry_set_position (entry, start_pos+len); } +static void +popup_cb (EEntry *entry, GdkEventButton *ev, gint pos, ESelectNamesModel *model) +{ + e_select_names_popup (model, ev, pos); +} -/* - * ESelectNamesManager lifecycle management and vcard loading/saving. - */ +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); -void -e_select_names_manager_add_section (ESelectNamesManager *manager, - const char *id, - const char *title) -{ - g_return_if_fail (E_IS_SELECT_NAMES_MANAGER (manager)); - g_return_if_fail (id != NULL); - g_return_if_fail (title != NULL); - - e_select_names_manager_add_section_with_limit (manager, id, title, -1); + return FALSE; } -void -e_select_names_manager_add_section_with_limit (ESelectNamesManager *manager, - const char *id, - const char *title, - gint limit) +static gint +focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data) { - ESelectNamesManagerSection *section; - ESelectNamesModel *model; + EEntry *entry = E_ENTRY (user_data); + ESelectNamesModel *model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model")); + ESelectNamesManager *manager = E_SELECT_NAMES_MANAGER (gtk_object_get_data (GTK_OBJECT (entry), "select_names_manager")); - g_return_if_fail (E_IS_SELECT_NAMES_MANAGER (manager)); - g_return_if_fail (id != NULL); - g_return_if_fail (title != NULL); - - model = e_select_names_model_new (); - e_select_names_model_set_limit (model, limit); - - section = e_select_names_manager_section_new (manager, id, title, model); + e_select_names_model_clean (model); - manager->sections = g_list_append (manager->sections, section); + if (!e_entry_completion_popup_is_visible (entry)) + e_select_names_model_cardify_all (model, manager->completion_book, 100); - gtk_object_unref (GTK_OBJECT (model)); + return FALSE; } -ESelectNamesModel * -e_select_names_manager_get_source (ESelectNamesManager *manager, - const char *id) +static void +completion_popup_cb (EEntry *entry, gint visible, gpointer user_data) { - GList *iter; + ESelectNamesModel *model = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model")); + ESelectNamesManager *manager = E_SELECT_NAMES_MANAGER (gtk_object_get_data (GTK_OBJECT (entry), "select_names_manager")); - g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL); - g_return_val_if_fail (id != NULL, NULL); - - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; - if (!strcmp (section->id, id)) - return section->model; - } - return NULL; + if (!visible && !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->canvas))) + e_select_names_model_cardify_all (model, manager->completion_book, 0); } GtkWidget * e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *id) { - GList *iter; - - g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL); - g_return_val_if_fail (id != NULL, NULL); - - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; + ETextModel *model; + 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)) { ESelectNamesManagerEntry *entry; + EEntry *eentry; + ECompletion *comp; - entry = e_select_names_manager_entry_new (manager, section->model, section->id); - manager->entries = g_list_append (manager->entries, entry); + eentry = E_ENTRY (e_entry_new ()); + gtk_object_set_data (GTK_OBJECT (eentry), "select_names_model", section->model); + gtk_object_set_data (GTK_OBJECT (eentry), "select_names_manager", manager); - return GTK_WIDGET(entry->entry); + gtk_signal_connect (GTK_OBJECT (eentry), + "popup", + 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; + + gtk_object_ref (GTK_OBJECT (entry->entry)); + + model = e_select_names_text_model_new (section->model); + e_list_append (manager->entries, entry); + g_free(entry); + + comp = e_select_names_completion_new (NULL, section->model); + if (manager->completion_book) + e_select_names_completion_add_book (E_SELECT_NAMES_COMPLETION (comp), + manager->completion_book); + e_entry_enable_completion_full (eentry, comp, 50, completion_handler); + + gtk_object_set_data (GTK_OBJECT (eentry), "completion_handler", comp); + + gtk_object_set(GTK_OBJECT(eentry), + "model", model, + "editable", TRUE, + "use_ellipsis", TRUE, + "allow_newlines", FALSE, + NULL); + + gtk_signal_connect(GTK_OBJECT(eentry), "destroy", + GTK_SIGNAL_FUNC(entry_destroyed), manager); + + return GTK_WIDGET(eentry); } } - return NULL; } @@ -489,159 +540,59 @@ e_select_names_clicked(ESelectNames *dialog, gint button, ESelectNamesManager *m switch(button) { case 0: - e_select_names_manager_discard_saved_models (manager); + /* We don't need to do much if they click on OK */ + gtk_signal_emit (GTK_OBJECT (manager), e_select_names_manager_signals[OK]); break; - case 1: - e_select_names_manager_revert_to_saved_models (manager); - gtk_signal_emit (GTK_OBJECT (manager), e_select_names_manager_signals[CANCEL]); + 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); + e_select_names_model_overwrite_copy (section->model, section->original_model); + } + + gtk_object_unref(GTK_OBJECT(iterator)); break; } + } } void e_select_names_manager_activate_dialog (ESelectNamesManager *manager, const char *id) { - g_return_if_fail (E_IS_SELECT_NAMES_MANAGER (manager)); - g_return_if_fail (id != NULL); - + EIterator *iterator; + if (manager->names) { - g_assert (GTK_WIDGET_REALIZED (GTK_WIDGET (manager->names))); - e_select_names_set_default (manager->names, id); + e_select_names_set_default(manager->names, id); gdk_window_show (GTK_WIDGET (manager->names)->window); gdk_window_raise (GTK_WIDGET (manager->names)->window); - } else { - - GList *iter; - manager->names = E_SELECT_NAMES (e_select_names_new ()); - for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) { - ESelectNamesManagerSection *section = iter->data; + iterator = e_list_get_iterator(manager->sections); + for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) { + 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 */ } - - e_select_names_set_default (manager->names, id); - - gtk_signal_connect(GTK_OBJECT(manager->names), - "clicked", - GTK_SIGNAL_FUNC(e_select_names_clicked), - manager); - - gtk_signal_connect(GTK_OBJECT(manager->names), - "destroy", + e_select_names_set_default(manager->names, id); + gtk_signal_connect(GTK_OBJECT(manager->names), "clicked", + GTK_SIGNAL_FUNC(e_select_names_clicked), manager); + gtk_signal_connect(GTK_OBJECT(manager->names), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &manager->names); - gtk_widget_show(GTK_WIDGET(manager->names)); } - - e_select_names_manager_save_models (manager); -} - -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -static void -e_select_names_manager_init (ESelectNamesManager *manager) -{ - manager->sections = NULL; - manager->entries = NULL; } -static void -e_select_names_manager_destroy (GtkObject *object) -{ - ESelectNamesManager *manager; - - manager = E_SELECT_NAMES_MANAGER (object); - - if (manager->names) { - gtk_widget_destroy (GTK_WIDGET (manager->names)); - manager->names = NULL; - } - - g_list_foreach (manager->sections, (GFunc) e_select_names_manager_section_free, NULL); - g_list_free (manager->sections); - manager->sections = NULL; - - g_list_foreach (manager->entries, (GFunc) e_select_names_manager_entry_free, NULL); - g_list_free (manager->entries); - manager->entries = NULL; -} - -static void -e_select_names_manager_class_init (ESelectNamesManagerClass *klass) -{ - GtkObjectClass *object_class; - - object_class = GTK_OBJECT_CLASS(klass); - - object_class->destroy = e_select_names_manager_destroy; - - e_select_names_manager_signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ESelectNamesManagerClass, changed), - gtk_marshal_NONE__POINTER_INT, - GTK_TYPE_NONE, 2, - GTK_TYPE_POINTER, - GTK_TYPE_INT); - - e_select_names_manager_signals[OK] = - gtk_signal_new ("ok", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ESelectNamesManagerClass, ok), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - e_select_names_manager_signals[CANCEL] = - gtk_signal_new ("cancel", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ESelectNamesManagerClass, cancel), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, e_select_names_manager_signals, LAST_SIGNAL); -} - -/** - * e_select_names_manager_get_type: - * @void: - * - * Registers the &ESelectNamesManager class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &ESelectNamesManager class. - **/ -GtkType -e_select_names_manager_get_type (void) -{ - static GtkType manager_type = 0; - - if (!manager_type) { - GtkTypeInfo manager_info = { - "ESelectNamesManager", - sizeof (ESelectNamesManager), - sizeof (ESelectNamesManagerClass), - (GtkClassInitFunc) e_select_names_manager_class_init, - (GtkObjectInitFunc) e_select_names_manager_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - manager_type = gtk_type_unique (gtk_object_get_type (), &manager_info); - } - - return manager_type; -} - - - diff --git a/addressbook/gui/component/select-names/e-select-names.c b/addressbook/gui/component/select-names/e-select-names.c index 095d928a41..680dd62a34 100644 --- a/addressbook/gui/component/select-names/e-select-names.c +++ b/addressbook/gui/component/select-names/e-select-names.c @@ -42,7 +42,7 @@ #include "e-select-names.h" #include <addressbook/backend/ebook/e-card-simple.h> -#include "e-select-names-text-model.h" +#include "e-select-names-table-model.h" #include <gal/widgets/e-categories-master-list-combo.h> #include <gal/widgets/e-unicode.h> #include <gal/e-text/e-entry.h> @@ -63,12 +63,11 @@ enum { }; typedef struct { - char *title; - ETableModel *model; - ESelectNamesModel *source; - ESelectNamesTextModel *text_model; - ESelectNames *names; - GtkWidget *label; + char *title; + ETableModel *model; + ESelectNamesModel *source; + ESelectNames *names; + GtkWidget *label; } ESelectNamesChild; GtkType @@ -216,7 +215,7 @@ real_add_address_cb (int model_row, gpointer closure) e_destination_set_card (dest, card, 0); e_select_names_model_append (child->source, dest); - e_select_names_model_clean (child->source, FALSE); + e_select_names_model_clean (child->source); gtk_object_unref(GTK_OBJECT(card)); } @@ -514,11 +513,10 @@ add_additional_select_names_uris (ESelectNames *e_select_names, CORBA_Environmen Bonobo_ConfigDatabase config_db; guint32 num_additional_uris; int i; - gboolean flag; config_db = addressbook_config_database (ev); - num_additional_uris = bonobo_config_get_ulong_with_default (config_db, "/Addressbook/additional_select_names_folders/num", 0, &flag); + num_additional_uris = bonobo_config_get_ulong_with_default (config_db, "/Addressbook/additional_select_names_folders/num", 0, ev); for (i = 0; i < num_additional_uris; i ++) { ESelectNamesFolder *e_folder; char *config_path; @@ -777,21 +775,18 @@ button_clicked(GtkWidget *button, ESelectNamesChild *child) real_add_address(child->names, child); } -#if 0 static void remove_address(ETable *table, int row, int col, GdkEvent *event, ESelectNamesChild *child) { e_select_names_model_delete (child->source, row); } -#endif struct _RightClickData { + ETable *table; ESelectNamesChild *child; - int index; }; typedef struct _RightClickData RightClickData; -#if 0 static GSList *selected_rows = NULL; static void @@ -810,38 +805,47 @@ selected_rows_foreach_cb (void *row, void *data) remove_address (NULL, GPOINTER_TO_INT (row), 0, NULL, child); } -#endif static void remove_cb (GtkWidget *widget, void *data) { RightClickData *rcdata = (RightClickData *)data; - e_select_names_model_delete (rcdata->child->source, rcdata->index); + e_select_names_model_freeze (rcdata->child->source); + + /* Build a list of selected rows */ + e_table_selected_row_foreach (rcdata->table, + etable_selection_foreach_cb, + rcdata->child); + + /* Now process the list we made, removing each selected row */ + g_slist_foreach (selected_rows, + (GFunc)selected_rows_foreach_cb, + rcdata->child); + + e_select_names_model_thaw (rcdata->child->source); /* Free everything we've created */ g_free (rcdata); + g_slist_free (selected_rows); + selected_rows = NULL; } static void -section_right_click_cb (EText *text, GdkEventButton *ev, gint pos, ESelectNamesChild *child) +section_right_click_cb (ETable *table, gint row, gint col, GdkEvent *event, ESelectNamesChild *child) { EPopupMenu right_click_menu[] = { { N_("Remove"), NULL, GTK_SIGNAL_FUNC (remove_cb), NULL, 0 }, { NULL, NULL, NULL, 0 } }; - gint index; - - e_select_names_model_text_pos (child->source, child->text_model->seplen, pos, &index, NULL, NULL); - if (index != -1) { - RightClickData *rcdata = g_new0 (RightClickData, 1); - rcdata->index = index; - rcdata->child = child; + RightClickData *rcdata = g_new0 (RightClickData, 1); + rcdata->table = table; + rcdata->child = child; - e_popup_menu_run (right_click_menu, (GdkEvent *)ev, 0, 0, rcdata); - } + e_popup_menu_run (right_click_menu, event, 0, 0, + rcdata); } void @@ -854,8 +858,8 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E GtkTable *table; char *label_text; - GtkWidget *sw; - GtkWidget *recipient_table; + ETableModel *model; + GtkWidget *etable; if (g_hash_table_lookup(e_select_names->children, id)) { return; @@ -868,12 +872,6 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E child->names = e_select_names; child->title = e_utf8_from_locale_string(_(name)); - child->text_model = (ESelectNamesTextModel *) e_select_names_text_model_new (source); - e_select_names_text_model_set_separator (child->text_model, "\n"); - - child->source = source; - gtk_object_ref(GTK_OBJECT(child->source)); - e_select_names->child_count++; alignment = gtk_alignment_new(0, 0, 1, 0); @@ -910,38 +908,28 @@ e_select_names_add_section(ESelectNames *e_select_names, char *name, char *id, E e_select_names->child_count + 1, GTK_FILL, GTK_FILL, 0, 0); - - sw = gtk_scrolled_window_new (NULL, NULL); - recipient_table = e_entry_new (); - gtk_object_set (GTK_OBJECT (recipient_table), - "model", child->text_model, - "allow_newlines", TRUE, - NULL); - - gtk_signal_connect (GTK_OBJECT (recipient_table), - "popup", - GTK_SIGNAL_FUNC (section_right_click_cb), - child); + model = e_select_names_table_model_new(source); + etable = e_table_scrolled_new (model, NULL, SPEC2, NULL); - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), recipient_table); - -#if 0 gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(etable))), "right_click", GTK_SIGNAL_FUNC(section_right_click_cb), child); gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(etable))), "double_click", GTK_SIGNAL_FUNC(remove_address), child); -#endif + child->model = model; + 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_all (sw); + gtk_widget_show(etable); - gtk_table_attach(table, sw, + gtk_table_attach(table, etable, 1, 2, e_select_names->child_count, e_select_names->child_count + 1, |