[evolution/wip/gsettings] Bug #224687 - Various fixes in contact list editor



commit b9ee422f50e9c634baa674347a139807b8085a5e
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Jun 29 15:30:38 2011 +0200

    Bug #224687 - Various fixes in contact list editor
    
    - fixed order of buttons in duplicate adding confirmation dialog
    - in the editor, don't display email addresses in sublist nodes
    - automatically remove sublists with no children

 addressbook/addressbook.error.xml                  |   10 ++-
 .../contact-list-editor/e-contact-list-editor.c    |   47 ++++++--
 .../gui/contact-list-editor/e-contact-list-model.c |  122 ++++++++++++++++----
 .../gui/contact-list-editor/e-contact-list-model.h |    3 +-
 4 files changed, 147 insertions(+), 35 deletions(-)
---
diff --git a/addressbook/addressbook.error.xml b/addressbook/addressbook.error.xml
index 6a7dc4b..88010ed 100644
--- a/addressbook/addressbook.error.xml
+++ b/addressbook/addressbook.error.xml
@@ -98,8 +98,16 @@
   <button stock="gtk-ok" _label="_Add" response="GTK_RESPONSE_YES"/>
  </error>
  
+ <error id="ask-list-add-some-mails-exist" type="question" default="GTK_RESPONSE_CANCEL">
+  <_primary>Some addresses already exist in this contact list.</_primary>
+  <_secondary>You are trying to add addresses that are part of this list already. Would you like to add them anyway?</_secondary>
+  <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
+  <button _label="Skip duplicates" response="GTK_RESPONSE_NO"/>
+  <button _label="Add with duplicates" response="GTK_RESPONSE_YES"/>
+ </error>
+ 
  <error id="ask-list-add-list-exists" type="question" default="GTK_RESPONSE_NO">
-   <_primary>'{0}' is already in this contact list.</_primary>
+   <_primary>List '{0}' is already in this contact list.</_primary>
    <_secondary>A contact list named '{0}' is already in this contact list. Would you like to add it anyway?</_secondary>
    <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
    <button stock="gtk-ok" _label="_Add" response="GTK_RESPONSE_YES"/>
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 c87d2e4..a0de8a5 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-editor.c
+++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.c
@@ -194,15 +194,40 @@ contact_list_editor_add_destination (GtkWidget *widget,
 	EDestinationStore *dest_store;
 	GtkTreeView *treeview = GTK_TREE_VIEW (WIDGET (TREE_VIEW));
 	GtkTreePath *path;
+	gboolean ignore_conflicts = TRUE;
 
 	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";
 
-		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;
+		if (e_contact_list_model_has_uid (model, id)) {
+			if (e_alert_run_dialog_for_args (GTK_WINDOW (WIDGET (DIALOG)),
+					"addressbook:ask-list-add-list-exists", name, NULL) != GTK_RESPONSE_YES)
+				return FALSE;
+		} else {
+			const GList *l_dests, *l_dest;
+			gint reply;
+
+			/* Check the new list mail-by-mail for conflicts and eventually ask user what to do
+			   with all conflicts */
+			l_dests = e_destination_list_get_dests (dest);
+			for (l_dest = l_dests; l_dest; l_dest = l_dest->next) {
+				if (e_contact_list_model_has_email (model, e_destination_get_email (l_dest->data))) {
+					reply = e_alert_run_dialog_for_args (GTK_WINDOW (WIDGET (DIALOG)),
+							"addressbook:ask-list-add-some-mails-exist", NULL);
+					if (reply == GTK_RESPONSE_YES) {
+						ignore_conflicts = TRUE;
+						break;
+					} else if (reply == GTK_RESPONSE_NO) {
+						ignore_conflicts = FALSE;
+						break;
+					} else {
+						return FALSE;
+					}
+				}
+			}
+		}
+
 	} else {
 		const gchar *email = e_destination_get_email (dest);
 		const gchar *tag = "addressbook:ask-list-add-exists";
@@ -213,7 +238,7 @@ contact_list_editor_add_destination (GtkWidget *widget,
 	}
 
 	/* always add to the root level */
-	path = e_contact_list_model_add_destination (model, dest, NULL);
+	path = e_contact_list_model_add_destination (model, dest, NULL, ignore_conflicts);
 	if (path) {
 		contact_list_editor_scroll_to_end (editor);
 		gtk_tree_view_expand_to_path (treeview, path);
@@ -363,9 +388,13 @@ contact_list_editor_render_destination (GtkTreeViewColumn *column,
 
 	textrep = e_destination_get_textrep (destination, TRUE);
 	if (eab_parse_qp_email (textrep, &name, &email)) {
-		out = g_strdup_printf ("%s <%s>", name, email);
-		g_object_set (renderer, "text", out, NULL);
-		g_free (out);
+		if (e_destination_is_evolution_list (destination)) {
+			g_object_set (renderer, "text", name, NULL);
+		} else {
+			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 {
@@ -1771,7 +1800,7 @@ e_contact_list_editor_set_contact (EContactListEditor *editor,
 		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);
+			path = e_contact_list_model_add_destination (E_CONTACT_LIST_MODEL (priv->model), dest->data, NULL, TRUE);
 			gtk_tree_path_free (path);
 		}
 
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 63e0f59..b94e8e7 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-model.c
+++ b/addressbook/gui/contact-list-editor/e-contact-list-model.c
@@ -82,12 +82,12 @@ 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);
+		g_hash_table_destroy (priv->uids_table);
 		priv->uids_table = NULL;
 	}
 
 	if (priv->emails_table) {
-		g_hash_table_unref (priv->emails_table);
+		g_hash_table_destroy (priv->emails_table);
 		priv->emails_table = NULL;
 	}
 
@@ -140,7 +140,8 @@ e_contact_list_model_has_uid (EContactListModel *model,
 GtkTreePath*
 e_contact_list_model_add_destination (EContactListModel *model,
                                       EDestination *destination,
-                                      GtkTreeIter *parent)
+                                      GtkTreeIter *parent,
+                                      gboolean ignore_conflicts)
 {
 	GtkTreeIter iter;
 	GtkTreePath *path;
@@ -148,25 +149,46 @@ e_contact_list_model_add_destination (EContactListModel *model,
 	g_return_val_if_fail (E_IS_CONTACT_LIST_MODEL (model), NULL);
 	g_return_val_if_fail (E_IS_DESTINATION (destination), NULL);
 
-	gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
-	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
-
 	if (e_destination_is_evolution_list (destination)) {
 		const GList *dest, *dests = e_destination_list_get_root_dests (destination);
+		/* Get number of instances of this list in the model */
+		gint list_refs = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->uids_table,
+					e_destination_get_contact_uid (destination)));
 
-		g_hash_table_insert (model->priv->uids_table,
-			g_strdup (e_destination_get_contact_uid (destination)),
-			destination);
+		gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
+		gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
 
 		for (dest = dests; dest; dest = dest->next) {
-			path = e_contact_list_model_add_destination (model, dest->data, &iter);
-			if (dest->next)
+			path = e_contact_list_model_add_destination (model, dest->data, &iter, ignore_conflicts);
+			if (dest->next && path)
 				gtk_tree_path_free (path);
 		}
+
+		/* When the list has no children the remove it. We don't want empty sublists displayed. */
+		if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (model), &iter)) {
+			gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+		} else {
+			g_hash_table_insert (model->priv->uids_table,
+				g_strdup (e_destination_get_contact_uid (destination)),
+				GINT_TO_POINTER (list_refs + 1));
+		}
 	} else {
+		gint dest_refs;
+
+		if (e_contact_list_model_has_email (model, e_destination_get_email (destination)) &&
+		    ignore_conflicts == FALSE) {
+			return NULL;
+		}
+
+		dest_refs = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->emails_table,
+				e_destination_get_email (destination)));
+
 		g_hash_table_insert (model->priv->emails_table,
 			g_strdup (e_destination_get_email (destination)),
-			destination);
+			GINT_TO_POINTER (dest_refs + 1));
+
+		gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
+		gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
 
 		path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
 	}
@@ -186,30 +208,82 @@ 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, NULL);
+	e_contact_list_model_add_destination (model, destination, NULL, TRUE);
+}
+
+static void
+contact_list_model_unref_row_dest (EContactListModel *model,
+				   GtkTreeIter *iter)
+{
+	EDestination *dest;
+	GtkTreeModel *tree_model;
+
+	tree_model = GTK_TREE_MODEL (model);
+	gtk_tree_model_get (tree_model, iter, 0, &dest, -1);
+
+	if (gtk_tree_model_iter_has_child (tree_model, iter)) {
+		GtkTreeIter child_iter;
+		gint list_refs = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->uids_table,
+			e_destination_get_contact_uid (dest)));
+
+		/* If the list is only once in the model, then remove it from the hash table,
+		   otherwise decrease the counter by one */
+		if (list_refs <= 1) {
+			g_hash_table_remove (model->priv->uids_table,
+				e_destination_get_contact_uid (dest));
+		} else {
+			g_hash_table_insert (model->priv->uids_table,
+				g_strdup (e_destination_get_contact_uid (dest)),
+				GINT_TO_POINTER (list_refs - 1));
+		}
+
+		if (gtk_tree_model_iter_children (tree_model, &child_iter, iter)) {
+			do {
+				contact_list_model_unref_row_dest (model, &child_iter);
+			} while (gtk_tree_model_iter_next (tree_model, &child_iter));
+		}
+
+	} else {
+		gint dest_refs = GPOINTER_TO_INT (g_hash_table_lookup (model->priv->emails_table,
+			e_destination_get_email (dest)));
+
+		if (dest_refs <= 1) {
+			g_hash_table_remove (model->priv->emails_table,
+				e_destination_get_email (dest));
+		} else {
+			g_hash_table_insert (model->priv->emails_table,
+				g_strdup (e_destination_get_email (dest)),
+				GINT_TO_POINTER (dest_refs - 1));
+		}
+	}
+
+	g_object_unref (dest);
 }
 
 void
 e_contact_list_model_remove_row (EContactListModel *model,
                                  GtkTreeIter *iter)
 {
-	EDestination *dest;
+	GtkTreeIter parent_iter;
 
 	g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
 	g_return_if_fail (iter);
 
-	gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 0, &dest, -1);
-
-	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);
+	/* Use helper function to update our reference counters in
+	   hash tables but don't remove any row. */
+	contact_list_model_unref_row_dest (model, iter);
+
+	/* Get iter of parent of the row to be removed. After the row is removed, check if there are
+	   any more children left for the parent_iter, an eventually remove the parent_iter as well */
+	if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (model), &parent_iter, iter)) {
+		gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
+		if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (model), &parent_iter)) {
+			contact_list_model_unref_row_dest (model, &parent_iter);
+			gtk_tree_store_remove (GTK_TREE_STORE (model), &parent_iter);
+		}
 	} else {
-		const gchar *email = e_destination_get_email (dest);
-		g_hash_table_remove (model->priv->emails_table, email);
+		gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
 	}
-
-	g_object_unref (dest);
-	gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
 }
 
 void
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 b902658..91e8a82 100644
--- a/addressbook/gui/contact-list-editor/e-contact-list-model.h
+++ b/addressbook/gui/contact-list-editor/e-contact-list-model.h
@@ -69,7 +69,8 @@ gboolean	e_contact_list_model_has_uid	(EContactListModel *model,
 GtkTreePath *	e_contact_list_model_add_destination
 						(EContactListModel *model,
 						 EDestination *dest,
-						 GtkTreeIter *parent);
+						 GtkTreeIter *parent,
+						 gboolean ignore_conflicts);
 void		e_contact_list_model_add_contact (EContactListModel *model,
 						 EContact *contact,
 						 gint email_num);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]