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.
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.
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/>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
22 #include "e-signature-editor.h"
25 #include <glib/gi18n.h>
27 #include <e-util/e-alert-dialog.h>
28 #include <e-util/e-signature-utils.h>
29 #include <misc/e-web-view.h>
31 #define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
32 (G_TYPE_INSTANCE_GET_PRIVATE \
33 ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate))
41 struct _ESignatureEditorPrivate
{
42 GtkActionGroup
*action_group
;
43 EFocusTracker
*focus_tracker
;
44 ESignature
*signature
;
49 static const gchar
*ui
=
51 " <menubar name='main-menu'>\n"
52 " <placeholder name='pre-edit-menu'>\n"
53 " <menu action='file-menu'>\n"
54 " <menuitem action='save-and-close'/>\n"
56 " <menuitem action='close'/>\n"
60 " <toolbar name='main-toolbar'>\n"
61 " <placeholder name='pre-main-toolbar'>\n"
62 " <toolitem action='save-and-close'/>\n"
67 static gpointer parent_class
= NULL
;
70 handle_error (GError
**error
)
73 g_warning ("%s", (*error
)->message
);
74 g_clear_error (error
);
79 action_close_cb (GtkAction
*action
,
80 ESignatureEditor
*editor
)
82 gboolean something_changed
= FALSE
;
83 const gchar
*original_name
;
84 const gchar
*signature_name
;
86 original_name
= editor
->priv
->original_name
;
87 signature_name
= gtk_entry_get_text (GTK_ENTRY (editor
->priv
->entry
));
89 something_changed
|= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor
));
90 something_changed
|= (strcmp (signature_name
, original_name
) != 0);
92 if (something_changed
) {
95 response
= e_alert_run_dialog_for_args (
97 "mail:ask-signature-changed", NULL
);
98 if (response
== GTK_RESPONSE_YES
) {
99 GtkActionGroup
*action_group
;
101 action_group
= editor
->priv
->action_group
;
102 action
= gtk_action_group_get_action (
103 action_group
, "save-and-close");
104 gtk_action_activate (action
);
106 } else if (response
== GTK_RESPONSE_CANCEL
)
110 gtk_widget_destroy (GTK_WIDGET (editor
));
114 action_save_and_close_cb (GtkAction
*action
,
115 ESignatureEditor
*editor
)
118 ESignatureList
*signature_list
;
119 ESignature
*signature
;
120 ESignature
*same_name
;
121 const gchar
*filename
;
122 gchar
*signature_name
;
124 GError
*error
= NULL
;
126 entry
= editor
->priv
->entry
;
127 html
= gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor
));
129 if (editor
->priv
->signature
== NULL
) {
132 signature
= e_signature_new ();
133 e_signature_set_name (signature
, _("Unnamed"));
134 e_signature_set_is_script (signature
, FALSE
);
135 e_signature_set_is_html (signature
, html
);
137 /* FIXME Pass a GError and deal with it. */
138 new_filename
= e_create_signature_file (NULL
);
139 e_signature_set_filename (signature
, new_filename
);
140 g_free (new_filename
);
142 signature
= g_object_ref (editor
->priv
->signature
);
143 e_signature_set_is_html (signature
, html
);
146 filename
= e_signature_get_filename (signature
);
147 gtkhtml_editor_save (GTKHTML_EDITOR (editor
), filename
, html
, &error
);
150 e_alert_run_dialog_for_args (
152 "mail:no-save-signature",
153 error
->message
, NULL
);
154 g_clear_error (&error
);
158 signature_list
= e_get_signature_list ();
160 signature_name
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
161 g_strstrip (signature_name
);
163 /* Make sure the signature name is not blank. */
164 if (*signature_name
== '\0') {
165 e_alert_run_dialog_for_args (
167 "mail:blank-signature", NULL
);
168 gtk_widget_grab_focus (entry
);
169 g_free (signature_name
);
173 /* Don't overwrite an existing signature of the same name.
174 * XXX ESignatureList misuses const. */
175 same_name
= (ESignature
*) e_signature_list_find (
176 signature_list
, E_SIGNATURE_FIND_NAME
, signature_name
);
177 if (same_name
!= NULL
&& !e_signature_is_equal (signature
, same_name
)) {
178 e_alert_run_dialog_for_args (
180 "mail:signature-already-exists",
181 signature_name
, NULL
);
182 gtk_widget_grab_focus (entry
);
183 g_free (signature_name
);
187 e_signature_set_name (signature
, signature_name
);
188 g_free (signature_name
);
190 if (editor
->priv
->signature
!= NULL
)
191 e_signature_list_change (signature_list
, signature
);
193 e_signature_list_add (signature_list
, signature
);
194 e_signature_list_save (signature_list
);
196 gtk_widget_destroy (GTK_WIDGET (editor
));
199 static GtkActionEntry entries
[] = {
206 G_CALLBACK (action_close_cb
) },
210 N_("_Save and Close"),
213 G_CALLBACK (action_save_and_close_cb
) },
224 signature_editor_delete_event_cb (ESignatureEditor
*editor
,
227 GtkActionGroup
*action_group
;
230 action_group
= editor
->priv
->action_group
;
231 action
= gtk_action_group_get_action (action_group
, "close");
232 gtk_action_activate (action
);
238 signature_editor_set_property (GObject
*object
,
243 switch (property_id
) {
245 e_signature_editor_set_signature (
246 E_SIGNATURE_EDITOR (object
),
247 g_value_get_object (value
));
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
255 signature_editor_get_property (GObject
*object
,
260 switch (property_id
) {
261 case PROP_FOCUS_TRACKER
:
263 value
, e_signature_editor_get_focus_tracker (
264 E_SIGNATURE_EDITOR (object
)));
269 value
, e_signature_editor_get_signature (
270 E_SIGNATURE_EDITOR (object
)));
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
278 signature_editor_dispose (GObject
*object
)
280 ESignatureEditorPrivate
*priv
;
282 priv
= E_SIGNATURE_EDITOR_GET_PRIVATE (object
);
284 if (priv
->action_group
!= NULL
) {
285 g_object_unref (priv
->action_group
);
286 priv
->action_group
= NULL
;
289 if (priv
->focus_tracker
!= NULL
) {
290 g_object_unref (priv
->focus_tracker
);
291 priv
->focus_tracker
= NULL
;
294 if (priv
->signature
!= NULL
) {
295 g_object_unref (priv
->signature
);
296 priv
->signature
= NULL
;
299 if (priv
->entry
!= NULL
) {
300 g_object_unref (priv
->entry
);
304 /* Chain up to parent's dispose() method. */
305 G_OBJECT_CLASS (parent_class
)->dispose (object
);
309 signature_editor_finalize (GObject
*object
)
311 ESignatureEditorPrivate
*priv
;
313 priv
= E_SIGNATURE_EDITOR_GET_PRIVATE (object
);
315 g_free (priv
->original_name
);
317 /* Chain up to parent's finalize() method. */
318 G_OBJECT_CLASS (parent_class
)->finalize (object
);
322 signature_editor_class_init (ESignatureEditorClass
*class)
324 GObjectClass
*object_class
;
326 parent_class
= g_type_class_peek_parent (class);
327 g_type_class_add_private (class, sizeof (ESignatureEditorPrivate
));
329 object_class
= G_OBJECT_CLASS (class);
330 object_class
->set_property
= signature_editor_set_property
;
331 object_class
->get_property
= signature_editor_get_property
;
332 object_class
->dispose
= signature_editor_dispose
;
333 object_class
->finalize
= signature_editor_finalize
;
335 g_object_class_install_property (
338 g_param_spec_object (
342 E_TYPE_FOCUS_TRACKER
,
345 g_object_class_install_property (
348 g_param_spec_object (
357 signature_editor_init (ESignatureEditor
*editor
)
359 GtkActionGroup
*action_group
;
360 EFocusTracker
*focus_tracker
;
361 GtkhtmlEditor
*gtkhtml_editor
;
362 GtkUIManager
*ui_manager
;
364 GtkWidget
*container
;
367 GError
*error
= NULL
;
369 editor
->priv
= E_SIGNATURE_EDITOR_GET_PRIVATE (editor
);
370 vbox
= GTKHTML_EDITOR (editor
)->vbox
;
372 gtkhtml_editor
= GTKHTML_EDITOR (editor
);
373 ui_manager
= gtkhtml_editor_get_ui_manager (gtkhtml_editor
);
375 gtk_ui_manager_add_ui_from_string (ui_manager
, ui
, -1, &error
);
376 handle_error (&error
);
378 action_group
= gtk_action_group_new ("signature");
379 gtk_action_group_set_translation_domain (
380 action_group
, GETTEXT_PACKAGE
);
381 gtk_action_group_add_actions (
382 action_group
, entries
,
383 G_N_ELEMENTS (entries
), editor
);
384 gtk_ui_manager_insert_action_group (ui_manager
, action_group
, 0);
385 editor
->priv
->action_group
= g_object_ref (action_group
);
387 gtk_ui_manager_ensure_update (ui_manager
);
389 gtk_window_set_title (GTK_WINDOW (editor
), _("Edit Signature"));
391 widget
= gtk_hbox_new (FALSE
, 6);
392 gtk_container_set_border_width (GTK_CONTAINER (widget
), 6);
393 gtk_box_pack_start (GTK_BOX (vbox
), widget
, FALSE
, FALSE
, 0);
394 /* Position 2 should be between the main and style toolbars. */
395 gtk_box_reorder_child (GTK_BOX (vbox
), widget
, 2);
396 gtk_widget_show (widget
);
399 widget
= gtk_entry_new ();
400 gtk_box_pack_end (GTK_BOX (container
), widget
, TRUE
, TRUE
, 0);
401 editor
->priv
->entry
= g_object_ref_sink (widget
);
402 gtk_widget_show (widget
);
404 widget
= gtk_label_new_with_mnemonic (_("_Signature Name:"));
405 gtk_label_set_mnemonic_widget (GTK_LABEL (widget
), editor
->priv
->entry
);
406 gtk_box_pack_end (GTK_BOX (container
), widget
, FALSE
, FALSE
, 0);
407 gtk_widget_show (widget
);
410 editor
, "delete-event",
411 G_CALLBACK (signature_editor_delete_event_cb
), NULL
);
413 e_signature_editor_set_signature (editor
, NULL
);
415 /* Configure an EFocusTracker to manage selection actions.
417 * XXX GtkhtmlEditor does not manage its own selection actions,
418 * which is technically a bug but works in our favor here
419 * because it won't cause any conflicts with EFocusTracker. */
421 focus_tracker
= e_focus_tracker_new (GTK_WINDOW (editor
));
423 action
= gtkhtml_editor_get_action (gtkhtml_editor
, "cut");
424 e_focus_tracker_set_cut_clipboard_action (focus_tracker
, action
);
426 action
= gtkhtml_editor_get_action (gtkhtml_editor
, "copy");
427 e_focus_tracker_set_copy_clipboard_action (focus_tracker
, action
);
429 action
= gtkhtml_editor_get_action (gtkhtml_editor
, "paste");
430 e_focus_tracker_set_paste_clipboard_action (focus_tracker
, action
);
432 action
= gtkhtml_editor_get_action (gtkhtml_editor
, "select-all");
433 e_focus_tracker_set_select_all_action (focus_tracker
, action
);
435 editor
->priv
->focus_tracker
= focus_tracker
;
439 e_signature_editor_get_type (void)
441 static GType type
= 0;
443 if (G_UNLIKELY (type
== 0)) {
444 static const GTypeInfo type_info
= {
445 sizeof (ESignatureEditorClass
),
446 (GBaseInitFunc
) NULL
,
447 (GBaseFinalizeFunc
) NULL
,
448 (GClassInitFunc
) signature_editor_class_init
,
449 (GClassFinalizeFunc
) NULL
,
450 NULL
, /* class_data */
451 sizeof (ESignatureEditor
),
453 (GInstanceInitFunc
) signature_editor_init
,
454 NULL
/* value_table */
457 type
= g_type_register_static (
458 GTKHTML_TYPE_EDITOR
, "ESignatureEditor",
466 e_signature_editor_new (void)
468 return g_object_new (
469 E_TYPE_SIGNATURE_EDITOR
,
470 "html", e_web_view_new (), NULL
);
474 e_signature_editor_get_focus_tracker (ESignatureEditor
*editor
)
476 g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor
), NULL
);
478 return editor
->priv
->focus_tracker
;
482 e_signature_editor_get_signature (ESignatureEditor
*editor
)
484 g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor
), NULL
);
486 return editor
->priv
->signature
;
490 e_signature_editor_set_signature (ESignatureEditor
*editor
,
491 ESignature
*signature
)
493 const gchar
*filename
;
494 const gchar
*signature_name
;
498 GError
*error
= NULL
;
500 g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor
));
502 if (signature
!= NULL
)
503 g_return_if_fail (E_SIGNATURE (signature
));
505 if (editor
->priv
->signature
!= NULL
) {
506 g_object_unref (editor
->priv
->signature
);
507 editor
->priv
->signature
= NULL
;
510 if (signature
== NULL
)
513 editor
->priv
->signature
= g_object_ref (signature
);
515 /* Load signature content. */
517 filename
= e_signature_get_filename (signature
);
518 is_html
= e_signature_get_is_html (signature
);
521 g_file_get_contents (filename
, &contents
, &length
, &error
);
525 data
= e_read_signature_file (signature
, FALSE
, &error
);
527 contents
= g_strdup_printf ("<PRE>\n%s", data
);
535 gtkhtml_editor_set_html_mode (
536 GTKHTML_EDITOR (editor
), is_html
);
537 gtkhtml_editor_set_text_html (
538 GTKHTML_EDITOR (editor
), contents
, length
);
541 g_warning ("%s", error
->message
);
542 g_error_free (error
);
546 if (signature
!= NULL
)
547 signature_name
= e_signature_get_name (signature
);
549 signature_name
= _("Unnamed");
551 /* Set the entry text before we grab focus. */
552 g_free (editor
->priv
->original_name
);
553 editor
->priv
->original_name
= g_strdup (signature_name
);
554 gtk_entry_set_text (GTK_ENTRY (editor
->priv
->entry
), signature_name
);
556 /* Set the focus appropriately. If this is a new signature, draw
557 * the user's attention to the signature name entry. Otherwise go
558 * straight to the editing area. */
559 if (signature
== NULL
)
560 gtk_widget_grab_focus (editor
->priv
->entry
);
564 html
= gtkhtml_editor_get_html (GTKHTML_EDITOR (editor
));
565 gtk_widget_grab_focus (GTK_WIDGET (html
));
568 g_object_notify (G_OBJECT (editor
), "signature");