Now the "load images" and "details" actions in msg view window are not in the
[modest] / src / gnome / modest-msg-view-window.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <glib/gi18n.h>
30 #include <string.h>
31 #include <tny-account-store.h>
32 #include <tny-simple-list.h>
33 #include <modest-tny-msg.h>
34 #include "modest-icon-names.h"
35 #include "modest-ui-actions.h"
36 #include <modest-widget-memory.h>
37 #include <modest-runtime.h>
38 #include <modest-main-window-ui.h>
39 #include "modest-msg-view-window-ui-dimming.h"
40 #include "modest-defs.h"
41 #include <widgets/modest-msg-view-window.h>
42 #include <widgets/modest-window-priv.h>
43 #include "widgets/modest-msg-view.h"
44 #include "modest-ui-dimming-manager.h"
45
46
47 static void  modest_msg_view_window_class_init   (ModestMsgViewWindowClass *klass);
48 static void  modest_msg_view_window_init         (ModestMsgViewWindow *obj);
49 static void  modest_msg_view_window_finalize     (GObject *obj);
50
51 static void  modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
52                                                          gpointer data);
53
54 /* list my signals */
55 enum {
56         /* MY_SIGNAL_1, */
57         /* MY_SIGNAL_2, */
58         LAST_SIGNAL
59 };
60
61 typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
62 struct _ModestMsgViewWindowPrivate {
63         GtkWidget   *toolbar;
64         GtkWidget   *menubar;
65         GtkWidget   *msg_view;
66
67         gchar *msg_uid;
68 };
69
70 #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
71                                                     MODEST_TYPE_MSG_VIEW_WINDOW, \
72                                                     ModestMsgViewWindowPrivate))
73 /* globals */
74 static GtkWindowClass *parent_class = NULL;
75
76 static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
77         { "FindInMessage",    GTK_STOCK_FIND,    N_("mcen_me_viewer_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
78         { "ToolsFindInMessage", NULL, N_("mcen_me_viewer_find"), "<CTRL>F", NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
79 };
80
81 static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
82         { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
83         { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
84         { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
85         { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
86         { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
87         { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
88 };
89
90 GType
91 modest_msg_view_window_get_type (void)
92 {
93         static GType my_type = 0;
94         if (!my_type) {
95                 static const GTypeInfo my_info = {
96                         sizeof(ModestMsgViewWindowClass),
97                         NULL,           /* base init */
98                         NULL,           /* base finalize */
99                         (GClassInitFunc) modest_msg_view_window_class_init,
100                         NULL,           /* class finalize */
101                         NULL,           /* class data */
102                         sizeof(ModestMsgViewWindow),
103                         1,              /* n_preallocs */
104                         (GInstanceInitFunc) modest_msg_view_window_init,
105                         NULL
106                 };
107                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
108                                                   "ModestMsgViewWindow",
109                                                   &my_info, 0);
110         }
111         return my_type;
112 }
113
114 static void
115 save_state (ModestWindow *self)
116 {
117         modest_widget_memory_save (modest_runtime_get_conf (),
118                                    G_OBJECT(self), 
119                                    MODEST_CONF_MSG_VIEW_WINDOW_KEY);
120 }
121
122
123 static void
124 restore_settings (ModestWindow *self)
125 {
126         modest_widget_memory_restore (modest_runtime_get_conf (),
127                                       G_OBJECT(self), 
128                                       MODEST_CONF_MSG_VIEW_WINDOW_KEY);
129 }
130
131 static void
132 modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
133 {
134         GObjectClass *gobject_class;
135         gobject_class = (GObjectClass*) klass;
136
137         parent_class            = g_type_class_peek_parent (klass);
138         gobject_class->finalize = modest_msg_view_window_finalize;
139
140         g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
141
142         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
143         modest_window_class->save_state_func = save_state;
144 }
145
146 static void
147 modest_msg_view_window_init (ModestMsgViewWindow *obj)
148 {
149         ModestMsgViewWindowPrivate *priv;
150         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
151
152         priv->toolbar  = NULL;
153         priv->menubar  = NULL;
154         priv->msg_view = NULL;
155         priv->msg_uid  = NULL;
156 }
157
158
159 static void
160 init_window (ModestMsgViewWindow *obj, TnyMsg *msg)
161 {
162         GtkWidget *main_vbox, *scrolled_window;
163         ModestMsgViewWindowPrivate *priv;
164         ModestWindowPrivate *parent_priv;
165         
166         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
167         parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
168
169         priv->msg_view = GTK_WIDGET (tny_platform_factory_new_msg_view (modest_tny_platform_factory_get_instance ()));
170         tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
171         main_vbox = gtk_vbox_new  (FALSE, 0);
172         
173         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
174         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
175         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
176         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
177                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
178         gtk_container_add (GTK_CONTAINER (scrolled_window), 
179                            priv->msg_view);
180         gtk_box_pack_start (GTK_BOX(main_vbox), scrolled_window, TRUE, TRUE, 0);
181
182         gtk_widget_show_all (GTK_WIDGET(main_vbox));
183         gtk_container_add   (GTK_CONTAINER(obj), main_vbox);
184 }
185
186
187 static void
188 modest_msg_view_window_finalize (GObject *obj)
189 {
190         ModestMsgViewWindowPrivate *priv;
191
192         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
193
194         G_OBJECT_CLASS(parent_class)->finalize (obj);
195 }
196
197
198
199 static gboolean
200 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgViewWindow *self)
201 {
202         modest_window_save_state (MODEST_WINDOW(self));
203         return FALSE;
204 }
205
206
207 ModestWindow *
208 modest_msg_view_window_new_for_attachment (TnyMsg *msg, 
209                                            const gchar *modest_account_name, 
210                                            const gchar *mailbox, /* ignored */
211                                            const gchar *msg_uid)
212 {
213         GObject *obj;
214         ModestMsgViewWindowPrivate *priv;
215         ModestWindowPrivate *parent_priv;
216         GtkActionGroup *action_group;
217         GError *error = NULL;
218         TnyHeader *header = NULL;
219         gchar *subject = NULL;
220         ModestDimmingRulesGroup *menu_rules_group = NULL;
221         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
222         ModestDimmingRulesGroup *clipboard_rules_group = NULL;
223
224         g_return_val_if_fail (msg, NULL);
225
226         obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
227         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
228         parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
229
230         priv->msg_uid = g_strdup (msg_uid);
231
232         modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
233         
234         parent_priv->ui_manager = gtk_ui_manager_new();
235         action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
236         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
237
238         /* Add common actions */
239         gtk_action_group_add_actions (action_group,
240                                       modest_action_entries,
241                                       G_N_ELEMENTS (modest_action_entries),
242                                       obj);
243         gtk_action_group_add_toggle_actions (action_group,
244                                              modest_toggle_action_entries,
245                                              G_N_ELEMENTS (modest_toggle_action_entries),
246                                              obj);
247         gtk_action_group_add_toggle_actions (action_group,
248                                              msg_view_toggle_action_entries,
249                                              G_N_ELEMENTS (msg_view_toggle_action_entries),
250                                              obj);
251         gtk_action_group_add_radio_actions (action_group,
252                                             msg_view_zoom_action_entries,
253                                             G_N_ELEMENTS (msg_view_zoom_action_entries),
254                                             100,
255                                             G_CALLBACK (modest_ui_actions_on_change_zoom),
256                                             obj);
257         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
258         g_object_unref (action_group);
259
260         
261         /* Load the UI definition */
262         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
263                                          MODEST_UIDIR "modest-msg-view-window-ui.xml",
264                                          &error);
265         if (error) {
266                 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
267                 g_error_free (error);
268                 error = NULL;
269         }
270         /* ****** */
271
272         /* Add accelerators */
273         gtk_window_add_accel_group (GTK_WINDOW (obj), 
274                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
275
276         /* Toolbar / Menubar */
277         priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
278         priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
279
280         gtk_toolbar_set_tooltips (GTK_TOOLBAR (priv->toolbar), TRUE);
281
282         /* Init window */
283         init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
284         restore_settings (MODEST_WINDOW(obj));
285
286         header = tny_msg_get_header (msg);
287         if (header)
288                 subject = tny_header_dup_subject (header);
289         
290         if (subject != NULL)
291                 gtk_window_set_title (GTK_WINDOW (obj), subject);
292         else
293                 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
294         g_free (subject);
295
296         if (header)
297                 g_object_unref (header);
298
299         gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
300
301         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
302
303         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
304         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
305         clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
306
307         /* Add common dimming rules */
308         modest_dimming_rules_group_add_rules (menu_rules_group, 
309                                               modest_msg_view_menu_dimming_entries,
310                                               G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
311                                               MODEST_WINDOW (obj));
312         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
313                                               modest_msg_view_toolbar_dimming_entries,
314                                               G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
315                                               MODEST_WINDOW (obj));
316         modest_dimming_rules_group_add_rules (clipboard_rules_group, 
317                                               modest_msg_view_clipboard_dimming_entries,
318                                               G_N_ELEMENTS (modest_msg_view_clipboard_dimming_entries),
319                                               MODEST_WINDOW (obj));
320
321         /* Insert dimming rules group for this window */
322         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
323         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
324         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
325         g_object_unref (menu_rules_group);
326         g_object_unref (toolbar_rules_group);
327         g_object_unref (clipboard_rules_group);
328
329         g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj);
330
331         return MODEST_WINDOW(obj);
332 }
333
334
335 TnyMsg*
336 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
337 {
338         GtkWidget *msg_view;    
339         g_return_val_if_fail (self, NULL);
340
341         msg_view = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self)->msg_view;
342
343         return tny_msg_view_get_msg (TNY_MSG_VIEW(msg_view));
344 }
345
346 const gchar*
347 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
348 {
349         ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
350         TnyMsg *msg;
351         TnyHeader *header;
352         const gchar *retval = NULL;
353
354         msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
355         msg = modest_msg_view_window_get_message (self);
356
357         if (!msg)
358                 return NULL;
359
360         header = tny_msg_get_header (msg);
361         g_free (priv->msg_uid);
362         if (header) {
363                 priv->msg_uid = tny_header_dup_uid (header);
364                 g_object_unref (header);
365         }
366         g_object_unref (msg);
367
368         return priv->msg_uid;
369 }
370
371 ModestWindow*   
372 modest_msg_view_window_new_with_header_model (TnyMsg *msg, 
373                                               const gchar *modest_account_name, 
374                                               const gchar *mailbox, /*ignored*/
375                                               const gchar *msg_uid,
376                                               GtkTreeModel *model, 
377                                               GtkTreeRowReference *row_reference)
378 {
379         /* Currently we simply redirect to new constructor. It should store a
380            reference to the header list model, to enable next/prev message
381            actions */
382         g_message ("partially implemented %s", __FUNCTION__);
383
384         return modest_msg_view_window_new_for_attachment (msg, modest_account_name, NULL, msg_uid);
385 }
386
387
388 gboolean
389 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
390 {
391         g_message ("not implemented %s", __FUNCTION__);
392         return FALSE;
393 }
394
395 gboolean
396 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
397 {
398         g_message ("not implemented %s", __FUNCTION__);
399         return FALSE;
400 }
401
402 void
403 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
404 {
405         g_message ("not implemented %s", __FUNCTION__);
406 }
407
408 void
409 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, TnyList *mime_parts)
410 {
411         g_message ("not implemented %s", __FUNCTION__);
412 }
413 void
414 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
415 {
416         g_message ("not implemented %s", __FUNCTION__);
417 }
418
419 TnyHeader *
420 modest_msg_view_window_get_header (ModestMsgViewWindow *self)
421 {
422         TnyMsg *msg;
423         TnyHeader *header = NULL;
424
425         msg = modest_msg_view_window_get_message (self);
426         if (msg) {
427                 header = tny_msg_get_header (msg);
428                 g_object_unref (msg);
429         }
430         return header;
431 }
432
433 TnyFolderType
434 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
435 {
436         ModestMsgViewWindowPrivate *priv;
437         TnyMsg *msg;
438         TnyFolderType folder_type;
439
440         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
441
442         folder_type = TNY_FOLDER_TYPE_UNKNOWN;
443
444         msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
445         if (msg) {
446                 TnyFolder *folder;
447
448                 folder = tny_msg_get_folder (msg);
449                 if (folder) {
450                         folder_type = tny_folder_get_folder_type (folder);
451                         g_object_unref (folder);
452                 }
453                 g_object_unref (msg);
454         }
455
456         return folder_type;
457 }
458
459 /* NOT IMPLEMENTED METHODS */
460
461 gboolean 
462 modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
463 {
464         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
465         return TRUE;
466 }
467
468 gboolean 
469 modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
470 {
471         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
472         return TRUE;
473 }
474
475 gboolean 
476 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
477 {
478         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
479         return FALSE;
480 }
481
482 gboolean  
483 modest_msg_view_window_toolbar_on_transfer_mode     (ModestMsgViewWindow *self)
484 {
485         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
486         return FALSE;
487 }
488
489
490 TnyList *         
491 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
492 {
493         TnyList *result;
494
495         result = tny_simple_list_new ();
496         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
497         return result;  
498 }
499
500 gboolean 
501 modest_msg_view_window_is_search_result (ModestMsgViewWindow *window)
502 {
503         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
504         return FALSE;   
505 }
506
507 gboolean 
508 modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
509 {
510         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
511         return FALSE;   
512 }
513
514 static void 
515 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
516                                             gpointer data)
517 {
518         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
519         return FALSE;   
520 }
521
522 void
523 modest_msg_view_window_add_to_contacts (ModestMsgViewWindow *self)
524 {
525         modest_ui_actions_on_add_to_contacts (NULL, MODEST_WINDOW (self));
526 }
527
528 void
529 modest_msg_view_window_fetch_images (ModestMsgViewWindow *self)
530 {
531         ModestMsgViewWindowPrivate *priv;
532         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
533
534         modest_msg_view_request_fetch_images (MODEST_MSG_VIEW (priv->msg_view));
535 }
536
537 gboolean 
538 modest_msg_view_window_has_blocked_external_images (ModestMsgViewWindow *self)
539 {
540         ModestMsgViewWindowPrivate *priv;
541         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
542
543         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
544
545         return modest_msg_view_has_blocked_external_images (MODEST_MSG_VIEW (priv->msg_view));
546 }