aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/gui
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2011-06-28 17:41:22 +0800
committerRodrigo Moya <rodrigo@gnome-db.org>2011-06-30 00:42:35 +0800
commit3fccaf1eab5c9e6a5db758d0f8670c965f3f5505 (patch)
treecfae5451fba0898e30d02363946a733bdcb46ff2 /addressbook/gui
parent489ff03bfaec34e13b80ec4b23ef9fc07d5588f6 (diff)
downloadgsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar.gz
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar.bz2
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar.lz
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar.xz
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.tar.zst
gsoc2013-evolution-3fccaf1eab5c9e6a5db758d0f8670c965f3f5505.zip
Bug #224687 - Create lists of lists
Diffstat (limited to 'addressbook/gui')
-rw-r--r--addressbook/gui/contact-list-editor/e-contact-list-editor.c392
-rw-r--r--addressbook/gui/contact-list-editor/e-contact-list-model.c162
-rw-r--r--addressbook/gui/contact-list-editor/e-contact-list-model.h19
-rw-r--r--addressbook/gui/widgets/Makefile.am2
-rw-r--r--addressbook/gui/widgets/eab-contact-display.c165
5 files changed, 417 insertions, 323 deletions
diff --git a/addressbook/gui/contact-list-editor/e-contact-list-editor.c b/addressbook/gui/contact-list-editor/e-contact-list-editor.c
index dc51011327..c87d2e42fe 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-editor.c
+++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.c
@@ -185,25 +185,59 @@ contact_list_editor_notify_cb (EContactListEditor *editor,
gtk_widget_set_sensitive (WIDGET (MEMBERS_VBOX), sensitive);
}
-static void
-contact_list_editor_add_email (EContactListEditor *editor)
+static gboolean
+contact_list_editor_add_destination (GtkWidget *widget,
+ EDestination *dest)
{
- EContactListEditorPrivate *priv = editor->priv;
- EContactListModel *model;
- GtkEntry *entry;
- const gchar *text;
+ EContactListEditor *editor = contact_list_editor_extract (widget);
+ EContactListModel *model = E_CONTACT_LIST_MODEL (editor->priv->model);
+ EDestinationStore *dest_store;
+ GtkTreeView *treeview = GTK_TREE_VIEW (WIDGET (TREE_VIEW));
+ GtkTreePath *path;
- entry = GTK_ENTRY (WIDGET (EMAIL_ENTRY));
- model = E_CONTACT_LIST_MODEL (priv->model);
+ if (e_destination_is_evolution_list (dest)) {
+ const gchar *id = e_destination_get_contact_uid (dest);
+ const gchar *name = e_destination_get_name (dest);
+ const gchar *tag = "addressbook:ask-list-add-list-exists";
- text = gtk_entry_get_text (entry);
- if (text != NULL && *text != '\0') {
- e_contact_list_model_add_email (model, text);
+ if (e_contact_list_model_has_uid (model, id) &&
+ (e_alert_run_dialog_for_args (GTK_WINDOW (WIDGET (DIALOG)), tag, name, NULL) != GTK_RESPONSE_YES))
+ return FALSE;
+ } else {
+ const gchar *email = e_destination_get_email (dest);
+ const gchar *tag = "addressbook:ask-list-add-exists";
+
+ if (e_contact_list_model_has_email (model, email) &&
+ (e_alert_run_dialog_for_args (GTK_WINDOW (WIDGET (DIALOG)), tag, email, NULL) != GTK_RESPONSE_YES))
+ return FALSE;
+ }
+
+ /* always add to the root level */
+ path = e_contact_list_model_add_destination (model, dest, NULL);
+ if (path) {
contact_list_editor_scroll_to_end (editor);
- priv->changed = TRUE;
+ gtk_tree_view_expand_to_path (treeview, path);
+ gtk_tree_path_free (path);
+
+ dest_store = e_name_selector_entry_peek_destination_store (E_NAME_SELECTOR_ENTRY (WIDGET (EMAIL_ENTRY)));
+ e_destination_store_remove_destination (dest_store, dest);
+
+ return TRUE;
}
- gtk_entry_set_text (entry, "");
+ return FALSE;
+}
+
+static void
+contact_list_editor_add_email (EContactListEditor *editor,
+ const gchar *email)
+{
+ EContactListEditorPrivate *priv = editor->priv;
+
+ EDestination *dest = e_destination_new ();
+ e_destination_set_email (dest, email);
+ priv->changed = contact_list_editor_add_destination (WIDGET (DIALOG), dest) || priv->changed;
+
contact_list_editor_update (editor);
}
@@ -251,19 +285,6 @@ exit:
g_object_unref (editor);
}
-static gboolean
-contact_list_editor_contact_exists (EContactListModel *model,
- const gchar *email)
-{
- const gchar *tag = "addressbook:ask-list-add-exists";
-
- if (!e_contact_list_model_has_email (model, email))
- return FALSE;
-
- return (e_alert_run_dialog_for_args (e_shell_get_active_window (NULL),
- tag, email, NULL) != GTK_RESPONSE_YES);
-}
-
static void
contact_list_editor_list_added_cb (EBookClient *book_client,
const GError *error,
@@ -301,7 +322,7 @@ contact_list_editor_list_modified_cb (EBookClient *book_client,
const GError *error,
gpointer closure)
{
- EditorCloseStruct *ecs = closure;
+ EditorCloseStruct *ecs = closure;
EContactListEditor *editor = ecs->editor;
EContactListEditorPrivate *priv = editor->priv;
gboolean should_close = ecs->should_close;
@@ -330,43 +351,28 @@ contact_list_editor_render_destination (GtkTreeViewColumn *column,
/* XXX Would be nice if EDestination had a text property
* that we could just bind the GtkCellRenderer to. */
- EDestination *destination;
+ EDestination *destination = NULL;
+ gchar *name = NULL, *email = NULL;
const gchar *textrep;
- gchar *name = NULL, *email = NULL, *tofree = NULL;
+ gchar *out;
+
+ g_return_if_fail (GTK_IS_TREE_MODEL (model));
gtk_tree_model_get (model, iter, 0, &destination, -1);
- textrep = e_destination_get_textrep (destination, TRUE);
+ g_return_if_fail (destination && E_IS_DESTINATION (destination));
+ textrep = e_destination_get_textrep (destination, TRUE);
if (eab_parse_qp_email (textrep, &name, &email)) {
- tofree = g_strdup_printf ("%s <%s>", name, email);
- textrep = tofree;
- g_free (name);
+ out = g_strdup_printf ("%s <%s>", name, email);
+ g_object_set (renderer, "text", out, NULL);
+ g_free (out);
g_free (email);
+ g_free (name);
+ } else {
+ g_object_set (renderer, "text", textrep, NULL);
}
- g_object_set (renderer, "text", textrep, NULL);
g_object_unref (destination);
- g_free (tofree);
-}
-
-static void
-contact_list_editor_row_deleted_cb (GtkTreeModel *model,
- GtkTreePath *path,
- EContactListEditor *editor)
-{
- gint n_children;
-
- n_children = gtk_tree_model_iter_n_children (model, NULL);
- gtk_widget_set_sensitive (WIDGET (REMOVE_BUTTON), n_children > 0);
-}
-
-static void
-contact_list_editor_row_inserted_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- EContactListEditor *editor)
-{
- gtk_widget_set_sensitive (WIDGET (REMOVE_BUTTON), TRUE);
}
static void
@@ -387,9 +393,12 @@ contact_list_editor_selection_changed_cb (GtkTreeSelection *selection,
gtk_widget_set_sensitive (WIDGET (UP_BUTTON), FALSE);
gtk_widget_set_sensitive (WIDGET (DOWN_BUTTON), FALSE);
gtk_widget_set_sensitive (WIDGET (BOTTOM_BUTTON), FALSE);
+ gtk_widget_set_sensitive (WIDGET (REMOVE_BUTTON), FALSE);
return;
}
+ gtk_widget_set_sensitive (WIDGET (REMOVE_BUTTON), TRUE);
+
/* Item before selected item exists => enable Top/Up buttons */
selected = gtk_tree_selection_get_selected_rows (selection, &model);
@@ -430,7 +439,9 @@ contact_list_editor_add_button_clicked_cb (GtkWidget *widget)
editor = contact_list_editor_extract (widget);
- contact_list_editor_add_email (editor);
+ contact_list_editor_add_email (editor,
+ gtk_entry_get_text (GTK_ENTRY (WIDGET (EMAIL_ENTRY))));
+ gtk_entry_set_text (GTK_ENTRY (WIDGET (EMAIL_ENTRY)), "");
}
void
@@ -502,7 +513,6 @@ contact_list_editor_drag_data_received_cb (GtkWidget *widget,
{
CamelInternetAddress *address;
EContactListEditor *editor;
- EContactListModel *model;
gboolean changed = FALSE;
gboolean handled = FALSE;
const guchar *data;
@@ -512,7 +522,6 @@ contact_list_editor_drag_data_received_cb (GtkWidget *widget,
gchar *text;
editor = contact_list_editor_extract (widget);
- model = E_CONTACT_LIST_MODEL (editor->priv->model);
target = gtk_selection_data_get_target (selection_data);
@@ -532,24 +541,14 @@ contact_list_editor_drag_data_received_cb (GtkWidget *widget,
for (iter = list; iter != NULL; iter = iter->next) {
EContact *contact = iter->data;
- const gchar *email;
+ EDestination *dest;
- if (e_contact_get (contact, E_CONTACT_IS_LIST))
- continue;
+ dest = e_destination_new ();
+ e_destination_set_contact (dest, contact, 0);
- email = e_contact_get (contact, E_CONTACT_EMAIL_1);
- if (email == NULL) {
- g_warning (
- "Contact with no email-ids listed "
- "can't be added to a Contact-List");
- continue;
- }
+ changed = contact_list_editor_add_destination (widget, dest) || changed;
- if (!contact_list_editor_contact_exists (model, email)) {
- /* Hard-wired for default e-mail */
- e_contact_list_model_add_contact (model, contact, 0);
- changed = TRUE;
- }
+ g_object_unref (dest);
}
e_client_util_free_object_slist (list);
@@ -583,7 +582,7 @@ handle_text:
g_free (text);
text = camel_address_format (CAMEL_ADDRESS (address));
- e_contact_list_model_add_email (model, text);
+ contact_list_editor_add_email (editor, text);
contact_list_editor_scroll_to_end (editor);
editor->priv->changed = TRUE;
@@ -605,10 +604,13 @@ void
contact_list_editor_email_entry_activate_cb (GtkWidget *widget)
{
EContactListEditor *editor;
+ GtkEntry *entry;
editor = contact_list_editor_extract (widget);
+ entry = GTK_ENTRY (WIDGET (EMAIL_ENTRY));
- contact_list_editor_add_email (editor);
+ contact_list_editor_add_email (editor, gtk_entry_get_text (entry));
+ gtk_entry_set_text (entry, "");
}
void
@@ -666,8 +668,7 @@ contact_list_editor_email_entry_key_press_event_cb (GtkWidget *widget,
}
if (can_comma || event->keyval == GDK_KEY_Return) {
- g_signal_emit_by_name (widget, "activate", 0);
- contact_list_editor_add_email (editor);
+ g_signal_emit_by_name (WIDGET (EMAIL_ENTRY), "activate", 0);
return TRUE;
}
@@ -676,40 +677,6 @@ contact_list_editor_email_entry_key_press_event_cb (GtkWidget *widget,
}
void
-contact_list_editor_email_entry_updated_cb (GtkWidget *widget,
- EDestination *destination);
-
-void
-contact_list_editor_email_entry_updated_cb (GtkWidget *widget,
- EDestination *destination)
-{
- EContactListEditor *editor;
- ENameSelectorEntry *entry;
- EContactListModel *model;
- EDestinationStore *store;
- gchar *email;
-
- editor = contact_list_editor_extract (widget);
-
- entry = E_NAME_SELECTOR_ENTRY (widget);
- model = E_CONTACT_LIST_MODEL (editor->priv->model);
-
- email = g_strdup (e_destination_get_textrep (destination, TRUE));
- store = e_name_selector_entry_peek_destination_store (entry);
- e_destination_store_remove_destination (store, destination);
- gtk_entry_set_text (GTK_ENTRY (WIDGET (EMAIL_ENTRY)), "");
-
- if (email && *email) {
- e_contact_list_model_add_email (model, email);
- contact_list_editor_scroll_to_end (editor);
- editor->priv->changed = TRUE;
- }
-
- g_free (email);
- contact_list_editor_update (editor);
-}
-
-void
contact_list_editor_list_name_entry_changed_cb (GtkWidget *widget);
void
@@ -798,7 +765,7 @@ contact_list_editor_remove_button_clicked_cb (GtkWidget *widget)
gtk_tree_path_free (path);
g_assert (valid);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+ e_contact_list_model_remove_row (E_CONTACT_LIST_MODEL (model), &iter);
gtk_tree_row_reference_free (reference);
}
@@ -838,7 +805,6 @@ void
contact_list_editor_select_button_clicked_cb (GtkWidget *widget)
{
EContactListEditor *editor;
- EContactListModel *model;
ENameSelectorDialog *dialog;
EDestinationStore *store;
GList *list, *iter;
@@ -846,7 +812,6 @@ contact_list_editor_select_button_clicked_cb (GtkWidget *widget)
editor = contact_list_editor_extract (widget);
- model = E_CONTACT_LIST_MODEL (editor->priv->model);
dialog = e_name_selector_peek_dialog (editor->priv->name_selector);
gtk_window_set_title (GTK_WINDOW (dialog), _("Contact List Members"));
@@ -876,18 +841,14 @@ contact_list_editor_select_button_clicked_cb (GtkWidget *widget)
for (iter = list; iter != NULL; iter = iter->next) {
EDestination *destination = iter->data;
- const gchar *email = e_destination_get_email (destination);
- if (email == NULL)
- continue;
-
- if (!contact_list_editor_contact_exists (model, email))
- e_contact_list_model_add_destination (
- model, destination);
+ contact_list_editor_add_destination (widget, destination);
}
g_list_free (list);
+ gtk_entry_set_text (GTK_ENTRY (WIDGET (EMAIL_ENTRY)), "");
+
editor->priv->changed = TRUE;
contact_list_editor_update (editor);
}
@@ -962,8 +923,8 @@ contact_list_editor_top_button_clicked_cb (GtkButton *button)
for (l = references; l; l = l->next) {
path = gtk_tree_row_reference_get_path (l->data);
gtk_tree_model_get_iter (model, &iter, path);
- gtk_list_store_move_after (
- GTK_LIST_STORE (model), &iter, NULL);
+ gtk_tree_store_move_after (
+ GTK_TREE_STORE (model), &iter, NULL);
gtk_tree_path_free (path);
}
@@ -1006,7 +967,7 @@ contact_list_editor_up_button_clicked_cb (GtkButton *button)
/* Get iter of the last selected item */
gtk_tree_model_get_iter (model, &iter2, g_list_last (selected)->data);
- gtk_list_store_move_after (GTK_LIST_STORE (model), &iter, &iter2);
+ gtk_tree_store_move_after (GTK_TREE_STORE (model), &iter, &iter2);
g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
g_list_free (selected);
@@ -1042,7 +1003,7 @@ contact_list_editor_down_button_clicked_cb (GtkButton *button)
gtk_tree_model_get_iter (model, &iter2, g_list_last (selected)->data);
gtk_tree_model_iter_next (model, &iter2);
- gtk_list_store_move_before (GTK_LIST_STORE (model), &iter2, &iter);
+ gtk_tree_store_move_before (GTK_TREE_STORE (model), &iter2, &iter);
g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
g_list_free (selected);
@@ -1082,8 +1043,8 @@ contact_list_editor_bottom_button_clicked_cb (GtkButton *button)
for (l = references; l; l = l->next) {
path = gtk_tree_row_reference_get_path (l->data);
gtk_tree_model_get_iter (model, &iter, path);
- gtk_list_store_move_before (
- GTK_LIST_STORE (model), &iter, NULL);
+ gtk_tree_store_move_before (
+ GTK_TREE_STORE (model), &iter, NULL);
gtk_tree_path_free (path);
}
@@ -1205,9 +1166,6 @@ setup_custom_widgets (EContactListEditor *editor)
g_signal_connect (
name_selector_entry, "key-press-event", G_CALLBACK (
contact_list_editor_email_entry_key_press_event_cb), NULL);
- g_signal_connect (
- name_selector_entry, "updated", G_CALLBACK (
- contact_list_editor_email_entry_updated_cb), NULL);
}
/***************************** GObject Callbacks *****************************/
@@ -1314,6 +1272,16 @@ contact_list_editor_dispose (GObject *object)
priv->name_selector = NULL;
}
+ if (priv->contact) {
+ g_object_unref (priv->contact);
+ priv->contact = NULL;
+ }
+
+ if (priv->builder) {
+ g_object_unref (priv->builder);
+ priv->builder = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -1561,13 +1529,6 @@ contact_list_editor_init (EContactListEditor *editor)
e_drag_dest_add_directory_targets (WIDGET (TREE_VIEW));
gtk_drag_dest_add_text_targets (WIDGET (TREE_VIEW));
- g_signal_connect (
- priv->model, "row-deleted",
- G_CALLBACK (contact_list_editor_row_deleted_cb), editor);
- g_signal_connect (
- priv->model, "row-inserted",
- G_CALLBACK (contact_list_editor_row_inserted_cb), editor);
-
column = gtk_tree_view_column_new ();
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
@@ -1666,15 +1627,63 @@ e_contact_list_editor_set_client (EContactListEditor *editor,
g_object_notify (G_OBJECT (editor), "client");
}
+static void
+save_contact_list (GtkTreeModel *model, GtkTreeIter *iter, GSList **attrs, gint *parent_id)
+{
+ EDestination *dest;
+ EVCardAttribute *attr;
+ gchar *pid_str = g_strdup_printf ("%d", *parent_id);
+
+ do {
+ gtk_tree_model_get (model, iter, 0, &dest, -1);
+
+ if (gtk_tree_model_iter_has_child (model, iter)) {
+ GtkTreeIter new_iter;
+ gchar *uid;
+
+ (*parent_id)++;
+ uid = g_strdup_printf ("%d", *parent_id);
+
+ attr = e_vcard_attribute_new (NULL, EVC_CONTACT_LIST);
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EVC_CL_UID), uid);
+ e_vcard_attribute_add_value (attr,
+ e_destination_get_name (dest));
+
+ g_free (uid);
+
+ /* Set new_iter to first child of iter */
+ gtk_tree_model_iter_children (model, &new_iter, iter);
+
+ /* Go recursive */
+ save_contact_list (model, &new_iter, attrs, parent_id);
+ } else {
+ attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+ e_destination_export_to_vcard_attribute (dest, attr);
+ }
+
+ e_vcard_attribute_add_param_with_value (attr,
+ e_vcard_attribute_param_new (EVC_PARENT_CL), pid_str);
+
+
+ *attrs = g_slist_prepend (*attrs, attr);
+
+ g_object_unref (dest);
+
+ } while (gtk_tree_model_iter_next (model, iter));
+
+ g_free (pid_str);
+}
+
EContact *
e_contact_list_editor_get_contact (EContactListEditor *editor)
{
GtkTreeModel *model;
EContact *contact;
GtkTreeIter iter;
- gboolean iter_valid;
const gchar *text;
GSList *attrs = NULL, *a;
+ gint parent_id = 0;
g_return_val_if_fail (E_IS_CONTACT_LIST_EDITOR (editor), NULL);
@@ -1686,8 +1695,8 @@ e_contact_list_editor_get_contact (EContactListEditor *editor)
text = gtk_entry_get_text (GTK_ENTRY (WIDGET (LIST_NAME_ENTRY)));
if (text != NULL && *text != '\0') {
- e_contact_set (contact, E_CONTACT_FILE_AS, (gpointer) text);
- e_contact_set (contact, E_CONTACT_FULL_NAME, (gpointer) text);
+ e_contact_set (contact, E_CONTACT_FILE_AS, text);
+ e_contact_set (contact, E_CONTACT_FULL_NAME, text);
}
e_contact_set (contact, E_CONTACT_LOGO, NULL);
@@ -1699,21 +1708,10 @@ e_contact_list_editor_get_contact (EContactListEditor *editor)
GTK_TOGGLE_BUTTON (WIDGET (CHECK_BUTTON)))));
e_vcard_remove_attributes (E_VCARD (contact), "", EVC_EMAIL);
+ e_vcard_remove_attributes (E_VCARD (contact), "", EVC_CONTACT_LIST);
- iter_valid = gtk_tree_model_get_iter_first (model, &iter);
-
- while (iter_valid) {
- EDestination *dest;
- EVCardAttribute *attr;
-
- gtk_tree_model_get (model, &iter, 0, &dest, -1);
- attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
- attrs = g_slist_prepend (attrs, attr);
- e_destination_export_to_vcard_attribute (dest, attr);
- g_object_unref (dest);
-
- iter_valid = gtk_tree_model_iter_next (model, &iter);
- }
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ save_contact_list (model, &iter, &attrs, &parent_id);
/* Put it in reverse order because e_vcard_add_attribute also uses prepend,
but we want to keep order of mails there. Hopefully noone will change
@@ -1722,59 +1720,9 @@ e_contact_list_editor_get_contact (EContactListEditor *editor)
e_vcard_add_attribute (E_VCARD (contact), a->data);
}
- return contact;
-}
+ g_slist_free (attrs);
-/* Helper for e_contact_list_editor_set_contact() */
-static void
-contact_list_editor_add_destination (EVCardAttribute *attr,
- EContactListEditor *editor)
-{
- EDestination *destination;
- gchar *contact_uid = NULL;
- gint email_num = -1;
- GList *list, *iter;
- GList *values;
- gchar *value;
-
- destination = e_destination_new ();
-
- list = e_vcard_attribute_get_params (attr);
- for (iter = list; iter; iter = iter->next) {
- EVCardAttributeParam *param = iter->data;
- const gchar *param_name;
- gpointer param_data;
-
- values = e_vcard_attribute_param_get_values (param);
- if (values == NULL)
- continue;
-
- param_name = e_vcard_attribute_param_get_name (param);
- param_data = values->data;
-
- if (!g_ascii_strcasecmp (param_name, EVC_X_DEST_CONTACT_UID))
- contact_uid = param_data;
- else if (!g_ascii_strcasecmp (param_name, EVC_X_DEST_EMAIL_NUM))
- email_num = atoi (param_data);
- else if (!g_ascii_strcasecmp (param_name, EVC_X_DEST_HTML_MAIL))
- e_destination_set_html_mail_pref (
- destination,
- !g_ascii_strcasecmp (param_data, "true"));
- }
-
- value = e_vcard_attribute_get_value (attr);
- if (value)
- e_destination_set_raw (destination, value);
- g_free (value);
-
- if (contact_uid != NULL)
- e_destination_set_contact_uid (
- destination, contact_uid, email_num);
-
- e_contact_list_model_add_destination (
- E_CONTACT_LIST_MODEL (editor->priv->model), destination);
-
- e_vcard_attribute_free (attr);
+ return contact;
}
void
@@ -1790,19 +1738,19 @@ e_contact_list_editor_set_contact (EContactListEditor *editor,
if (priv->contact != NULL)
g_object_unref (priv->contact);
+
priv->contact = e_contact_duplicate (contact);
if (priv->contact != NULL) {
const gchar *file_as;
gboolean show_addresses;
- GList *email_list;
+ const GList *dests, *dest;
- file_as = e_contact_get_const (
- priv->contact, E_CONTACT_FILE_AS);
- email_list = e_contact_get_attributes (
- priv->contact, E_CONTACT_EMAIL);
- show_addresses = GPOINTER_TO_INT (e_contact_get (
- priv->contact, E_CONTACT_LIST_SHOW_ADDRESSES));
+ /* The root destination */
+ EDestination *list_dest = e_destination_new ();
+
+ file_as = e_contact_get_const (priv->contact, E_CONTACT_FILE_AS);
+ show_addresses = GPOINTER_TO_INT (e_contact_get (priv->contact, E_CONTACT_LIST_SHOW_ADDRESSES));
if (file_as == NULL)
file_as = "";
@@ -1817,10 +1765,19 @@ e_contact_list_editor_set_contact (EContactListEditor *editor,
e_contact_list_model_remove_all (
E_CONTACT_LIST_MODEL (priv->model));
- g_list_foreach (
- email_list, (GFunc)
- contact_list_editor_add_destination, editor);
- g_list_free (email_list);
+ e_destination_set_name (list_dest, file_as);
+ e_destination_set_contact (list_dest, priv->contact, 0);
+
+ dests = e_destination_list_get_root_dests (list_dest);
+ for (dest = dests; dest; dest = dest->next) {
+ GtkTreePath *path;
+ path = e_contact_list_model_add_destination (E_CONTACT_LIST_MODEL (priv->model), dest->data, NULL);
+ gtk_tree_path_free (path);
+ }
+
+ g_object_unref (list_dest);
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (WIDGET (TREE_VIEW)));
}
if (priv->book_client != NULL) {
@@ -1835,6 +1792,7 @@ e_contact_list_editor_set_contact (EContactListEditor *editor,
contact_list_editor_update (editor);
g_object_notify (G_OBJECT (editor), "contact");
+
}
gboolean
diff --git a/addressbook/gui/contact-list-editor/e-contact-list-model.c b/addressbook/gui/contact-list-editor/e-contact-list-model.c
index 1a0cc6d0b6..63e0f59105 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-model.c
+++ b/addressbook/gui/contact-list-editor/e-contact-list-model.c
@@ -31,6 +31,15 @@
static gpointer parent_class;
+G_DEFINE_TYPE (EContactListModel, e_contact_list_model, GTK_TYPE_TREE_STORE);
+
+struct _EContactListModelPrivate {
+
+ GHashTable *uids_table;
+ GHashTable *emails_table;
+
+};
+
static gboolean
contact_list_get_iter (EContactListModel *model,
GtkTreeIter *iter,
@@ -61,38 +70,51 @@ contact_list_model_constructor (GType type,
object = G_OBJECT_CLASS (parent_class)->constructor (
type, n_construct_properties, construct_properties);
- gtk_list_store_set_column_types (
- GTK_LIST_STORE (object), G_N_ELEMENTS (types), types);
+ gtk_tree_store_set_column_types (
+ GTK_TREE_STORE (object), G_N_ELEMENTS (types), types);
return object;
}
static void
-contact_list_model_class_init (EContactListModelClass *class)
+contact_list_model_dispose (GObject *object)
+{
+ EContactListModelPrivate *priv = E_CONTACT_LIST_MODEL (object)->priv;
+
+ if (priv->uids_table) {
+ g_hash_table_unref (priv->uids_table);
+ priv->uids_table = NULL;
+ }
+
+ if (priv->emails_table) {
+ g_hash_table_unref (priv->emails_table);
+ priv->emails_table = NULL;
+ }
+
+ G_OBJECT_CLASS (e_contact_list_model_parent_class)->dispose (object);
+}
+
+static void
+e_contact_list_model_class_init (EContactListModelClass *class)
{
GObjectClass *object_class;
+ g_type_class_add_private (class, sizeof (EContactListModelPrivate));
+
parent_class = g_type_class_peek_parent (class);
object_class = G_OBJECT_CLASS (class);
object_class->constructor = contact_list_model_constructor;
+ object_class->dispose = contact_list_model_dispose;
}
-GType
-e_contact_list_model_get_type (void)
+static void
+e_contact_list_model_init (EContactListModel *model)
{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- type = g_type_register_static_simple (
- GTK_TYPE_LIST_STORE,
- "EContactListModel",
- sizeof (EContactListModelClass),
- (GClassInitFunc) contact_list_model_class_init,
- sizeof (EContactListModel),
- (GInstanceInitFunc) NULL, 0);
-
- return type;
+ model->priv = G_TYPE_INSTANCE_GET_PRIVATE (model, E_TYPE_CONTACT_LIST_MODEL, EContactListModelPrivate);
+
+ model->priv->uids_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ model->priv->emails_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
GtkTreeModel *
@@ -105,64 +127,51 @@ gboolean
e_contact_list_model_has_email (EContactListModel *model,
const gchar *email)
{
- GtkTreeIter iter;
- gboolean iter_valid;
- gboolean has_email = FALSE;
-
- g_return_val_if_fail (E_IS_CONTACT_LIST_MODEL (model), FALSE);
- g_return_val_if_fail (email != NULL, FALSE);
-
- iter_valid = gtk_tree_model_get_iter_first (
- GTK_TREE_MODEL (model), &iter);
-
- while (!has_email && iter_valid) {
- EDestination *destination;
- const gchar *textrep;
-
- gtk_tree_model_get (
- GTK_TREE_MODEL (model), &iter, 0, &destination, -1);
- textrep = e_destination_get_textrep (destination, TRUE);
- has_email = (strcmp (email, textrep) == 0);
- g_object_unref (destination);
-
- iter_valid = gtk_tree_model_iter_next (
- GTK_TREE_MODEL (model), &iter);
- }
+ return (g_hash_table_lookup (model->priv->emails_table, email) != NULL);
+}
- return has_email;
+gboolean
+e_contact_list_model_has_uid (EContactListModel *model,
+ const gchar* uid)
+{
+ return (g_hash_table_lookup (model->priv->uids_table, uid) != NULL);
}
-void
+GtkTreePath*
e_contact_list_model_add_destination (EContactListModel *model,
- EDestination *destination)
+ EDestination *destination,
+ GtkTreeIter *parent)
{
GtkTreeIter iter;
+ GtkTreePath *path;
- g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
- g_return_if_fail (E_IS_DESTINATION (destination));
+ g_return_val_if_fail (E_IS_CONTACT_LIST_MODEL (model), NULL);
+ g_return_val_if_fail (E_IS_DESTINATION (destination), NULL);
- gtk_list_store_append (GTK_LIST_STORE (model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, destination, -1);
-}
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
-void
-e_contact_list_model_add_email (EContactListModel *model,
- const gchar *email)
-{
- const gchar *tag = "addressbook:ask-list-add-exists";
- EDestination *destination;
+ if (e_destination_is_evolution_list (destination)) {
+ const GList *dest, *dests = e_destination_list_get_root_dests (destination);
- g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
- g_return_if_fail (email != NULL);
+ g_hash_table_insert (model->priv->uids_table,
+ g_strdup (e_destination_get_contact_uid (destination)),
+ destination);
- if (e_contact_list_model_has_email (model, email))
- if (e_alert_run_dialog_for_args (e_shell_get_active_window
- (NULL), tag, email, NULL) != GTK_RESPONSE_YES)
- return;
+ for (dest = dests; dest; dest = dest->next) {
+ path = e_contact_list_model_add_destination (model, dest->data, &iter);
+ if (dest->next)
+ gtk_tree_path_free (path);
+ }
+ } else {
+ g_hash_table_insert (model->priv->emails_table,
+ g_strdup (e_destination_get_email (destination)),
+ destination);
- destination = e_destination_new ();
- e_destination_set_email (destination, email);
- e_contact_list_model_add_destination (model, destination);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+ }
+
+ return path;
}
void
@@ -177,22 +186,30 @@ e_contact_list_model_add_contact (EContactListModel *model,
destination = e_destination_new ();
e_destination_set_contact (destination, contact, email_num);
- e_contact_list_model_add_destination (model, destination);
+ e_contact_list_model_add_destination (model, destination, NULL);
}
void
e_contact_list_model_remove_row (EContactListModel *model,
- gint row)
+ GtkTreeIter *iter)
{
- GtkTreeIter iter;
- gboolean iter_valid;
+ EDestination *dest;
g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
+ g_return_if_fail (iter);
- iter_valid = contact_list_get_iter (model, &iter, row);
- g_return_if_fail (iter_valid);
+ gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 0, &dest, -1);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+ if (e_destination_is_evolution_list (dest)) {
+ const gchar *uid = e_destination_get_contact_uid (dest);
+ g_hash_table_remove (model->priv->uids_table, uid);
+ } else {
+ const gchar *email = e_destination_get_email (dest);
+ g_hash_table_remove (model->priv->emails_table, email);
+ }
+
+ g_object_unref (dest);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
}
void
@@ -200,7 +217,10 @@ e_contact_list_model_remove_all (EContactListModel *model)
{
g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
- gtk_list_store_clear (GTK_LIST_STORE (model));
+ g_hash_table_remove_all (model->priv->uids_table);
+ g_hash_table_remove_all (model->priv->emails_table);
+
+ gtk_tree_store_clear (GTK_TREE_STORE (model));
}
EDestination *
diff --git a/addressbook/gui/contact-list-editor/e-contact-list-model.h b/addressbook/gui/contact-list-editor/e-contact-list-model.h
index 43d3288756..b902658365 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-model.h
+++ b/addressbook/gui/contact-list-editor/e-contact-list-model.h
@@ -46,30 +46,35 @@
G_BEGIN_DECLS
typedef struct _EContactListModel EContactListModel;
+typedef struct _EContactListModelPrivate EContactListModelPrivate;
typedef struct _EContactListModelClass EContactListModelClass;
struct _EContactListModel {
- GtkListStore parent;
+ GtkTreeStore parent;
+ EContactListModelPrivate *priv;
};
struct _EContactListModelClass {
- GtkListStoreClass parent_class;
+ GtkTreeStoreClass parent_class;
};
GType e_contact_list_model_get_type (void);
GtkTreeModel * e_contact_list_model_new (void);
gboolean e_contact_list_model_has_email (EContactListModel *model,
const gchar *email);
-void e_contact_list_model_add_destination
+
+gboolean e_contact_list_model_has_uid (EContactListModel *model,
+ const gchar *uid);
+
+GtkTreePath * e_contact_list_model_add_destination
(EContactListModel *model,
- EDestination *dest);
-void e_contact_list_model_add_email (EContactListModel *model,
- const gchar *email);
+ EDestination *dest,
+ GtkTreeIter *parent);
void e_contact_list_model_add_contact (EContactListModel *model,
EContact *contact,
gint email_num);
void e_contact_list_model_remove_row (EContactListModel *model,
- gint row);
+ GtkTreeIter *iter);
void e_contact_list_model_remove_all (EContactListModel *model);
EDestination * e_contact_list_model_get_destination
(EContactListModel *model,
diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am
index 64777ee332..40c57650bb 100644
--- a/addressbook/gui/widgets/Makefile.am
+++ b/addressbook/gui/widgets/Makefile.am
@@ -9,6 +9,7 @@ libeabwidgets_la_CPPFLAGS = \
-DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \
-DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \
-DEVOLUTION_RULEDIR=\"$(ruledir)\" \
+ -DEVOLUTION_IMAGESDIR=\"${imagesdir}\" \
-I$(top_srcdir) \
-I$(top_srcdir)/filter \
-I$(top_srcdir)/widgets \
@@ -69,6 +70,7 @@ libeabwidgets_la_LIBADD = \
$(top_builddir)/widgets/table/libetable.la \
$(top_builddir)/widgets/menus/libmenus.la \
$(top_builddir)/a11y/libevolution-a11y.la \
+ $(top_builddir)/e-util/libeutil.la \
$(GNOME_PLATFORM_LIBS) \
$(CHAMPLAIN_LIBS)
diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c
index c3d8fb7628..ab66e8d554 100644
--- a/addressbook/gui/widgets/eab-contact-display.c
+++ b/addressbook/gui/widgets/eab-contact-display.c
@@ -28,6 +28,7 @@
#include "eab-gui-util.h"
#include "e-util/e-util.h"
+#include "e-util/e-util-private.h"
#include "e-util/e-html-utils.h"
#include "e-util/e-icon-factory.h"
#include "e-util/e-plugin-ui.h"
@@ -50,6 +51,8 @@ struct _EABContactDisplayPrivate {
EABContactDisplayMode mode;
GtkOrientation orientation;
gboolean show_maps;
+
+ GHashTable *closed_lists; /* see render_contact_list_* */
};
enum {
@@ -409,7 +412,7 @@ render_title_block (GString *buffer, EContact *contact)
g_string_append_printf (
buffer, "<table border=\"0\"><tr>"
- "<td %s valign=\"top\">", TEXT_IS_RIGHT_TO_LEFT ?
+ "<td %s valign=\"middle\">", TEXT_IS_RIGHT_TO_LEFT ?
"align=\"right\"" : "");
photo = e_contact_get (contact, E_CONTACT_PHOTO);
if (!photo)
@@ -421,6 +424,9 @@ render_title_block (GString *buffer, EContact *contact)
if (photo)
e_contact_photo_free (photo);
+ if (e_contact_get (contact, E_CONTACT_IS_LIST))
+ g_string_append (buffer, "<img src=\"evo-icon:" CONTACT_LIST_ICON "\">");
+
g_string_append_printf (
buffer, "</td><td width=\"20\"></td><td %s valign=\"top\">\n",
TEXT_IS_RIGHT_TO_LEFT ? "align=\"right\"" : "");
@@ -443,43 +449,126 @@ render_title_block (GString *buffer, EContact *contact)
}
static void
-render_contact_list (GString *buffer,
- EContact *contact)
+render_contact_list_row (GString *buffer,
+ EDestination *destination,
+ EABContactDisplay *display)
+ {
+ gchar *evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+ gboolean list_collapsed = FALSE;
+ const gchar *listId = e_destination_get_contact_uid (destination), *textrep;
+ gchar *name = NULL, *email_addr = NULL;
+
+ if (listId)
+ list_collapsed = GPOINTER_TO_INT (g_hash_table_lookup (display->priv->closed_lists, listId));
+
+ textrep = e_destination_get_textrep (destination, TRUE);
+ if (!eab_parse_qp_email (textrep, &name, &email_addr))
+ email_addr = g_strdup (textrep);
+
+ g_string_append (buffer, "<tr>");
+ if (e_destination_is_evolution_list (destination)) {
+ g_string_append_printf (buffer,
+ "<td width=" IMAGE_COL_WIDTH " valign=\"top\"><a href=\"##%s##\"><img src=\"%s/%s.png\"></a></td><td width=\"100%%\">%s",
+ e_destination_get_contact_uid (destination),
+ evolution_imagesdir,
+ (list_collapsed ? "plus" : "minus"),
+ name ? name : email_addr);
+
+ if (!list_collapsed) {
+ const GList *dest, *dests;
+ g_string_append (buffer, "<br><table cellspacing=\"1\">");
+
+ dests = e_destination_list_get_root_dests (destination);
+ for (dest = dests; dest; dest = dest->next) {
+ render_contact_list_row (buffer, dest->data, display);
+ }
+
+ g_string_append (buffer, "</table>");
+ }
+
+ g_string_append (buffer, "</td>");
+
+ } else {
+ if (name && *name) {
+ g_string_append_printf (buffer, "<td colspan=\"2\">%s &lt<a href=\"mailto:%s\">%s</a>&gt;</td>", name, email_addr, email_addr);
+ } else {
+ g_string_append_printf (buffer, "<td colspan=\"2\"><a href=\"mailto:%s\">%s</a></td>", email_addr, email_addr);
+ }
+ }
+
+ g_string_append (buffer, "</tr>");
+
+ g_free (evolution_imagesdir);
+ g_free (name);
+ g_free (email_addr);
+}
+
+static void
+render_contact_list_vertical (GString *buffer,
+ EContact *contact,
+ EABContactDisplay *display)
{
- GList *email_list;
- GList *l;
+ EDestination *destination;
+ const GList *dest, *dests;
+
+ destination = e_destination_new ();
+ e_destination_set_contact (destination, contact, 0);
+ dests = e_destination_list_get_root_dests (destination);
render_title_block (buffer, contact);
- g_string_append (
- buffer, "<br><table border=\"0\" cellspacing=\"0\" "
- "cellpadding=\"0\"><tr>");
- g_string_append (
- buffer, "<td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\">");
- g_string_append (
- buffer, "<img width=\"16\" height=\"16\" "
- "src=\"evo-icon:" CONTACT_LIST_ICON "\">");
- g_string_append_printf (
- buffer, "</td><td valign=\"top\" width=\"100\" nowrap>"
- "<font color=" HEADER_COLOR ">%s:</font></td> "
- "<td valign=\"top\">", _("List Members"));
+ g_string_append_printf (buffer, "<table border=\"0\"><tr><td valign=\"top\"><font color=" HEADER_COLOR ">%s</font></td><td>",
+ _("List Members:"));
+ g_string_append (buffer, "<table border=\"0\" cellspacing=\"1\">");
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- for (l = email_list; l; l = l->next) {
- gchar *value;
+ for (dest = dests; dest; dest = dest->next) {
+ render_contact_list_row (buffer, dest->data, display);
+ }
+
+ g_string_append (buffer, "</table>");
+ g_string_append (buffer, "</td></tr></table>");
+
+ g_object_unref (destination);
+}
- value = eab_parse_qp_email_to_html (l->data);
+static void
+render_contact_list_horizontal (GString *buffer,
+ EContact *contact,
+ EABContactDisplay *display)
+{
+ EDestination *destination;
+ const GList *dest, *dests;
+
+ destination = e_destination_new ();
+ e_destination_set_contact (destination, contact, 0);
+ dests = e_destination_list_get_root_dests (destination);
- if (!value)
- value = e_text_to_html (l->data, E_TEXT_TO_HTML_CONVERT_ADDRESSES);
+ render_title_block (buffer, contact);
- g_string_append_printf (buffer, "%s<br>", value);
+ g_string_append_printf (buffer, "<table border=\"0\"><tr><td colspan=\"2\" valign=\"top\"><font color=" HEADER_COLOR ">%s</font></td></tr>"
+ "<tr><td with=" IMAGE_COL_WIDTH "></td><td>", _("List Members:"));
+ g_string_append (buffer, "<table border=\"0\" cellspacing=\"1\">");
- g_free (value);
- }
+ for (dest = dests; dest; dest = dest->next) {
+ render_contact_list_row (buffer, dest->data, display);
+ }
+ g_string_append (buffer, "</table>");
g_string_append (buffer, "</td></tr></table>");
- g_list_free (email_list);
+
+ g_object_unref (destination);
+}
+
+static void
+render_contact_list (GString *buffer,
+ EContact *contact,
+ EABContactDisplay *display)
+
+{
+ if (display->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ render_contact_list_vertical (buffer, contact, display);
+ else
+ render_contact_list_horizontal (buffer, contact, display);
}
static void
@@ -751,7 +840,7 @@ eab_contact_display_render_normal (EABContactDisplay *display,
orientation = display->priv->orientation;
if (e_contact_get (contact, E_CONTACT_IS_LIST))
- render_contact_list (buffer, contact);
+ render_contact_list (buffer, contact, display);
else
render_contact (buffer, contact, orientation, display->priv->show_maps);
@@ -1035,6 +1124,11 @@ contact_display_dispose (GObject *object)
priv->contact = NULL;
}
+ if (priv->closed_lists != NULL) {
+ g_hash_table_unref (priv->closed_lists);
+ priv->closed_lists = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -1160,6 +1254,19 @@ contact_display_link_clicked (EWebView *web_view,
index = atoi (uri + length);
contact_display_emit_send_message (display, index);
return;
+ } else if (g_str_has_prefix (uri, "##") && g_str_has_suffix (uri, "##")) {
+ gchar *list_id = g_strndup (uri+2, strlen (uri) - 4);
+
+ if (g_hash_table_lookup (display->priv->closed_lists, list_id)) {
+ g_hash_table_remove (display->priv->closed_lists, list_id);
+ g_free (list_id);
+ } else {
+ g_hash_table_insert (display->priv->closed_lists, list_id, GINT_TO_POINTER (TRUE));
+ }
+
+ eab_contact_display_render_normal (display, display->priv->contact);
+
+ return;
}
/* Chain up to parent's link_clicked() method. */
@@ -1338,6 +1445,8 @@ eab_contact_display_init (EABContactDisplay *display)
display->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL;
display->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
display->priv->show_maps = FALSE;
+ display->priv->closed_lists = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
web_view = E_WEB_VIEW (display);
ui_manager = e_web_view_get_ui_manager (web_view);