evolution-3.6.4/modules/imap-features/e-mail-config-header-manager.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-config-header-manager.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-config-header-manager.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  * e-mail-config-header-manager.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  */
 18 
 19 #include "e-mail-config-header-manager.h"
 20 
 21 #define E_MAIL_CONFIG_HEADER_MANAGER_GET_PRIVATE(obj) \
 22 	(G_TYPE_INSTANCE_GET_PRIVATE \
 23 	((obj), E_TYPE_MAIL_CONFIG_HEADER_MANAGER, EMailConfigHeaderManagerPrivate))
 24 
 25 struct _EMailConfigHeaderManagerPrivate {
 26 	GHashTable *headers;
 27 
 28 	GtkWidget *entry;          /* not referenced */
 29 	GtkWidget *tree_view;      /* not referenced */
 30 	GtkWidget *add_button;     /* not referenced */
 31 	GtkWidget *remove_button;  /* not referenced */
 32 };
 33 
 34 enum {
 35 	PROP_0,
 36 	PROP_HEADERS
 37 };
 38 
 39 G_DEFINE_DYNAMIC_TYPE (
 40 	EMailConfigHeaderManager,
 41 	e_mail_config_header_manager,
 42 	GTK_TYPE_GRID)
 43 
 44 static gboolean
 45 mail_config_header_manager_header_is_valid (const gchar *header)
 46 {
 47 	gchar *stripped_header;
 48 	gboolean is_valid;
 49 	glong length;
 50 
 51 	if (header == NULL)
 52 		return FALSE;
 53 
 54 	stripped_header = g_strstrip (g_strdup (header));
 55 	length = g_utf8_strlen (stripped_header, -1);
 56 
 57 	is_valid =
 58 		(*stripped_header != '\0') &&
 59 		(g_utf8_strchr (stripped_header, length, ':') == NULL) &&
 60 		(g_utf8_strchr (stripped_header, length, ' ') == NULL);
 61 
 62 	g_free (stripped_header);
 63 
 64 	return is_valid;
 65 }
 66 
 67 static gboolean
 68 mail_config_header_manager_header_to_boolean (GBinding *binding,
 69                                               const GValue *source_value,
 70                                               GValue *target_value,
 71                                               gpointer unused)
 72 {
 73 	gboolean is_valid;
 74 	const gchar *string;
 75 
 76 	string = g_value_get_string (source_value);
 77 	is_valid = mail_config_header_manager_header_is_valid (string);
 78 	g_value_set_boolean (target_value, is_valid);
 79 
 80 	return TRUE;
 81 }
 82 
 83 static void
 84 mail_config_header_manager_update_list (EMailConfigHeaderManager *manager)
 85 {
 86 	GtkTreeView *tree_view;
 87 	GtkTreeModel *tree_model;
 88 	GtkListStore *list_store;
 89 	GtkTreeSelection *selection;
 90 	GtkTreePath *path = NULL;
 91 	GList *list, *link;
 92 
 93 	tree_view = GTK_TREE_VIEW (manager->priv->tree_view);
 94 	selection = gtk_tree_view_get_selection (tree_view);
 95 
 96 	list = gtk_tree_selection_get_selected_rows (selection, &tree_model);
 97 	if (g_list_length (list) == 1)
 98 		path = gtk_tree_path_copy (list->data);
 99 	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
100 
101 	list_store = GTK_LIST_STORE (tree_model);
102 	gtk_list_store_clear (list_store);
103 
104 	list = g_hash_table_get_keys (manager->priv->headers);
105 	list = g_list_sort (list, (GCompareFunc) g_utf8_collate);
106 
107 	for (link = list; link != NULL; link = g_list_next (link)) {
108 		GtkTreeIter iter;
109 		const gchar *header = link->data;
110 		gtk_list_store_append (list_store, &iter);
111 		gtk_list_store_set (list_store, &iter, 0, header, -1);
112 	}
113 
114 	g_list_free (list);
115 
116 	if (path != NULL) {
117 		gtk_tree_selection_select_path (selection, path);
118 		if (!gtk_tree_selection_path_is_selected (selection, path))
119 			if (gtk_tree_path_prev (path))
120 				gtk_tree_selection_select_path (selection, path);
121 		gtk_tree_path_free (path);
122 	}
123 }
124 
125 static gboolean
126 mail_config_header_manager_add_header (EMailConfigHeaderManager *manager,
127                                        const gchar *header)
128 {
129 	gchar *stripped_header;
130 
131 	if (!mail_config_header_manager_header_is_valid (header))
132 		return FALSE;
133 
134 	stripped_header = g_strstrip (g_strdup (header));
135 
136 	g_hash_table_replace (
137 		manager->priv->headers,
138 		stripped_header, stripped_header);
139 
140 	g_object_notify (G_OBJECT (manager), "headers");
141 
142 	mail_config_header_manager_update_list (manager);
143 
144 	return TRUE;
145 }
146 
147 static void
148 mail_config_header_manager_remove_selected (EMailConfigHeaderManager *manager)
149 {
150 	GtkTreeView *tree_view;
151 	GtkTreeModel *tree_model;
152 	GtkTreeSelection *selection;
153 	GList *list, *link;
154 
155 	tree_view = GTK_TREE_VIEW (manager->priv->tree_view);
156 	selection = gtk_tree_view_get_selection (tree_view);
157 	list = gtk_tree_selection_get_selected_rows (selection, &tree_model);
158 
159 	for (link = list; link != NULL; link = g_list_next (link)) {
160 		GtkTreePath *path = link->data;
161 		GtkTreeIter iter;
162 		gchar *header;
163 
164 		gtk_tree_model_get_iter (tree_model, &iter, path);
165 		gtk_tree_model_get (tree_model, &iter, 0, &header, -1);
166 		g_hash_table_remove (manager->priv->headers, header);
167 	}
168 
169 	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
170 
171 	g_object_notify (G_OBJECT (manager), "headers");
172 
173 	mail_config_header_manager_update_list (manager);
174 }
175 
176 static void
177 mail_config_header_manager_entry_activate (GtkEntry *entry,
178                                            EMailConfigHeaderManager *manager)
179 {
180 	const gchar *header;
181 
182 	header = gtk_entry_get_text (entry);
183 	if (mail_config_header_manager_add_header (manager, header))
184 		gtk_entry_set_text (entry, "");
185 }
186 
187 static gboolean
188 mail_config_header_manager_key_press_event (GtkTreeView *tree_view,
189                                             GdkEventKey *event,
190                                             EMailConfigHeaderManager *manager)
191 {
192 	if (event->keyval == GDK_KEY_Delete) {
193 		mail_config_header_manager_remove_selected (manager);
194 		return TRUE;
195 	}
196 
197 	return FALSE;
198 }
199 
200 static void
201 mail_config_header_manager_add_clicked (GtkButton *button,
202                                         EMailConfigHeaderManager *manager)
203 {
204 	GtkEntry *entry;
205 	const gchar *header;
206 
207 	entry = GTK_ENTRY (manager->priv->entry);
208 
209 	header = gtk_entry_get_text (entry);
210 	if (mail_config_header_manager_add_header (manager, header))
211 		gtk_entry_set_text (entry, "");
212 }
213 
214 static void
215 mail_config_header_manager_remove_clicked (GtkButton *button,
216                                            EMailConfigHeaderManager *manager)
217 {
218 	mail_config_header_manager_remove_selected (manager);
219 }
220 
221 static void
222 mail_config_header_manager_selection_changed (GtkTreeSelection *selection,
223                                               EMailConfigHeaderManager *manager)
224 {
225 	gint n_rows;
226 
227 	n_rows = gtk_tree_selection_count_selected_rows (selection);
228 	gtk_widget_set_sensitive (manager->priv->remove_button, n_rows > 0);
229 }
230 
231 static void
232 mail_config_header_manager_set_property (GObject *object,
233                                          guint property_id,
234                                          const GValue *value,
235                                          GParamSpec *pspec)
236 {
237 	switch (property_id) {
238 		case PROP_HEADERS:
239 			e_mail_config_header_manager_set_headers (
240 				E_MAIL_CONFIG_HEADER_MANAGER (object),
241 				g_value_get_boxed (value));
242 			return;
243 	}
244 
245 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
246 }
247 
248 static void
249 mail_config_header_manager_get_property (GObject *object,
250                                          guint property_id,
251                                          GValue *value,
252                                          GParamSpec *pspec)
253 {
254 	switch (property_id) {
255 		case PROP_HEADERS:
256 			g_value_take_boxed (
257 				value,
258 				e_mail_config_header_manager_dup_headers (
259 				E_MAIL_CONFIG_HEADER_MANAGER (object)));
260 			return;
261 	}
262 
263 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
264 }
265 
266 static void
267 mail_config_header_manager_finalize (GObject *object)
268 {
269 	EMailConfigHeaderManagerPrivate *priv;
270 
271 	priv = E_MAIL_CONFIG_HEADER_MANAGER_GET_PRIVATE (object);
272 
273 	g_hash_table_destroy (priv->headers);
274 
275 	/* Chain up to parent's finalize() method. */
276 	G_OBJECT_CLASS (e_mail_config_header_manager_parent_class)->
277 		finalize (object);
278 }
279 
280 static void
281 mail_config_header_manager_constructed (GObject *object)
282 {
283 	EMailConfigHeaderManager *manager;
284 	GtkTreeViewColumn *column;
285 	GtkTreeSelection *selection;
286 	GtkCellRenderer *renderer;
287 	GtkListStore *list_store;
288 	GtkWidget *widget;
289 	GtkWidget *container;
290 
291 	manager = E_MAIL_CONFIG_HEADER_MANAGER (object);
292 
293 	/* Chain up to parent's constructed() method. */
294 	G_OBJECT_CLASS (e_mail_config_header_manager_parent_class)->
295 		constructed (object);
296 
297 	gtk_grid_set_row_spacing (GTK_GRID (manager), 6);
298 	gtk_grid_set_column_spacing (GTK_GRID (manager), 12);
299 
300 	widget = gtk_entry_new ();
301 	gtk_widget_set_hexpand (widget, TRUE);
302 	gtk_grid_attach (GTK_GRID (manager), widget, 0, 0, 1, 1);
303 	manager->priv->entry = widget;  /* not referenced */
304 	gtk_widget_show (widget);
305 
306 	widget = gtk_scrolled_window_new (NULL, NULL);
307 	gtk_scrolled_window_set_policy (
308 		GTK_SCROLLED_WINDOW (widget),
309 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
310 	gtk_scrolled_window_set_shadow_type (
311 		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
312 	gtk_widget_set_hexpand (widget, TRUE);
313 	gtk_widget_set_vexpand (widget, TRUE);
314 	gtk_grid_attach (GTK_GRID (manager), widget, 0, 1, 1, 1);
315 	gtk_widget_show (widget);
316 
317 	container = widget;
318 
319 	list_store = gtk_list_store_new (1, G_TYPE_STRING);
320 	widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
321 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), FALSE);
322 	gtk_container_add (GTK_CONTAINER (container), widget);
323 	manager->priv->tree_view = widget;  /* not referenced */
324 	gtk_widget_show (widget);
325 	g_object_unref (list_store);
326 
327 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
328 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
329 
330 	widget = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
331 	gtk_box_set_spacing (GTK_BOX (widget), 6);
332 	gtk_button_box_set_layout (
333 		GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
334 	gtk_grid_attach (GTK_GRID (manager), widget, 1, 0, 1, 2);
335 	gtk_widget_show (widget);
336 
337 	container = widget;
338 
339 	widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
340 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
341 	manager->priv->add_button = widget;  /* not referenced */
342 	gtk_widget_show (widget);
343 
344 	widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
345 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
346 	manager->priv->remove_button = widget;  /* not referenced */
347 	gtk_widget_show (widget);
348 
349 	column = gtk_tree_view_column_new ();
350 	gtk_tree_view_append_column (
351 		GTK_TREE_VIEW (manager->priv->tree_view), column);
352 
353 	renderer = gtk_cell_renderer_text_new ();
354 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
355 	gtk_cell_layout_add_attribute (
356 		GTK_CELL_LAYOUT (column), renderer, "text", 0);
357 
358 	g_object_bind_property_full (
359 		manager->priv->entry, "text",
360 		manager->priv->add_button, "sensitive",
361 		G_BINDING_SYNC_CREATE,
362 		mail_config_header_manager_header_to_boolean,
363 		NULL,
364 		NULL, (GDestroyNotify) NULL);
365 
366 	g_signal_connect (
367 		manager->priv->entry, "activate",
368 		G_CALLBACK (mail_config_header_manager_entry_activate),
369 		manager);
370 
371 	g_signal_connect (
372 		manager->priv->tree_view, "key-press-event",
373 		G_CALLBACK (mail_config_header_manager_key_press_event),
374 		manager);
375 
376 	g_signal_connect (
377 		manager->priv->add_button, "clicked",
378 		G_CALLBACK (mail_config_header_manager_add_clicked),
379 		manager);
380 
381 	g_signal_connect (
382 		manager->priv->remove_button, "clicked",
383 		G_CALLBACK (mail_config_header_manager_remove_clicked),
384 		manager);
385 
386 	g_signal_connect (
387 		selection, "changed",
388 		G_CALLBACK (mail_config_header_manager_selection_changed),
389 		manager);
390 
391 	mail_config_header_manager_selection_changed (selection, manager);
392 }
393 
394 static void
395 e_mail_config_header_manager_class_init (EMailConfigHeaderManagerClass *class)
396 {
397 	GObjectClass *object_class;
398 
399 	g_type_class_add_private (
400 		class, sizeof (EMailConfigHeaderManagerPrivate));
401 
402 	object_class = G_OBJECT_CLASS (class);
403 	object_class->set_property = mail_config_header_manager_set_property;
404 	object_class->get_property = mail_config_header_manager_get_property;
405 	object_class->finalize = mail_config_header_manager_finalize;
406 	object_class->constructed = mail_config_header_manager_constructed;
407 
408 	g_object_class_install_property (
409 		object_class,
410 		PROP_HEADERS,
411 		g_param_spec_boxed (
412 			"headers",
413 			"Headers",
414 			"Array of header names",
415 			G_TYPE_STRV,
416 			G_PARAM_READWRITE));
417 }
418 
419 static void
420 e_mail_config_header_manager_class_finalize (EMailConfigHeaderManagerClass *class)
421 {
422 }
423 
424 static void
425 e_mail_config_header_manager_init (EMailConfigHeaderManager *manager)
426 {
427 	manager->priv = E_MAIL_CONFIG_HEADER_MANAGER_GET_PRIVATE (manager);
428 
429 	manager->priv->headers = g_hash_table_new_full (
430 		(GHashFunc) g_str_hash,
431 		(GEqualFunc) g_str_equal,
432 		(GDestroyNotify) g_free,
433 		(GDestroyNotify) NULL);
434 }
435 
436 void
437 e_mail_config_header_manager_type_register (GTypeModule *type_module)
438 {
439 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
440 	 *     function, so we have to wrap it with a public function in
441 	 *     order to register types from a separate compilation unit. */
442 	e_mail_config_header_manager_register_type (type_module);
443 }
444 
445 GtkWidget *
446 e_mail_config_header_manager_new (void)
447 {
448 	return g_object_new (E_TYPE_MAIL_CONFIG_HEADER_MANAGER, NULL);
449 }
450 
451 gchar **
452 e_mail_config_header_manager_dup_headers (EMailConfigHeaderManager *manager)
453 {
454 	GList *list, *link;
455 	gchar **headers = NULL;
456 	guint ii = 0;
457 
458 	g_return_val_if_fail (E_IS_MAIL_CONFIG_HEADER_MANAGER (manager), NULL);
459 
460 	list = g_hash_table_get_keys (manager->priv->headers);
461 	list = g_list_sort (list, (GCompareFunc) g_utf8_collate);
462 
463 	if (list != NULL) {
464 		headers = g_new0 (gchar *, g_list_length (list) + 1);
465 		for (link = list; link != NULL; link = g_list_next (link))
466 			headers[ii++] = g_strdup (link->data);
467 		g_list_free (list);
468 	}
469 
470 	return headers;
471 }
472 
473 void
474 e_mail_config_header_manager_set_headers (EMailConfigHeaderManager *manager,
475                                           const gchar * const *headers)
476 {
477 	gint ii = 0;
478 
479 	g_return_if_fail (E_IS_MAIL_CONFIG_HEADER_MANAGER (manager));
480 
481 	g_hash_table_remove_all (manager->priv->headers);
482 
483 	while (headers != NULL && headers[ii] != NULL) {
484 		gchar *stripped_header;
485 
486 		stripped_header = g_strstrip (g_strdup (headers[ii++]));
487 
488 		if (*stripped_header != '\0')
489 			g_hash_table_insert (
490 				manager->priv->headers,
491 				stripped_header, stripped_header);
492 		else
493 			g_free (stripped_header);
494 	}
495 
496 	g_object_notify (G_OBJECT (manager), "headers");
497 
498 	mail_config_header_manager_update_list (manager);
499 }