* src/gnome/modest-account-view-window.c:
[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
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 *msg_uid)
211 {
212         GObject *obj;
213         ModestMsgViewWindowPrivate *priv;
214         ModestWindowPrivate *parent_priv;
215         GtkActionGroup *action_group;
216         GError *error = NULL;
217         TnyHeader *header = NULL;
218         const gchar *subject = NULL;
219         ModestDimmingRulesGroup *menu_rules_group = NULL;
220         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
221         ModestDimmingRulesGroup *clipboard_rules_group = NULL;
222
223         g_return_val_if_fail (msg, NULL);
224
225         obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
226         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
227         parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
228
229         priv->msg_uid = g_strdup (msg_uid);
230
231         modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
232         
233         parent_priv->ui_manager = gtk_ui_manager_new();
234         action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
235         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
236
237         /* Add common actions */
238         gtk_action_group_add_actions (action_group,
239                                       modest_action_entries,
240                                       G_N_ELEMENTS (modest_action_entries),
241                                       obj);
242         gtk_action_group_add_toggle_actions (action_group,
243                                              modest_toggle_action_entries,
244                                              G_N_ELEMENTS (modest_toggle_action_entries),
245                                              obj);
246         gtk_action_group_add_toggle_actions (action_group,
247                                              msg_view_toggle_action_entries,
248                                              G_N_ELEMENTS (msg_view_toggle_action_entries),
249                                              obj);
250         gtk_action_group_add_radio_actions (action_group,
251                                             msg_view_zoom_action_entries,
252                                             G_N_ELEMENTS (msg_view_zoom_action_entries),
253                                             100,
254                                             G_CALLBACK (modest_ui_actions_on_change_zoom),
255                                             obj);
256         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
257         g_object_unref (action_group);
258
259         
260         /* Load the UI definition */
261         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
262                                          MODEST_UIDIR "modest-msg-view-window-ui.xml",
263                                          &error);
264         if (error) {
265                 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
266                 g_error_free (error);
267                 error = NULL;
268         }
269         /* ****** */
270
271         /* Add accelerators */
272         gtk_window_add_accel_group (GTK_WINDOW (obj), 
273                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
274
275         /* Toolbar / Menubar */
276         priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
277         priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
278
279         gtk_toolbar_set_tooltips (GTK_TOOLBAR (priv->toolbar), TRUE);
280
281         /* Init window */
282         init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
283         restore_settings (MODEST_WINDOW(obj));
284
285         header = tny_msg_get_header (msg);
286         if (header)
287                 subject = tny_header_get_subject (header);
288         
289         if (subject != NULL)
290                 gtk_window_set_title (GTK_WINDOW (obj), subject);
291         else
292                 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
293
294         if (header)
295                 g_object_unref (header);
296
297         gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
298
299         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
300
301         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
302         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
303         clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
304
305         /* Add common dimming rules */
306         modest_dimming_rules_group_add_rules (menu_rules_group, 
307                                               modest_msg_view_menu_dimming_entries,
308                                               G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
309                                               MODEST_WINDOW (obj));
310         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
311                                               modest_msg_view_toolbar_dimming_entries,
312                                               G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
313                                               MODEST_WINDOW (obj));
314         modest_dimming_rules_group_add_rules (clipboard_rules_group, 
315                                               modest_msg_view_clipboard_dimming_entries,
316                                               G_N_ELEMENTS (modest_msg_view_clipboard_dimming_entries),
317                                               MODEST_WINDOW (obj));
318
319         /* Insert dimming rules group for this window */
320         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
321         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
322         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
323         g_object_unref (menu_rules_group);
324         g_object_unref (toolbar_rules_group);
325         g_object_unref (clipboard_rules_group);
326
327         g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj);
328
329         return MODEST_WINDOW(obj);
330 }
331
332
333 TnyMsg*
334 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
335 {
336         GtkWidget *msg_view;    
337         g_return_val_if_fail (self, NULL);
338
339         msg_view = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self)->msg_view;
340
341         return tny_msg_view_get_msg (TNY_MSG_VIEW(msg_view));
342 }
343
344 const gchar*
345 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
346 {
347         ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
348         TnyMsg *msg;
349         TnyHeader *header;
350         const gchar *retval = NULL;
351
352         msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
353         msg = modest_msg_view_window_get_message (self);
354
355         if (!msg)
356                 return NULL;
357
358         header = tny_msg_get_header (msg);
359         if (header) {
360                 retval = tny_header_get_uid (header);
361                 g_object_unref (header);
362         }
363         g_object_unref (msg);
364
365         return retval;
366 }
367
368 ModestWindow*   
369 modest_msg_view_window_new_with_header_model (TnyMsg *msg, 
370                                               const gchar *modest_account_name, 
371                                               const gchar *msg_uid,
372                                               GtkTreeModel *model, 
373                                               GtkTreeRowReference *row_reference)
374 {
375         /* Currently we simply redirect to new constructor. It should store a
376            reference to the header list model, to enable next/prev message
377            actions */
378         g_message ("partially implemented %s", __FUNCTION__);
379
380         return modest_msg_view_window_new_for_attachment (msg, modest_account_name, msg_uid);
381 }
382
383
384 gboolean
385 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
386 {
387         g_message ("not implemented %s", __FUNCTION__);
388         return FALSE;
389 }
390
391 gboolean
392 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
393 {
394         g_message ("not implemented %s", __FUNCTION__);
395         return FALSE;
396 }
397
398 void
399 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
400 {
401         g_message ("not implemented %s", __FUNCTION__);
402 }
403
404 void
405 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, TnyList *mime_parts)
406 {
407         g_message ("not implemented %s", __FUNCTION__);
408 }
409 void
410 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
411 {
412         g_message ("not implemented %s", __FUNCTION__);
413 }
414
415 TnyHeader *
416 modest_msg_view_window_get_header (ModestMsgViewWindow *self)
417 {
418         TnyMsg *msg;
419         TnyHeader *header = NULL;
420
421         msg = modest_msg_view_window_get_message (self);
422         if (msg) {
423                 header = tny_msg_get_header (msg);
424                 g_object_unref (msg);
425         }
426         return header;
427 }
428
429 TnyFolderType
430 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
431 {
432         ModestMsgViewWindowPrivate *priv;
433         TnyMsg *msg;
434         TnyFolderType folder_type;
435
436         priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
437
438         folder_type = TNY_FOLDER_TYPE_UNKNOWN;
439
440         msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
441         if (msg) {
442                 TnyFolder *folder;
443
444                 folder = tny_msg_get_folder (msg);
445                 if (folder) {
446                         folder_type = tny_folder_get_folder_type (folder);
447                         g_object_unref (folder);
448                 }
449                 g_object_unref (msg);
450         }
451
452         return folder_type;
453 }
454
455 /* NOT IMPLEMENTED METHODS */
456
457 gboolean 
458 modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
459 {
460         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
461         return TRUE;
462 }
463
464 gboolean 
465 modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
466 {
467         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
468         return TRUE;
469 }
470
471 gboolean 
472 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
473 {
474         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
475         return FALSE;
476 }
477
478 gboolean  
479 modest_msg_view_window_toolbar_on_transfer_mode     (ModestMsgViewWindow *self)
480 {
481         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
482         return FALSE;
483 }
484
485
486 TnyList *         
487 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
488 {
489         TnyList *result;
490
491         result = tny_simple_list_new ();
492         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
493         return result;  
494 }
495
496 gboolean 
497 modest_msg_view_window_is_search_result (ModestMsgViewWindow *window)
498 {
499         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
500         return FALSE;   
501 }
502
503 gboolean 
504 modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
505 {
506         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
507         return FALSE;   
508 }
509
510 static void 
511 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
512                                             gpointer data)
513 {
514         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
515         return FALSE;   
516 }