Updated Galician translation
[evolution.git] / widgets / misc / e-signature-editor.c
blob91a4d81c8d589d1c55f313332f29f76930c5738a
1 /*
2 * e-signature-editor.c
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"
24 #include <string.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))
35 enum {
36 PROP_0,
37 PROP_FOCUS_TRACKER,
38 PROP_SIGNATURE
41 struct _ESignatureEditorPrivate {
42 GtkActionGroup *action_group;
43 EFocusTracker *focus_tracker;
44 ESignature *signature;
45 GtkWidget *entry;
46 gchar *original_name;
49 static const gchar *ui =
50 "<ui>\n"
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"
55 " <separator/>"
56 " <menuitem action='close'/>\n"
57 " </menu>\n"
58 " </placeholder>\n"
59 " </menubar>\n"
60 " <toolbar name='main-toolbar'>\n"
61 " <placeholder name='pre-main-toolbar'>\n"
62 " <toolitem action='save-and-close'/>\n"
63 " </placeholder>\n"
64 " </toolbar>\n"
65 "</ui>";
67 static gpointer parent_class = NULL;
69 static void
70 handle_error (GError **error)
72 if (*error != NULL) {
73 g_warning ("%s", (*error)->message);
74 g_clear_error (error);
78 static void
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) {
93 gint response;
95 response = e_alert_run_dialog_for_args (
96 GTK_WINDOW (editor),
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);
105 return;
106 } else if (response == GTK_RESPONSE_CANCEL)
107 return;
110 gtk_widget_destroy (GTK_WIDGET (editor));
113 static void
114 action_save_and_close_cb (GtkAction *action,
115 ESignatureEditor *editor)
117 GtkWidget *entry;
118 ESignatureList *signature_list;
119 ESignature *signature;
120 ESignature *same_name;
121 const gchar *filename;
122 gchar *signature_name;
123 gboolean html;
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) {
130 gchar *new_filename;
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);
141 } else {
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);
149 if (error != NULL) {
150 e_alert_run_dialog_for_args (
151 GTK_WINDOW (editor),
152 "mail:no-save-signature",
153 error->message, NULL);
154 g_clear_error (&error);
155 return;
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 (
166 GTK_WINDOW (editor),
167 "mail:blank-signature", NULL);
168 gtk_widget_grab_focus (entry);
169 g_free (signature_name);
170 return;
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 (
179 GTK_WINDOW (editor),
180 "mail:signature-already-exists",
181 signature_name, NULL);
182 gtk_widget_grab_focus (entry);
183 g_free (signature_name);
184 return;
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);
192 else
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[] = {
201 { "close",
202 GTK_STOCK_CLOSE,
203 N_("_Close"),
204 "<Control>w",
205 NULL,
206 G_CALLBACK (action_close_cb) },
208 { "save-and-close",
209 GTK_STOCK_SAVE,
210 N_("_Save and Close"),
211 "<Control>Return",
212 NULL,
213 G_CALLBACK (action_save_and_close_cb) },
215 { "file-menu",
216 NULL,
217 N_("_File"),
218 NULL,
219 NULL,
220 NULL }
223 static gboolean
224 signature_editor_delete_event_cb (ESignatureEditor *editor,
225 GdkEvent *event)
227 GtkActionGroup *action_group;
228 GtkAction *action;
230 action_group = editor->priv->action_group;
231 action = gtk_action_group_get_action (action_group, "close");
232 gtk_action_activate (action);
234 return TRUE;
237 static void
238 signature_editor_set_property (GObject *object,
239 guint property_id,
240 const GValue *value,
241 GParamSpec *pspec)
243 switch (property_id) {
244 case PROP_SIGNATURE:
245 e_signature_editor_set_signature (
246 E_SIGNATURE_EDITOR (object),
247 g_value_get_object (value));
248 return;
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
254 static void
255 signature_editor_get_property (GObject *object,
256 guint property_id,
257 GValue *value,
258 GParamSpec *pspec)
260 switch (property_id) {
261 case PROP_FOCUS_TRACKER:
262 g_value_set_object (
263 value, e_signature_editor_get_focus_tracker (
264 E_SIGNATURE_EDITOR (object)));
265 return;
267 case PROP_SIGNATURE:
268 g_value_set_object (
269 value, e_signature_editor_get_signature (
270 E_SIGNATURE_EDITOR (object)));
271 return;
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
277 static void
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);
301 priv->entry = NULL;
304 /* Chain up to parent's dispose() method. */
305 G_OBJECT_CLASS (parent_class)->dispose (object);
308 static void
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);
321 static void
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 (
336 object_class,
337 PROP_FOCUS_TRACKER,
338 g_param_spec_object (
339 "focus-tracker",
340 NULL,
341 NULL,
342 E_TYPE_FOCUS_TRACKER,
343 G_PARAM_READABLE));
345 g_object_class_install_property (
346 object_class,
347 PROP_SIGNATURE,
348 g_param_spec_object (
349 "signature",
350 NULL,
351 NULL,
352 E_TYPE_SIGNATURE,
353 G_PARAM_READWRITE));
356 static void
357 signature_editor_init (ESignatureEditor *editor)
359 GtkActionGroup *action_group;
360 EFocusTracker *focus_tracker;
361 GtkhtmlEditor *gtkhtml_editor;
362 GtkUIManager *ui_manager;
363 GtkAction *action;
364 GtkWidget *container;
365 GtkWidget *widget;
366 GtkWidget *vbox;
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);
397 container = 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);
409 g_signal_connect (
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;
438 GType
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),
452 0, /* n_preallocs */
453 (GInstanceInitFunc) signature_editor_init,
454 NULL /* value_table */
457 type = g_type_register_static (
458 GTKHTML_TYPE_EDITOR, "ESignatureEditor",
459 &type_info, 0);
462 return type;
465 GtkWidget *
466 e_signature_editor_new (void)
468 return g_object_new (
469 E_TYPE_SIGNATURE_EDITOR,
470 "html", e_web_view_new (), NULL);
473 EFocusTracker *
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;
481 ESignature *
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;
489 void
490 e_signature_editor_set_signature (ESignatureEditor *editor,
491 ESignature *signature)
493 const gchar *filename;
494 const gchar *signature_name;
495 gboolean is_html;
496 gchar *contents;
497 gsize length;
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)
511 goto exit;
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);
520 if (is_html)
521 g_file_get_contents (filename, &contents, &length, &error);
522 else {
523 gchar *data;
525 data = e_read_signature_file (signature, FALSE, &error);
526 if (data != NULL)
527 contents = g_strdup_printf ("<PRE>\n%s", data);
528 else
529 contents = NULL;
530 length = -1;
531 g_free (data);
534 if (error == NULL) {
535 gtkhtml_editor_set_html_mode (
536 GTKHTML_EDITOR (editor), is_html);
537 gtkhtml_editor_set_text_html (
538 GTKHTML_EDITOR (editor), contents, length);
539 g_free (contents);
540 } else {
541 g_warning ("%s", error->message);
542 g_error_free (error);
545 exit:
546 if (signature != NULL)
547 signature_name = e_signature_get_name (signature);
548 else
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);
561 else {
562 GtkHTML *html;
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");