aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Trowbridge <trow@ximian.com>2001-02-20 06:49:18 +0800
committerJon Trowbridge <trow@src.gnome.org>2001-02-20 06:49:18 +0800
commitd369e177b199c4c798f0b6ad8972951d8586bcd9 (patch)
tree492dd3459df5e78e6709e7879a70011f4f729012
parent54105acd4e5283899c1659e64e41341eec8d667c (diff)
downloadgsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar.gz
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar.bz2
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar.lz
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar.xz
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.tar.zst
gsoc2013-evolution-d369e177b199c4c798f0b6ad8972951d8586bcd9.zip
When creating the entry, open up an ebook (corresponding to the local
2001-02-19 Jon Trowbridge <trow@ximian.com> * 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
-rw-r--r--addressbook/ChangeLog32
-rw-r--r--addressbook/backend/ebook/Makefile.am19
-rw-r--r--addressbook/backend/ebook/e-address-completion.c315
-rw-r--r--addressbook/backend/ebook/e-address-completion.h65
-rw-r--r--addressbook/gui/component/select-names/Makefile.am2
-rw-r--r--addressbook/gui/component/select-names/e-select-names-manager.c41
-rw-r--r--addressbook/gui/component/select-names/e-select-names-model.c36
-rw-r--r--addressbook/gui/component/select-names/e-select-names-model.h3
-rw-r--r--addressbook/gui/component/select-names/e-select-names-text-model.c115
9 files changed, 608 insertions, 20 deletions
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 <trow@ximian.com>
+
+ * 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 <toshok@ximian.com>
* backend/idl/addressbook.idl: add sequence<string> 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 <trow@ximian.com>
+ *
+ * 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 <config.h>
+#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 <trow@ximian.com>
+ *
+ * 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 <gal/e-text/e-completion.h>
+
+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 <addressbook/backend/ebook/e-address-completion.h>
#include <gal/e-text/e-entry.h>
/* 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 <string.h>
#include <gtk/gtk.h>
+#include <addressbook/contact-editor/e-contact-editor.h>
#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);
}