* Added detection of horizontal-movement and tree view row resolution
[modest] / src / hildon2 / modest-header-window.c
1 /* Copyright (c) 2008, 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
30 #include <modest-header-window.h>
31 #include <modest-osso-state-saving.h>
32 #include <libosso.h>
33 #include <hildon/hildon-pannable-area.h>
34 #include <hildon/hildon-helper.h>
35 #include <modest-window-mgr.h>
36 #include <modest-window-priv.h>
37 #include <modest-signal-mgr.h>
38 #include <modest-runtime.h>
39 #include <modest-platform.h>
40 #include <modest-maemo-utils.h>
41 #include <modest-icon-names.h>
42 #include <modest-ui-constants.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
45 #include <modest-defs.h>
46 #include <modest-widget-memory.h>
47 #include <modest-ui-actions.h>
48 #include <modest-platform.h>
49 #include <modest-text-utils.h>
50 #include <hildon/hildon-button.h>
51 #include <hildon/hildon-program.h>
52 #include <hildon/hildon-banner.h>
53 #include <modest-ui-dimming-rules.h>
54 #include <modest-tny-folder.h>
55 #include <tny-simple-list.h>
56
57 typedef enum {
58         CONTENTS_STATE_NONE = 0,
59         CONTENTS_STATE_EMPTY = 1,
60         CONTENTS_STATE_HEADERS = 2
61 } ContentsState;
62
63 typedef enum {
64         EDIT_MODE_COMMAND_MOVE = 1,
65         EDIT_MODE_COMMAND_DELETE = 2,
66 } EditModeCommand;
67
68 typedef struct _ModestHeaderWindowPrivate ModestHeaderWindowPrivate;
69 struct _ModestHeaderWindowPrivate {
70
71         GtkWidget *header_view;
72         GtkWidget *empty_view;
73         GtkWidget *contents_view;
74         GtkWidget *top_vbox;
75         GtkWidget *new_message_button;
76
77         /* state bar */
78         ContentsState contents_state;
79
80         TnyFolder *folder;
81
82         /* autoscroll */
83         gboolean autoscroll;
84
85         /* banners */
86         GtkWidget *updating_banner;
87         guint updating_banner_timeout;
88
89         /* signals */
90         GSList *sighandlers;
91         gulong queue_change_handler;
92
93         /* progress hint */
94         gboolean progress_hint;
95         gchar *current_store_account;
96
97         /* sort button */
98         GtkWidget *sort_button;
99 };
100 #define MODEST_HEADER_WINDOW_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE((o), \
101                                                                           MODEST_TYPE_HEADER_WINDOW, \
102                                                                           ModestHeaderWindowPrivate))
103
104 /* 'private'/'protected' functions */
105 static void modest_header_window_class_init  (ModestHeaderWindowClass *klass);
106 static void modest_header_window_init        (ModestHeaderWindow *obj);
107 static void modest_header_window_finalize    (GObject *obj);
108
109 static void connect_signals (ModestHeaderWindow *self);
110 static void modest_header_window_disconnect_signals (ModestWindow *self);
111
112 static void setup_menu (ModestHeaderWindow *self);
113 static GtkWidget *create_empty_view (ModestWindow *self);
114 static GtkWidget *create_header_view (ModestWindow *progress_window,
115                                       TnyFolder *folder);
116
117 static void update_view (ModestHeaderWindow *self,
118                          TnyFolderChange *change);
119 static void set_contents_state (ModestHeaderWindow *window, 
120                                 ContentsState state);
121
122 static void on_msg_count_changed (ModestHeaderView *header_view,
123                                   TnyFolder *folder,
124                                   TnyFolderChange *change,
125                                   ModestHeaderWindow *header_window);
126 static void on_header_activated (ModestHeaderView *header_view,
127                                  TnyHeader *header,
128                                  GtkTreePath *path,
129                                  ModestHeaderWindow *header_window);
130 static void on_updating_msg_list (ModestHeaderView *header_view,
131                                   gboolean starting,
132                                   gpointer user_data);
133 static void set_delete_edit_mode (GtkButton *button,
134                                   ModestHeaderWindow *self);
135 static void set_moveto_edit_mode (GtkButton *button,
136                                   ModestHeaderWindow *self);
137 static gboolean on_expose_event(GtkTreeView *header_view,
138                                 GdkEventExpose *event,
139                                 gpointer user_data);
140 static gboolean on_map_event (GtkWidget *widget,
141                               GdkEvent *event,
142                               gpointer userdata);
143 static void on_vertical_movement (HildonPannableArea *area,
144                                   HildonMovementDirection direction,
145                                   gdouble x, gdouble y, gpointer user_data);
146 static void on_queue_changed    (ModestMailOperationQueue *queue,
147                                  ModestMailOperation *mail_op,
148                                  ModestMailOperationQueueNotification type,
149                                  ModestHeaderWindow *self);
150 static void modest_header_window_pack_toolbar (ModestHildon2Window *self,
151                                                GtkPackType pack_type,
152                                                GtkWidget *toolbar);
153 static void edit_mode_changed (ModestHeaderWindow *header_window,
154                                gint edit_mode_id,
155                                gboolean enabled,
156                                ModestHeaderWindow *self);
157 static void on_progress_list_changed (ModestWindowMgr *mgr,
158                                       ModestHeaderWindow *self);
159 static void update_progress_hint (ModestHeaderWindow *self);
160 static void on_sort_column_changed (GtkTreeSortable *treesortable,
161                                     gpointer         user_data);
162 static void update_sort_button (ModestHeaderWindow *self);
163 static void on_horizontal_movement (HildonPannableArea *hildonpannable,
164                                     gint                direction,
165                                     gdouble             initial_x,
166                                     gdouble             initial_y,
167                                     gpointer            user_data);
168
169 /* globals */
170 static GtkWindowClass *parent_class = NULL;
171
172 #define EMPTYVIEW_XALIGN 0.5
173 #define EMPTYVIEW_YALIGN 0.5
174 #define EMPTYVIEW_XSPACE 1.0
175 #define EMPTYVIEW_YSPACE 1.0
176
177
178
179 /************************************************************************/
180
181 GType
182 modest_header_window_get_type (void)
183 {
184         static GType my_type = 0;
185         if (!my_type) {
186                 static const GTypeInfo my_info = {
187                         sizeof(ModestHeaderWindowClass),
188                         NULL,           /* base init */
189                         NULL,           /* base finalize */
190                         (GClassInitFunc) modest_header_window_class_init,
191                         NULL,           /* class finalize */
192                         NULL,           /* class data */
193                         sizeof(ModestHeaderWindow),
194                         1,              /* n_preallocs */
195                         (GInstanceInitFunc) modest_header_window_init,
196                         NULL
197                 };
198                 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
199                                                   "ModestHeaderWindow",
200                                                   &my_info, 0);
201         }
202         return my_type;
203 }
204
205 static void
206 modest_header_window_class_init (ModestHeaderWindowClass *klass)
207 {
208         GObjectClass *gobject_class;
209         gobject_class = (GObjectClass*) klass;
210         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
211         ModestHildon2WindowClass *modest_hildon2_window_class = (ModestHildon2WindowClass *) klass;
212
213         parent_class            = g_type_class_peek_parent (klass);
214         gobject_class->finalize = modest_header_window_finalize;
215
216         g_type_class_add_private (gobject_class, sizeof(ModestHeaderWindowPrivate));
217         
218         modest_window_class->disconnect_signals_func = modest_header_window_disconnect_signals;
219         modest_hildon2_window_class->pack_toolbar_func = modest_header_window_pack_toolbar;
220 }
221
222 static void
223 modest_header_window_init (ModestHeaderWindow *obj)
224 {
225         ModestHeaderWindowPrivate *priv;
226
227         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(obj);
228
229         priv->sighandlers = NULL;
230         
231         priv->header_view = NULL;
232         priv->empty_view = NULL;
233         priv->top_vbox = NULL;
234         priv->contents_view = NULL;
235         priv->contents_state = CONTENTS_STATE_NONE;
236         priv->folder = NULL;
237         priv->updating_banner = NULL;
238         priv->updating_banner_timeout = 0;
239         priv->autoscroll = TRUE;
240         priv->progress_hint = FALSE;
241         priv->queue_change_handler = 0;
242         priv->current_store_account = NULL;
243         priv->sort_button = NULL;
244         priv->new_message_button = NULL;
245         
246         modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
247                                             GTK_WINDOW(obj),
248                                             "applications_email_headerview");
249 }
250
251 static void
252 modest_header_window_finalize (GObject *obj)
253 {
254         ModestHeaderWindowPrivate *priv;
255
256         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(obj);
257
258         g_object_unref (priv->folder);
259         g_object_unref (priv->header_view);
260         g_object_unref (priv->empty_view);
261
262         if (priv->current_store_account) {
263                 g_free (priv->current_store_account);
264                 priv->current_store_account = NULL;
265         }
266
267         /* Sanity check: shouldn't be needed, the window mgr should
268            call this function before */
269         modest_header_window_disconnect_signals (MODEST_WINDOW (obj));  
270
271         if (priv->updating_banner_timeout > 0) {
272                 g_source_remove (priv->updating_banner_timeout);
273                 priv->updating_banner_timeout = 0;
274         }
275         if (priv->updating_banner) {
276                 gtk_widget_destroy (priv->updating_banner);
277                 priv->updating_banner = NULL;
278         }
279
280         G_OBJECT_CLASS(parent_class)->finalize (obj);
281 }
282
283 static void
284 modest_header_window_disconnect_signals (ModestWindow *self)
285 {
286         ModestHeaderWindowPrivate *priv;
287         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(self);
288
289         if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
290                                            priv->queue_change_handler))
291                 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
292                                              priv->queue_change_handler);
293
294         modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
295         priv->sighandlers = NULL;
296
297 }
298
299 static void
300 connect_signals (ModestHeaderWindow *self)
301 {       
302         ModestHeaderWindowPrivate *priv;
303         GtkTreeSortable *sortable;
304         
305         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(self);
306
307         /* header view */
308
309         priv->sighandlers = 
310                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), 
311                                            "msg_count_changed",
312                                            G_CALLBACK(on_msg_count_changed), self);
313         priv->sighandlers =
314                 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT (priv->header_view),
315                                            "header-activated",
316                                            G_CALLBACK (on_header_activated), self);
317         priv->sighandlers = 
318                 modest_signal_mgr_connect (priv->sighandlers,
319                                            G_OBJECT (priv->header_view), 
320                                            "updating-msg-list",
321                                            G_CALLBACK (on_updating_msg_list), 
322                                            self);
323         priv->sighandlers =
324                 modest_signal_mgr_connect (priv->sighandlers,
325                                            G_OBJECT (priv->header_view),
326                                            "expose-event",
327                                            G_CALLBACK (on_expose_event),
328                                            self);
329
330         sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view)));
331
332         priv->sighandlers = 
333                 modest_signal_mgr_connect (priv->sighandlers,
334                                            G_OBJECT (sortable),
335                                            "sort-column-changed",
336                                            G_CALLBACK (on_sort_column_changed),
337                                            self);
338
339         priv->sighandlers =
340                 modest_signal_mgr_connect (priv->sighandlers,
341                                            G_OBJECT (self),
342                                            "map-event",
343                                            G_CALLBACK (on_map_event),
344                                            self);
345
346         priv->sighandlers =
347                 modest_signal_mgr_connect (priv->sighandlers,
348                                            G_OBJECT (priv->contents_view), 
349                                            "vertical-movement", 
350                                            G_CALLBACK (on_vertical_movement), 
351                                            self);
352
353         /* Mail Operation Queue */
354         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
355                                                        G_OBJECT (modest_runtime_get_window_mgr ()),
356                                                        "progress-list-changed",
357                                                        G_CALLBACK (on_progress_list_changed), self);
358         priv->sighandlers =
359                 modest_signal_mgr_connect (priv->sighandlers,
360                                            G_OBJECT (priv->new_message_button),
361                                            "clicked",
362                                            G_CALLBACK (modest_ui_actions_on_new_msg), self);
363
364         /* Pannable area */
365         priv->sighandlers =
366                 modest_signal_mgr_connect (priv->sighandlers,
367                                            (GObject *) priv->contents_view,
368                                            "horizontal-movement",
369                                            G_CALLBACK (on_horizontal_movement),
370                                            self);
371 }
372
373 static void
374 folder_refreshed_cb (ModestMailOperation *mail_op,
375                      TnyFolder *folder,
376                      gpointer user_data)
377 {
378         /* Update the view (folder could be empty) */
379         update_view (MODEST_HEADER_WINDOW (user_data), NULL);
380 }
381
382 static GtkWidget *
383 create_header_view (ModestWindow *self, TnyFolder *folder)
384 {
385         GtkWidget *header_view;
386
387         header_view  = modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_TWOLINES);
388         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), folder,
389                                        TRUE, self, folder_refreshed_cb, self);
390         modest_header_view_set_filter (MODEST_HEADER_VIEW (header_view),
391                                        MODEST_HEADER_VIEW_FILTER_NONE);
392         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(header_view),
393                                       MODEST_CONF_HEADER_VIEW_KEY);
394
395         return header_view;
396 }
397
398 static GtkWidget *
399 create_empty_view (ModestWindow *self)
400 {
401         GtkWidget *viewport = NULL;
402         GtkWidget *label = NULL;
403         GtkWidget *align = NULL;
404         GtkWidget *vbox = NULL;
405         GtkWidget *button = NULL;
406         GdkPixbuf *new_message_pixbuf;
407
408         vbox = gtk_vbox_new (0, FALSE);
409
410         align = gtk_alignment_new(EMPTYVIEW_XALIGN, EMPTYVIEW_YALIGN, EMPTYVIEW_XSPACE, EMPTYVIEW_YSPACE);
411         label = gtk_label_new (_("mcen_ia_nomessages"));
412         hildon_helper_set_logical_font (label, "LargeSystemFont");
413         gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
414         gtk_widget_show (label);
415         gtk_widget_show (align);
416         gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);  
417         gtk_container_add (GTK_CONTAINER (align), label);
418         gtk_box_pack_end (GTK_BOX (vbox), align, TRUE, TRUE, 0);
419
420         button = hildon_button_new (MODEST_EDITABLE_SIZE, 
421                                     HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
422
423         hildon_button_set_title (HILDON_BUTTON (button), _("mcen_ti_new_message"));
424         new_message_pixbuf = modest_platform_get_icon ("general_add", MODEST_ICON_SIZE_BIG);
425         hildon_button_set_image (HILDON_BUTTON (button), 
426                                  gtk_image_new_from_pixbuf (new_message_pixbuf));
427         g_object_unref (new_message_pixbuf);
428         gtk_widget_show_all (button);
429         gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
430
431         gtk_widget_show (vbox);
432
433         g_signal_connect (button,
434                           "clicked",
435                           G_CALLBACK (modest_ui_actions_on_new_msg), self);
436
437         viewport = gtk_viewport_new ((GtkAdjustment *) gtk_adjustment_new (0, 0, 0, 0, 0, 0), 
438                                      (GtkAdjustment *) gtk_adjustment_new (0, 0, 0, 0, 0, 0));
439         gtk_container_add (GTK_CONTAINER (viewport), vbox);
440
441         return viewport;
442 }
443
444 static void
445 on_vertical_movement (HildonPannableArea *area,
446                       HildonMovementDirection direction,
447                       gdouble x, gdouble y, gpointer user_data)
448 {
449         ModestHeaderWindow *self = (ModestHeaderWindow *) user_data;
450         ModestHeaderWindowPrivate *priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
451
452         priv->autoscroll = FALSE;
453 }
454
455
456 ModestWindow *
457 modest_header_window_new (TnyFolder *folder, const gchar *account_name, const gchar *mailbox)
458 {
459         ModestHeaderWindow *self = NULL;        
460         ModestHeaderWindowPrivate *priv = NULL;
461         HildonProgram *app;
462         GdkPixbuf *window_icon;
463         ModestAccountMgr *mgr;
464         ModestAccountSettings *settings = NULL;
465         ModestServerAccountSettings *store_settings = NULL;
466         GtkWidget *action_area_box;
467         GdkPixbuf *new_message_pixbuf;
468         GtkWidget *alignment;
469         gchar *account_display_name = NULL;
470         
471         self  = MODEST_HEADER_WINDOW(g_object_new(MODEST_TYPE_HEADER_WINDOW, NULL));
472         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(self);
473
474         priv->folder = g_object_ref (folder);
475
476         priv->contents_view = hildon_pannable_area_new ();
477         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
478         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
479                                    0, 0,
480                                    HILDON_MARGIN_DOUBLE, HILDON_MARGIN_DOUBLE);
481
482         /* We need to do this here to properly listen for mail
483            operations because create_header_view launches a mail
484            operation */
485         priv->queue_change_handler =
486                 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
487                                   "queue-changed",
488                                   G_CALLBACK (on_queue_changed),
489                                   self);
490
491         priv->header_view  = create_header_view (MODEST_WINDOW (self), folder);
492         priv->empty_view = create_empty_view (MODEST_WINDOW (self));
493
494         /* Transform the floating reference in a "hard" reference. We
495            need to do this because the widgets could be added/removed
496            to containers many times so we always need to keep a
497            reference. It could happen also that some widget is never
498            added to any container */
499         g_object_ref_sink (priv->header_view);
500         g_object_ref_sink (priv->empty_view);
501
502         g_signal_connect (G_OBJECT (self), "edit-mode-changed",
503                           G_CALLBACK (edit_mode_changed), (gpointer) self);
504
505         action_area_box = hildon_tree_view_get_action_area_box (GTK_TREE_VIEW (priv->header_view));
506         priv->new_message_button = hildon_button_new (0, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
507
508         hildon_button_set_title (HILDON_BUTTON (priv->new_message_button), _("mcen_ti_new_message"));
509         new_message_pixbuf = modest_platform_get_icon ("general_add", MODEST_ICON_SIZE_BIG);
510         hildon_button_set_image (HILDON_BUTTON (priv->new_message_button), gtk_image_new_from_pixbuf (new_message_pixbuf));
511         g_object_unref (new_message_pixbuf);
512
513         gtk_box_pack_start (GTK_BOX (action_area_box), priv->new_message_button, TRUE, TRUE, 0);
514         gtk_widget_show_all (priv->new_message_button);
515         hildon_tree_view_set_action_area_visible (GTK_TREE_VIEW (priv->header_view), TRUE);
516         
517         setup_menu (self);
518
519         priv->top_vbox = gtk_vbox_new (FALSE, 0);
520         gtk_container_add (GTK_CONTAINER (alignment), priv->contents_view);
521         gtk_box_pack_end (GTK_BOX (priv->top_vbox), alignment, TRUE, TRUE, 0);
522
523         gtk_container_add (GTK_CONTAINER (self), priv->top_vbox);
524
525         gtk_widget_show (alignment);
526         gtk_widget_show (priv->contents_view);
527         gtk_widget_show (priv->top_vbox);
528
529         connect_signals (MODEST_HEADER_WINDOW (self));
530
531         update_view (self, NULL);
532
533         /* Load previous osso state, for instance if we are being restored from 
534          * hibernation:  */
535         modest_osso_load_state ();
536
537         /* Get device name */
538         modest_maemo_utils_get_device_name ();
539
540         app = hildon_program_get_instance ();
541         hildon_program_add_window (app, HILDON_WINDOW (self));
542
543         /* Set window icon */
544         window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
545         if (window_icon) {
546                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
547                 g_object_unref (window_icon);
548         }
549
550         /* Dont't restore settings here, 
551          * because it requires a gtk_widget_show(), 
552          * and we don't want to do that until later,
553          * so that the UI is not visible for non-menu D-Bus activation.
554          */
555
556         /* setup edit modes */
557         modest_hildon2_window_register_edit_mode (MODEST_HILDON2_WINDOW (self), EDIT_MODE_COMMAND_DELETE,
558                                                   _("mcen_ti_edit_delete"), _HL("wdgt_bd_delete"),
559                                                   GTK_TREE_VIEW (priv->header_view),
560                                                   GTK_SELECTION_MULTIPLE,
561                                                   EDIT_MODE_CALLBACK (modest_ui_actions_on_edit_mode_delete_message));
562         modest_hildon2_window_register_edit_mode (MODEST_HILDON2_WINDOW (self), EDIT_MODE_COMMAND_MOVE,
563                                                   _("mcen_ti_edit_move"), _HL("wdgt_bd_move"),
564                                                   GTK_TREE_VIEW (priv->header_view),
565                                                   GTK_SELECTION_MULTIPLE,
566                                                   EDIT_MODE_CALLBACK (modest_ui_actions_on_edit_mode_move_to));
567
568
569         modest_window_set_active_account (MODEST_WINDOW (self), account_name);
570         modest_window_set_active_mailbox (MODEST_WINDOW (self), mailbox);
571         mgr = modest_runtime_get_account_mgr ();
572         settings = modest_account_mgr_load_account_settings (mgr, account_name);
573         if (settings) {
574                 account_display_name = g_strdup (modest_account_settings_get_display_name (settings));
575                 store_settings = modest_account_settings_get_store_settings (settings);
576                 if (store_settings) {
577                         priv->current_store_account = 
578                                 g_strdup (modest_server_account_settings_get_account_name (store_settings));
579                         g_object_unref (store_settings);
580                 }
581                 g_object_unref (settings);
582         }
583         /* Set window title */
584         if (TNY_IS_FOLDER (folder)) {
585                 gchar *folder_name;
586
587                 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
588                         const gchar *box_name;
589                         box_name = mailbox;
590                         if (box_name == NULL || box_name[0] == '\0') {
591                                 box_name = account_display_name;
592                         }
593                         folder_name = g_strconcat (_("mcen_me_folder_inbox"), " - ", box_name, NULL);
594                 } else {
595                         folder_name = modest_tny_folder_get_display_name (folder);
596                 }
597                 
598                 gtk_window_set_title (GTK_WINDOW (self), folder_name);
599                 g_free (folder_name);
600         }
601         g_free (account_display_name);
602
603
604         update_progress_hint (self);
605         update_sort_button (self);
606
607         return MODEST_WINDOW(self);
608 }
609
610 ModestHeaderView *
611 modest_header_window_get_header_view (ModestHeaderWindow *self)
612 {
613         ModestHeaderWindowPrivate *priv = NULL;
614
615         g_return_val_if_fail (MODEST_IS_HEADER_WINDOW(self), FALSE);
616
617         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
618         
619         return MODEST_HEADER_VIEW (priv->header_view);
620 }
621
622 static void setup_menu (ModestHeaderWindow *self)
623 {
624         ModestHeaderWindowPrivate *priv;
625
626         g_return_if_fail (MODEST_IS_HEADER_WINDOW(self));
627         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
628
629         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_new_message"), "<Control>n",
630                                            APP_MENU_CALLBACK (modest_ui_actions_on_new_msg),
631                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_new_msg));
632         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_move_messages"), NULL,
633                                            APP_MENU_CALLBACK (set_moveto_edit_mode),
634                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_move_to));
635         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_delete_messages"), NULL,
636                                            APP_MENU_CALLBACK (set_delete_edit_mode),
637                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_delete));
638         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_folder_details"), NULL,
639                                            APP_MENU_CALLBACK (modest_ui_actions_on_details),
640                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_details));
641         priv->sort_button = hildon_button_new (MODEST_EDITABLE_SIZE,
642                                                HILDON_BUTTON_ARRANGEMENT_VERTICAL);
643         hildon_button_set_title (HILDON_BUTTON (priv->sort_button), _("mcen_me_sort"));
644         g_signal_connect (G_OBJECT (priv->sort_button), "clicked",
645                           G_CALLBACK (modest_ui_actions_on_sort), (gpointer) self);
646         hildon_button_set_style(HILDON_BUTTON (priv->sort_button), HILDON_BUTTON_STYLE_PICKER);
647         hildon_button_set_title_alignment (HILDON_BUTTON (priv->sort_button), 0.5, 0.5);
648         hildon_button_set_value_alignment (HILDON_BUTTON (priv->sort_button), 0.5, 0.5);
649         modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->sort_button),
650                                                   modest_ui_dimming_rules_on_sort);
651         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_sendandreceive"), NULL,
652                                            APP_MENU_CALLBACK (modest_ui_actions_on_send_receive),
653                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_send_receive));
654         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_outbox_cancelsend"), NULL,
655                                            APP_MENU_CALLBACK (modest_ui_actions_cancel_send),
656                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_cancel_sending_all));
657 }
658
659 static void 
660 update_view (ModestHeaderWindow *self,
661              TnyFolderChange *change)
662 {
663         ModestHeaderWindowPrivate *priv = NULL;
664         gboolean refilter = FALSE;
665         gboolean folder_empty = FALSE;
666         gboolean all_marked_as_deleted = FALSE;
667
668         g_return_if_fail (MODEST_IS_HEADER_WINDOW(self));
669         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
670         g_return_if_fail (priv->folder);
671
672         if (change != NULL) {
673                 TnyFolderChangeChanged changed;
674
675                 changed = tny_folder_change_get_changed (change);
676                 /* If something changes */
677                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
678                         folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
679                 else
680                         folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (priv->folder))) == 0);
681
682                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
683                         refilter = TRUE;
684         } else {
685                 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (priv->folder))) == 0);
686         }
687
688         /* Check if all messages are marked to be deleted */
689         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW (priv->header_view));
690         folder_empty = folder_empty || all_marked_as_deleted;
691
692         /* Set style of headers view */
693         set_contents_state (self, folder_empty?CONTENTS_STATE_EMPTY:CONTENTS_STATE_HEADERS);
694
695         if (refilter)
696                 modest_header_view_refilter (MODEST_HEADER_VIEW (priv->header_view));
697 }
698
699 static void 
700 set_contents_state (ModestHeaderWindow *self, 
701                     ContentsState state)
702 {
703         ModestHeaderWindowPrivate *priv = NULL;
704
705         g_return_if_fail (MODEST_IS_HEADER_WINDOW(self));
706         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
707
708         if (priv->contents_state == state)
709                 return;
710
711         /* Remove from container the old content */
712         switch (priv->contents_state) {
713         case CONTENTS_STATE_EMPTY:
714                 gtk_container_remove (GTK_CONTAINER (priv->contents_view), priv->empty_view);
715                 break;
716         case CONTENTS_STATE_HEADERS:
717                 gtk_container_remove (GTK_CONTAINER (priv->contents_view), priv->header_view);
718                 break;
719         case CONTENTS_STATE_NONE:
720                 break;
721         }
722
723         /* Add the new content */
724         switch (state) {
725         case CONTENTS_STATE_EMPTY:
726                 gtk_container_add (GTK_CONTAINER (priv->contents_view), priv->empty_view);
727                 gtk_widget_show (priv->empty_view);
728                 break;
729         case CONTENTS_STATE_HEADERS:
730                 gtk_container_add (GTK_CONTAINER (priv->contents_view), priv->header_view);
731                 gtk_widget_show (priv->header_view);
732                 break;
733         case CONTENTS_STATE_NONE:
734                 break;
735         }
736         priv->contents_state = state;
737 }
738
739 static void
740 on_msg_count_changed (ModestHeaderView *header_view,
741                       TnyFolder *folder,
742                       TnyFolderChange *change,
743                       ModestHeaderWindow *header_window)
744 {
745         g_return_if_fail (MODEST_IS_HEADER_WINDOW (header_window));
746
747         update_view (MODEST_HEADER_WINDOW (header_window), change);
748 }
749
750 static void 
751 on_header_activated (ModestHeaderView *header_view,
752                      TnyHeader *header,
753                      GtkTreePath *path,
754                      ModestHeaderWindow *header_window)
755 {
756         modest_ui_actions_on_header_activated (header_view, header, path, MODEST_WINDOW (header_window));
757 }
758
759 static void
760 updating_banner_destroyed (gpointer data,
761                            GObject *where_the_object_was)
762 {
763         ModestHeaderWindowPrivate *priv = NULL;
764
765         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (data);
766
767         priv->updating_banner = NULL;
768 }
769
770 static gboolean
771 show_updating_banner (gpointer user_data)
772 {
773         ModestHeaderWindowPrivate *priv = NULL;
774
775         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (user_data);
776
777         if (priv->updating_banner == NULL) {
778
779                 /* We're outside the main lock */
780                 gdk_threads_enter ();
781                 priv->updating_banner = 
782                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
783                                                           _CS ("ckdg_pb_updating"));
784
785                 /* We need this because banners in Maemo could be
786                    destroyed by dialogs so we need to properly update
787                    our reference to it */
788                 g_object_weak_ref (G_OBJECT (priv->updating_banner),
789                                    updating_banner_destroyed,
790                                    user_data);
791                 gdk_threads_leave ();
792         }
793
794         /* Remove timeout */
795         priv->updating_banner_timeout = 0;
796         return FALSE;
797 }
798
799 /**
800  * We use this function to show/hide a progress banner showing
801  * "Updating" while the header view is being filled. We're not showing
802  * it unless the update takes more than 2 seconds
803  *
804  * If starting = TRUE then the refresh is starting, otherwise it means
805  * that is has just finished
806  */
807 static void 
808 on_updating_msg_list (ModestHeaderView *header_view,
809                       gboolean starting,
810                       gpointer user_data)
811 {
812         ModestHeaderWindowPrivate *priv = NULL;
813
814         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (user_data);
815         
816         /* Remove old timeout */
817         if (priv->updating_banner_timeout > 0) {
818                 g_source_remove (priv->updating_banner_timeout);
819                 priv->updating_banner_timeout = 0;
820         }
821
822         /* Create a new timeout */
823         if (starting) {
824                 priv->updating_banner_timeout = 
825                         g_timeout_add (2000, show_updating_banner, user_data);
826         } else {
827                 /* Remove the banner if exists */
828                 if (priv->updating_banner) {
829                         gtk_widget_destroy (priv->updating_banner);
830                         priv->updating_banner = NULL;
831                 }
832         }
833 }
834
835 static void
836 set_delete_edit_mode (GtkButton *button,
837                       ModestHeaderWindow *self)
838 {
839         modest_hildon2_window_set_edit_mode (MODEST_HILDON2_WINDOW (self), EDIT_MODE_COMMAND_DELETE);
840 }
841
842 static void
843 set_moveto_edit_mode (GtkButton *button,
844                     ModestHeaderWindow *self)
845 {
846         modest_hildon2_window_set_edit_mode (MODEST_HILDON2_WINDOW (self), EDIT_MODE_COMMAND_MOVE);
847 }
848
849 static gboolean 
850 on_expose_event(GtkTreeView *header_view,
851                 GdkEventExpose *event,
852                 gpointer user_data)
853 {
854         ModestHeaderWindow *self = (ModestHeaderWindow *) user_data;
855         ModestHeaderWindowPrivate *priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
856
857         g_return_val_if_fail (MODEST_IS_HEADER_WINDOW (self), FALSE);
858
859         if (priv->autoscroll)
860                 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (priv->contents_view), 0.0, 0.0);
861
862         return FALSE;
863 }
864
865 static gboolean 
866 on_map_event(GtkWidget *widget,
867              GdkEvent *event,
868              gpointer user_data)
869 {
870         ModestHeaderWindow *self = (ModestHeaderWindow *) user_data;
871         ModestHeaderWindowPrivate *priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
872
873         g_return_val_if_fail (MODEST_IS_HEADER_WINDOW (self), FALSE);
874
875         if (priv->progress_hint) {
876                 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
877         }
878         return FALSE;
879 }
880
881 static void
882 on_progress_list_changed (ModestWindowMgr *mgr,
883                           ModestHeaderWindow *self)
884 {
885         update_progress_hint (self);
886 }
887
888 static gboolean
889 has_active_operations (ModestHeaderWindow *self)
890 {
891         GSList *operations = NULL, *node;
892         ModestMailOperationQueue *queue;
893         gboolean has_active = FALSE;
894
895         queue = modest_runtime_get_mail_operation_queue ();
896         operations = modest_mail_operation_queue_get_by_source (queue, G_OBJECT (self));
897
898         for (node = operations; node != NULL; node = g_slist_next (node)) {
899                 if (!modest_mail_operation_is_finished (MODEST_MAIL_OPERATION (node->data))) {
900                         has_active = TRUE;
901                         break;
902                 }
903         }
904
905         if (operations) {
906                 g_slist_foreach (operations, (GFunc) g_object_unref, NULL);
907                 g_slist_free (operations);
908         }
909
910         return has_active;
911 }
912
913 static void
914 update_progress_hint (ModestHeaderWindow *self)
915 {
916         ModestHeaderWindowPrivate *priv;
917
918         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
919
920         priv->progress_hint = FALSE;
921
922         if (has_active_operations (self)) {
923                 priv->progress_hint = TRUE;
924         } else {
925                 priv->progress_hint = FALSE;
926         }
927
928         if (!priv->progress_hint && priv->current_store_account) {
929                 priv->progress_hint = 
930                         modest_window_mgr_has_progress_operation_on_account (modest_runtime_get_window_mgr (),
931                                                                              priv->current_store_account);
932         }
933
934         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
935
936         if (GTK_WIDGET_VISIBLE (self)) {
937                 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), priv->progress_hint?1:0);
938         }
939 }
940
941 gboolean
942 modest_header_window_toolbar_on_transfer_mode     (ModestHeaderWindow *self)
943 {
944         ModestHeaderWindowPrivate *priv= NULL; 
945
946         g_return_val_if_fail (MODEST_IS_HEADER_WINDOW (self), FALSE);
947         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
948
949         return priv->progress_hint;
950 }
951
952 gboolean 
953 modest_header_window_transfer_mode_enabled (ModestHeaderWindow *self)
954 {
955         ModestHeaderWindowPrivate *priv;
956         
957         g_return_val_if_fail (MODEST_IS_HEADER_WINDOW (self), FALSE);   
958         priv = MODEST_HEADER_WINDOW_GET_PRIVATE(self);
959
960         return priv->progress_hint;
961 }
962
963 static void 
964 on_mail_operation_started (ModestMailOperation *mail_op,
965                            gpointer user_data)
966 {
967         ModestHeaderWindow *self;
968         ModestMailOperationTypeOperation op_type;
969         GObject *source = NULL;
970
971         self = MODEST_HEADER_WINDOW (user_data);
972         op_type = modest_mail_operation_get_type_operation (mail_op);
973         source = modest_mail_operation_get_source(mail_op);
974         if (G_OBJECT (self) == source) {
975                 update_progress_hint (self);
976         }
977         g_object_unref (source);
978 }
979
980 static void 
981 on_mail_operation_finished (ModestMailOperation *mail_op,
982                             gpointer user_data)
983 {
984         ModestHeaderWindow *self;
985
986         self = MODEST_HEADER_WINDOW (user_data);
987
988         /* Don't disable the progress hint if there are more pending
989            operations from this window */
990         update_progress_hint (self);
991
992         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
993 }
994
995 static void
996 on_queue_changed (ModestMailOperationQueue *queue,
997                   ModestMailOperation *mail_op,
998                   ModestMailOperationQueueNotification type,
999                   ModestHeaderWindow *self)
1000 {
1001         ModestHeaderWindowPrivate *priv;
1002
1003         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
1004
1005         /* If this operations was created by another window, do nothing */
1006         if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self))) 
1007                 return;
1008
1009         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
1010                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1011                                                                G_OBJECT (mail_op),
1012                                                                "operation-started",
1013                                                                G_CALLBACK (on_mail_operation_started),
1014                                                                self);
1015                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1016                                                                G_OBJECT (mail_op),
1017                                                                "operation-finished",
1018                                                                G_CALLBACK (on_mail_operation_finished),
1019                                                                self);
1020         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
1021                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1022                                                                   G_OBJECT (mail_op),
1023                                                                   "operation-started");
1024                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1025                                                                   G_OBJECT (mail_op),
1026                                                                   "operation-finished");
1027         }
1028 }
1029
1030 static void
1031 modest_header_window_pack_toolbar (ModestHildon2Window *self,
1032                                    GtkPackType pack_type,
1033                                    GtkWidget *toolbar)
1034 {
1035         ModestHeaderWindowPrivate *priv;
1036
1037         g_return_if_fail (MODEST_IS_HEADER_WINDOW (self));
1038         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
1039
1040         if (pack_type == GTK_PACK_START) {
1041                 gtk_box_pack_start (GTK_BOX (priv->top_vbox), toolbar, FALSE, FALSE, 0);
1042         } else {
1043                 gtk_box_pack_end (GTK_BOX (priv->top_vbox), toolbar, FALSE, FALSE, 0);
1044         }
1045 }
1046
1047 static void 
1048 edit_mode_changed (ModestHeaderWindow *header_window,
1049                    gint edit_mode_id,
1050                    gboolean enabled,
1051                    ModestHeaderWindow *self)
1052 {
1053         ModestHeaderWindowPrivate *priv;
1054         ModestHeaderViewFilter filter = MODEST_HEADER_VIEW_FILTER_NONE;
1055
1056         g_return_if_fail (MODEST_IS_HEADER_WINDOW (self));
1057         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
1058
1059         switch (edit_mode_id) {
1060         case EDIT_MODE_COMMAND_MOVE:
1061                 filter = MODEST_HEADER_VIEW_FILTER_MOVEABLE;
1062                 break;
1063         case EDIT_MODE_COMMAND_DELETE:
1064                 filter = MODEST_HEADER_VIEW_FILTER_DELETABLE;
1065                 break;
1066         case MODEST_HILDON2_WINDOW_EDIT_MODE_NONE:
1067                 filter = MODEST_HEADER_VIEW_FILTER_NONE;
1068                 break;
1069         }
1070
1071         hildon_tree_view_set_action_area_visible (GTK_TREE_VIEW (priv->header_view), !enabled);
1072         if (enabled) {
1073                 modest_header_view_set_filter (MODEST_HEADER_VIEW (priv->header_view), 
1074                                                filter);
1075         } else {
1076                 GtkTreeSelection *sel;
1077
1078                 /* Unselect all. This will prevent us from keeping a
1079                    reference to a TnyObject that we don't want to
1080                    have */
1081                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1082                 gtk_tree_selection_unselect_all (sel);
1083
1084                 modest_header_view_unset_filter (MODEST_HEADER_VIEW (priv->header_view), 
1085                                                  filter);
1086         }
1087 }
1088
1089 static void 
1090 on_sort_column_changed (GtkTreeSortable *treesortable,
1091                         gpointer         user_data)
1092 {
1093         update_sort_button (MODEST_HEADER_WINDOW (user_data));
1094 }
1095
1096 static void
1097 update_sort_button (ModestHeaderWindow *self)
1098 {
1099         ModestHeaderWindowPrivate *priv;
1100         GtkTreeSortable *sortable;
1101         gint current_sort_colid = -1;
1102         GtkSortType current_sort_type;
1103         const gchar *value = NULL;
1104
1105         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (self);
1106         sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view)));
1107
1108         if (!gtk_tree_sortable_get_sort_column_id (sortable,
1109                                                    &current_sort_colid, &current_sort_type)) {
1110                 value =  _("mcen_li_sort_sender_date_newest");
1111         } else {
1112                 switch (current_sort_colid) {
1113                 case TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN:
1114                 {
1115                         GList *cols = NULL;
1116                         cols = modest_header_view_get_columns (MODEST_HEADER_VIEW (priv->header_view));
1117                         if (cols != NULL) {
1118                                 gpointer flags_sort_type_pointer;
1119                                 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), 
1120                                                                              MODEST_HEADER_VIEW_FLAG_SORT);
1121                                 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
1122                                         value = _("mcen_li_sort_priority");
1123                                 else
1124                                         value = _("mcen_li_sort_attachment");
1125                                 g_list_free(cols);      
1126                         }
1127                 } 
1128                 break;
1129                 case TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN:
1130                 case TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN:
1131                         if (current_sort_type == GTK_SORT_ASCENDING)
1132                                 value = _("mcen_li_sort_sender_recipient_az");
1133                         else
1134                                 value = _("mcen_li_sort_sender_recipient_za");
1135                         break;
1136                 case TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN:
1137                 case TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN:
1138                         if (current_sort_type == GTK_SORT_ASCENDING)
1139                                 value = _("mcen_li_sort_date_oldest");
1140                         else
1141                                 value = _("mcen_li_sort_date_newest");
1142                         break;
1143                 case TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN:
1144                         if (current_sort_type == GTK_SORT_ASCENDING)
1145                                 value = _("mcen_li_sort_subject_az");
1146                         else
1147                                 value = _("mcen_li_sort_subject_za");
1148                         break;
1149                 case TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN:
1150                         if (current_sort_type == GTK_SORT_ASCENDING)
1151                                 value = _("mcen_li_sort_size_smallest");
1152                         else
1153                                 value = _("mcen_li_sort_size_largest");
1154                         break;
1155                 } 
1156         }
1157
1158         hildon_button_set_value (HILDON_BUTTON (priv->sort_button), value?value:"");
1159 }
1160
1161 static void
1162 on_horizontal_movement (HildonPannableArea *hildonpannable,
1163                         gint                direction,
1164                         gdouble             initial_x,
1165                         gdouble             initial_y,
1166                         gpointer            user_data)
1167 {
1168         ModestHeaderWindowPrivate *priv;
1169         gint dest_x, dest_y;
1170         TnyHeader *header;
1171
1172         /* Ignore right to left movement */
1173         if (direction == HILDON_MOVEMENT_LEFT)
1174                 return;
1175
1176         /* Get the header to delete */
1177         priv = MODEST_HEADER_WINDOW_GET_PRIVATE (user_data);
1178
1179         /* Get tree view coordinates */
1180         if (!gtk_widget_translate_coordinates ((GtkWidget *) hildonpannable,
1181                                                priv->header_view,
1182                                                initial_x,
1183                                                initial_y,
1184                                                &dest_x,
1185                                                &dest_y))
1186             return;
1187
1188         header = modest_header_view_get_header_at_pos ((ModestHeaderView *) priv->header_view,
1189                                                        dest_x, dest_y);
1190         if (header) {
1191                 gint response;
1192                 gchar *subject, *msg;
1193
1194                 subject = tny_header_dup_subject (header);
1195                 if (!subject)
1196                         subject = g_strdup (_("mail_va_no_subject"));
1197
1198                 msg = g_strdup_printf (ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 1),
1199                                        subject);
1200                 g_free (subject);
1201
1202                 /* Confirmation dialog */
1203                 response = modest_platform_run_confirmation_dialog ((GtkWindow *) user_data, msg);
1204                 g_free (msg);
1205
1206                 if (response == GTK_RESPONSE_OK) {
1207                         ModestMailOperation *mail_op;
1208                         TnyList *header_list;
1209
1210                         header_list = tny_simple_list_new ();
1211                         tny_list_append (header_list, (GObject *) header);
1212                         mail_op = modest_mail_operation_new ((GObject *) user_data);
1213                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1214                                                          mail_op);
1215                         modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
1216                         g_object_unref (mail_op);
1217                         g_object_unref (header_list);
1218                 }
1219                 g_object_unref (header);
1220         }
1221 }