aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--addressbook/ChangeLog11
-rw-r--r--addressbook/gui/component/select-names/e-select-names-bonobo.c19
-rw-r--r--addressbook/gui/component/select-names/e-select-names-manager.c814
-rw-r--r--addressbook/gui/component/select-names/e-select-names-manager.h8
-rw-r--r--addressbook/gui/component/select-names/e-select-names.c2
5 files changed, 433 insertions, 421 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog
index 44cb5e44d7..39de1ee629 100644
--- a/addressbook/ChangeLog
+++ b/addressbook/ChangeLog
@@ -1,3 +1,14 @@
+2001-12-07 Jon Trowbridge <trow@ximian.com>
+
+ * gui/component/select-names/e-select-names-manager.c: Extensively
+ refactored -- this code had gotten _really_ ugly. Untangle things
+ to the point where our reference counting problems are fixable.
+
+ * gui/component/select-names/e-select-names-bonobo.c
+ (impl_destroy): Remove all of the ugly hacks to work around our
+ memory management problems, and just unref the manager.
+ (Fixes #14412)
+
2001-12-05 Chris Toshok <toshok@ximian.com>
* backend/pas/pas-backend-ldap.c
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 071b2e0b2b..55ef3ec89a 100644
--- a/addressbook/gui/component/select-names/e-select-names-bonobo.c
+++ b/addressbook/gui/component/select-names/e-select-names-bonobo.c
@@ -348,18 +348,11 @@ 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;
@@ -369,17 +362,7 @@ impl_destroy (GtkObject *object)
priv->manager->names = NULL;
}
- /* 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)); */
+ gtk_object_unref (GTK_OBJECT (priv->manager));
g_free (priv);
}
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 e2b0238123..1a7dae4a74 100644
--- a/addressbook/gui/component/select-names/e-select-names-manager.c
+++ b/addressbook/gui/component/select-names/e-select-names-manager.c
@@ -2,8 +2,9 @@
/*
* Authors:
* Chris Lahey <clahey@ximian.com>
+ * Jon Trowbridge <trow@ximian.com.
*
- * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000, 2001 Ximian, Inc.
*/
#include <config.h>
@@ -26,15 +27,10 @@
#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
};
@@ -47,489 +43,411 @@ typedef struct {
ESelectNamesModel *model;
ESelectNamesModel *original_model;
ESelectNamesManager *manager;
- guint changed_handler;
+ guint changed_tag;
} ESelectNamesManagerSection;
typedef struct {
char *id;
EEntry *entry;
+ ESelectNamesManager *manager;
+ ESelectNamesModel *model;
} 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;
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
- 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;
-}
+/* ESelectNamesManagerSection routines */
static void
-open_book_cb (EBook *book, EBookStatus status, ESelectNamesManager *manager)
+section_model_changed_cb (ESelectNamesModel *model, gpointer closure)
{
- 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) */
+ ESelectNamesManagerSection *section = closure;
+ gtk_signal_emit (GTK_OBJECT (section->manager),
+ e_select_names_manager_signals[CHANGED],
+ section->id,
+ FALSE);
}
-/**
- * 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 ESelectNamesManagerSection *
+e_select_names_manager_section_new (ESelectNamesManager *manager,
+ const gchar *id,
+ const gchar *title,
+ ESelectNamesModel *model)
{
- ESelectNamesManager *manager = E_SELECT_NAMES_MANAGER(gtk_type_new(e_select_names_manager_get_type()));
- Bonobo_ConfigDatabase db;
- CORBA_Environment ev;
- char *val;
+ ESelectNamesManagerSection *section;
- CORBA_exception_init (&ev);
+ g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL);
+ g_return_val_if_fail (E_IS_SELECT_NAMES_MODEL (model), NULL);
- db = addressbook_config_database (&ev);
+ section = g_new0 (ESelectNamesManagerSection, 1);
- val = bonobo_config_get_string (db, "/Addressbook/Completion/uri", &ev);
+ section->id = g_strdup (id);
+ section->title = g_strdup (title);
- CORBA_exception_free (&ev);
+ section->manager = manager;
- 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;
+ 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);
- return manager;
+ return section;
}
static void
-e_select_names_manager_class_init (ESelectNamesManagerClass *klass)
+e_select_names_manager_section_free (ESelectNamesManagerSection *section)
{
- GtkObjectClass *object_class;
-
- object_class = GTK_OBJECT_CLASS(klass);
-
- gtk_object_add_arg_type ("ESelectNamesManager::card",
- GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_CARD);
+ if (section == NULL)
+ return;
- 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;
+ g_free (section->id);
+ g_free (section->title);
- 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);
+ if (section->model) {
+ gtk_signal_disconnect (GTK_OBJECT (section->model), section->changed_tag);
+ gtk_object_unref (GTK_OBJECT (section->model));
+ }
- 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);
+ if (section->original_model) {
+ gtk_object_unref (GTK_OBJECT (section->original_model));
+ }
- gtk_object_class_add_signals (object_class, e_select_names_manager_signals, LAST_SIGNAL);
+ g_free (section);
}
-/*
- * ESelectNamesManager lifecycle management and vcard loading/saving.
- */
-
-static void
-e_select_names_manager_destroy (GtkObject *object)
-{
- ESelectNamesManager *manager;
-
- manager = E_SELECT_NAMES_MANAGER (object);
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
- gtk_object_unref(GTK_OBJECT(manager->sections));
- gtk_object_unref(GTK_OBJECT(manager->entries));
+/* ESelectNamesManagerEntry routines */
- if (manager->names) {
- gtk_widget_destroy (GTK_WIDGET (manager->names));
- manager->names = NULL;
- }
+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");
}
-
-/* Set_arg handler for the manager */
static void
-e_select_names_manager_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+popup_cb (EEntry *eentry, GdkEventButton *ev, gint pos, gpointer user_data)
{
- ESelectNamesManager *manager;
-
- manager = E_SELECT_NAMES_MANAGER (object);
+ ESelectNamesManagerEntry *entry = user_data;
- switch (arg_id) {
- case ARG_CARD:
- break;
- default:
- return;
- }
+ e_select_names_popup (entry->model, ev, pos);
}
-/* Get_arg handler for the manager */
-static void
-e_select_names_manager_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+static gint
+focus_in_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
- ESelectNamesManager *manager;
+ ESelectNamesManagerEntry *entry = user_data;
- manager = E_SELECT_NAMES_MANAGER (object);
+ e_select_names_model_cancel_cardify_all (entry->model);
- switch (arg_id) {
- case ARG_CARD:
- break;
- default:
- arg->type = GTK_TYPE_INVALID;
- break;
- }
+ return FALSE;
}
-static void *
-section_copy(const void *sec, void *data)
+static gint
+focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
{
- 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;
-}
+ ESelectNamesManagerEntry *entry = user_data;
-static void
-section_free(void *sec, void *data)
-{
- 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));
+ e_select_names_model_clean (entry->model);
- g_free(section);
-}
+ if (!e_entry_completion_popup_is_visible (entry->entry))
+ e_select_names_model_cardify_all (entry->model, entry->manager->completion_book, 100);
-static void *
-entry_copy(const void *ent, void *data)
-{
- const ESelectNamesManagerEntry *entry = ent;
- ESelectNamesManagerEntry *newent;
-
- 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;
+ return FALSE;
}
static void
-entry_free(void *ent, void *data)
+completion_popup_cb (EEntry *w, gint visible, gpointer user_data)
{
- ESelectNamesManagerEntry *entry = ent;
- g_free(entry->id);
- if (entry->entry)
- gtk_object_unref(GTK_OBJECT(entry->entry));
- g_free(entry);
-}
+ ESelectNamesManagerEntry *entry = user_data;
-/**
- * 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 (!visible && !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->entry->canvas)))
+ e_select_names_model_cardify_all (entry->model, entry->manager->completion_book, 0);
}
static void
-section_model_changed_cb (ESelectNamesModel *model, gpointer closure)
+completion_handler (EEntry *entry, ECompletionMatch *match)
{
- ESelectNamesManagerSection *section = closure;
- gtk_signal_emit (GTK_OBJECT (section->manager),
- e_select_names_manager_signals[CHANGED],
- section->id,
- FALSE);
-}
+ ESelectNamesManagerEntry *mgr_entry;
+ EDestination *dest;
+ gint i, pos, start_pos, len;
-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);
-}
+ if (match == NULL || match->user_data == NULL)
+ return;
-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);
+ 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));
+
+ pos = e_entry_get_position (entry);
+ e_select_names_model_text_pos (mgr_entry->model, pos, &i, NULL, NULL);
+ e_select_names_model_replace (mgr_entry->model, i, dest);
+ e_select_names_model_name_pos (mgr_entry->model, i, &start_pos, &len);
+ e_entry_set_position (entry, start_pos+len);
}
-void
-e_select_names_manager_add_section_with_limit (ESelectNamesManager *manager,
- const char *id,
- const char *title,
- gint limit)
+static ESelectNamesManagerEntry *
+e_select_names_manager_entry_new (ESelectNamesManager *manager, ESelectNamesModel *model, const gchar *id)
{
- ESelectNamesManagerSection *section;
+ 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, model);
+ if (manager->completion_book)
+ e_select_names_completion_add_book (E_SELECT_NAMES_COMPLETION (comp),
+ manager->completion_book);
+ e_select_names_completion_add_destination_cache (E_SELECT_NAMES_COMPLETION (comp),
+ addressbook_destination_cache ());
+
+ e_entry_enable_completion_full (entry->entry, comp, 50, completion_handler);
+
+ entry->manager = manager;
+
+ entry->model = model;
+ gtk_object_ref (GTK_OBJECT (model));
- section = g_new(ESelectNamesManagerSection, 1);
- section->id = g_strdup(id);
- section->title = g_strdup(title);
+ 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);
+
+ gtk_signal_connect (GTK_OBJECT (entry->entry->canvas),
+ "focus_out_event",
+ GTK_SIGNAL_FUNC (focus_out_cb),
+ entry);
- section->model = e_select_names_model_new();
- e_select_names_model_set_limit (section->model, limit);
+ gtk_signal_connect (GTK_OBJECT (entry->entry),
+ "completion_popup",
+ GTK_SIGNAL_FUNC (completion_popup_cb),
+ entry);
- section->original_model = NULL;
+ 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), "completion_handler", comp);
- section->manager = manager;
+ return entry;
+}
- section->changed_handler = gtk_signal_connect (GTK_OBJECT (section->model),
- "changed",
- GTK_SIGNAL_FUNC (section_model_changed_cb),
- section);
+static void
+e_select_names_manager_entry_free (ESelectNamesManagerEntry *entry)
+{
+ if (entry == NULL)
+ return;
- e_list_append(manager->sections, section);
- section_free(section, manager);
+ g_free (entry->id);
+ gtk_object_unref (GTK_OBJECT (entry->model));
+ gtk_object_unref (GTK_OBJECT (entry->entry));
+
+ g_free (entry);
}
-ESelectNamesModel *
-e_select_names_manager_get_source (ESelectNamesManager *manager, const char *id)
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+
+static void
+e_select_names_manager_save_models (ESelectNamesManager *manager)
{
- EIterator *iterator;
+ GList *iter;
+
+ for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) {
+ ESelectNamesManagerSection *section = iter->data;
- g_return_val_if_fail (manager && E_IS_SELECT_NAMES_MANAGER (manager), NULL);
- g_return_val_if_fail (id, NULL);
+ if (section->original_model == NULL && section->model != NULL)
+ section->original_model = e_select_names_model_duplicate (section->model);
- 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
-entry_destroyed(EEntry *entry, ESelectNamesManager *manager)
+e_select_names_manager_revert_to_saved_models (ESelectNamesManager *manager)
{
- 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;
- }
+ GList *iter;
+
+ 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;
}
}
}
static void
-completion_handler (EEntry *entry, ECompletionMatch *match)
+e_select_names_manager_discard_saved_models (ESelectNamesManager *manager)
{
- ESelectNamesModel *snm;
- EDestination *dest;
- gint i, pos, start_pos, len;
+ GList *iter;
- if (match == NULL || match->user_data == NULL)
- return;
+ 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;
+ }
+ }
+}
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
- snm = E_SELECT_NAMES_MODEL (gtk_object_get_data (GTK_OBJECT (entry), "select_names_model"));
- 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));
+static void
+open_book_cb (EBook *book, EBookStatus status, ESelectNamesManager *manager)
+{
+ if (status != E_BOOK_STATUS_SUCCESS) {
+ gtk_object_unref (GTK_OBJECT (book));
+ manager->completion_book = NULL;
+ }
- 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);
+ gtk_object_unref (GTK_OBJECT (manager)); /* unref ourself (matches ref before the load_uri call below) */
}
-static void
-popup_cb (EEntry *entry, GdkEventButton *ev, gint pos, 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)
{
- e_select_names_popup (model, ev, pos);
+ 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);
+
+ db = addressbook_config_database (&ev);
+
+ val = bonobo_config_get_string (db, "/Addressbook/Completion/uri", &ev);
+
+ CORBA_exception_free (&ev);
+
+ 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 manager;
}
-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);
+/*
+ * ESelectNamesManager lifecycle management and vcard loading/saving.
+ */
- return FALSE;
+
+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);
}
-static gint
-focus_out_cb (GtkWidget *w, GdkEventFocus *ev, gpointer user_data)
+void
+e_select_names_manager_add_section_with_limit (ESelectNamesManager *manager,
+ const char *id,
+ const char *title,
+ gint limit)
{
- 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"));
+ ESelectNamesManagerSection *section;
+ ESelectNamesModel *model;
- e_select_names_model_clean (model);
+ 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);
- if (!e_entry_completion_popup_is_visible (entry))
- e_select_names_model_cardify_all (model, manager->completion_book, 100);
+ manager->sections = g_list_append (manager->sections, section);
- return FALSE;
+ gtk_object_unref (GTK_OBJECT (model));
}
-static void
-completion_popup_cb (EEntry *entry, gint visible, gpointer user_data)
+ESelectNamesModel *
+e_select_names_manager_get_source (ESelectNamesManager *manager,
+ const char *id)
{
- 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"));
+ GList *iter;
+
+ g_return_val_if_fail (E_IS_SELECT_NAMES_MANAGER (manager), NULL);
+ g_return_val_if_fail (id != NULL, NULL);
- if (!visible && !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->canvas)))
- e_select_names_model_cardify_all (model, manager->completion_book, 0);
+ 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;
}
GtkWidget *
e_select_names_manager_create_entry (ESelectNamesManager *manager, const char *id)
{
- 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);
+ 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;
if (!strcmp(section->id, id)) {
ESelectNamesManagerEntry *entry;
- EEntry *eentry;
- ECompletion *comp;
- 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);
+ entry = e_select_names_manager_entry_new (manager, section->model, section->id);
+ manager->entries = g_list_append (manager->entries, 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 GTK_WIDGET(entry->entry);
}
}
+
return NULL;
}
@@ -540,59 +458,159 @@ e_select_names_clicked(ESelectNames *dialog, gint button, ESelectNamesManager *m
switch(button) {
case 0:
- /* We don't need to do much if they click on OK */
-
+ e_select_names_manager_discard_saved_models (manager);
gtk_signal_emit (GTK_OBJECT (manager), e_select_names_manager_signals[OK]);
break;
- case 1: {
- EList *list = manager->sections;
- EIterator *iterator = e_list_get_iterator(list);
-
- for (e_iterator_reset(iterator); e_iterator_is_valid(iterator); e_iterator_next(iterator)) {
- ESelectNamesManagerSection *section = (void *) e_iterator_get(iterator);
- e_select_names_model_overwrite_copy (section->model, section->original_model);
- }
-
- gtk_object_unref(GTK_OBJECT(iterator));
+ case 1:
+ e_select_names_manager_revert_to_saved_models (manager);
+ gtk_signal_emit (GTK_OBJECT (manager), e_select_names_manager_signals[CANCEL]);
break;
}
- }
}
void
e_select_names_manager_activate_dialog (ESelectNamesManager *manager,
const char *id)
{
- EIterator *iterator;
-
+ g_return_if_fail (E_IS_SELECT_NAMES_MANAGER (manager));
+ g_return_if_fail (id != NULL);
+
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 ());
- 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);
+ for (iter = manager->sections; iter != NULL; iter = g_list_next (iter)) {
+ ESelectNamesManagerSection *section = iter->data;
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-manager.h b/addressbook/gui/component/select-names/e-select-names-manager.h
index 1304a13a71..9fdad2c304 100644
--- a/addressbook/gui/component/select-names/e-select-names-manager.h
+++ b/addressbook/gui/component/select-names/e-select-names-manager.h
@@ -27,8 +27,8 @@ typedef struct _ESelectNamesManagerClass ESelectNamesManagerClass;
struct _ESelectNamesManager {
GtkObject object;
- EList *sections;
- EList *entries;
+ GList *sections;
+ GList *entries;
ESelectNames *names;
@@ -40,6 +40,7 @@ struct _ESelectNamesManagerClass {
void (*changed) (ESelectNamesManager *, const gchar *section_id, gint changed_working_copy);
void (*ok) (ESelectNamesManager *);
+ void (*cancel) (ESelectNamesManager *);
};
ESelectNamesManager *e_select_names_manager_new (void);
@@ -51,12 +52,11 @@ void e_select_names_manager_add_section_with_limit (ESelectNames
const char *title,
gint limit);
ESelectNamesModel *e_select_names_manager_get_source (ESelectNamesManager *manager,
- const char *id);
+ const char *id);
GtkWidget *e_select_names_manager_create_entry (ESelectNamesManager *manager,
const char *id);
void e_select_names_manager_activate_dialog (ESelectNamesManager *manager,
const char *id);
-
/* Standard Gtk function */
GtkType e_select_names_manager_get_type (void);
diff --git a/addressbook/gui/component/select-names/e-select-names.c b/addressbook/gui/component/select-names/e-select-names.c
index fe737bbce7..5d6baa26fa 100644
--- a/addressbook/gui/component/select-names/e-select-names.c
+++ b/addressbook/gui/component/select-names/e-select-names.c
@@ -847,7 +847,7 @@ 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);
-
+
model = e_select_names_table_model_new(source);
etable = e_table_scrolled_new (model, NULL, SPEC2, NULL);