* add progress indication.
[modest] / src / gtk-glade / modest-ui-main-view.c
1 #include <gtk/gtk.h>
2 #include <glade/glade.h>
3 #include <glib/gi18n.h>
4 #include <string.h>
5
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif /*HAVE_CONFIG_H*/
9
10 /* TODO: put in auto* */
11 #include <tny-text-buffer-stream.h>
12 #include <tny-msg-folder.h>
13
14 #include "../modest-ui.h"
15 #include "../modest-window-mgr.h"
16 #include "../modest-account-mgr.h"
17 #include "../modest-account-mgr.h"
18 #include "../modest-identity-mgr.h"
19
20 #include "../modest-tny-account-store.h"
21 #include "../modest-tny-folder-tree-view.h"
22 #include "../modest-tny-header-tree-view.h"
23 #include "../modest-tny-msg-view.h"
24 #include "../modest-tny-transport-actions.h"
25 #include "../modest-tny-store-actions.h"
26
27 #include "../modest-text-utils.h"
28 #include "../modest-tny-msg-actions.h"
29
30 #include "../modest-editor-window.h"
31
32 #include "modest-ui-glade.h"
33 #include "modest-ui-wizard.h"
34 #include "modest-ui-account-setup.h"
35
36 #include "modest-ui-main-view.h"
37 #include "modest-ui-message-editor.h"
38 #include "modest-ui-message-viewer.h"
39
40
41 static GtkWidget* modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr,
42                                                   TnyAccountStoreIface *account_store);
43
44 static GtkWidget* modest_main_window_header_tree (TnyMsgFolderIface *folder);
45
46 static void on_folder_clicked (ModestTnyFolderTreeView *folder_tree,
47                                TnyMsgFolderIface *folder,
48                                gpointer data);
49
50 static void on_message_clicked (ModestTnyFolderTreeView *folder_tree,
51                                 TnyMsgIface *message,
52                                 gpointer data);
53
54 static void on_reply_clicked (GtkWidget *widget, gpointer user_data);
55
56 static void on_forward_clicked (GtkWidget *widget, gpointer user_data);
57
58 static void on_delete_clicked (GtkWidget *widget, gpointer user_data);
59
60 static void on_view_attachments_toggled(GtkWidget *widget, gpointer user_data);
61
62 static void on_sendreceive_button_clicked (GtkWidget *widget, gpointer user_data);
63
64 static void on_forward_attached_activated (GtkWidget *widget, gpointer user_data);
65
66 static void on_headers_status_update (GtkWidget *header_view, const gchar *msg, gint status,
67                           gpointer user_data);
68 static void on_status_cleanup (gpointer user_data);
69
70 static void register_toolbar_callbacks (ModestUI *modest_ui);
71
72
73 static void
74 modest_ui_main_view_destroy (GtkWidget *win, GdkEvent *event, gpointer data)
75 {
76         ModestUIPrivate *priv;
77
78         g_return_if_fail (data);
79         g_return_if_fail(MODEST_IS_UI(data));
80         priv = MODEST_UI_GET_PRIVATE((ModestUI *)data);
81         g_return_if_fail(priv);
82         if (!modest_window_mgr_unregister (priv->modest_window_mgr, G_OBJECT(win)))
83                 g_warning ("modest window mgr: failed to unregister %p",
84                            G_OBJECT(win));
85         else
86                 gtk_widget_hide(win);
87 }
88
89
90 gboolean
91 modest_ui_show_main_window (ModestUI *modest_ui)
92 {
93         GtkWidget       *win;
94         gint              height, width;
95         ModestUIPrivate *priv;
96         GtkWidget     *folder_view, *header_view;
97         GtkWidget     *message_view;
98         GtkWidget     *account_settings_item;
99         GtkWidget     *forward_attached_menu_item;
100         GtkWidget     *delete_item;
101         GtkWidget     *open_item;
102         GtkWidget     *view_attachments_item;
103         GtkWidget     *new_account_item;
104         
105         GtkWidget  *folder_view_holder,
106                 *header_view_holder,
107                 *mail_paned;
108         gboolean show_attachments_inline;
109
110         priv = MODEST_UI_GET_PRIVATE(modest_ui);
111         
112         height = modest_conf_get_int (priv->modest_conf,
113                                       MODEST_CONF_MAIN_WINDOW_HEIGHT,NULL);
114         width  = modest_conf_get_int (priv->modest_conf,
115                                       MODEST_CONF_MAIN_WINDOW_WIDTH,NULL);
116
117         win = glade_xml_get_widget (priv->glade_xml, "main");
118         if (!win) {
119                 g_warning ("could not create main window");
120                 return FALSE;
121         }
122
123         folder_view = GTK_WIDGET(modest_main_window_folder_tree(priv->modest_acc_mgr,
124                                                           priv->account_store));
125         priv->folder_view = folder_view;
126         folder_view_holder = glade_xml_get_widget (priv->glade_xml, "folders");
127         if (!folder_view||!folder_view_holder) {
128                 g_warning ("failed to create folder tree");
129                 return FALSE;
130         }
131         gtk_container_add (GTK_CONTAINER(folder_view_holder), folder_view);
132
133         header_view  =  GTK_WIDGET(modest_main_window_header_tree (NULL));
134         priv->header_view = header_view;
135         header_view_holder = glade_xml_get_widget (priv->glade_xml, "mail_list");
136         if (!header_view) {
137                 g_warning ("failed to create header tree");
138                 return FALSE;
139         }
140         gtk_container_add (GTK_CONTAINER(header_view_holder), header_view);
141
142         g_signal_connect (G_OBJECT(folder_view), "folder_selected",
143                           G_CALLBACK(on_folder_clicked), modest_ui);
144
145         show_attachments_inline = modest_conf_get_bool(priv->modest_conf,
146                                              MODEST_CONF_MSG_VIEW_SHOW_ATTACHMENTS_INLINE,
147                                              NULL);
148
149         message_view  = GTK_WIDGET(modest_tny_msg_view_new (NULL, show_attachments_inline));
150         priv->message_view = message_view;
151         if (!message_view) {
152                 g_warning ("failed to create message view");
153                 return FALSE;
154         }
155
156         mail_paned = glade_xml_get_widget (priv->glade_xml, "mail_paned");
157         gtk_paned_add2 (GTK_PANED(mail_paned), message_view);
158
159         g_signal_connect (header_view, "message_selected",
160                           G_CALLBACK(on_message_clicked),
161                           modest_ui);
162
163         g_signal_connect (header_view, "status_update",
164                           G_CALLBACK(on_headers_status_update), modest_ui);
165
166         g_signal_connect (header_view, "row-activated",
167                           G_CALLBACK(on_message_activated),
168                           modest_ui);
169
170         account_settings_item = glade_xml_get_widget (priv->glade_xml, "AccountSettingsMenuItem");
171         if (!account_settings_item) {
172                 g_warning ("The account settings item isn't available!\n");
173                 return FALSE;
174         }
175
176         g_signal_connect (account_settings_item, "activate",
177                           G_CALLBACK(account_settings), modest_ui);
178
179         new_account_item = glade_xml_get_widget (priv->glade_xml, "NewAccountWizardMenuItem");
180         if (!new_account_item) {
181                 g_warning ("The new account item isn't available!\n");
182                 return FALSE;
183         }
184
185         g_signal_connect (new_account_item, "activate",
186                 G_CALLBACK(new_wizard_account), modest_ui);
187
188         open_item = glade_xml_get_widget (priv->glade_xml, "open1");
189         if (!open_item) {
190                 g_warning ("The open item isn't available!\n");
191                 return FALSE;
192         }
193         g_signal_connect (open_item, "activate", G_CALLBACK(on_open_message_clicked),
194                           modest_ui);
195
196         delete_item = glade_xml_get_widget (priv->glade_xml, "delete1");
197         if (!delete_item) {
198                 g_warning ("The delete item isn't available!\n");
199                 return FALSE;
200         }
201         g_signal_connect (delete_item, "activate", G_CALLBACK(on_delete_clicked),
202                           modest_ui);
203
204         view_attachments_item = glade_xml_get_widget (priv->glade_xml, "menu_view_attachments");
205         if (!view_attachments_item) {
206                 g_warning ("The view_attachments_item isn't available!");
207                 return FALSE;
208         }
209
210         forward_attached_menu_item = glade_xml_get_widget (priv->glade_xml, "forward_attached");
211         if (!forward_attached_menu_item) {
212                 g_warning ("The forward_attached_menu_item isn't available!");
213                 return FALSE;
214         }
215         g_signal_connect (forward_attached_menu_item, "activate", G_CALLBACK(on_forward_attached_activated),
216                           modest_ui);
217
218         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(view_attachments_item),
219                                         modest_conf_get_bool(priv->modest_conf,
220                                         MODEST_CONF_MSG_VIEW_SHOW_ATTACHMENTS_INLINE,
221                                         NULL));
222
223         g_signal_connect (view_attachments_item, "toggled",
224                                 G_CALLBACK(on_view_attachments_toggled), modest_ui);
225
226         register_toolbar_callbacks (modest_ui);
227
228         modest_window_mgr_register (priv->modest_window_mgr,
229                                     G_OBJECT(win), MODEST_MAIN_WINDOW, 0);
230         g_signal_connect (win, "destroy-event", G_CALLBACK(modest_ui_main_view_destroy),
231                           modest_ui);
232         g_signal_connect (win, "delete-event", G_CALLBACK(modest_ui_main_view_destroy),
233                           modest_ui);
234         gtk_widget_set_usize (GTK_WIDGET(win), width, height);
235         gtk_window_set_title (GTK_WINDOW(win), PACKAGE_STRING);
236
237         gtk_widget_show_all (win);
238         return TRUE;
239 }
240
241
242 static void
243 register_toolbar_callbacks (ModestUI *modest_ui)
244 {
245         ModestUIPrivate *priv;
246         GtkWidget *button;
247
248         g_return_if_fail (modest_ui);
249
250         priv = MODEST_UI_GET_PRIVATE (modest_ui);
251
252         button = glade_xml_get_widget (priv->glade_xml, "toolb_new_mail");
253         if (button)
254                 g_signal_connect (button, "clicked",
255                                   G_CALLBACK(on_new_mail_clicked), modest_ui);
256
257         button = glade_xml_get_widget (priv->glade_xml, "toolb_reply");
258         if (button) {
259                 g_signal_connect (button, "clicked",
260                                   G_CALLBACK(on_reply_clicked), modest_ui);
261                 gtk_widget_set_sensitive(button, FALSE);
262         }
263
264         button = glade_xml_get_widget (priv->glade_xml, "toolb_reply_all");
265         if (button) {
266                 //g_signal_connect (button, "clicked",
267                 //                G_CALLBACK(on_reply_all_clicked), modest_ui);
268                 gtk_widget_set_sensitive(button, FALSE);
269         }
270
271         button = glade_xml_get_widget (priv->glade_xml, "toolb_forward");
272         if (button) {
273                 g_signal_connect (button, "clicked",
274                                   G_CALLBACK(on_forward_clicked), modest_ui);
275                 gtk_widget_set_sensitive(button, FALSE);
276         }
277
278         button = glade_xml_get_widget (priv->glade_xml, "toolb_move_to");
279         if (button) {
280                 //g_signal_connect (button, "clicked",
281                 //                G_CALLBACK(on_move_to_clicked), modest_ui);
282                 gtk_widget_set_sensitive(button, FALSE);
283         }
284
285         button = glade_xml_get_widget (priv->glade_xml, "toolb_delete");
286         if (button) {
287                 g_signal_connect (button, "clicked",
288                                   G_CALLBACK(on_delete_clicked), modest_ui);
289                 gtk_widget_set_sensitive(button, FALSE);
290         }
291
292         button = glade_xml_get_widget (priv->glade_xml, "toolb_send_receive");
293         if (button) {
294                 g_signal_connect (button, "clicked",
295                                   G_CALLBACK(on_sendreceive_button_clicked), modest_ui);
296                 gtk_widget_set_sensitive(button, TRUE);
297         }
298 }
299
300
301 static void
302 on_folder_clicked (ModestTnyFolderTreeView *folder_tree,
303                    TnyMsgFolderIface *folder,
304                    gpointer data)
305 {
306         GtkWidget *win;
307         GtkWidget *button;
308         ModestTnyHeaderTreeView *tree_view;
309         ModestTnyMsgView *msg_view;
310         ModestUIPrivate *priv;
311         GtkWidget *scrollview;
312
313         g_return_if_fail (folder);
314         g_return_if_fail (data);
315
316         priv = MODEST_UI_GET_PRIVATE(data);
317         scrollview = glade_xml_get_widget (priv->glade_xml,"mail_list");
318
319         tree_view = MODEST_TNY_HEADER_TREE_VIEW (priv->header_view);
320
321         win = glade_xml_get_widget (priv->glade_xml, "main");
322         gtk_window_set_title (GTK_WINDOW(win),
323                               tny_msg_folder_iface_get_name(folder));
324
325         modest_tny_header_tree_view_set_folder (tree_view, folder);
326         priv->current_folder = folder;
327
328         button = glade_xml_get_widget (priv->glade_xml, "toolb_reply");
329         if (button) {
330                 gtk_widget_set_sensitive(button, FALSE);
331         }
332
333         button = glade_xml_get_widget (priv->glade_xml, "toolb_forward");
334         if (button) {
335                 gtk_widget_set_sensitive(button, FALSE);
336         }
337
338         button = glade_xml_get_widget (priv->glade_xml, "toolb_delete");
339         if (button) {
340                 gtk_widget_set_sensitive(button, FALSE);
341         }
342
343         msg_view = MODEST_TNY_MSG_VIEW (priv->message_view);
344         g_return_if_fail (msg_view);
345
346         modest_tny_msg_view_set_message  (msg_view, NULL);
347 }
348
349
350 static void
351 on_message_clicked (ModestTnyFolderTreeView *folder_tree,
352                                 TnyMsgIface *message,
353                                 gpointer data)
354 {
355         GtkWidget *button;
356         ModestTnyMsgView *msg_view;
357         ModestUIPrivate *priv;
358
359         g_return_if_fail (data);
360
361         priv = MODEST_UI_GET_PRIVATE (data);
362         msg_view = MODEST_TNY_MSG_VIEW (priv->message_view);
363
364         modest_tny_msg_view_set_message (msg_view, message);
365         
366         button = glade_xml_get_widget (priv->glade_xml, "toolb_reply");
367         if (button) {
368                 gtk_widget_set_sensitive(button, TRUE);
369         }
370         button = glade_xml_get_widget (priv->glade_xml, "toolb_forward");
371         if (button) {
372                 gtk_widget_set_sensitive(button, TRUE);
373         }
374         button = glade_xml_get_widget (priv->glade_xml, "toolb_delete");
375         if (button) {
376                 gtk_widget_set_sensitive(button, TRUE);
377         }
378 }
379
380
381 static GtkWidget*
382 modest_main_window_header_tree (TnyMsgFolderIface *folder)
383 {
384         int i;
385         GSList *columns = NULL;
386         GtkWidget *header_tree;
387         ModestTnyHeaderTreeViewColumn cols[] = {
388                 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE,
389                 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH,
390                 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM,
391                 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT,
392                 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE
393         };
394
395         for (i = 0 ; i != sizeof(cols) / sizeof(ModestTnyHeaderTreeViewColumn); ++i)
396                 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
397
398         header_tree = GTK_WIDGET(modest_tny_header_tree_view_new(folder, columns,
399                                                                  MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL));
400         g_slist_free (columns);
401
402         if (!header_tree) {
403                 g_warning ("could not create header tree");
404                 return NULL;
405         }
406
407         return GTK_WIDGET(header_tree);
408 }
409
410
411 static GtkWidget*
412 modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr,
413                                 TnyAccountStoreIface *account_store)
414 {
415         GtkWidget *folder_tree;
416
417         folder_tree = GTK_WIDGET (modest_tny_folder_tree_view_new (account_store));
418         if (!folder_tree) {
419                 g_warning ("could not create folder list");
420                 return NULL;
421         }
422
423         return folder_tree;
424 }
425
426
427 static void
428 on_reply_clicked (GtkWidget *widget, gpointer user_data)
429 {
430         ModestUI *modest_ui = (ModestUI *)user_data;
431
432         quoted_send_msg (modest_ui, QUOTED_SEND_REPLY);
433 }
434
435
436 static void
437 on_forward_clicked (GtkWidget *widget, gpointer user_data)
438 {
439         ModestUI *modest_ui = (ModestUI *)user_data;
440
441         quoted_send_msg (modest_ui, QUOTED_SEND_FORWARD);
442 }
443
444
445 static void
446 on_view_attachments_toggled(GtkWidget *widget, gpointer user_data)
447 {
448         ModestUI *modest_ui = (ModestUI *)user_data;
449         GtkWidget *view_attachments_item;
450         ModestTnyMsgView *msg_view;
451         ModestUIPrivate *priv;
452         gboolean view_attachments_inline;
453
454         priv = MODEST_UI_GET_PRIVATE(modest_ui);
455         view_attachments_item = glade_xml_get_widget (priv->glade_xml, "menu_view_attachments");
456         g_return_if_fail(view_attachments_item);
457
458         msg_view = MODEST_TNY_MSG_VIEW(priv->message_view);
459
460         view_attachments_inline = gtk_check_menu_item_get_active(
461                                         GTK_CHECK_MENU_ITEM(view_attachments_item));
462
463         modest_conf_set_bool(priv->modest_conf,
464                              MODEST_CONF_MSG_VIEW_SHOW_ATTACHMENTS_INLINE,
465                              view_attachments_inline,
466                              NULL);
467
468         modest_tny_msg_view_set_show_attachments_inline_flag(msg_view, view_attachments_inline);
469 }
470
471
472 static void
473 on_delete_clicked (GtkWidget *widget, gpointer user_data)
474 {
475         ModestUI *modest_ui = (ModestUI *)user_data;
476         GtkTreeSelection *sel;
477         GtkTreeModel *model;
478         GtkTreeIter iter;
479         GtkTreeModel *mymodel;
480
481         ModestTnyHeaderTreeView *header_view;
482         ModestTnyMsgView *msg_view;
483         ModestUIPrivate *priv;
484
485         g_return_if_fail (modest_ui);
486
487         priv = MODEST_UI_GET_PRIVATE(modest_ui);
488
489         msg_view = MODEST_TNY_MSG_VIEW(priv->message_view);
490         g_return_if_fail (msg_view);
491
492         header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view);
493         g_return_if_fail (header_view);
494
495         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
496         g_return_if_fail (sel);
497
498         /* get all selected mails */
499         if (G_LIKELY (gtk_tree_selection_get_selected (sel, &model, &iter))) {
500                 TnyMsgHeaderIface *header;
501
502                 gtk_tree_model_get (model, &iter, TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN,
503                         &header, -1);
504
505                 if (G_LIKELY (header)) {
506                         TnyMsgFolderIface *folder;
507                         // const TnyMsgIface *msg;
508
509                         if (GTK_IS_TREE_MODEL_SORT (model)) {
510                                 mymodel = gtk_tree_model_sort_get_model
511                                         (GTK_TREE_MODEL_SORT (model));
512                         } else
513                                 mymodel = model;
514
515                         folder = (TnyMsgFolderIface*)tny_msg_header_iface_get_folder (header);
516
517                         /* this will make the message as deleted */
518                         /*      tny_msg_folder_iface_expunge (folder); will finally delete messages */
519                         if (TNY_IS_MSG_FOLDER (folder))
520                                 tny_msg_folder_iface_remove_message (folder, header);
521                         gtk_widget_queue_draw (GTK_WIDGET (header_view));
522                 }
523         }
524 }
525
526
527 static void
528 on_sendreceive_button_clicked (GtkWidget *widget, gpointer user_data)
529 {
530         ModestUI *modest_ui = (ModestUI *)user_data;
531         ModestUIPrivate *priv;
532         TnyAccountStoreIface *account_store;
533         const GList *store_accounts;
534         const GList *iter;
535
536         g_return_if_fail (modest_ui);
537         priv = MODEST_UI_GET_PRIVATE(modest_ui);
538
539         account_store = priv->account_store;
540         store_accounts =
541                 tny_account_store_iface_get_store_accounts (account_store);
542                 
543         for (iter = store_accounts; iter; iter = iter->next) {
544                 modest_tny_store_actions_update_folders (TNY_STORE_ACCOUNT_IFACE (iter->data));
545
546         }
547         
548         if (priv->header_view && priv->current_folder) {
549                         
550                 modest_tny_header_tree_view_set_folder (MODEST_TNY_HEADER_TREE_VIEW(priv->header_view),
551                                                         priv->current_folder);
552                 gtk_widget_queue_draw (priv->header_view);
553         }
554 }
555 static void
556 on_forward_attached_activated (GtkWidget *widget, gpointer user_data)
557 {
558         ModestUI *modest_ui = (ModestUI *)user_data;
559
560         quoted_send_msg (modest_ui, QUOTED_SEND_FORWARD_ATTACHED);
561 }
562
563 static void
564 on_headers_status_update (GtkWidget *header_view, const gchar *msg, gint status_id,
565                           gpointer user_data)
566 {
567         ModestUIPrivate *priv;
568         ModestUI *modest_ui;
569
570         GtkStatusbar *status_bar;
571         GtkProgressBar *progress_bar;
572         GtkWidget    *status_box;
573         
574         modest_ui = MODEST_UI (user_data);
575         priv      = MODEST_UI_GET_PRIVATE(modest_ui);
576
577         progress_bar = GTK_PROGRESS_BAR(glade_xml_get_widget
578                                         (priv->glade_xml, "progressbar"));
579         status_bar   = GTK_STATUSBAR  (glade_xml_get_widget
580                                        (priv->glade_xml, "statusbar"));
581
582         
583         status_box   = glade_xml_get_widget (priv->glade_xml, "statusbox");
584         
585         
586         if (!status_bar || !progress_bar) {
587                 g_warning ("failed to find status / progress bar");
588                 return;
589         }
590
591         if (msg && status_id) {
592                 gtk_widget_show (status_box);
593                 gtk_progress_bar_pulse (progress_bar);
594                 gtk_statusbar_push (status_bar, status_id, msg);
595         } else {
596                 gtk_widget_hide   (status_box);
597                 gtk_statusbar_pop (status_bar, status_id);
598         }
599 }               
600