No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with the program; if not, see <http://www.gnu.org/licenses/>
15 *
16 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include "e-composer-actions.h"
24 #include "e-composer-private.h"
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <libevolution-utils/e-alert-dialog.h>
29
30 static void
31 action_attach_cb (GtkAction *action,
32 EMsgComposer *composer)
33 {
34 EAttachmentView *view;
35 EAttachmentStore *store;
36
37 view = e_msg_composer_get_attachment_view (composer);
38 store = e_attachment_view_get_store (view);
39
40 e_attachment_store_run_load_dialog (store, GTK_WINDOW (composer));
41 }
42
43 static void
44 action_charset_cb (GtkRadioAction *action,
45 GtkRadioAction *current,
46 EMsgComposer *composer)
47 {
48 const gchar *charset;
49
50 if (action != current)
51 return;
52
53 charset = g_object_get_data (G_OBJECT (action), "charset");
54
55 g_free (composer->priv->charset);
56 composer->priv->charset = g_strdup (charset);
57 }
58
59 static void
60 action_close_cb (GtkAction *action,
61 EMsgComposer *composer)
62 {
63 if (e_msg_composer_can_close (composer, TRUE))
64 gtk_widget_destroy (GTK_WIDGET (composer));
65 }
66
67 static void
68 action_new_message_cb (GtkAction *action,
69 EMsgComposer *composer)
70 {
71 EMsgComposer *new_composer;
72 EShell *shell;
73
74 shell = e_msg_composer_get_shell (composer);
75
76 new_composer = e_msg_composer_new (shell);
77 gtk_widget_show (GTK_WIDGET (new_composer));
78 }
79
80 static void
81 action_pgp_encrypt_cb (GtkToggleAction *action,
82 EMsgComposer *composer)
83 {
84 GtkhtmlEditor *editor;
85
86 editor = GTKHTML_EDITOR (composer);
87 gtkhtml_editor_set_changed (editor, TRUE);
88 }
89
90 static void
91 action_pgp_sign_cb (GtkToggleAction *action,
92 EMsgComposer *composer)
93 {
94 GtkhtmlEditor *editor;
95
96 editor = GTKHTML_EDITOR (composer);
97 gtkhtml_editor_set_changed (editor, TRUE);
98 }
99
100 static void
101 action_preferences_cb (GtkAction *action,
102 EMsgComposer *composer)
103 {
104 EShell *shell;
105 GtkWidget *preferences_window;
106 const gchar *page_name = "composer";
107
108 shell = e_msg_composer_get_shell (composer);
109 preferences_window = e_shell_get_preferences_window (shell);
110 e_preferences_window_setup (E_PREFERENCES_WINDOW (preferences_window));
111
112 gtk_window_set_transient_for (
113 GTK_WINDOW (preferences_window),
114 GTK_WINDOW (composer));
115 gtk_window_set_position (
116 GTK_WINDOW (preferences_window),
117 GTK_WIN_POS_CENTER_ON_PARENT);
118 gtk_window_present (GTK_WINDOW (preferences_window));
119
120 if (e_shell_get_express_mode (shell))
121 e_preferences_window_filter_page (
122 E_PREFERENCES_WINDOW (preferences_window), page_name);
123 else
124 e_preferences_window_show_page (
125 E_PREFERENCES_WINDOW (preferences_window), page_name);
126 }
127
128 static void
129 action_print_cb (GtkAction *action,
130 EMsgComposer *composer)
131 {
132 GtkPrintOperationAction print_action;
133
134 print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG;
135 e_msg_composer_print (composer, print_action);
136 }
137
138 static void
139 action_print_preview_cb (GtkAction *action,
140 EMsgComposer *composer)
141 {
142 GtkPrintOperationAction print_action;
143
144 print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
145 e_msg_composer_print (composer, print_action);
146 }
147
148 static void
149 action_save_cb (GtkAction *action,
150 EMsgComposer *composer)
151 {
152 GtkhtmlEditor *editor = GTKHTML_EDITOR (composer);
153 const gchar *filename;
154 gint fd;
155 GError *error = NULL;
156
157 filename = gtkhtml_editor_get_filename (editor);
158 if (filename == NULL) {
159 gtk_action_activate (ACTION (SAVE_AS));
160 return;
161 }
162
163 /* Check if the file already exists and we can create it. */
164 fd = g_open (filename, O_RDONLY | O_CREAT | O_EXCL, 0777);
165 if (fd < 0) {
166 gint errno_saved = errno;
167
168 if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
169 gint response;
170
171 response = e_alert_run_dialog_for_args (
172 GTK_WINDOW (composer),
173 E_ALERT_ASK_FILE_EXISTS_OVERWRITE,
174 filename, NULL);
175 if (response != GTK_RESPONSE_OK)
176 return;
177 } else {
178 e_alert_submit (
179 E_ALERT_SINK (composer),
180 E_ALERT_NO_SAVE_FILE, filename,
181 g_strerror (errno_saved), NULL);
182 return;
183 }
184 } else
185 close (fd);
186
187 if (!gtkhtml_editor_save (editor, filename, TRUE, &error)) {
188 e_alert_submit (
189 E_ALERT_SINK (composer),
190 E_ALERT_NO_SAVE_FILE,
191 filename, error->message, NULL);
192 g_error_free (error);
193 return;
194 }
195
196 gtkhtml_editor_run_command (GTKHTML_EDITOR (composer), "saved");
197 }
198
199 static void
200 action_save_as_cb (GtkAction *action,
201 EMsgComposer *composer)
202 {
203 GtkWidget *dialog;
204 gchar *filename;
205 gint response;
206
207 dialog = gtk_file_chooser_dialog_new (
208 _("Save as..."), GTK_WINDOW (composer),
209 GTK_FILE_CHOOSER_ACTION_SAVE,
210 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
211 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
212 NULL);
213
214 gtk_dialog_set_default_response (
215 GTK_DIALOG (dialog), GTK_RESPONSE_OK);
216 gtk_file_chooser_set_local_only (
217 GTK_FILE_CHOOSER (dialog), FALSE);
218 gtk_window_set_icon_name (
219 GTK_WINDOW (dialog), "mail-message-new");
220
221 response = gtk_dialog_run (GTK_DIALOG (dialog));
222
223 if (response != GTK_RESPONSE_OK)
224 goto exit;
225
226 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
227 gtkhtml_editor_set_filename (GTKHTML_EDITOR (composer), filename);
228 g_free (filename);
229
230 gtk_action_activate (ACTION (SAVE));
231
232 exit:
233 gtk_widget_destroy (dialog);
234 }
235
236 static void
237 action_save_draft_cb (GtkAction *action,
238 EMsgComposer *composer)
239 {
240 e_msg_composer_save_to_drafts (composer);
241 }
242
243 static void
244 action_send_cb (GtkAction *action,
245 EMsgComposer *composer)
246 {
247 CamelSession *session;
248
249 session = e_msg_composer_get_session (composer);
250
251 /* If we're online, send the message now.
252 * Otherwise write the message to Outbox. */
253 if (camel_session_get_online (session))
254 e_msg_composer_send (composer);
255 else {
256 /* Inform the user. */
257 e_alert_run_dialog_for_args (
258 GTK_WINDOW (composer),
259 "mail-composer:saving-to-outbox", NULL);
260 e_msg_composer_save_to_outbox (composer);
261 }
262 }
263
264 static void
265 action_smime_encrypt_cb (GtkToggleAction *action,
266 EMsgComposer *composer)
267 {
268 GtkhtmlEditor *editor;
269
270 editor = GTKHTML_EDITOR (composer);
271 gtkhtml_editor_set_changed (editor, TRUE);
272 }
273
274 static void
275 action_smime_sign_cb (GtkToggleAction *action,
276 EMsgComposer *composer)
277 {
278 GtkhtmlEditor *editor;
279
280 editor = GTKHTML_EDITOR (composer);
281 gtkhtml_editor_set_changed (editor, TRUE);
282 }
283
284 static GtkActionEntry entries[] = {
285
286 { "attach",
287 "mail-attachment",
288 N_("_Attachment..."),
289 "<Control>m",
290 N_("Attach a file"),
291 G_CALLBACK (action_attach_cb) },
292
293 { "close",
294 GTK_STOCK_CLOSE,
295 N_("_Close"),
296 "<Control>w",
297 N_("Close the current file"),
298 G_CALLBACK (action_close_cb) },
299
300 { "new-message",
301 "mail-message-new",
302 N_("New _Message"),
303 "<Control>n",
304 N_("Open New Message window"),
305 G_CALLBACK (action_new_message_cb) },
306
307 { "preferences",
308 GTK_STOCK_PREFERENCES,
309 NULL,
310 NULL,
311 N_("Configure Evolution"),
312 G_CALLBACK (action_preferences_cb) },
313
314 { "save",
315 GTK_STOCK_SAVE,
316 N_("_Save"),
317 "<Shift><Control>s",
318 N_("Save the current file"),
319 G_CALLBACK (action_save_cb) },
320
321 { "save-as",
322 GTK_STOCK_SAVE_AS,
323 N_("Save _As..."),
324 NULL,
325 N_("Save the current file with a different name"),
326 G_CALLBACK (action_save_as_cb) },
327
328 /* Menus */
329
330 { "charset-menu",
331 NULL,
332 N_("Character _Encoding"),
333 NULL,
334 NULL,
335 NULL },
336
337 { "options-menu",
338 NULL,
339 N_("_Options"),
340 NULL,
341 NULL,
342 NULL }
343 };
344
345 static GtkActionEntry async_entries[] = {
346
347 { "print",
348 GTK_STOCK_PRINT,
349 N_("_Print..."),
350 "<Control>p",
351 NULL,
352 G_CALLBACK (action_print_cb) },
353
354 { "print-preview",
355 GTK_STOCK_PRINT_PREVIEW,
356 N_("Print Pre_view"),
357 "<Shift><Control>p",
358 NULL,
359 G_CALLBACK (action_print_preview_cb) },
360
361 { "save-draft",
362 GTK_STOCK_SAVE,
363 N_("Save as _Draft"),
364 "<Control>s",
365 N_("Save as draft"),
366 G_CALLBACK (action_save_draft_cb) },
367
368 { "send",
369 "mail-send",
370 N_("S_end"),
371 "<Control>Return",
372 N_("Send this message"),
373 G_CALLBACK (action_send_cb) },
374 };
375
376 static GtkToggleActionEntry toggle_entries[] = {
377
378 { "pgp-encrypt",
379 NULL,
380 N_("PGP _Encrypt"),
381 NULL,
382 N_("Encrypt this message with PGP"),
383 G_CALLBACK (action_pgp_encrypt_cb),
384 FALSE },
385
386 { "pgp-sign",
387 NULL,
388 N_("PGP _Sign"),
389 NULL,
390 N_("Sign this message with your PGP key"),
391 G_CALLBACK (action_pgp_sign_cb),
392 FALSE },
393
394 { "picture-gallery",
395 "emblem-photos",
396 N_("_Picture Gallery"),
397 NULL,
398 N_("Show a collection of pictures that you can drag to your message"),
399 NULL, /* no callback */
400 FALSE },
401
402 { "prioritize-message",
403 NULL,
404 N_("_Prioritize Message"),
405 NULL,
406 N_("Set the message priority to high"),
407 NULL, /* no callback */
408 FALSE },
409
410 { "request-read-receipt",
411 NULL,
412 N_("Re_quest Read Receipt"),
413 NULL,
414 N_("Get delivery notification when your message is read"),
415 NULL, /* no callback */
416 FALSE },
417
418 { "smime-encrypt",
419 NULL,
420 N_("S/MIME En_crypt"),
421 NULL,
422 N_("Encrypt this message with your S/MIME Encryption Certificate"),
423 G_CALLBACK (action_smime_encrypt_cb),
424 FALSE },
425
426 { "smime-sign",
427 NULL,
428 N_("S/MIME Sig_n"),
429 NULL,
430 N_("Sign this message with your S/MIME Signature Certificate"),
431 G_CALLBACK (action_smime_sign_cb),
432 FALSE },
433
434 { "view-bcc",
435 NULL,
436 N_("_Bcc Field"),
437 NULL,
438 N_("Toggles whether the BCC field is displayed"),
439 NULL, /* Handled by property bindings */
440 FALSE },
441
442 { "view-cc",
443 NULL,
444 N_("_Cc Field"),
445 NULL,
446 N_("Toggles whether the CC field is displayed"),
447 NULL, /* Handled by property bindings */
448 FALSE },
449
450 { "view-reply-to",
451 NULL,
452 N_("_Reply-To Field"),
453 NULL,
454 N_("Toggles whether the Reply-To field is displayed"),
455 NULL, /* Handled by property bindings */
456 FALSE },
457 };
458
459 void
460 e_composer_actions_init (EMsgComposer *composer)
461 {
462 GtkActionGroup *action_group;
463 GtkUIManager *ui_manager;
464 GtkhtmlEditor *editor;
465 EWebViewGtkHTML *web_view;
466 gboolean visible;
467
468 g_return_if_fail (E_IS_MSG_COMPOSER (composer));
469
470 editor = GTKHTML_EDITOR (composer);
471 web_view = e_msg_composer_get_web_view (composer);
472 ui_manager = gtkhtml_editor_get_ui_manager (editor);
473
474 /* Composer Actions */
475 action_group = composer->priv->composer_actions;
476 gtk_action_group_set_translation_domain (
477 action_group, GETTEXT_PACKAGE);
478 gtk_action_group_add_actions (
479 action_group, entries,
480 G_N_ELEMENTS (entries), composer);
481 gtk_action_group_add_toggle_actions (
482 action_group, toggle_entries,
483 G_N_ELEMENTS (toggle_entries), composer);
484 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
485
486 /* Asynchronous Actions */
487 action_group = composer->priv->async_actions;
488 gtk_action_group_set_translation_domain (
489 action_group, GETTEXT_PACKAGE);
490 gtk_action_group_add_actions (
491 action_group, async_entries,
492 G_N_ELEMENTS (async_entries), composer);
493 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
494
495 /* Character Set Actions */
496 action_group = composer->priv->charset_actions;
497 gtk_action_group_set_translation_domain (
498 action_group, GETTEXT_PACKAGE);
499 e_charset_add_radio_actions (
500 action_group, "charset-", composer->priv->charset,
501 G_CALLBACK (action_charset_cb), composer);
502 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
503
504 /* Fine Tuning */
505
506 g_object_set (
507 ACTION (ATTACH), "short-label", _("Attach"), NULL);
508
509 g_object_set (
510 ACTION (PICTURE_GALLERY), "is-important", TRUE, NULL);
511
512 g_object_set (
513 ACTION (SAVE_DRAFT), "short-label", _("Save Draft"), NULL);
514
515 g_object_bind_property (
516 composer, "html-mode",
517 ACTION (PICTURE_GALLERY), "sensitive",
518 G_BINDING_SYNC_CREATE);
519
520 g_object_bind_property (
521 web_view, "editable",
522 GTKHTML_EDITOR_ACTION_EDIT_MENU (editor), "sensitive",
523 G_BINDING_SYNC_CREATE);
524
525 g_object_bind_property (
526 web_view, "editable",
527 GTKHTML_EDITOR_ACTION_FORMAT_MENU (editor), "sensitive",
528 G_BINDING_SYNC_CREATE);
529
530 g_object_bind_property (
531 web_view, "editable",
532 GTKHTML_EDITOR_ACTION_INSERT_MENU (editor), "sensitive",
533 G_BINDING_SYNC_CREATE);
534
535 #if defined (HAVE_NSS)
536 visible = TRUE;
537 #else
538 visible = FALSE;
539 #endif
540
541 gtk_action_set_visible (ACTION (SMIME_ENCRYPT), visible);
542 gtk_action_set_visible (ACTION (SMIME_SIGN), visible);
543 }