No issues found
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 * Ashish Shrivastava <shashish@novell.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <glib/gi18n.h>
29 #include "mail/em-utils.h"
30 #include "mail/em-event.h"
31 #include "composer/e-msg-composer.h"
32 #include "e-util/e-config.h"
33 #include "e-util/e-util.h"
34 #include "email-custom-header.h"
35
36 #define d(x)
37
38 #define ECM_SETTINGS_ID "org.gnome.evolution.plugin.email-custom-header"
39 #define ECM_SETTINGS_KEY "custom-header"
40
41 #define CUSTOM_HEADER_OPTIONS_DIALOG_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE \
43 ((obj), EMAIL_CUSTOM_HEADER_OPTIONS_DIALOG, CustomHeaderOptionsDialogPrivate))
44
45 typedef struct {
46 GtkWidget *treeview;
47 GtkWidget *header_add;
48 GtkWidget *header_edit;
49 GtkWidget *header_remove;
50 GtkListStore *store;
51 } ConfigData;
52
53 enum {
54 HEADER_KEY_COLUMN,
55 HEADER_VALUE_COLUMN,
56 HEADER_N_COLUMNS
57 };
58
59 struct _CustomHeaderOptionsDialogPrivate {
60 GtkBuilder *builder;
61 /*Widgets*/
62 GtkWidget *main;
63 GtkWidget *page;
64 GtkWidget *header_table;
65 GtkWidget *header_type_name_label;
66 GArray *combo_box_header_value;
67 GArray *email_custom_header_details;
68 GArray *header_index_type;
69 gint flag;
70 gchar *help_section;
71 };
72
73 /* epech - e-plugin email custom header*/
74 GType custom_header_options_dialog_get_type (void);
75 static void epech_dialog_finalize (GObject *object);
76 static void epech_setup_widgets (CustomHeaderOptionsDialog *mch);
77 static gint epech_check_existing_composer_window (gconstpointer a, gconstpointer b);
78 static void commit_changes (ConfigData *cd);
79 gint e_plugin_lib_enable (EPlugin *ep, gint enable);
80 GtkWidget *e_plugin_lib_get_configure_widget (EPlugin *epl);
81 gboolean e_plugin_ui_init (GtkUIManager *ui_manager, EMsgComposer *composer);
82 GtkWidget *org_gnome_email_custom_header_config_option (EPlugin *epl, struct _EConfigHookItemFactoryData *data);
83
84 G_DEFINE_TYPE (
85 CustomHeaderOptionsDialog,
86 custom_header_options_dialog,
87 G_TYPE_OBJECT)
88
89 gint
90 e_plugin_lib_enable (EPlugin *ep,
91 gint enable)
92 {
93 return 0;
94 }
95
96 static void
97 epech_get_widgets_data (CustomHeaderOptionsDialog *mch)
98 {
99 CustomHeaderOptionsDialogPrivate *priv;
100 HeaderValueComboBox *sub_combo_box_get;
101 gint selected_item;
102 gint index_column;
103
104 priv = mch->priv;
105 priv->header_index_type = g_array_new (FALSE, FALSE, sizeof (gint));
106 priv->flag++;
107
108 for (index_column = 0;
109 index_column < priv->email_custom_header_details->len; index_column++) {
110
111 sub_combo_box_get = &g_array_index (priv->combo_box_header_value, HeaderValueComboBox,index_column);
112 selected_item = gtk_combo_box_get_active ((GtkComboBox *) sub_combo_box_get->header_value_combo_box);
113 g_array_append_val (priv->header_index_type, selected_item);
114 }
115 }
116
117 static gboolean
118 epech_get_widgets (CustomHeaderOptionsDialog *mch)
119 {
120 CustomHeaderOptionsDialogPrivate *priv;
121 priv = mch->priv;
122
123 #define EMAIL_CUSTOM_HEADER(name) e_builder_get_widget (priv->builder, name)
124 priv->main = EMAIL_CUSTOM_HEADER ("email-custom-header-dialog");
125
126 if (!priv->main)
127 return FALSE;
128
129 priv->page = EMAIL_CUSTOM_HEADER ("email-custom-header-vbox");
130 priv->header_table = EMAIL_CUSTOM_HEADER ("email-custom-header-options");
131 #undef EMAIL_CUSTOM_HEADER
132
133 return (priv->page
134 &&priv->header_table);
135 }
136
137 static void
138 epech_fill_widgets_with_data (CustomHeaderOptionsDialog *mch)
139 {
140 CustomHeaderOptionsDialogPrivate *priv;
141 HeaderValueComboBox *sub_combo_box_fill;
142 gint set_index_column;
143
144 priv = mch->priv;
145 priv->help_section = g_strdup ("mail-composer-custom-header-lines");
146
147 for (set_index_column = 0;
148 set_index_column < priv->email_custom_header_details->len; set_index_column++) {
149 sub_combo_box_fill = &g_array_index (priv->combo_box_header_value, HeaderValueComboBox,set_index_column);
150
151 if (priv->flag == 0) {
152 gtk_combo_box_set_active ((GtkComboBox *) sub_combo_box_fill->header_value_combo_box,0);
153 } else {
154 gtk_combo_box_set_active (
155 (GtkComboBox *) sub_combo_box_fill->header_value_combo_box,
156 g_array_index (priv->header_index_type, gint, set_index_column));
157 }
158 }
159 }
160
161 CustomHeaderOptionsDialog *
162 epech_dialog_new (void)
163 {
164 return g_object_new (EMAIL_CUSTOM_HEADER_OPTIONS_DIALOG, NULL);
165 }
166
167 static void
168 epech_header_options_cb (GtkDialog *dialog,
169 gint state,
170 gpointer func_data)
171 {
172 CustomHeaderOptionsDialogPrivate *priv;
173 CustomHeaderOptionsDialog *mch;
174
175 mch = func_data;
176 priv = mch->priv;
177
178 switch (state) {
179 case GTK_RESPONSE_OK:
180 epech_get_widgets_data (mch);
181 case GTK_RESPONSE_CANCEL:
182 gtk_widget_hide (priv->main);
183 gtk_widget_destroy (priv->main);
184 g_object_unref (priv->builder);
185 break;
186 case GTK_RESPONSE_HELP:
187 e_display_help (
188 GTK_WINDOW (priv->main),
189 priv->help_section);
190 break;
191 }
192
193 g_signal_emit (func_data, signals[MCH_RESPONSE], 0, state);
194 }
195
196 static gboolean
197 epech_dialog_run (CustomHeaderOptionsDialog *mch,
198 GtkWidget *parent)
199 {
200 CustomHeaderOptionsDialogPrivate *priv;
201 GSettings *settings;
202 GtkWidget *toplevel;
203
204 g_return_val_if_fail (mch != NULL || EMAIL_CUSTOM_HEADER_OPTIONS_IS_DIALOG (mch), FALSE);
205 priv = mch->priv;
206
207 settings = g_settings_new (ECM_SETTINGS_ID);
208 epech_load_from_settings (settings, ECM_SETTINGS_KEY, mch);
209 g_object_unref (settings);
210
211 priv->builder = gtk_builder_new ();
212 e_load_ui_builder_definition (
213 priv->builder, "org-gnome-email-custom-header.ui");
214
215 if (!epech_get_widgets (mch)) {
216 g_object_unref (priv->builder);
217 d (printf ("\n Could not get the Widgets\n"));
218 }
219
220 epech_setup_widgets (mch);
221 toplevel = gtk_widget_get_toplevel (priv->main);
222
223 if (parent)
224 gtk_window_set_transient_for (GTK_WINDOW (toplevel),GTK_WINDOW (parent));
225
226 epech_fill_widgets_with_data (mch);
227 g_signal_connect (
228 priv->main, "response",
229 G_CALLBACK (epech_header_options_cb), mch);
230 gtk_widget_show (priv->main);
231
232 return TRUE;
233 }
234
235 static void
236 epech_load_from_settings (GSettings *settings,
237 const gchar *key,
238 CustomHeaderOptionsDialog *mch)
239 {
240 CustomHeaderOptionsDialogPrivate *priv;
241 EmailCustomHeaderDetails temp_header_details= {-1, -1, NULL, NULL};
242 CustomSubHeader temp_header_value_details = {NULL};
243 gchar **headers;
244 gint index,pos;
245
246 priv = mch->priv;
247 priv->email_custom_header_details = g_array_new (TRUE, TRUE, sizeof (EmailCustomHeaderDetails));
248 headers = g_settings_get_strv (settings, key);
249
250 for (pos = 0; headers && headers[pos]; pos++) {
251 gchar **parse_header_list;
252
253 memset (&temp_header_value_details, 0, sizeof (CustomSubHeader));
254 temp_header_details.sub_header_type_value = g_array_new (TRUE, TRUE, sizeof (CustomSubHeader));
255 parse_header_list = g_strsplit_set (headers[pos], "=;,", -1);
256 temp_header_details.header_type_value = g_string_new ("");
257 if (temp_header_details.header_type_value) {
258 g_string_assign (temp_header_details.header_type_value, parse_header_list[0]);
259 }
260
261 for (index = 0; parse_header_list[index + 1] ; ++index) {
262 temp_header_value_details.sub_header_string_value = g_string_new ("");
263
264 if (temp_header_value_details.sub_header_string_value) {
265 g_string_assign (temp_header_value_details.sub_header_string_value, parse_header_list[index + 1]);
266 }
267
268 g_array_append_val (temp_header_details.sub_header_type_value, temp_header_value_details);
269 }
270
271 temp_header_details.number_of_subtype_header = index;
272 g_array_append_val (priv->email_custom_header_details, temp_header_details);
273 }
274
275 temp_header_details.number_of_header = pos;
276
277 g_strfreev (headers);
278 }
279
280 static void
281 epech_setup_widgets (CustomHeaderOptionsDialog *mch)
282 {
283 CustomHeaderOptionsDialogPrivate *priv;
284 EmailCustomHeaderDetails *temp_header_ptr,*temp;
285 CustomSubHeader *temp_header_value_ptr;
286 HeaderValueComboBox sub_combo_box = {NULL};
287 HeaderValueComboBox *sub_combo_box_ptr;
288 gint sub_index,row_combo,column_combo;
289 gint header_section_id,sub_type_index,row,column;
290 gint i;
291 const gchar *str;
292 static const gchar *security_field = NC_("email-custom-header-Security", "Security:");
293 static struct _security_values {
294 const gchar *value, *str;
295 } security_values[] = {
296 { "Personal", NC_("email-custom-header-Security", "Personal") } ,
297 { "Unclassified", NC_("email-custom-header-Security", "Unclassified") },
298 { "Protected", NC_("email-custom-header-Security", "Protected") },
299 { "InConfidence", NC_("email-custom-header-Security", "Confidential") },
300 { "Secret", NC_("email-custom-header-Security", "Secret") },
301 { "Topsecret", NC_("email-custom-header-Security", "Top secret") },
302 { NULL, NULL }
303 };
304
305 priv = mch->priv;
306 priv->combo_box_header_value = g_array_new (TRUE, FALSE, sizeof (HeaderValueComboBox));
307
308 for (header_section_id = 0,row = 0,column = 1;
309 header_section_id < priv->email_custom_header_details->len; header_section_id++,row++,column++) {
310
311 /* To create an empty label widget. Text will be added dynamically. */
312 priv->header_type_name_label = gtk_label_new ("");
313 temp_header_ptr = &g_array_index (priv->email_custom_header_details, EmailCustomHeaderDetails,header_section_id);
314 str = (temp_header_ptr->header_type_value)->str;
315 if (strcmp (str, security_field) == 0)
316 str = g_dpgettext2 (GETTEXT_PACKAGE, "email-custom-header-Security", security_field);
317 gtk_label_set_markup (GTK_LABEL (priv->header_type_name_label), str);
318
319 gtk_table_attach (
320 GTK_TABLE (priv->header_table),
321 priv->header_type_name_label, 0, 1, row, column,
322 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
323 (GtkAttachOptions) (0), 0, 0);
324
325 gtk_misc_set_alignment (GTK_MISC (priv->header_type_name_label), 0, 0.5);
326 gtk_widget_show (priv->header_type_name_label);
327 sub_combo_box.header_value_combo_box = gtk_combo_box_text_new ();
328 g_array_append_val (priv->combo_box_header_value, sub_combo_box);
329 }
330
331 for (sub_index = 0,row_combo = 0,column_combo = 1; sub_index < priv->combo_box_header_value->len;
332 sub_index++,row_combo++,column_combo++) {
333 temp = &g_array_index (priv->email_custom_header_details, EmailCustomHeaderDetails,sub_index);
334
335 sub_combo_box_ptr = &g_array_index (priv->combo_box_header_value, HeaderValueComboBox,sub_index);
336 gtk_table_attach (
337 GTK_TABLE (priv->header_table),
338 sub_combo_box_ptr->header_value_combo_box, 1, 2, row_combo, column_combo,
339 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
340 (GtkAttachOptions) (GTK_FILL), 0, 0);
341
342 for (sub_type_index = 0; sub_type_index < temp->number_of_subtype_header; sub_type_index++) {
343 temp_header_value_ptr = &g_array_index (temp->sub_header_type_value, CustomSubHeader,sub_type_index);
344 str = (temp_header_value_ptr->sub_header_string_value)->str;
345 for (i = 0; security_values[i].value != NULL; i++) {
346 if (strcmp (str, security_values[i].value) == 0) {
347 str = g_dpgettext2 (GETTEXT_PACKAGE, "email-custom-header-Security", security_values[i].str);
348 break;
349 }
350 }
351 gtk_combo_box_text_append_text (
352 GTK_COMBO_BOX_TEXT (
353 sub_combo_box_ptr->header_value_combo_box), str);
354 }
355
356 /* Translators: "None" as an email custom header option in a dialog invoked by Insert->Custom Header from Composer,
357 * indicating the header will not be added to a mail message */
358 gtk_combo_box_text_append_text (
359 GTK_COMBO_BOX_TEXT (
360 sub_combo_box_ptr->header_value_combo_box),
361 C_("email-custom-header", "None"));
362 gtk_widget_show (sub_combo_box_ptr->header_value_combo_box);
363 }
364 }
365
366 static void
367 custom_header_options_dialog_class_init (CustomHeaderOptionsDialogClass *class)
368 {
369 GObjectClass *object_class;
370
371 g_type_class_add_private (
372 class, sizeof (CustomHeaderOptionsDialogPrivate));
373
374 object_class = G_OBJECT_CLASS (class);
375 object_class->finalize = epech_dialog_finalize;
376
377 signals[MCH_RESPONSE] = g_signal_new (
378 "emch_response",
379 G_TYPE_FROM_CLASS (class),
380 G_SIGNAL_RUN_FIRST,
381 G_STRUCT_OFFSET (CustomHeaderOptionsDialogClass, emch_response),
382 NULL, NULL,
383 g_cclosure_marshal_VOID__INT,
384 G_TYPE_NONE, 1,
385 G_TYPE_INT);
386 }
387
388 static void
389 custom_header_options_dialog_init (CustomHeaderOptionsDialog *mch)
390 {
391 mch->priv = CUSTOM_HEADER_OPTIONS_DIALOG_GET_PRIVATE (mch);
392 }
393
394 static void
395 epech_dialog_finalize (GObject *object)
396 {
397 CustomHeaderOptionsDialogPrivate *priv;
398
399 priv = CUSTOM_HEADER_OPTIONS_DIALOG_GET_PRIVATE (object);
400
401 g_free (priv->help_section);
402
403 /* Chain up to parent's finalize() method. */
404 G_OBJECT_CLASS (custom_header_options_dialog_parent_class)->finalize (object);
405 }
406
407 static void
408 epech_append_to_custom_header (CustomHeaderOptionsDialog *dialog,
409 gint state,
410 gpointer data)
411 {
412 EMsgComposer *composer;
413 CustomHeaderOptionsDialogPrivate *priv;
414 EmailCustomHeaderDetails *temp_header_ptr;
415 CustomSubHeader *temp_header_value_ptr;
416 gint index_subtype,sub_type_index;
417
418 composer = (EMsgComposer *) data;
419 priv = dialog->priv;
420
421 if (state == GTK_RESPONSE_OK) {
422
423 for (index_subtype = 0; index_subtype < priv->email_custom_header_details->len; index_subtype++) {
424
425 temp_header_ptr = &g_array_index (priv->email_custom_header_details, EmailCustomHeaderDetails,index_subtype);
426
427 for (sub_type_index = 0; sub_type_index < temp_header_ptr->number_of_subtype_header; sub_type_index++) {
428 temp_header_value_ptr = &g_array_index (temp_header_ptr->sub_header_type_value, CustomSubHeader,sub_type_index);
429
430 if (sub_type_index == g_array_index (priv->header_index_type, gint, index_subtype)) {
431 e_msg_composer_set_header (
432 composer, (temp_header_ptr->header_type_value)->str,
433 (temp_header_value_ptr->sub_header_string_value)->str);
434 }
435 }
436 }
437 }
438 }
439
440 static void
441 epech_custom_header_options_commit (EMsgComposer *comp,
442 gpointer user_data)
443 {
444 EMsgComposer *composer;
445 EmailCustomHeaderWindow *new_email_custom_header_window = NULL;
446 CustomHeaderOptionsDialog *current_dialog = NULL;
447
448 composer = (EMsgComposer *) user_data;
449
450 if (!user_data || !EMAIL_CUSTOM_HEADER_OPTIONS_IS_DIALOG (user_data))
451 return;
452
453 new_email_custom_header_window = g_object_get_data ((GObject *) composer, "compowindow");
454
455 if (new_email_custom_header_window) {
456 current_dialog = new_email_custom_header_window->epech_dialog;
457 }
458
459 if (current_dialog) {
460 g_free (current_dialog);
461 current_dialog = NULL;
462 }
463
464 if (new_email_custom_header_window) {
465 g_free (new_email_custom_header_window);
466 new_email_custom_header_window = NULL;
467 }
468 }
469
470 static gint
471 epech_check_existing_composer_window (gconstpointer compowindow,
472 gconstpointer other_compowindow)
473 {
474 if ((compowindow) && (other_compowindow)) {
475 if (((EmailCustomHeaderWindow *) compowindow)->epech_window == (GdkWindow *) other_compowindow) {
476 return 0;
477 }
478 }
479
480 return -1;
481 }
482
483 static void
484 destroy_compo_data (gpointer data)
485 {
486 EmailCustomHeaderWindow *compo_data = (EmailCustomHeaderWindow *) data;
487
488 if (!compo_data)
489 return;
490
491 g_free (compo_data);
492 }
493
494 static void action_email_custom_header_cb (GtkAction *action, EMsgComposer *composer)
495
496 {
497 GtkUIManager *ui_manager;
498 GtkWidget *menuitem;
499 GdkWindow *window;
500 CustomHeaderOptionsDialog *dialog = NULL;
501 EmailCustomHeaderWindow *new_email_custom_header_window = NULL;
502
503 ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (composer));
504 menuitem = gtk_ui_manager_get_widget (ui_manager, "/main-menu/insert-menu/insert-menu-top/Custom Header");
505
506 new_email_custom_header_window = g_object_get_data ((GObject *) composer, "compowindow");
507
508 window = gtk_widget_get_window (menuitem);
509 if (epech_check_existing_composer_window (new_email_custom_header_window,window) == 0) {
510 dialog = new_email_custom_header_window->epech_dialog;
511 } else {
512 dialog = epech_dialog_new ();
513 if (dialog) {
514 EmailCustomHeaderWindow *new_email_custom_header_window;
515 new_email_custom_header_window = g_new0 (EmailCustomHeaderWindow, 1);
516 new_email_custom_header_window->epech_window = window;
517 new_email_custom_header_window->epech_dialog = dialog;
518 g_object_set_data_full ((GObject *) composer, "compowindow", new_email_custom_header_window, destroy_compo_data);
519 }
520 }
521
522 epech_dialog_run (dialog, GTK_WIDGET (composer));
523 g_signal_connect (
524 dialog, "emch_response",
525 G_CALLBACK (epech_append_to_custom_header), composer);
526 g_signal_connect (
527 composer, "destroy",
528 G_CALLBACK (epech_custom_header_options_commit), composer);
529 }
530
531 static GtkActionEntry entries[] = {
532
533 { "Custom Header",
534 NULL,
535 N_("_Custom Header"),
536 NULL,
537 NULL,
538 G_CALLBACK (action_email_custom_header_cb) }
539 };
540
541 gboolean
542 e_plugin_ui_init (GtkUIManager *ui_manager,
543 EMsgComposer *composer)
544 {
545 GtkhtmlEditor *editor;
546
547 editor = GTKHTML_EDITOR (composer);
548
549 /* Add actions to the "composer" action group. */
550 gtk_action_group_add_actions (
551 gtkhtml_editor_get_action_group (editor, "composer"),
552 entries, G_N_ELEMENTS (entries), composer);
553
554 return TRUE;
555 }
556
557 static void
558 commit_changes (ConfigData *cd)
559 {
560 GtkTreeModel *model = NULL;
561 GPtrArray *headers;
562 GtkTreeIter iter;
563 gboolean valid;
564 GSettings *settings;
565
566 headers = g_ptr_array_new_full (3, g_free);
567
568 model = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->treeview));
569 valid = gtk_tree_model_get_iter_first (model, &iter);
570
571 while (valid) {
572 gchar *keyword = NULL, *value = NULL;
573
574 gtk_tree_model_get (
575 model, &iter,
576 HEADER_KEY_COLUMN, &keyword,
577 HEADER_VALUE_COLUMN, &value,
578 -1);
579
580 /* Check if the keyword is not empty */
581 if ((keyword) && (g_utf8_strlen (g_strstrip (keyword), -1) > 0)) {
582 if ((value) && (g_utf8_strlen (g_strstrip (value), -1) > 0)) {
583 gchar *tmp = keyword;
584
585 keyword = g_strconcat (keyword, "=", value, NULL);
586 g_free (tmp);
587 }
588 g_ptr_array_add (headers, g_strdup (keyword));
589 }
590
591 g_free (keyword);
592 g_free (value);
593
594 valid = gtk_tree_model_iter_next (model, &iter);
595 }
596
597 g_ptr_array_add (headers, NULL);
598
599 settings = g_settings_new (ECM_SETTINGS_ID);
600 g_settings_set_strv (settings, ECM_SETTINGS_KEY, (const gchar * const *) headers->pdata);
601 g_object_unref (settings);
602
603 g_ptr_array_free (headers, TRUE);
604 }
605
606 static void
607 cell_edited_cb (GtkCellRendererText *cell,
608 gchar *path_string,
609 gchar *new_text,
610 ConfigData *cd)
611 {
612 GtkTreeModel *model;
613 GtkTreeIter iter;
614
615 model = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->treeview));
616 gtk_tree_model_get_iter_from_string (model, &iter, path_string);
617
618 if (new_text == NULL || *g_strstrip (new_text) == '\0')
619 gtk_button_clicked (GTK_BUTTON (cd->header_remove));
620 else {
621 gtk_list_store_set (
622 GTK_LIST_STORE (model), &iter,
623 HEADER_KEY_COLUMN, new_text, -1);
624 commit_changes (cd);
625 }
626 }
627
628 static void
629 cell_editing_canceled_cb (GtkCellRenderer *cell,
630 ConfigData *cd)
631 {
632 gtk_button_clicked (GTK_BUTTON (cd->header_remove));
633 }
634
635 static void
636 cell_value_edited_cb (GtkCellRendererText *cell,
637 gchar *path_string,
638 gchar *new_text,
639 ConfigData *cd)
640 {
641 GtkTreeModel *model;
642 GtkTreeIter iter;
643
644 model = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->treeview));
645
646 gtk_tree_model_get_iter_from_string (model, &iter, path_string);
647
648 gtk_list_store_set (
649 GTK_LIST_STORE (model), &iter,
650 HEADER_VALUE_COLUMN, new_text, -1);
651
652 commit_changes (cd);
653 }
654
655 static void
656 header_add_clicked (GtkButton *button,
657 ConfigData *cd)
658 {
659 GtkTreeModel *model;
660 GtkTreeView *tree_view;
661 GtkTreeViewColumn *column;
662 GtkTreePath *path;
663 GtkTreeIter iter;
664
665 tree_view = GTK_TREE_VIEW (cd->treeview);
666 model = gtk_tree_view_get_model (tree_view);
667
668 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
669
670 path = gtk_tree_model_get_path (model, &iter);
671 column = gtk_tree_view_get_column (tree_view, HEADER_KEY_COLUMN);
672 gtk_tree_view_set_cursor (tree_view, path, column, TRUE);
673 gtk_tree_view_row_activated (tree_view, path, column);
674 gtk_tree_path_free (path);
675 }
676
677 static void
678 header_remove_clicked (GtkButton *button,
679 ConfigData *cd)
680 {
681 GtkTreeSelection *selection;
682 GtkTreeModel *model;
683 GtkTreeIter iter;
684 GtkTreePath *path;
685 gboolean valid;
686 gint len;
687
688 valid = FALSE;
689 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cd->treeview));
690 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
691 return;
692
693 /* Get the path and move to the previous node :) */
694 path = gtk_tree_model_get_path (model, &iter);
695 if (path)
696 valid = gtk_tree_path_prev (path);
697
698 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
699
700 len = gtk_tree_model_iter_n_children (model, NULL);
701 if (len > 0) {
702 if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (model), &iter)) {
703 gtk_tree_selection_select_iter (selection, &iter);
704 } else {
705 if (path && valid) {
706 gtk_tree_model_get_iter (model, &iter, path);
707 gtk_tree_selection_select_iter (selection, &iter);
708 }
709 }
710 } else {
711 gtk_widget_set_sensitive (cd->header_edit, FALSE);
712 gtk_widget_set_sensitive (cd->header_remove, FALSE);
713 }
714
715 gtk_widget_grab_focus (cd->treeview);
716 gtk_tree_path_free (path);
717
718 commit_changes (cd);
719 }
720
721 static void
722 header_edit_clicked (GtkButton *button,
723 ConfigData *cd)
724 {
725 GtkTreeSelection *selection;
726 GtkTreeModel *model;
727 GtkTreePath *path;
728 GtkTreeIter iter;
729 GtkTreeViewColumn *focus_col;
730
731 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cd->treeview));
732 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
733 return;
734
735 focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (cd->treeview), HEADER_KEY_COLUMN);
736 path = gtk_tree_model_get_path (model, &iter);
737
738 if (path) {
739 gtk_tree_view_set_cursor (GTK_TREE_VIEW (cd->treeview), path, focus_col, TRUE);
740 gtk_tree_path_free (path);
741 }
742 }
743
744 static void
745 selection_changed (GtkTreeSelection *selection,
746 ConfigData *cd)
747 {
748 GtkTreeModel *model;
749 GtkTreeIter iter;
750
751 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
752 gtk_widget_set_sensitive (cd->header_edit, TRUE);
753 gtk_widget_set_sensitive (cd->header_remove, TRUE);
754 } else {
755 gtk_widget_set_sensitive (cd->header_edit, FALSE);
756 gtk_widget_set_sensitive (cd->header_remove, FALSE);
757 }
758 }
759
760 static void
761 destroy_cd_data (gpointer data)
762 {
763 ConfigData *cd = (ConfigData *) data;
764
765 if (!cd)
766 return;
767
768 g_free (cd);
769 }
770
771 GtkWidget *
772 e_plugin_lib_get_configure_widget (EPlugin *epl)
773 {
774 GtkCellRenderer *renderer;
775 GtkTreeSelection *selection;
776 GtkTreeIter iter;
777 GtkWidget *hbox;
778 gchar **headers;
779 gint index;
780 GtkTreeViewColumn *col;
781 gint col_pos;
782 GSettings *settings;
783 ConfigData *cd = g_new0 (ConfigData, 1);
784
785 GtkWidget *ech_configuration_box;
786 GtkWidget *vbox2;
787 GtkWidget *label1;
788 GtkWidget *header_configuration_box;
789 GtkWidget *header_container;
790 GtkWidget *scrolledwindow1;
791 GtkWidget *header_treeview;
792 GtkWidget *vbuttonbox1;
793 GtkWidget *header_add;
794 GtkWidget *header_edit;
795 GtkWidget *header_remove;
796
797 ech_configuration_box = gtk_vbox_new (FALSE, 6);
798 gtk_widget_show (ech_configuration_box);
799
800 vbox2 = gtk_vbox_new (FALSE, 0);
801 gtk_widget_show (vbox2);
802 gtk_box_pack_start (GTK_BOX (ech_configuration_box), vbox2, FALSE, FALSE, 0);
803
804 /* To translators: This string is used while adding a new message header to configuration, to specifying the format of the key values */
805 label1 = gtk_label_new (_("The format for specifying a Custom Header key value is:\nName of the Custom Header key values separated by \";\"."));
806 gtk_widget_show (label1);
807 gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, TRUE, 0);
808 gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_CENTER);
809 gtk_label_set_line_wrap (GTK_LABEL (label1), TRUE);
810
811 header_configuration_box = gtk_vbox_new (FALSE, 6);
812 gtk_widget_show (header_configuration_box);
813 gtk_box_pack_start (GTK_BOX (ech_configuration_box), header_configuration_box, TRUE, TRUE, 0);
814
815 header_container = gtk_hbox_new (FALSE, 12);
816 gtk_widget_show (header_container);
817 gtk_box_pack_start (GTK_BOX (header_configuration_box), header_container, TRUE, TRUE, 0);
818
819 scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
820 gtk_widget_show (scrolledwindow1);
821 gtk_box_pack_start (GTK_BOX (header_container), scrolledwindow1, TRUE, TRUE, 0);
822 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
823
824 header_treeview = gtk_tree_view_new ();
825 gtk_widget_show (header_treeview);
826 gtk_container_add (GTK_CONTAINER (scrolledwindow1), header_treeview);
827 gtk_container_set_border_width (GTK_CONTAINER (header_treeview), 1);
828
829 vbuttonbox1 = gtk_vbutton_box_new ();
830 gtk_widget_show (vbuttonbox1);
831 gtk_box_pack_start (GTK_BOX (header_container), vbuttonbox1, FALSE, TRUE, 0);
832 gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox1), GTK_BUTTONBOX_START);
833 gtk_box_set_spacing (GTK_BOX (vbuttonbox1), 6);
834
835 header_add = gtk_button_new_from_stock ("gtk-add");
836 gtk_widget_show (header_add);
837 gtk_container_add (GTK_CONTAINER (vbuttonbox1), header_add);
838 gtk_widget_set_can_default (header_add, TRUE);
839
840 header_edit = gtk_button_new_from_stock ("gtk-edit");
841 gtk_widget_show (header_edit);
842 gtk_container_add (GTK_CONTAINER (vbuttonbox1), header_edit);
843 gtk_widget_set_can_default (header_edit, TRUE);
844
845 header_remove = gtk_button_new_from_stock ("gtk-remove");
846 gtk_widget_show (header_remove);
847 gtk_container_add (GTK_CONTAINER (vbuttonbox1), header_remove);
848 gtk_widget_set_can_default (header_remove, TRUE);
849
850 cd->treeview = header_treeview;
851
852 cd->store = gtk_list_store_new (HEADER_N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
853
854 gtk_tree_view_set_model (GTK_TREE_VIEW (cd->treeview), GTK_TREE_MODEL (cd->store));
855
856 renderer = gtk_cell_renderer_text_new ();
857 col_pos = gtk_tree_view_insert_column_with_attributes (
858 GTK_TREE_VIEW (cd->treeview), -1, _("Key"),
859 renderer, "text", HEADER_KEY_COLUMN, NULL);
860 col = gtk_tree_view_get_column (GTK_TREE_VIEW (cd->treeview), col_pos -1);
861 gtk_tree_view_column_set_resizable (col, TRUE);
862 gtk_tree_view_column_set_reorderable (col, TRUE);
863 g_object_set (col, "min-width", 50, NULL);
864
865 g_object_set (renderer, "editable", TRUE, NULL);
866 g_signal_connect (
867 renderer, "edited",
868 G_CALLBACK (cell_edited_cb), cd);
869 g_signal_connect (
870 renderer, "editing-canceled",
871 G_CALLBACK (cell_editing_canceled_cb), cd);
872
873 renderer = gtk_cell_renderer_text_new ();
874 col_pos = gtk_tree_view_insert_column_with_attributes (
875 GTK_TREE_VIEW (cd->treeview), -1, _("Values"),
876 renderer, "text", HEADER_VALUE_COLUMN, NULL);
877 col = gtk_tree_view_get_column (GTK_TREE_VIEW (cd->treeview), col_pos -1);
878 gtk_tree_view_column_set_resizable (col, TRUE);
879 gtk_tree_view_column_set_reorderable (col, TRUE);
880 g_object_set (renderer, "editable", TRUE, NULL);
881
882 g_signal_connect (
883 renderer, "edited",
884 G_CALLBACK (cell_value_edited_cb), cd);
885
886 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cd->treeview));
887 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
888 g_signal_connect (
889 selection, "changed",
890 G_CALLBACK (selection_changed), cd);
891 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (cd->treeview), TRUE);
892
893 cd->header_add = header_add;
894 g_signal_connect (
895 cd->header_add, "clicked",
896 G_CALLBACK (header_add_clicked), cd);
897
898 cd->header_remove = header_remove;
899 g_signal_connect (
900 cd->header_remove, "clicked",
901 G_CALLBACK (header_remove_clicked), cd);
902 gtk_widget_set_sensitive (cd->header_remove, FALSE);
903
904 cd->header_edit = header_edit;
905 g_signal_connect (
906 cd->header_edit, "clicked",
907 G_CALLBACK (header_edit_clicked), cd);
908 gtk_widget_set_sensitive (cd->header_edit, FALSE);
909
910 /* Populate tree view with values from settings */
911 settings = g_settings_new (ECM_SETTINGS_ID);
912 headers = g_settings_get_strv (settings, ECM_SETTINGS_KEY);
913 g_object_unref (settings);
914
915 if (headers) {
916 gint ii;
917
918 for (ii = 0; headers[ii]; ii++) {
919 gchar **parse_header_list;
920
921 gtk_list_store_append (cd->store, &iter);
922
923 parse_header_list = g_strsplit_set (headers[ii], "=,", -1);
924
925 gtk_list_store_set (cd->store, &iter, HEADER_KEY_COLUMN, parse_header_list[0], -1);
926
927 for (index = 0; parse_header_list[index + 1] ; ++index) {
928 gtk_list_store_set (cd->store, &iter, HEADER_VALUE_COLUMN, parse_header_list[index + 1], -1);
929 }
930 }
931
932 g_strfreev (headers);
933 }
934
935 /* Add the list here */
936
937 hbox = gtk_vbox_new (FALSE, 0);
938
939 gtk_box_pack_start (GTK_BOX (hbox), ech_configuration_box, TRUE, TRUE, 0);
940
941 /* to let free data properly on destroy of configuration widget */
942 g_object_set_data_full (G_OBJECT (hbox), "mycd-data", cd, destroy_cd_data);
943
944 return hbox;
945 }
946
947 /* Configuration in Mail Prefs Page goes here */
948
949 GtkWidget *
950 org_gnome_email_custom_header_config_option (EPlugin *epl,
951 struct _EConfigHookItemFactoryData *data)
952 {
953 /* This function and the hook needs to be removed,
954 once the configure code is thoroughly tested */
955
956 return NULL;
957
958 }