evolution-3.6.4/addressbook/gui/contact-list-editor/e-contact-list-model.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-contact-list-model.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-contact-list-model.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *
 18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 19  *
 20  */
 21 
 22 #ifdef HAVE_CONFIG_H
 23 #include <config.h>
 24 #endif
 25 
 26 #include <string.h>
 27 
 28 #include "e-contact-list-model.h"
 29 #include "libevolution-utils/e-alert-dialog.h"
 30 #include "shell/e-shell.h"
 31 
 32 #define E_CONTACT_LIST_MODEL_GET_PRIVATE(obj) \
 33 	(G_TYPE_INSTANCE_GET_PRIVATE \
 34 	((obj), E_TYPE_CONTACT_LIST_MODEL, EContactListModelPrivate))
 35 
 36 G_DEFINE_TYPE (EContactListModel, e_contact_list_model, GTK_TYPE_TREE_STORE);
 37 
 38 struct _EContactListModelPrivate {
 39 
 40 	GHashTable *uids_table;
 41 	GHashTable *emails_table;
 42 
 43 };
 44 
 45 static gboolean
 46 contact_list_get_iter (EContactListModel *model,
 47                        GtkTreeIter *iter,
 48                        gint row)
 49 {
 50 	GtkTreePath *path;
 51 	gboolean iter_valid;
 52 
 53 	path = gtk_tree_path_new_from_indices (row, -1);
 54 	iter_valid = gtk_tree_model_get_iter (
 55 		GTK_TREE_MODEL (model), iter, path);
 56 	gtk_tree_path_free (path);
 57 
 58 	return iter_valid;
 59 }
 60 
 61 static GObject *
 62 contact_list_model_constructor (GType type,
 63                                 guint n_construct_properties,
 64                                 GObjectConstructParam *construct_properties)
 65 {
 66 	GObject *object;
 67 	GType types[1];
 68 
 69 	types[0] = E_TYPE_DESTINATION;
 70 
 71 	/* Chain up to parent's constructor() method. */
 72 	object = G_OBJECT_CLASS (e_contact_list_model_parent_class)->
 73 		constructor (type, n_construct_properties, construct_properties);
 74 
 75 	gtk_tree_store_set_column_types (
 76 		GTK_TREE_STORE (object), G_N_ELEMENTS (types), types);
 77 
 78 	return object;
 79 }
 80 
 81 static void
 82 contact_list_model_dispose (GObject *object)
 83 {
 84 	EContactListModelPrivate *priv = E_CONTACT_LIST_MODEL (object)->priv;
 85 
 86 	if (priv->uids_table) {
 87 		g_hash_table_destroy (priv->uids_table);
 88 		priv->uids_table = NULL;
 89 	}
 90 
 91 	if (priv->emails_table) {
 92 		g_hash_table_destroy (priv->emails_table);
 93 		priv->emails_table = NULL;
 94 	}
 95 
 96 	G_OBJECT_CLASS (e_contact_list_model_parent_class)->dispose (object);
 97 }
 98 
 99 static void
100 e_contact_list_model_class_init (EContactListModelClass *class)
101 {
102 	GObjectClass *object_class;
103 
104 	g_type_class_add_private (class, sizeof (EContactListModelPrivate));
105 
106 	object_class = G_OBJECT_CLASS (class);
107 	object_class->constructor = contact_list_model_constructor;
108 	object_class->dispose = contact_list_model_dispose;
109 }
110 
111 static void
112 e_contact_list_model_init (EContactListModel *model)
113 {
114 	model->priv = E_CONTACT_LIST_MODEL_GET_PRIVATE (model);
115 
116 	model->priv->uids_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
117 	model->priv->emails_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
118 }
119 
120 GtkTreeModel *
121 e_contact_list_model_new (void)
122 {
123 	return g_object_new (E_TYPE_CONTACT_LIST_MODEL, NULL);
124 }
125 
126 gboolean
127 e_contact_list_model_has_email (EContactListModel *model,
128                                 const gchar *email)
129 {
130 	return (g_hash_table_lookup (model->priv->emails_table, email) != NULL);
131 }
132 
133 gboolean
134 e_contact_list_model_has_uid (EContactListModel *model,
135                               const gchar *uid)
136 {
137 	return (g_hash_table_lookup (model->priv->uids_table, uid) != NULL);
138 }
139 
140 GtkTreePath *
141 e_contact_list_model_add_destination (EContactListModel *model,
142                                       EDestination *destination,
143                                       GtkTreeIter *parent,
144                                       gboolean ignore_conflicts)
145 {
146 	GtkTreeIter iter;
147 	GtkTreePath *path = NULL;
148 
149 	g_return_val_if_fail (E_IS_CONTACT_LIST_MODEL (model), NULL);
150 	g_return_val_if_fail (E_IS_DESTINATION (destination), NULL);
151 
152 	if (e_destination_is_evolution_list (destination)) {
153 		const GList *dest, *dests = e_destination_list_get_root_dests (destination);
154 		/* Get number of instances of this list in the model */
155 		gint list_refs = GPOINTER_TO_INT (
156 			g_hash_table_lookup (model->priv->uids_table,
157 			e_destination_get_contact_uid (destination)));
158 
159 		gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
160 		gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
161 
162 		for (dest = dests; dest; dest = dest->next) {
163 			path = e_contact_list_model_add_destination (model, dest->data, &iter, ignore_conflicts);
164 			if (dest->next && path) {
165 				gtk_tree_path_free (path);
166 				path = NULL;
167 			}
168 		}
169 
170 		/* When the list has no children the remove it. We don't want empty sublists displayed. */
171 		if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (model), &iter)) {
172 			gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
173 		} else {
174 			g_hash_table_insert (
175 				model->priv->uids_table,
176 				g_strdup (e_destination_get_contact_uid (destination)),
177 				GINT_TO_POINTER (list_refs + 1));
178 		}
179 	} else {
180 		gint dest_refs;
181 
182 		if (e_contact_list_model_has_email (model, e_destination_get_email (destination)) &&
183 		    ignore_conflicts == FALSE) {
184 			return NULL;
185 		}
186 
187 		dest_refs = GPOINTER_TO_INT (
188 			g_hash_table_lookup (model->priv->emails_table,
189 			e_destination_get_email (destination)));
190 
191 		g_hash_table_insert (
192 			model->priv->emails_table,
193 			g_strdup (e_destination_get_email (destination)),
194 			GINT_TO_POINTER (dest_refs + 1));
195 
196 		gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
197 		gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, destination, -1);
198 
199 		path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
200 	}
201 
202 	return path;
203 }
204 
205 void
206 e_contact_list_model_add_contact (EContactListModel *model,
207                                   EContact *contact,
208                                   gint email_num)
209 {
210 	EDestination *destination;
211 
212 	g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
213 	g_return_if_fail (E_IS_CONTACT (contact));
214 
215 	destination = e_destination_new ();
216 	e_destination_set_contact (destination, contact, email_num);
217 	e_contact_list_model_add_destination (model, destination, NULL, TRUE);
218 }
219 
220 static void
221 contact_list_model_unref_row_dest (EContactListModel *model,
222                                    GtkTreeIter *iter)
223 {
224 	EDestination *dest;
225 	GtkTreeModel *tree_model;
226 
227 	tree_model = GTK_TREE_MODEL (model);
228 	gtk_tree_model_get (tree_model, iter, 0, &dest, -1);
229 
230 	if (gtk_tree_model_iter_has_child (tree_model, iter)) {
231 		GtkTreeIter child_iter;
232 		gint list_refs = GPOINTER_TO_INT (
233 			g_hash_table_lookup (model->priv->uids_table,
234 			e_destination_get_contact_uid (dest)));
235 
236 		/* If the list is only once in the model, then remove it from the hash table,
237 		 * otherwise decrease the counter by one */
238 		if (list_refs <= 1) {
239 			g_hash_table_remove (
240 				model->priv->uids_table,
241 				e_destination_get_contact_uid (dest));
242 		} else {
243 			g_hash_table_insert (
244 				model->priv->uids_table,
245 				g_strdup (e_destination_get_contact_uid (dest)),
246 				GINT_TO_POINTER (list_refs - 1));
247 		}
248 
249 		if (gtk_tree_model_iter_children (tree_model, &child_iter, iter)) {
250 			do {
251 				contact_list_model_unref_row_dest (model, &child_iter);
252 			} while (gtk_tree_model_iter_next (tree_model, &child_iter));
253 		}
254 
255 	} else {
256 		gint dest_refs = GPOINTER_TO_INT (
257 			g_hash_table_lookup (
258 				model->priv->emails_table,
259 				e_destination_get_email (dest)));
260 
261 		if (dest_refs <= 1) {
262 			g_hash_table_remove (
263 				model->priv->emails_table,
264 				e_destination_get_email (dest));
265 		} else {
266 			g_hash_table_insert (
267 				model->priv->emails_table,
268 				g_strdup (e_destination_get_email (dest)),
269 				GINT_TO_POINTER (dest_refs - 1));
270 		}
271 	}
272 
273 	g_object_unref (dest);
274 }
275 
276 void
277 e_contact_list_model_remove_row (EContactListModel *model,
278                                  GtkTreeIter *iter)
279 {
280 	GtkTreeIter parent_iter;
281 
282 	g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
283 	g_return_if_fail (iter);
284 
285 	/* Use helper function to update our reference counters in
286 	 * hash tables but don't remove any row. */
287 	contact_list_model_unref_row_dest (model, iter);
288 
289 	/* Get iter of parent of the row to be removed. After the row is removed, check if there are
290 	 * any more children left for the parent_iter, an eventually remove the parent_iter as well */
291 	if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (model), &parent_iter, iter)) {
292 		gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
293 		if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (model), &parent_iter)) {
294 			contact_list_model_unref_row_dest (model, &parent_iter);
295 			gtk_tree_store_remove (GTK_TREE_STORE (model), &parent_iter);
296 		}
297 	} else {
298 		gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
299 	}
300 }
301 
302 void
303 e_contact_list_model_remove_all (EContactListModel *model)
304 {
305 	g_return_if_fail (E_IS_CONTACT_LIST_MODEL (model));
306 
307 	g_hash_table_remove_all (model->priv->uids_table);
308 	g_hash_table_remove_all (model->priv->emails_table);
309 
310 	gtk_tree_store_clear (GTK_TREE_STORE (model));
311 }
312 
313 EDestination *
314 e_contact_list_model_get_destination (EContactListModel *model,
315                                       gint row)
316 {
317 	EDestination *destination;
318 	GtkTreeIter iter;
319 	gboolean iter_valid;
320 
321 	g_return_val_if_fail (E_IS_CONTACT_LIST_MODEL (model), NULL);
322 
323 	iter_valid = contact_list_get_iter (model, &iter, row);
324 	g_return_val_if_fail (iter_valid, NULL);
325 
326 	gtk_tree_model_get (
327 		GTK_TREE_MODEL (model), &iter, 0, &destination, -1);
328 
329 	return destination;
330 }