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