No issues found
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 |
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 }