From d369e177b199c4c798f0b6ad8972951d8586bcd9 Mon Sep 17 00:00:00 2001 From: Jon Trowbridge Date: Mon, 19 Feb 2001 22:49:18 +0000 Subject: When creating the entry, open up an ebook (corresponding to the local 2001-02-19 Jon Trowbridge * gui/component/select-names/e-select-names-manager.c (e_select_names_manager_create_entry): When creating the entry, open up an ebook (corresponding to the local addressbook) and make the entry use an EAddressCompletion. (completion_handler): Added; this is the actual completion handler, which manipulates the entry when the user selects something from the drop-down. * gui/component/select-names/e-select-names-model.c: Various hacks by clahey to unbreak e_select_names_model_add_item, e_select_names_model_replace_item (which I added) and e_select_names_model_remove_item. * gui/component/select-names/e-select-names-text-model.c (e_select_names_text_model_obj_count, e_select_names_text_model_get_nth_obj): Make chunks of text that correspond to ECards in the ESelectNamesModel be embedded objects. (e_select_names_text_model_activate_obj): On activation, pop up a contact editor for the embedded object's card. (e_select_names_text_model_model_changed): Fixed to work with ETextModel API changes. (e_select_names_text_model_set_text): Make const correct. (e_select_names_text_model_insert): Make const correct. (e_select_names_text_model_insert_length): Make const correct. * backend/ebook/e-address-completion.h, backend/ebook/e-address-completion.c: Added. EAddressCompletion is a derived class of ECompletion that does asynchronous address lookups for completions. svn path=/trunk/; revision=8282 --- addressbook/ChangeLog | 32 +++ addressbook/backend/ebook/Makefile.am | 19 +- addressbook/backend/ebook/e-address-completion.c | 315 +++++++++++++++++++++ addressbook/backend/ebook/e-address-completion.h | 65 +++++ addressbook/gui/component/select-names/Makefile.am | 2 + .../select-names/e-select-names-manager.c | 41 ++- .../component/select-names/e-select-names-model.c | 36 ++- .../component/select-names/e-select-names-model.h | 3 + .../select-names/e-select-names-text-model.c | 115 ++++++-- 9 files changed, 608 insertions(+), 20 deletions(-) create mode 100644 addressbook/backend/ebook/e-address-completion.c create mode 100644 addressbook/backend/ebook/e-address-completion.h (limited to 'addressbook') diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index 7a297fcc9e..6c6fcc952e 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,35 @@ +2001-02-19 Jon Trowbridge + + * gui/component/select-names/e-select-names-manager.c + (e_select_names_manager_create_entry): When creating the entry, + open up an ebook (corresponding to the local addressbook) and make + the entry use an EAddressCompletion. + (completion_handler): Added; this is the actual completion + handler, which manipulates the entry when the user selects + something from the drop-down. + + * gui/component/select-names/e-select-names-model.c: Various hacks + by clahey to unbreak e_select_names_model_add_item, + e_select_names_model_replace_item (which I added) and + e_select_names_model_remove_item. + + * gui/component/select-names/e-select-names-text-model.c + (e_select_names_text_model_obj_count, + e_select_names_text_model_get_nth_obj): Make chunks of text that + correspond to ECards in the ESelectNamesModel be embedded objects. + (e_select_names_text_model_activate_obj): On activation, pop up a + contact editor for the embedded object's card. + (e_select_names_text_model_model_changed): Fixed to work with + ETextModel API changes. + (e_select_names_text_model_set_text): Make const correct. + (e_select_names_text_model_insert): Make const correct. + (e_select_names_text_model_insert_length): Make const correct. + + * backend/ebook/e-address-completion.h, + backend/ebook/e-address-completion.c: Added. EAddressCompletion + is a derived class of ECompletion that does asynchronous address + lookups for completions. + 2001-02-17 Chris Toshok * backend/idl/addressbook.idl: add sequence typedef, and diff --git a/addressbook/backend/ebook/Makefile.am b/addressbook/backend/ebook/Makefile.am index 335f74cb4c..0072ef8820 100644 --- a/addressbook/backend/ebook/Makefile.am +++ b/addressbook/backend/ebook/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = test-card test-client test-client-list +noinst_PROGRAMS = test-card test-client test-client-list test-completion bin_PROGRAMS = evolution-gnomecard-importer \ load-pine-addressbook load-gnomecard-addressbook @@ -39,6 +39,7 @@ lib_LTLIBRARIES = libebook.la libebook_la_SOURCES = \ $(CORBA_SOURCE) \ + e-address-completion.c \ e-book-listener.c \ e-book-view-listener.c \ e-book-view.c \ @@ -50,6 +51,7 @@ libebook_la_SOURCES = \ libebookincludedir = $(includedir)/evolution/ebook libebookinclude_HEADERS = \ + e-address-completion.h \ e-book-listener.h \ e-book-types.h \ e-book-view-listener.h \ @@ -103,6 +105,17 @@ test_card_LDADD = \ $(top_builddir)/libversit/libversit.la \ $(top_builddir)/e-util/libeutil.la +test_completion_SOURCES = \ + test-completion.c + +test_completion_LDADD = \ + libebook.la \ + $(BONOBO_GNOME_LIBS) \ + $(EXTRA_GNOME_LIBS) \ + $(top_builddir)/e-util/ename/libename.la \ + $(top_builddir)/libversit/libversit.la \ + $(top_builddir)/e-util/libeutil.la + evolution_gnomecard_importer_SOURCES = \ evolution-gnomecard-importer.c evolution_gnomecard_importer_LDADD = \ @@ -151,3 +164,7 @@ oaf_DATA = $(oaf_in_files:.oaf.in=.oaf) # GNOME_Evolution_Addressbook_Pine_Importer.oafinfo EXTRA_DIST = $(oaf_in_files) $(oaf_DATA) + + + + diff --git a/addressbook/backend/ebook/e-address-completion.c b/addressbook/backend/ebook/e-address-completion.c new file mode 100644 index 0000000000..398782e13e --- /dev/null +++ b/addressbook/backend/ebook/e-address-completion.c @@ -0,0 +1,315 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * An auto-completer for addresses from the address book. + * + * Author: + * Jon Trowbridge + * + * Copyright (C) 2001 Ximian, Inc. + */ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include "e-address-completion.h" + +static void e_address_completion_class_init (EAddressCompletionClass *klass); +static void e_address_completion_init (EAddressCompletion *addr_comp); +static void e_address_completion_destroy (GtkObject *object); + +static GtkObjectClass *parent_class; + +typedef struct _BookQuery BookQuery; +struct _BookQuery { + EAddressCompletion *completion; + guint seq_no; + + gchar *text; + + EBookView *book_view; + guint card_added_id; + guint sequence_complete_id; +}; + +static BookQuery *book_query_new (EAddressCompletion *, const gchar *query_text); +static void book_query_attach_book_view (BookQuery *, EBookView *); +static void book_query_free (BookQuery *); +static gboolean book_query_has_expired (BookQuery *); +static double book_query_score_e_card (BookQuery *, ECard *); +static void book_query_book_view_cb (EBook *, EBookStatus, EBookView *, gpointer book_query); +static void book_query_card_added_cb (EBookView *, const GList *cards, gpointer book_query); +static void book_query_sequence_complete_cb (EBookView *, gpointer book_query); + + + +GtkType +e_address_completion_get_type (void) +{ + static GtkType address_completion_type = 0; + + if (!address_completion_type) { + GtkTypeInfo address_completion_info = { + "EAddressCompletion", + sizeof (EAddressCompletion), + sizeof (EAddressCompletionClass), + (GtkClassInitFunc) e_address_completion_class_init, + (GtkObjectInitFunc) e_address_completion_init, + NULL, NULL, + (GtkClassInitFunc) NULL + }; + address_completion_type = gtk_type_unique (e_completion_get_type (), + &address_completion_info); + } + + return address_completion_type; +} + +static void +e_address_completion_class_init (EAddressCompletionClass *klass) +{ + GtkObjectClass *object_class = (GtkObjectClass *) klass; + + parent_class = GTK_OBJECT_CLASS (gtk_type_class (e_completion_get_type ())); + + object_class->destroy = e_address_completion_destroy; +} + +static void +e_address_completion_init (EAddressCompletion *addr_comp) +{ + +} + +static void +e_address_completion_destroy (GtkObject *object) +{ + EAddressCompletion *addr_comp = E_ADDRESS_COMPLETION (object); + + gtk_object_unref (GTK_OBJECT (addr_comp->book)); +} + +static BookQuery * +book_query_new (EAddressCompletion *comp, const gchar *text) +{ + BookQuery *q = g_new0 (BookQuery, 1); + + q->completion = comp; + gtk_object_ref (GTK_OBJECT (comp)); + + q->seq_no = comp->seq_no; + + q->text = g_strdup (text); + + return q; +} + +static void +book_query_attach_book_view (BookQuery *q, EBookView *book_view) +{ + g_return_if_fail (q); + + g_assert (q->book_view == NULL); + q->book_view = book_view; + gtk_object_ref (GTK_OBJECT (book_view)); + + q->card_added_id = gtk_signal_connect (GTK_OBJECT (book_view), + "card_added", + GTK_SIGNAL_FUNC (book_query_card_added_cb), + q); + q->sequence_complete_id = gtk_signal_connect (GTK_OBJECT (book_view), + "sequence_complete", + GTK_SIGNAL_FUNC (book_query_sequence_complete_cb), + q); +} + +static void +book_query_free (BookQuery *q) +{ + if (q) { + if (q->book_view) { + gtk_signal_disconnect (GTK_OBJECT (q->book_view), q->card_added_id); + gtk_signal_disconnect (GTK_OBJECT (q->book_view), q->sequence_complete_id); + gtk_object_unref (GTK_OBJECT (q->book_view)); + } + + gtk_object_unref (GTK_OBJECT (q->completion)); + + g_free (q->text); + + g_free (q); + } +} + +static gboolean +book_query_has_expired (BookQuery *q) +{ + g_return_val_if_fail (q != NULL, FALSE); + return q->seq_no != q->completion->seq_no; +} + +static double +book_query_score_e_card (BookQuery *q, ECard *card) +{ + gint len; + + g_return_val_if_fail (q != NULL, -1); + g_return_val_if_fail (card != NULL && E_IS_CARD (card), -1); + + len = strlen (q->text); + + if (card->name->given && !g_strncasecmp (card->name->given, q->text, len)) + return len; + + if (card->name->additional && !g_strncasecmp (card->name->additional, q->text, len)) + return len; + + if (card->name->family && !g_strncasecmp (card->name->family, q->text, len)) + return len; + + return 0.5; /* Not good, but we'll leave them in anyway for now... */ +} + +static gchar* +book_query_card_text (ECard *card) +{ + if (card->name) { + /* Sort of a lame hack. */ + return g_strdup_printf ("%s %s%s%s", + card->name->given ? card->name->given : "", + card->name->additional ? card->name->additional : "", + card->name->additional ? " " : "", + card->name->family ? card->name->family : ""); + } else if (card->fname) { + return g_strdup (card->fname); + } else if (card->file_as) { + return g_strdup (card->file_as); + } + + return NULL; +} + +static void +book_query_book_view_cb (EBook *book, EBookStatus status, EBookView *book_view, gpointer user_data) +{ + BookQuery *q = (BookQuery *) user_data; + + if (book_query_has_expired (q)) { + book_query_free (q); + return; + } + + book_query_attach_book_view (q, book_view); +} + +static void +book_query_card_added_cb (EBookView *book_view, const GList *cards, gpointer user_data) +{ + BookQuery *q = (BookQuery *) user_data; + + if (book_query_has_expired (q)) { + book_query_free (q); + return; + } + + while (cards) { + ECard *card = (ECard *) cards->data; + double score; + + if (card && (score = book_query_score_e_card (q, card)) >= 0) { + gchar *str = book_query_card_text (card); + + if (str) { + gtk_object_ref (GTK_OBJECT (card)); + e_completion_found_match_full (E_COMPLETION (q->completion), str, score, + card, (GtkDestroyNotify)gtk_object_unref); + } + } + + cards = g_list_next (cards); + } +} + +static void +book_query_sequence_complete_cb (EBookView *book_view, gpointer user_data) +{ + BookQuery *q = (BookQuery *) user_data; + + if (! book_query_has_expired (q)) { + e_completion_end_search (E_COMPLETION (q->completion)); + } + + book_query_free (q); +} + +static void +e_address_completion_begin (ECompletion *comp, const gchar *text, gint pos, gint limit, gpointer user_data) +{ + EAddressCompletion *addr_comp = E_ADDRESS_COMPLETION (comp); + BookQuery *q; + gchar *query; + + ++addr_comp->seq_no; /* Paranoia, in case completion_begin were to be called twice in a row + without an intervening completion_end. (Of course, this shouldn't + happen...) */ + q = book_query_new (addr_comp, text); + + query = g_strdup_printf ("(contains \"x-evolution-any-field\" \"%s\")", text); + e_book_get_book_view (addr_comp->book, query, book_query_book_view_cb, q); + g_free (query); +} + +static void +e_address_completion_end (ECompletion *comp, gboolean finished, gpointer user_data) +{ + EAddressCompletion *addr_comp = E_ADDRESS_COMPLETION (comp); + + ++addr_comp->seq_no; +} + +void +e_address_completion_construct (EAddressCompletion *addr_comp, EBook *book) +{ + g_return_if_fail (addr_comp != NULL); + g_return_if_fail (E_IS_ADDRESS_COMPLETION (addr_comp)); + g_return_if_fail (book != NULL); + g_return_if_fail (E_IS_BOOK (book)); + + /* No switching books mid-stream. */ + g_return_if_fail (addr_comp->book == NULL); + + e_completion_construct (E_COMPLETION (addr_comp), + e_address_completion_begin, + e_address_completion_end, + NULL); + + addr_comp->book = book; + gtk_object_ref (GTK_OBJECT (book)); +} + +ECompletion * +e_address_completion_new (EBook *book) +{ + gpointer ptr; + + g_return_val_if_fail (book != NULL, NULL); + g_return_val_if_fail (E_IS_BOOK (book), NULL); + + ptr = gtk_type_new (e_address_completion_get_type ()); + e_address_completion_construct (E_ADDRESS_COMPLETION (ptr), book); + return E_COMPLETION (ptr); +} diff --git a/addressbook/backend/ebook/e-address-completion.h b/addressbook/backend/ebook/e-address-completion.h new file mode 100644 index 0000000000..d0fca50cda --- /dev/null +++ b/addressbook/backend/ebook/e-address-completion.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * An auto-completer for addresses from the address book. + * + * Author: + * Jon Trowbridge + * + * Copyright (C) 2001 Ximian, Inc. + */ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef E_ADDRESS_COMPLETION_H +#define E_ADDRESS_COMPLETION_H + +#include "e-book.h" +#include + +BEGIN_GNOME_DECLS + +#define E_ADDRESS_COMPLETION_TYPE (e_address_completion_get_type ()) +#define E_ADDRESS_COMPLETION(o) (GTK_CHECK_CAST ((o), E_ADDRESS_COMPLETION_TYPE, EAddressCompletion)) +#define E_ADDRESS_COMPLETION_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), E_ADDRESS_COMPLETION_TYPE, EAddressCompletionClass)) +#define E_IS_ADDRESS_COMPLETION(o) (GTK_CHECK_TYPE ((o), E_ADDRESS_COMPLETION_TYPE)) +#define E_IS_ADDRESS_COMPLETION_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_ADDRESS_COMPLETION_TYPE)) + +typedef struct _EAddressCompletion EAddressCompletion; +typedef struct _EAddressCompletionClass EAddressCompletionClass; + +struct _EAddressCompletion { + ECompletion parent; + + EBook *book; + guint seq_no; +}; + +struct _EAddressCompletionClass { + ECompletionClass parent_class; +}; + +GtkType e_address_completion_get_type (void); + +void e_address_completion_construct (EAddressCompletion *addr_comp, EBook *book); +ECompletion *e_address_completion_new (EBook *book); + + + + +#endif /* E_ADDRESS_COMPLETION_H */ + diff --git a/addressbook/gui/component/select-names/Makefile.am b/addressbook/gui/component/select-names/Makefile.am index 0bbff76a71..312ff72ee7 100644 --- a/addressbook/gui/component/select-names/Makefile.am +++ b/addressbook/gui/component/select-names/Makefile.am @@ -67,6 +67,8 @@ libeselectnames_la_SOURCES = \ gladedir = $(datadir)/evolution/glade glade_DATA = select-names.glade + + EXTRA_DIST = \ $(glade_DATA) \ $(oaf_in_files) \ 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 3af59611ab..3e629af19d 100644 --- a/addressbook/gui/component/select-names/e-select-names-manager.c +++ b/addressbook/gui/component/select-names/e-select-names-manager.c @@ -16,6 +16,7 @@ #include "e-select-names-model.h" #include "e-select-names-text-model.h" #include "e-select-names.h" +#include #include /* Object argument IDs */ @@ -242,6 +243,32 @@ entry_destroyed(EEntry *entry, ESelectNamesManager *manager) gtk_object_unref(GTK_OBJECT(manager)); } +static void +completion_handler (EEntry *entry, const gchar *text, gpointer user_data) +{ + ESelectNamesModel *snm = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model")); + ESelectNamesModelData *data = g_new0 (ESelectNamesModelData, 1); + EIterator *iterator; + + data->type = E_SELECT_NAMES_MODEL_DATA_TYPE_CARD; + data->card = E_CARD (user_data); + gtk_object_ref (GTK_OBJECT (data->card)); + data->string = g_strdup (text); + + iterator = e_list_get_iterator (snm->data); + e_select_names_model_replace_item (snm, iterator, data); +} + +static void +set_completion (EBook *book, EBookStatus status, EEntry *entry) +{ + ECompletion *addr_comp; + + addr_comp = e_address_completion_new (book); + e_entry_enable_completion_full (entry, addr_comp, -1, completion_handler); + gtk_object_unref (GTK_OBJECT (book)); +} + GtkWidget *e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *id) { @@ -253,11 +280,23 @@ GtkWidget *e_select_names_manager_create_entry ( if (!strcmp(section->id, id)) { ESelectNamesManagerEntry *entry; EEntry *eentry; - eentry = E_ENTRY(e_entry_new()); + gchar *filename = gnome_util_prepend_user_home ("evolution/local/Contacts/addressbook.db"); + gchar *uri = g_strdup_printf ("file://%s", filename); + EBook *book; + eentry = E_ENTRY(e_entry_new()); + gtk_object_set_data (GTK_OBJECT (eentry), "select_names_model", section->model); + + book = e_book_new (); + gtk_object_ref (GTK_OBJECT (book)); + e_book_load_uri (book, uri, (EBookCallback) set_completion, eentry); + g_free (uri); + g_free (filename); + entry = g_new(ESelectNamesManagerEntry, 1); entry->entry = eentry; entry->id = (char *)id; + model = e_select_names_text_model_new(section->model); e_list_append(manager->entries, entry); g_free(entry); 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 0bbbe588a6..735840d2b3 100644 --- a/addressbook/gui/component/select-names/e-select-names-model.c +++ b/addressbook/gui/component/select-names/e-select-names-model.c @@ -420,13 +420,45 @@ e_select_names_model_replace (ESelectNamesModel *model, gtk_object_unref(GTK_OBJECT(iterator)); } +static void +esnm_add_item_real (ESelectNamesModel *model, + EIterator *iterator, /* NULL for at the beginning. */ + gboolean before, + ESelectNamesModelData *data) +{ + if (iterator == NULL) + iterator = e_list_get_iterator(model->data); + else + gtk_object_ref(GTK_OBJECT(iterator)); + + e_iterator_insert(iterator, data, before); + + gtk_object_unref(GTK_OBJECT(iterator)); +} + +static void +esnm_remove_item_real (ESelectNamesModel *model, + EIterator *iterator) +{ + e_iterator_delete(iterator); +} void e_select_names_model_add_item (ESelectNamesModel *model, EIterator *iterator, /* NULL for at the beginning. */ ESelectNamesModelData *data) { - e_iterator_insert(iterator, data, FALSE); + esnm_add_item_real(model, iterator, FALSE, data); + e_select_names_model_changed(model); +} + +void +e_select_names_model_replace_item (ESelectNamesModel *model, + EIterator *iterator, + ESelectNamesModelData *data) +{ + esnm_remove_item_real(model, iterator); + esnm_add_item_real(model, iterator, FALSE, data); e_select_names_model_changed(model); } @@ -434,7 +466,7 @@ void e_select_names_model_remove_item (ESelectNamesModel *model, EIterator *iterator) { - e_iterator_delete(iterator); + esnm_remove_item_real(model, iterator); 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 4ea1bdc8db..576d5e6a9a 100644 --- a/addressbook/gui/component/select-names/e-select-names-model.h +++ b/addressbook/gui/component/select-names/e-select-names-model.h @@ -78,6 +78,9 @@ void e_select_names_model_replace (ESelectNamesModel *mo void e_select_names_model_add_item (ESelectNamesModel *model, EIterator *iterator, /* NULL for at the beginning. */ ESelectNamesModelData *data); +void e_select_names_model_replace_item (ESelectNamesModel *model, + EIterator *iterator, + ESelectNamesModelData *data); void e_select_names_model_remove_item (ESelectNamesModel *model, EIterator *iterator); 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 71934c46dc..5983ccb93d 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 @@ -12,6 +12,7 @@ #include #include +#include #include "e-select-names-text-model.h" /* Object argument IDs */ @@ -27,11 +28,15 @@ static void e_select_names_text_model_destroy (GtkObject *object); static void e_select_names_text_model_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); static void e_select_names_text_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_select_names_text_model_set_text (ETextModel *model, gchar *text); -static void e_select_names_text_model_insert (ETextModel *model, gint position, gchar *text); -static void e_select_names_text_model_insert_length (ETextModel *model, gint position, gchar *text, gint length); +static void e_select_names_text_model_set_text (ETextModel *model, const gchar *text); +static void e_select_names_text_model_insert (ETextModel *model, gint position, const gchar *text); +static void e_select_names_text_model_insert_length (ETextModel *model, gint position, const gchar *text, gint length); static void e_select_names_text_model_delete (ETextModel *model, gint position, gint length); +static gint e_select_names_text_model_obj_count (ETextModel *model); +static const gchar *e_select_names_text_model_get_nth_obj (ETextModel *model, gint n, gint *len); +static void e_select_names_text_model_activate_obj (ETextModel *model, gint n); + static void e_select_names_text_model_model_changed (ESelectNamesModel *source, ESelectNamesTextModel *model); @@ -110,6 +115,10 @@ e_select_names_text_model_class_init (ESelectNamesTextModelClass *klass) text_model_class->insert = e_select_names_text_model_insert; text_model_class->insert_length = e_select_names_text_model_insert_length; text_model_class->delete = e_select_names_text_model_delete; + + text_model_class->obj_count = e_select_names_text_model_obj_count; + text_model_class->get_nth_obj = e_select_names_text_model_get_nth_obj; + text_model_class->object_activated = e_select_names_text_model_activate_obj; } static int @@ -120,14 +129,11 @@ get_length(EIterator *iterator) } static void -e_select_names_text_model_set_text (ETextModel *model, gchar *text) +e_select_names_text_model_set_text (ETextModel *model, const gchar *text) { ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL(model)->source; EIterator *iterator = e_list_get_iterator(e_select_names_model_get_data(source)); - int length = 0; - if (model->text) { - length = strlen(model->text); - } + int length = e_text_model_get_text_length (model); e_iterator_reset(iterator); if (!e_iterator_is_valid(iterator)) { @@ -138,13 +144,13 @@ e_select_names_text_model_set_text (ETextModel *model, gchar *text) iterator, 0, length, - text); + (gchar *) text); if (iterator) gtk_object_unref(GTK_OBJECT(iterator)); } static void -e_select_names_text_model_insert (ETextModel *model, gint position, gchar *text) +e_select_names_text_model_insert (ETextModel *model, gint position, const gchar *text) { ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL(model)->source; EIterator *iterator = e_list_get_iterator(e_select_names_model_get_data(source)); @@ -164,13 +170,13 @@ e_select_names_text_model_insert (ETextModel *model, gint position, gchar e_select_names_model_insert(source, iterator, position, - text); + (gchar *) text); if (iterator) gtk_object_unref(GTK_OBJECT(iterator)); } static void -e_select_names_text_model_insert_length (ETextModel *model, gint position, gchar *text, gint length) +e_select_names_text_model_insert_length (ETextModel *model, gint position, const gchar *text, gint length) { ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL(model)->source; EIterator *iterator = e_list_get_iterator(e_select_names_model_get_data(source)); @@ -190,7 +196,7 @@ e_select_names_text_model_insert_length (ETextModel *model, gint position, gchar e_select_names_model_insert_length(source, iterator, position, - text, + (gchar *) text, length); if (iterator) gtk_object_unref(GTK_OBJECT(iterator)); @@ -218,6 +224,83 @@ e_select_names_text_model_delete (ETextModel *model, gint position, gint gtk_object_unref(GTK_OBJECT(iterator)); } +static gint +e_select_names_text_model_obj_count (ETextModel *model) +{ + ESelectNamesModel *source = E_SELECT_NAMES_TEXT_MODEL (model)->source; + EIterator *iterator = e_list_get_iterator (e_select_names_model_get_data (source)); + gint count = 0; + + for (e_iterator_reset (iterator); e_iterator_is_valid (iterator); e_iterator_next (iterator)) { + const ESelectNamesModelData *data = e_iterator_get (iterator); + if (data->type == E_SELECT_NAMES_MODEL_DATA_TYPE_CARD) + ++count; + } + + return count; +} + +static const gchar * +e_select_names_text_model_get_nth_obj (ETextModel *model, gint n, gint *len) +{ + ESelectNamesTextModel *select_text_model = E_SELECT_NAMES_TEXT_MODEL (model); + ESelectNamesModel *source = select_text_model->source; + EIterator *iterator = e_list_get_iterator (e_select_names_model_get_data (source)); + const ESelectNamesModelData *data; + gint i, pos; + + pos = 0; + i = 0; + e_iterator_reset (iterator); + while (e_iterator_is_valid (iterator) && n > 0) { + gint len; + data = e_iterator_get (iterator); + len = strlen (data->string); + + pos += len + 1; /* advance and extra space for comma */ + ++i; + if (data->type == E_SELECT_NAMES_MODEL_DATA_TYPE_CARD) + --n; + + if (n >= 0) + e_iterator_next (iterator); + } + + if (len) { + data = e_iterator_get (iterator); + *len = strlen (data->string); + } + + return e_text_model_get_text (model) + pos; +} + +static void +e_select_names_text_model_activate_obj (ETextModel *model, gint n) +{ + ESelectNamesTextModel *select_text_model = E_SELECT_NAMES_TEXT_MODEL (model); + ESelectNamesModel *source = select_text_model->source; + EIterator *iterator = e_list_get_iterator (e_select_names_model_get_data (source)); + const ESelectNamesModelData *data; + const ECard *card; + EContactEditor *contact_editor; + + e_iterator_reset (iterator); + while (e_iterator_is_valid (iterator) && n > 0) { + data = e_iterator_get (iterator); + if (data->type == E_SELECT_NAMES_MODEL_DATA_TYPE_CARD) + --n; + + if (n >= 0) + e_iterator_next (iterator); + } + + data = e_iterator_get (iterator); + card = E_CARD (data->card); + + contact_editor = e_contact_editor_new (card, FALSE); + e_contact_editor_raise (contact_editor); +} + static void e_select_names_text_model_model_changed (ESelectNamesModel *source, ESelectNamesTextModel *model) @@ -260,9 +343,9 @@ e_select_names_text_model_model_changed (ESelectNamesModel *source, *stringp = 0; } *lengthsp = -1; - g_free(E_TEXT_MODEL(model)->text); - E_TEXT_MODEL(model)->text = string; - e_text_model_changed(E_TEXT_MODEL(model)); + + E_TEXT_MODEL_CLASS (parent_class)->set_text (E_TEXT_MODEL (model), string); + g_free (string); } -- cgit