version and bug fix info update for week 46, 2009 - second release
[modest] / src / hildon2 / modest-accounts-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-accounts-window.h>
31 #include <hildon/hildon-pannable-area.h>
32 #include <hildon/hildon-banner.h>
33 #include <hildon/hildon-helper.h>
34 #include <modest-ui-actions.h>
35 #include <modest-window-mgr.h>
36 #include <modest-signal-mgr.h>
37 #include <modest-runtime.h>
38 #include <modest-platform.h>
39 #include <hildon/hildon-program.h>
40 #include <hildon/hildon-button.h>
41 #include <modest-maemo-utils.h>
42 #include <modest-icon-names.h>
43 #include <modest-defs.h>
44 #include <modest-folder-window.h>
45 #include <modest-ui-dimming-rules.h>
46 #include <modest-ui-dimming-manager.h>
47 #include <modest-window-priv.h>
48 #include <modest-ui-constants.h>
49 #include <modest-account-mgr-helpers.h>
50 #include <modest-mailboxes-window.h>
51
52
53 /* 'private'/'protected' functions */
54 static void modest_accounts_window_class_init  (ModestAccountsWindowClass *klass);
55 static void modest_accounts_window_instance_init (ModestAccountsWindow *obj);
56 static void modest_accounts_window_finalize    (GObject *obj);
57
58 static void connect_signals (ModestAccountsWindow *self);
59 static void modest_accounts_window_disconnect_signals (ModestWindow *self);
60
61 static void on_account_activated (GtkTreeView *treeview,
62                                   GtkTreePath *path,
63                                   GtkTreeViewColumn *column,
64                                   ModestAccountsWindow *accounts_window);
65 static void on_progress_list_changed (ModestWindowMgr *mgr,
66                                       ModestAccountsWindow *self);
67 static void setup_menu (ModestAccountsWindow *self);
68 static gboolean _modest_accounts_window_map_event (GtkWidget *widget,
69                                                    GdkEvent *event,
70                                                    gpointer userdata);
71 static void update_progress_hint (ModestAccountsWindow *self);
72 static void on_queue_changed    (ModestMailOperationQueue *queue,
73                                  ModestMailOperation *mail_op,
74                                  ModestMailOperationQueueNotification type,
75                                  ModestAccountsWindow *self);
76 static void on_row_inserted (GtkTreeModel *tree_model,
77                              GtkTreePath  *path,
78                              GtkTreeIter  *iter,
79                              gpointer      user_data);
80 static void on_row_deleted (GtkTreeModel *tree_model,
81                             GtkTreePath  *path,
82                             gpointer      user_data);
83 static void row_count_changed (ModestAccountsWindow *self);
84 static gboolean on_key_press(GtkWidget *widget,
85                                 GdkEventKey *event,
86                                 gpointer user_data);
87
88 typedef struct _ModestAccountsWindowPrivate ModestAccountsWindowPrivate;
89 struct _ModestAccountsWindowPrivate {
90
91         GtkWidget *box;
92         GtkWidget *pannable;
93         GtkWidget *account_view;
94         GtkWidget *no_accounts_container;
95         GtkWidget *new_message_button;
96
97         /* signals */
98         GSList *sighandlers;
99
100         gboolean progress_hint;
101         guint queue_change_handler;
102 };
103 #define MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE((o), \
104                                                                             MODEST_TYPE_ACCOUNTS_WINDOW, \
105                                                                             ModestAccountsWindowPrivate))
106
107 /* globals */
108 static GtkWindowClass *parent_class = NULL;
109 static GtkWidget *pre_created_accounts_window = NULL;
110
111 /************************************************************************/
112
113 GType
114 modest_accounts_window_get_type (void)
115 {
116         static GType my_type = 0;
117         if (!my_type) {
118                 static const GTypeInfo my_info = {
119                         sizeof(ModestAccountsWindowClass),
120                         NULL,           /* base init */
121                         NULL,           /* base finalize */
122                         (GClassInitFunc) modest_accounts_window_class_init,
123                         NULL,           /* class finalize */
124                         NULL,           /* class data */
125                         sizeof(ModestAccountsWindow),
126                         1,              /* n_preallocs */
127                         (GInstanceInitFunc) modest_accounts_window_instance_init,
128                         NULL
129                 };
130                 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
131                                                   "ModestAccountsWindow",
132                                                   &my_info, 0);
133         }
134         return my_type;
135 }
136
137 static void
138 modest_accounts_window_class_init (ModestAccountsWindowClass *klass)
139 {
140         GObjectClass *gobject_class;
141         gobject_class = (GObjectClass*) klass;
142         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
143
144         parent_class            = g_type_class_peek_parent (klass);
145         gobject_class->finalize = modest_accounts_window_finalize;
146
147         g_type_class_add_private (gobject_class, sizeof(ModestAccountsWindowPrivate));
148         
149         modest_window_class->disconnect_signals_func = modest_accounts_window_disconnect_signals;
150 }
151
152 static void
153 modest_accounts_window_instance_init (ModestAccountsWindow *obj)
154 {
155         ModestAccountsWindowPrivate *priv;
156
157         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(obj);
158
159         priv->sighandlers = NULL;
160         
161         priv->account_view = NULL;
162         priv->progress_hint = FALSE;
163         
164         modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
165                                             GTK_WINDOW(obj),
166                                             "applications_email_accountsview");
167 }
168
169 static void
170 modest_accounts_window_finalize (GObject *obj)
171 {
172         ModestAccountsWindowPrivate *priv;
173
174         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(obj);
175
176         /* Sanity check: shouldn't be needed, the window mgr should
177            call this function before */
178         modest_accounts_window_disconnect_signals (MODEST_WINDOW (obj));        
179
180         G_OBJECT_CLASS(parent_class)->finalize (obj);
181 }
182
183 static void
184 modest_accounts_window_disconnect_signals (ModestWindow *self)
185 {       
186         ModestAccountsWindowPrivate *priv;      
187         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(self);
188
189         if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
190                                            priv->queue_change_handler))
191                 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
192                                              priv->queue_change_handler);
193
194         modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
195         priv->sighandlers = NULL;       
196 }
197
198 static void
199 connect_signals (ModestAccountsWindow *self)
200 {
201         ModestAccountsWindowPrivate *priv;
202         GtkTreeModel *model;
203
204         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(self);
205
206         /* accounts view */
207         priv->sighandlers = 
208                 modest_signal_mgr_connect (priv->sighandlers,
209                                            G_OBJECT (priv->account_view), "row-activated", 
210                                            G_CALLBACK (on_account_activated), self);
211
212         priv->sighandlers = 
213                 modest_signal_mgr_connect (priv->sighandlers,
214                                            G_OBJECT (modest_runtime_get_window_mgr ()),
215                                            "progress-list-changed",
216                                            G_CALLBACK (on_progress_list_changed), self);
217
218         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->account_view));
219
220         priv->sighandlers =
221                 modest_signal_mgr_connect (priv->sighandlers,
222                                            G_OBJECT (model),
223                                            "row-inserted",
224                                            G_CALLBACK (on_row_inserted), self);
225
226         priv->sighandlers =
227                 modest_signal_mgr_connect (priv->sighandlers,
228                                            G_OBJECT (model),
229                                            "row-deleted",
230                                            G_CALLBACK (on_row_deleted), self);
231
232         priv->sighandlers = 
233                 modest_signal_mgr_connect (priv->sighandlers,
234                                            G_OBJECT (priv->new_message_button),
235                                            "clicked",
236                                            G_CALLBACK (modest_ui_actions_on_new_msg), self);
237
238         /* we don't register this in sighandlers, as it should be run
239          * after disconnecting all signals, in destroy stage */
240
241
242         g_signal_connect(G_OBJECT(self), "key-press-event",
243                         G_CALLBACK(on_key_press), self);
244 }
245
246 static ModestWindow *
247 modest_accounts_window_new_real (void)
248 {
249         ModestAccountsWindow *self = NULL;
250         ModestAccountsWindowPrivate *priv = NULL;
251         GdkPixbuf *window_icon;
252         GdkPixbuf *new_message_pixbuf;
253         guint accel_key;
254         GdkModifierType accel_mods;
255         GtkAccelGroup *accel_group;
256         GtkWidget *no_accounts_label;
257         GtkWidget *empty_view_new_message_button;
258         GtkWidget *box_alignment;
259
260         self  = MODEST_ACCOUNTS_WINDOW(g_object_new(MODEST_TYPE_ACCOUNTS_WINDOW, NULL));
261         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(self);
262
263         new_message_pixbuf = modest_platform_get_icon ("general_add", MODEST_ICON_SIZE_BIG);
264
265         box_alignment = gtk_alignment_new (0, 0, 1.0, 1.0);
266         gtk_alignment_set_padding (GTK_ALIGNMENT (box_alignment), 
267                                    HILDON_MARGIN_HALF, 0,
268                                    HILDON_MARGIN_DOUBLE, HILDON_MARGIN_DOUBLE);
269         priv->box = gtk_vbox_new (FALSE, 0);
270
271         no_accounts_label = gtk_label_new (_("mcen_ia_noaccounts"));
272         
273         gtk_misc_set_alignment (GTK_MISC (no_accounts_label), 0.5, 0.5);
274         hildon_helper_set_logical_font (no_accounts_label, "LargeSystemFont");
275
276         empty_view_new_message_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
277         hildon_button_set_title (HILDON_BUTTON (empty_view_new_message_button), _("mcen_ti_new_message"));
278         hildon_button_set_image (HILDON_BUTTON (empty_view_new_message_button), gtk_image_new_from_pixbuf (new_message_pixbuf));
279
280
281         priv->no_accounts_container = gtk_vbox_new (FALSE, 0);
282         gtk_box_pack_start (GTK_BOX (priv->no_accounts_container), empty_view_new_message_button, FALSE, FALSE, 0);
283         gtk_widget_show_all (empty_view_new_message_button);
284         gtk_box_pack_end (GTK_BOX (priv->no_accounts_container), no_accounts_label, TRUE, TRUE, 0);
285         gtk_widget_show (no_accounts_label);
286         gtk_box_pack_start (GTK_BOX (priv->box), priv->no_accounts_container, TRUE, TRUE, 0);
287
288         g_signal_connect (G_OBJECT (empty_view_new_message_button),
289                           "clicked",
290                           G_CALLBACK (modest_ui_actions_on_new_msg), self);
291         
292         priv->pannable = hildon_pannable_area_new ();
293
294         priv->queue_change_handler =
295                 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
296                                   "queue-changed",
297                                   G_CALLBACK (on_queue_changed),
298                                   self);
299
300         priv->new_message_button = hildon_button_new (MODEST_EDITABLE_SIZE,
301                                                       HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
302
303         hildon_button_set_title (HILDON_BUTTON (priv->new_message_button), _("mcen_ti_new_message"));
304         hildon_button_set_image (HILDON_BUTTON (priv->new_message_button), gtk_image_new_from_pixbuf (new_message_pixbuf));
305
306         gtk_widget_show_all (priv->new_message_button);
307
308         g_object_unref (new_message_pixbuf);
309         setup_menu (self);
310
311         gtk_box_pack_start (GTK_BOX (priv->box), priv->pannable, TRUE, TRUE, 0);
312         gtk_container_add (GTK_CONTAINER (box_alignment), priv->box);
313         gtk_container_add (GTK_CONTAINER (self), box_alignment);
314
315         gtk_widget_show (priv->pannable);
316         gtk_widget_show (priv->box);
317         gtk_widget_show (box_alignment);
318
319         /* Get device name */
320         modest_maemo_utils_get_device_name ();
321
322         /* Set window icon */
323         window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
324         if (window_icon) {
325                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
326                 g_object_unref (window_icon);
327         }
328
329         accel_group = gtk_accel_group_new ();
330         gtk_accelerator_parse ("<Control>n", &accel_key, &accel_mods);
331         gtk_widget_add_accelerator (priv->new_message_button, "clicked", accel_group,
332                                     accel_key, accel_mods, 0);
333         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
334
335         return MODEST_WINDOW(self);
336 }
337
338 ModestWindow *
339 modest_accounts_window_new (void)
340 {
341         GtkWidget *action_area_box;
342         ModestWindow *self;
343         ModestAccountsWindowPrivate *priv = NULL;
344         HildonProgram *app;
345
346         if (pre_created_accounts_window) {
347                 self = MODEST_WINDOW (pre_created_accounts_window);
348                 pre_created_accounts_window = NULL;
349         } else {
350                 self = modest_accounts_window_new_real ();
351         }
352         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(self);
353         priv->account_view  = GTK_WIDGET (modest_account_view_new (modest_runtime_get_account_mgr ()));
354
355         action_area_box = hildon_tree_view_get_action_area_box (GTK_TREE_VIEW (priv->account_view));
356         gtk_box_pack_start (GTK_BOX (action_area_box), priv->new_message_button, TRUE, TRUE, 0);
357         hildon_tree_view_set_action_area_visible (GTK_TREE_VIEW (priv->account_view), TRUE);
358         gtk_container_add (GTK_CONTAINER (priv->pannable), priv->account_view);
359
360         connect_signals (MODEST_ACCOUNTS_WINDOW (self));
361
362         app = hildon_program_get_instance ();
363         hildon_program_add_window (app, HILDON_WINDOW (self));
364         
365         /* Dont't restore settings here, 
366          * because it requires a gtk_widget_show(), 
367          * and we don't want to do that until later,
368          * so that the UI is not visible for non-menu D-Bus activation.
369          */
370
371         g_signal_connect (G_OBJECT (self), "map-event",
372                           G_CALLBACK (_modest_accounts_window_map_event),
373                           G_OBJECT (self));
374         update_progress_hint (MODEST_ACCOUNTS_WINDOW (self));
375
376         row_count_changed (MODEST_ACCOUNTS_WINDOW (self));
377
378         gtk_window_set_title (GTK_WINDOW (self), _("mcen_ap_name"));
379
380         return self;
381 }
382
383
384 ModestAccountView *
385 modest_accounts_window_get_account_view (ModestAccountsWindow *self)
386 {
387         ModestAccountsWindowPrivate *priv = NULL;
388
389         g_return_val_if_fail (MODEST_IS_ACCOUNTS_WINDOW(self), FALSE);
390
391         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
392         
393         return MODEST_ACCOUNT_VIEW (priv->account_view);
394 }
395
396 static void 
397 setup_menu (ModestAccountsWindow *self)
398 {
399         g_return_if_fail (MODEST_IS_ACCOUNTS_WINDOW(self));
400
401         /* Settings menu buttons */
402         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_new_account"), NULL, 
403                                            APP_MENU_CALLBACK (modest_ui_actions_on_new_account), 
404                                            NULL);
405         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self),
406                                            dngettext(GETTEXT_PACKAGE,
407                                                      "mcen_me_edit_account",
408                                                      "mcen_me_edit_accounts",
409                                                      2),
410                                            NULL,
411                                            APP_MENU_CALLBACK (modest_ui_actions_on_accounts), 
412                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_edit_accounts));
413         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_globalsmtpservers"), NULL,
414                                            APP_MENU_CALLBACK (modest_ui_actions_on_smtp_servers),
415                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_tools_smtp_servers));
416         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_sendandreceive"), NULL,
417                                            APP_MENU_CALLBACK (modest_ui_actions_on_send_receive),
418                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_send_receive_all));
419         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_outbox_cancelsend"), NULL,
420                                            APP_MENU_CALLBACK (modest_ui_actions_cancel_send),
421                                            MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_cancel_sending_all));
422         modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_options"), NULL,
423                                            APP_MENU_CALLBACK (modest_ui_actions_on_settings), 
424                                            NULL);
425 }
426
427
428 static void
429 on_account_activated (GtkTreeView *account_view,
430                       GtkTreePath *path,
431                       GtkTreeViewColumn *column,
432                       ModestAccountsWindow *self)
433 {
434         ModestAccountsWindowPrivate *priv;
435         gchar* account_name; 
436         GtkWidget *new_window;
437         gboolean registered;
438         ModestProtocolType store_protocol;
439         gboolean mailboxes_protocol;
440
441         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
442
443         account_name = modest_account_view_get_path_account (MODEST_ACCOUNT_VIEW (priv->account_view), path);
444         if (!account_name)
445                 return;
446
447         /* If it's a multimailbox container, we have to show the mailboxes window */
448         store_protocol = modest_account_mgr_get_store_protocol (modest_runtime_get_account_mgr (), 
449                                                                 account_name);
450         mailboxes_protocol = 
451                 modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
452                                                                 store_protocol,
453                                                                 MODEST_PROTOCOL_REGISTRY_MULTI_MAILBOX_PROVIDER_PROTOCOLS);
454         if (mailboxes_protocol) {
455                 new_window = GTK_WIDGET (modest_mailboxes_window_new (account_name));
456         } else {
457
458                 new_window = GTK_WIDGET (modest_folder_window_new (NULL));
459         }
460
461         registered = modest_window_mgr_register_window (modest_runtime_get_window_mgr (), 
462                                                         MODEST_WINDOW (new_window),
463                                                         MODEST_WINDOW (self));
464
465         if (!registered) {
466                 gtk_widget_destroy (new_window);
467                 new_window = NULL;
468         } else {
469                 if (!mailboxes_protocol) {
470                         modest_folder_window_set_account (MODEST_FOLDER_WINDOW (new_window), account_name);
471                 }
472                 gtk_widget_show (new_window);
473         }
474         g_free (account_name);
475 }
476
477 static gboolean
478 _modest_accounts_window_map_event (GtkWidget *widget,
479                                    GdkEvent *event,
480                                    gpointer userdata)
481 {
482         ModestAccountsWindow *self = (ModestAccountsWindow *) userdata;
483         ModestAccountsWindowPrivate *priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
484
485         if (priv->progress_hint) {
486                 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
487         }
488
489         return FALSE;
490 }
491
492 static gboolean
493 has_active_operations (ModestAccountsWindow *self)
494 {
495         GSList *operations = NULL, *node;
496         ModestMailOperationQueue *queue;
497         gboolean has_active = FALSE;
498
499         queue = modest_runtime_get_mail_operation_queue ();
500         operations = modest_mail_operation_queue_get_by_source (queue, G_OBJECT (self));
501
502         for (node = operations; node != NULL; node = g_slist_next (node)) {
503                 if (!modest_mail_operation_is_finished (MODEST_MAIL_OPERATION (node->data))) {
504                         has_active = TRUE;
505                         break;
506                 }
507         }
508
509         if (operations) {
510                 g_slist_foreach (operations, (GFunc) g_object_unref, NULL);
511                 g_slist_free (operations);
512         }
513
514         return has_active;
515 }
516
517 static void
518 update_progress_hint (ModestAccountsWindow *self)
519 {
520         ModestAccountsWindowPrivate *priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
521
522         if (has_active_operations (self)) {
523                 priv->progress_hint = TRUE;
524         } else {
525                 priv->progress_hint = FALSE;
526         }
527
528         if (!priv->progress_hint) {
529                 priv->progress_hint = modest_window_mgr_has_progress_operation (modest_runtime_get_window_mgr ());
530         }
531         
532         if (GTK_WIDGET_VISIBLE (self)) {
533                 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), priv->progress_hint?1:0);
534         }
535 }
536
537 static void
538 on_progress_list_changed (ModestWindowMgr *mgr,
539                           ModestAccountsWindow *self)
540 {
541         update_progress_hint (self);
542 }
543
544 static void
545 on_row_inserted (GtkTreeModel *tree_model,
546                  GtkTreePath  *path,
547                  GtkTreeIter  *iter,
548                  gpointer      user_data)
549 {
550         ModestAccountsWindow *self;
551
552         self = (ModestAccountsWindow *) user_data;
553
554         row_count_changed (self);
555 }
556
557 static void
558 on_row_deleted (GtkTreeModel *tree_model,
559                 GtkTreePath  *path,
560                 gpointer      user_data)
561 {
562         ModestAccountsWindow *self;
563
564         self = (ModestAccountsWindow *) user_data;
565
566         row_count_changed (self);
567 }
568
569 static void 
570 row_count_changed (ModestAccountsWindow *self)
571 {
572         ModestAccountsWindowPrivate *priv;
573         GtkTreeModel *model;
574         gint count;
575
576         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
577         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->account_view));
578
579         count = gtk_tree_model_iter_n_children (model, NULL);
580
581         if (count == 0) {
582                 gtk_widget_hide (priv->account_view);
583                 gtk_widget_show (priv->no_accounts_container);
584                 g_debug ("%s: hiding accounts view", __FUNCTION__);
585         } else {
586                 gtk_widget_hide (priv->no_accounts_container);
587                 gtk_widget_show (priv->account_view);
588                 g_debug ("%s: showing accounts view", __FUNCTION__);
589         }
590         gtk_container_child_set (GTK_CONTAINER(priv->box), priv->pannable, 
591                                  "expand", count > 0,
592                                  "fill", count > 0,
593                                  NULL);
594 }
595
596 static void 
597 on_mail_operation_started (ModestMailOperation *mail_op,
598                            gpointer user_data)
599 {
600         ModestAccountsWindow *self;
601         ModestMailOperationTypeOperation op_type;
602         GObject *source = NULL;
603
604         self = MODEST_ACCOUNTS_WINDOW (user_data);
605         op_type = modest_mail_operation_get_type_operation (mail_op);
606         source = modest_mail_operation_get_source(mail_op);
607         if (G_OBJECT (self) == source) {
608                 update_progress_hint (self);
609         }
610         g_object_unref (source);
611 }
612
613 static void 
614 on_mail_operation_finished (ModestMailOperation *mail_op,
615                             gpointer user_data)
616 {
617         ModestAccountsWindow *self;
618
619         self = MODEST_ACCOUNTS_WINDOW (user_data);
620
621         /* Don't disable the progress hint if there are more pending
622            operations from this window */
623         update_progress_hint (self);
624
625         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
626 }
627
628 static void
629 on_queue_changed (ModestMailOperationQueue *queue,
630                   ModestMailOperation *mail_op,
631                   ModestMailOperationQueueNotification type,
632                   ModestAccountsWindow *self)
633 {
634         ModestAccountsWindowPrivate *priv;
635
636         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE (self);
637
638         /* If this operations was created by another window, do nothing */
639         if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self))) 
640                 return;
641
642         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
643                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
644                                                                G_OBJECT (mail_op),
645                                                                "operation-started",
646                                                                G_CALLBACK (on_mail_operation_started),
647                                                                self);
648                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
649                                                                G_OBJECT (mail_op),
650                                                                "operation-finished",
651                                                                G_CALLBACK (on_mail_operation_finished),
652                                                                self);
653         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
654                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
655                                                                   G_OBJECT (mail_op),
656                                                                   "operation-started");
657                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
658                                                                   G_OBJECT (mail_op),
659                                                                   "operation-finished");
660         }
661 }
662
663 void 
664 modest_accounts_window_pre_create (void)
665 {
666         static gboolean pre_created = FALSE;
667         if (!pre_created) {
668                 pre_created = TRUE;
669                 pre_created_accounts_window = GTK_WIDGET (modest_accounts_window_new_real ());
670         }
671 }
672
673
674 static gboolean
675 on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
676 {
677         ModestAccountsWindowPrivate *priv;
678         HildonPannableArea *pannable;
679
680         if (event->type == GDK_KEY_RELEASE)
681                 return FALSE;
682
683         priv = MODEST_ACCOUNTS_WINDOW_GET_PRIVATE(user_data);
684
685         pannable = HILDON_PANNABLE_AREA (priv->pannable);
686
687         switch (event->keyval) {
688
689         case GDK_Up:
690                 modest_maemo_utils_scroll_pannable(pannable, 0, -1);
691                 break;
692
693         case GDK_Down:
694                 modest_maemo_utils_scroll_pannable(pannable, 0, 1);
695                 break;
696         }
697
698         return FALSE;
699 }