No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-signature-editor.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-signature-editor.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-mail-signature-editor.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-signature-editor.h"
20
21 #include <string.h>
22 #include <glib/gi18n.h>
23
24 #include <libevolution-utils/e-alert-dialog.h>
25 #include <libevolution-utils/e-alert-sink.h>
26 #include <misc/e-alert-bar.h>
27 #include <misc/e-web-view-gtkhtml.h>
28
29 #define E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
30 (G_TYPE_INSTANCE_GET_PRIVATE \
31 ((obj), E_TYPE_MAIL_SIGNATURE_EDITOR, EMailSignatureEditorPrivate))
32
33 typedef struct _AsyncContext AsyncContext;
34
35 struct _EMailSignatureEditorPrivate {
36 GtkActionGroup *action_group;
37 EFocusTracker *focus_tracker;
38 GCancellable *cancellable;
39 ESourceRegistry *registry;
40 ESource *source;
41 gchar *original_name;
42
43 GtkWidget *entry; /* not referenced */
44 GtkWidget *alert_bar; /* not referenced */
45 };
46
47 struct _AsyncContext {
48 ESource *source;
49 GCancellable *cancellable;
50 gchar *contents;
51 gsize length;
52 };
53
54 enum {
55 PROP_0,
56 PROP_FOCUS_TRACKER,
57 PROP_REGISTRY,
58 PROP_SOURCE
59 };
60
61 static const gchar *ui =
62 "<ui>\n"
63 " <menubar name='main-menu'>\n"
64 " <placeholder name='pre-edit-menu'>\n"
65 " <menu action='file-menu'>\n"
66 " <menuitem action='save-and-close'/>\n"
67 " <separator/>"
68 " <menuitem action='close'/>\n"
69 " </menu>\n"
70 " </placeholder>\n"
71 " </menubar>\n"
72 " <toolbar name='main-toolbar'>\n"
73 " <placeholder name='pre-main-toolbar'>\n"
74 " <toolitem action='save-and-close'/>\n"
75 " </placeholder>\n"
76 " </toolbar>\n"
77 "</ui>";
78
79 /* Forward Declarations */
80 static void e_mail_signature_editor_alert_sink_init
81 (EAlertSinkInterface *interface);
82
83 G_DEFINE_TYPE_WITH_CODE (
84 EMailSignatureEditor,
85 e_mail_signature_editor,
86 GTKHTML_TYPE_EDITOR,
87 G_IMPLEMENT_INTERFACE (
88 E_TYPE_ALERT_SINK,
89 e_mail_signature_editor_alert_sink_init))
90
91 static void
92 async_context_free (AsyncContext *async_context)
93 {
94 if (async_context->source != NULL)
95 g_object_unref (async_context->source);
96
97 if (async_context->cancellable != NULL)
98 g_object_unref (async_context->cancellable);
99
100 g_free (async_context->contents);
101
102 g_slice_free (AsyncContext, async_context);
103 }
104
105 static void
106 mail_signature_editor_loaded_cb (GObject *object,
107 GAsyncResult *result,
108 gpointer user_data)
109 {
110 ESource *source;
111 EMailSignatureEditor *editor;
112 ESourceMailSignature *extension;
113 const gchar *extension_name;
114 const gchar *mime_type;
115 gchar *contents = NULL;
116 gboolean is_html;
117 GError *error = NULL;
118
119 source = E_SOURCE (object);
120 editor = E_MAIL_SIGNATURE_EDITOR (user_data);
121
122 e_source_mail_signature_load_finish (
123 source, result, &contents, NULL, &error);
124
125 /* Ignore cancellations. */
126 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
127 g_warn_if_fail (contents == NULL);
128 g_object_unref (editor);
129 g_error_free (error);
130 return;
131
132 } else if (error != NULL) {
133 g_warn_if_fail (contents == NULL);
134 e_alert_submit (
135 E_ALERT_SINK (editor),
136 "widgets:no-load-signature",
137 error->message, NULL);
138 g_object_unref (editor);
139 g_error_free (error);
140 return;
141 }
142
143 g_return_if_fail (contents != NULL);
144
145 /* The load operation should have set the MIME type. */
146 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
147 extension = e_source_get_extension (source, extension_name);
148 mime_type = e_source_mail_signature_get_mime_type (extension);
149 is_html = (g_strcmp0 (mime_type, "text/html") == 0);
150
151 gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (editor), is_html);
152
153 if (is_html) {
154 gtkhtml_editor_insert_html (
155 GTKHTML_EDITOR (editor), contents);
156 } else {
157 gtkhtml_editor_insert_text (
158 GTKHTML_EDITOR (editor), contents);
159
160 gtkhtml_editor_run_command (GTKHTML_EDITOR (editor), "cursor-position-save");
161 gtkhtml_editor_run_command (GTKHTML_EDITOR (editor), "select-all");
162 gtkhtml_editor_run_command (GTKHTML_EDITOR (editor), "style-pre");
163 gtkhtml_editor_run_command (GTKHTML_EDITOR (editor), "unselect-all");
164 gtkhtml_editor_run_command (GTKHTML_EDITOR (editor), "cursor-position-restore");
165 }
166
167 g_free (contents);
168
169 g_object_unref (editor);
170 }
171
172 static gboolean
173 mail_signature_editor_delete_event_cb (EMailSignatureEditor *editor,
174 GdkEvent *event)
175 {
176 GtkActionGroup *action_group;
177 GtkAction *action;
178
179 action_group = editor->priv->action_group;
180 action = gtk_action_group_get_action (action_group, "close");
181 gtk_action_activate (action);
182
183 return TRUE;
184 }
185
186 static void
187 action_close_cb (GtkAction *action,
188 EMailSignatureEditor *editor)
189 {
190 gboolean something_changed = FALSE;
191 const gchar *original_name;
192 const gchar *signature_name;
193
194 original_name = editor->priv->original_name;
195 signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry));
196
197 something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor));
198 something_changed |= (strcmp (signature_name, original_name) != 0);
199
200 if (something_changed) {
201 gint response;
202
203 response = e_alert_run_dialog_for_args (
204 GTK_WINDOW (editor),
205 "widgets:ask-signature-changed", NULL);
206 if (response == GTK_RESPONSE_YES) {
207 GtkActionGroup *action_group;
208
209 action_group = editor->priv->action_group;
210 action = gtk_action_group_get_action (
211 action_group, "save-and-close");
212 gtk_action_activate (action);
213 return;
214 } else if (response == GTK_RESPONSE_CANCEL)
215 return;
216 }
217
218 gtk_widget_destroy (GTK_WIDGET (editor));
219 }
220
221 static void
222 action_save_and_close_cb (GtkAction *action,
223 EMailSignatureEditor *editor)
224 {
225 GtkEntry *entry;
226 EAsyncClosure *closure;
227 GAsyncResult *result;
228 ESource *source;
229 gchar *display_name;
230 GError *error = NULL;
231
232 entry = GTK_ENTRY (editor->priv->entry);
233 source = e_mail_signature_editor_get_source (editor);
234
235 display_name = g_strstrip (g_strdup (gtk_entry_get_text (entry)));
236
237 /* Make sure the signature name is not blank. */
238 if (*display_name == '\0') {
239 e_alert_submit (
240 E_ALERT_SINK (editor),
241 "widgets:blank-signature", NULL);
242 gtk_widget_grab_focus (GTK_WIDGET (entry));
243 g_free (display_name);
244 return;
245 }
246
247 e_source_set_display_name (source, display_name);
248
249 g_free (display_name);
250
251 /* Cancel any ongoing load or save operations. */
252 if (editor->priv->cancellable != NULL) {
253 g_cancellable_cancel (editor->priv->cancellable);
254 g_object_unref (editor->priv->cancellable);
255 }
256
257 editor->priv->cancellable = g_cancellable_new ();
258
259 closure = e_async_closure_new ();
260
261 e_mail_signature_editor_commit (
262 editor, editor->priv->cancellable,
263 e_async_closure_callback, closure);
264
265 result = e_async_closure_wait (closure);
266
267 e_mail_signature_editor_commit_finish (editor, result, &error);
268
269 e_async_closure_free (closure);
270
271 /* Ignore cancellations. */
272 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
273 g_error_free (error);
274
275 } else if (error != NULL) {
276 e_alert_submit (
277 E_ALERT_SINK (editor),
278 "widgets:no-save-signature",
279 error->message, NULL);
280 g_error_free (error);
281
282 /* Only destroy the editor if the save was successful. */
283 } else {
284 gtk_widget_destroy (GTK_WIDGET (editor));
285 }
286 }
287
288 static GtkActionEntry entries[] = {
289
290 { "close",
291 GTK_STOCK_CLOSE,
292 N_("_Close"),
293 "<Control>w",
294 N_("Close"),
295 G_CALLBACK (action_close_cb) },
296
297 { "save-and-close",
298 GTK_STOCK_SAVE,
299 N_("_Save and Close"),
300 "<Control>Return",
301 N_("Save and Close"),
302 G_CALLBACK (action_save_and_close_cb) },
303
304 { "file-menu",
305 NULL,
306 N_("_File"),
307 NULL,
308 NULL,
309 NULL }
310 };
311
312 static void
313 mail_signature_editor_set_registry (EMailSignatureEditor *editor,
314 ESourceRegistry *registry)
315 {
316 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
317 g_return_if_fail (editor->priv->registry == NULL);
318
319 editor->priv->registry = g_object_ref (registry);
320 }
321
322 static void
323 mail_signature_editor_set_source (EMailSignatureEditor *editor,
324 ESource *source)
325 {
326 GDBusObject *dbus_object = NULL;
327 const gchar *extension_name;
328 GError *error = NULL;
329
330 g_return_if_fail (source == NULL || E_IS_SOURCE (source));
331 g_return_if_fail (editor->priv->source == NULL);
332
333 if (source != NULL)
334 dbus_object = e_source_ref_dbus_object (source);
335
336 /* Clone the source so we can make changes to it freely. */
337 editor->priv->source = e_source_new (dbus_object, NULL, &error);
338
339 if (dbus_object != NULL)
340 g_object_unref (dbus_object);
341
342 /* This should rarely fail. If the file was loaded successfully
343 * once then it should load successfully here as well, unless an
344 * I/O error occurs. */
345 if (error != NULL) {
346 g_warning ("%s: %s", G_STRFUNC, error->message);
347 g_error_free (error);
348 }
349
350 /* Make sure the source has a mail signature extension. */
351 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
352 e_source_get_extension (editor->priv->source, extension_name);
353 }
354
355 static void
356 mail_signature_editor_set_property (GObject *object,
357 guint property_id,
358 const GValue *value,
359 GParamSpec *pspec)
360 {
361 switch (property_id) {
362 case PROP_REGISTRY:
363 mail_signature_editor_set_registry (
364 E_MAIL_SIGNATURE_EDITOR (object),
365 g_value_get_object (value));
366 return;
367
368 case PROP_SOURCE:
369 mail_signature_editor_set_source (
370 E_MAIL_SIGNATURE_EDITOR (object),
371 g_value_get_object (value));
372 return;
373 }
374
375 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
376 }
377
378 static void
379 mail_signature_editor_get_property (GObject *object,
380 guint property_id,
381 GValue *value,
382 GParamSpec *pspec)
383 {
384 switch (property_id) {
385 case PROP_FOCUS_TRACKER:
386 g_value_set_object (
387 value,
388 e_mail_signature_editor_get_focus_tracker (
389 E_MAIL_SIGNATURE_EDITOR (object)));
390 return;
391
392 case PROP_REGISTRY:
393 g_value_set_object (
394 value,
395 e_mail_signature_editor_get_registry (
396 E_MAIL_SIGNATURE_EDITOR (object)));
397 return;
398
399 case PROP_SOURCE:
400 g_value_set_object (
401 value,
402 e_mail_signature_editor_get_source (
403 E_MAIL_SIGNATURE_EDITOR (object)));
404 return;
405 }
406
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
408 }
409
410 static void
411 mail_signature_editor_dispose (GObject *object)
412 {
413 EMailSignatureEditorPrivate *priv;
414
415 priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (object);
416
417 if (priv->action_group != NULL) {
418 g_object_unref (priv->action_group);
419 priv->action_group = NULL;
420 }
421
422 if (priv->focus_tracker != NULL) {
423 g_object_unref (priv->focus_tracker);
424 priv->focus_tracker = NULL;
425 }
426
427 if (priv->cancellable != NULL) {
428 g_cancellable_cancel (priv->cancellable);
429 g_object_unref (priv->cancellable);
430 priv->cancellable = NULL;
431 }
432
433 if (priv->registry != NULL) {
434 g_object_unref (priv->registry);
435 priv->registry = NULL;
436 }
437
438 if (priv->source != NULL) {
439 g_object_unref (priv->source);
440 priv->source = NULL;
441 }
442
443 /* Chain up to parent's dispose() method. */
444 G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
445 dispose (object);
446 }
447
448 static void
449 mail_signature_editor_finalize (GObject *object)
450 {
451 EMailSignatureEditorPrivate *priv;
452
453 priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (object);
454
455 g_free (priv->original_name);
456
457 /* Chain up to parent's finalize() method. */
458 G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
459 finalize (object);
460 }
461
462 static void
463 mail_signature_editor_constructed (GObject *object)
464 {
465 EMailSignatureEditor *editor;
466 GtkActionGroup *action_group;
467 EFocusTracker *focus_tracker;
468 GtkhtmlEditor *gtkhtml_editor;
469 GtkUIManager *ui_manager;
470 GDBusObject *dbus_object;
471 ESource *source;
472 GtkAction *action;
473 GtkWidget *container;
474 GtkWidget *widget;
475 const gchar *display_name;
476 GError *error = NULL;
477
478 /* Chain up to parent's constructed() method. */
479 G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->
480 constructed (object);
481
482 editor = E_MAIL_SIGNATURE_EDITOR (object);
483
484 gtkhtml_editor = GTKHTML_EDITOR (editor);
485 ui_manager = gtkhtml_editor_get_ui_manager (gtkhtml_editor);
486
487 /* Because we are loading from a hard-coded string, there is
488 * no chance of I/O errors. Failure here implies a malformed
489 * UI definition. Full stop. */
490 gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
491 if (error != NULL)
492 g_error ("%s", error->message);
493
494 action_group = gtk_action_group_new ("signature");
495 gtk_action_group_set_translation_domain (
496 action_group, GETTEXT_PACKAGE);
497 gtk_action_group_add_actions (
498 action_group, entries,
499 G_N_ELEMENTS (entries), editor);
500 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
501 editor->priv->action_group = g_object_ref (action_group);
502
503 /* Hide page properties because it is not inherited in the mail. */
504 action = gtkhtml_editor_get_action (gtkhtml_editor, "properties-page");
505 gtk_action_set_visible (action, FALSE);
506
507 action = gtkhtml_editor_get_action (
508 gtkhtml_editor, "context-properties-page");
509 gtk_action_set_visible (action, FALSE);
510
511 gtk_ui_manager_ensure_update (ui_manager);
512
513 gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature"));
514
515 /* Construct the signature name entry. */
516
517 container = gtkhtml_editor->vbox;
518
519 widget = gtk_hbox_new (FALSE, 6);
520 gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
521 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
522 /* Position 2 should be between the main and style toolbars. */
523 gtk_box_reorder_child (GTK_BOX (container), widget, 2);
524 gtk_widget_show (widget);
525
526 container = widget;
527
528 widget = gtk_entry_new ();
529 gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0);
530 editor->priv->entry = widget; /* not referenced */
531 gtk_widget_show (widget);
532
533 widget = gtk_label_new_with_mnemonic (_("_Signature Name:"));
534 gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry);
535 gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
536 gtk_widget_show (widget);
537
538 g_signal_connect (
539 editor, "delete-event",
540 G_CALLBACK (mail_signature_editor_delete_event_cb), NULL);
541
542 /* Construct the alert bar for errors. */
543
544 container = gtkhtml_editor->vbox;
545
546 widget = e_alert_bar_new ();
547 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
548 /* Position 5 should be between the style toolbar and editing area. */
549 gtk_box_reorder_child (GTK_BOX (container), widget, 5);
550 editor->priv->alert_bar = widget; /* not referenced */
551 /* EAlertBar controls its own visibility. */
552
553 /* Configure an EFocusTracker to manage selection actions.
554 *
555 * XXX GtkhtmlEditor does not manage its own selection actions,
556 * which is technically a bug but works in our favor here
557 * because it won't cause any conflicts with EFocusTracker. */
558
559 focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor));
560
561 action = gtkhtml_editor_get_action (gtkhtml_editor, "cut");
562 e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
563
564 action = gtkhtml_editor_get_action (gtkhtml_editor, "copy");
565 e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
566
567 action = gtkhtml_editor_get_action (gtkhtml_editor, "paste");
568 e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
569
570 action = gtkhtml_editor_get_action (gtkhtml_editor, "select-all");
571 e_focus_tracker_set_select_all_action (focus_tracker, action);
572
573 editor->priv->focus_tracker = focus_tracker;
574
575 source = e_mail_signature_editor_get_source (editor);
576
577 display_name = e_source_get_display_name (source);
578 if (display_name == NULL || *display_name == '\0')
579 display_name = _("Unnamed");
580
581 /* Set the entry text before we grab focus. */
582 g_free (editor->priv->original_name);
583 editor->priv->original_name = g_strdup (display_name);
584 gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), display_name);
585
586 /* Set the focus appropriately. If this is a new signature, draw
587 * the user's attention to the signature name entry. Otherwise go
588 * straight to the editing area. */
589 if (source == NULL)
590 gtk_widget_grab_focus (editor->priv->entry);
591 else {
592 GtkHTML *html;
593
594 html = gtkhtml_editor_get_html (gtkhtml_editor);
595 gtk_widget_grab_focus (GTK_WIDGET (html));
596 }
597
598 /* Load file content only for an existing signature.
599 * (A new signature will not yet have a GDBusObject.) */
600 dbus_object = e_source_ref_dbus_object (source);
601 if (dbus_object != NULL) {
602 GCancellable *cancellable;
603
604 cancellable = g_cancellable_new ();
605
606 e_source_mail_signature_load (
607 source,
608 G_PRIORITY_DEFAULT,
609 cancellable,
610 mail_signature_editor_loaded_cb,
611 g_object_ref (editor));
612
613 g_warn_if_fail (editor->priv->cancellable == NULL);
614 editor->priv->cancellable = cancellable;
615
616 g_object_unref (dbus_object);
617 }
618 }
619
620 static void
621 mail_signature_editor_cut_clipboard (GtkhtmlEditor *editor)
622 {
623 /* Do nothing. EFocusTracker handles this. */
624 }
625
626 static void
627 mail_signature_editor_copy_clipboard (GtkhtmlEditor *editor)
628 {
629 /* Do nothing. EFocusTracker handles this. */
630 }
631
632 static void
633 mail_signature_editor_paste_clipboard (GtkhtmlEditor *editor)
634 {
635 /* Do nothing. EFocusTracker handles this. */
636 }
637
638 static void
639 mail_signature_editor_select_all (GtkhtmlEditor *editor)
640 {
641 /* Do nothing. EFocusTracker handles this. */
642 }
643
644 static void
645 mail_signature_editor_submit_alert (EAlertSink *alert_sink,
646 EAlert *alert)
647 {
648 EMailSignatureEditorPrivate *priv;
649 EAlertBar *alert_bar;
650 GtkWidget *dialog;
651 GtkWindow *parent;
652
653 priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (alert_sink);
654
655 switch (e_alert_get_message_type (alert)) {
656 case GTK_MESSAGE_INFO:
657 case GTK_MESSAGE_WARNING:
658 case GTK_MESSAGE_ERROR:
659 alert_bar = E_ALERT_BAR (priv->alert_bar);
660 e_alert_bar_add_alert (alert_bar, alert);
661 break;
662
663 default:
664 parent = GTK_WINDOW (alert_sink);
665 dialog = e_alert_dialog_new (parent, alert);
666 gtk_dialog_run (GTK_DIALOG (dialog));
667 gtk_widget_destroy (dialog);
668 break;
669 }
670 }
671
672 static void
673 e_mail_signature_editor_class_init (EMailSignatureEditorClass *class)
674 {
675 GObjectClass *object_class;
676 GtkhtmlEditorClass *editor_class;
677
678 g_type_class_add_private (class, sizeof (EMailSignatureEditorPrivate));
679
680 object_class = G_OBJECT_CLASS (class);
681 object_class->set_property = mail_signature_editor_set_property;
682 object_class->get_property = mail_signature_editor_get_property;
683 object_class->dispose = mail_signature_editor_dispose;
684 object_class->finalize = mail_signature_editor_finalize;
685 object_class->constructed = mail_signature_editor_constructed;
686
687 editor_class = GTKHTML_EDITOR_CLASS (class);
688 editor_class->cut_clipboard = mail_signature_editor_cut_clipboard;
689 editor_class->copy_clipboard = mail_signature_editor_copy_clipboard;
690 editor_class->paste_clipboard = mail_signature_editor_paste_clipboard;
691 editor_class->select_all = mail_signature_editor_select_all;
692
693 g_object_class_install_property (
694 object_class,
695 PROP_FOCUS_TRACKER,
696 g_param_spec_object (
697 "focus-tracker",
698 NULL,
699 NULL,
700 E_TYPE_FOCUS_TRACKER,
701 G_PARAM_READABLE |
702 G_PARAM_STATIC_STRINGS));
703
704 g_object_class_install_property (
705 object_class,
706 PROP_REGISTRY,
707 g_param_spec_object (
708 "registry",
709 "Registry",
710 "Data source registry",
711 E_TYPE_SOURCE_REGISTRY,
712 G_PARAM_READWRITE |
713 G_PARAM_CONSTRUCT_ONLY |
714 G_PARAM_STATIC_STRINGS));
715
716 g_object_class_install_property (
717 object_class,
718 PROP_SOURCE,
719 g_param_spec_object (
720 "source",
721 NULL,
722 NULL,
723 E_TYPE_SOURCE,
724 G_PARAM_READWRITE |
725 G_PARAM_CONSTRUCT_ONLY |
726 G_PARAM_STATIC_STRINGS));
727 }
728
729 static void
730 e_mail_signature_editor_alert_sink_init (EAlertSinkInterface *interface)
731 {
732 interface->submit_alert = mail_signature_editor_submit_alert;
733 }
734
735 static void
736 e_mail_signature_editor_init (EMailSignatureEditor *editor)
737 {
738 editor->priv = E_MAIL_SIGNATURE_EDITOR_GET_PRIVATE (editor);
739 }
740
741 GtkWidget *
742 e_mail_signature_editor_new (ESourceRegistry *registry,
743 ESource *source)
744 {
745 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
746
747 if (source != NULL)
748 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
749
750 return g_object_new (
751 E_TYPE_MAIL_SIGNATURE_EDITOR,
752 "html", e_web_view_gtkhtml_new (),
753 "registry", registry,
754 "source", source, NULL);
755 }
756
757 EFocusTracker *
758 e_mail_signature_editor_get_focus_tracker (EMailSignatureEditor *editor)
759 {
760 g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
761
762 return editor->priv->focus_tracker;
763 }
764
765 ESourceRegistry *
766 e_mail_signature_editor_get_registry (EMailSignatureEditor *editor)
767 {
768 g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
769
770 return editor->priv->registry;
771 }
772
773 ESource *
774 e_mail_signature_editor_get_source (EMailSignatureEditor *editor)
775 {
776 g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor), NULL);
777
778 return editor->priv->source;
779 }
780
781 /********************** e_mail_signature_editor_commit() *********************/
782
783 static void
784 mail_signature_editor_replace_cb (GObject *object,
785 GAsyncResult *result,
786 gpointer user_data)
787 {
788 GSimpleAsyncResult *simple;
789 GError *error = NULL;
790
791 simple = G_SIMPLE_ASYNC_RESULT (user_data);
792
793 e_source_mail_signature_replace_finish (
794 E_SOURCE (object), result, &error);
795
796 if (error != NULL)
797 g_simple_async_result_take_error (simple, error);
798
799 g_simple_async_result_complete (simple);
800
801 g_object_unref (simple);
802 }
803
804 static void
805 mail_signature_editor_commit_cb (GObject *object,
806 GAsyncResult *result,
807 gpointer user_data)
808 {
809 GSimpleAsyncResult *simple;
810 AsyncContext *async_context;
811 GError *error = NULL;
812
813 simple = G_SIMPLE_ASYNC_RESULT (user_data);
814 async_context = g_simple_async_result_get_op_res_gpointer (simple);
815
816 e_source_registry_commit_source_finish (
817 E_SOURCE_REGISTRY (object), result, &error);
818
819 if (error != NULL) {
820 g_simple_async_result_take_error (simple, error);
821 g_simple_async_result_complete (simple);
822 g_object_unref (simple);
823 return;
824 }
825
826 /* We can call this on our scratch source because only its UID is
827 * really needed, which even a new scratch source already knows. */
828 e_source_mail_signature_replace (
829 async_context->source,
830 async_context->contents,
831 async_context->length,
832 G_PRIORITY_DEFAULT,
833 async_context->cancellable,
834 mail_signature_editor_replace_cb,
835 simple);
836 }
837
838 void
839 e_mail_signature_editor_commit (EMailSignatureEditor *editor,
840 GCancellable *cancellable,
841 GAsyncReadyCallback callback,
842 gpointer user_data)
843 {
844 GSimpleAsyncResult *simple;
845 AsyncContext *async_context;
846 ESourceMailSignature *extension;
847 ESourceRegistry *registry;
848 ESource *source;
849 const gchar *extension_name;
850 const gchar *mime_type;
851 gchar *contents;
852 gboolean is_html;
853 gsize length;
854
855 g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor));
856
857 registry = e_mail_signature_editor_get_registry (editor);
858 source = e_mail_signature_editor_get_source (editor);
859 is_html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor));
860
861 if (is_html) {
862 mime_type = "text/html";
863 contents = gtkhtml_editor_get_text_html (
864 GTKHTML_EDITOR (editor), &length);
865 } else {
866 mime_type = "text/plain";
867 contents = gtkhtml_editor_get_text_plain (
868 GTKHTML_EDITOR (editor), &length);
869 }
870
871 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
872 extension = e_source_get_extension (source, extension_name);
873 e_source_mail_signature_set_mime_type (extension, mime_type);
874
875 async_context = g_slice_new0 (AsyncContext);
876 async_context->source = g_object_ref (source);
877 async_context->contents = contents; /* takes ownership */
878 async_context->length = length;
879
880 if (G_IS_CANCELLABLE (cancellable))
881 async_context->cancellable = g_object_ref (cancellable);
882
883 simple = g_simple_async_result_new (
884 G_OBJECT (editor), callback, user_data,
885 e_mail_signature_editor_commit);
886
887 g_simple_async_result_set_op_res_gpointer (
888 simple, async_context, (GDestroyNotify) async_context_free);
889
890 e_source_registry_commit_source (
891 registry, source,
892 async_context->cancellable,
893 mail_signature_editor_commit_cb,
894 simple);
895 }
896
897 gboolean
898 e_mail_signature_editor_commit_finish (EMailSignatureEditor *editor,
899 GAsyncResult *result,
900 GError **error)
901 {
902 GSimpleAsyncResult *simple;
903
904 g_return_val_if_fail (
905 g_simple_async_result_is_valid (
906 result, G_OBJECT (editor),
907 e_mail_signature_editor_commit), FALSE);
908
909 simple = G_SIMPLE_ASYNC_RESULT (result);
910
911 /* Assume success unless a GError is set. */
912 return !g_simple_async_result_propagate_error (simple, error);
913 }