1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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.
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.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-utils.h>
57 #include <modest-maemo-utils.h>
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-mail-operation.h"
61 #include "modest-icon-names.h"
62 #include "modest-progress-bar-widget.h"
63 #include "modest-text-utils.h"
64 #include "modest-ui-dimming-manager.h"
65 #include "maemo/modest-osso-state-saving.h"
66 #include "modest-text-utils.h"
67 #include "modest-signal-mgr.h"
69 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
76 /* 'private'/'protected' functions */
77 static void modest_main_window_class_init (ModestMainWindowClass *klass);
78 static void modest_main_window_init (ModestMainWindow *obj);
79 static void modest_main_window_finalize (GObject *obj);
81 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
82 GdkEventWindowState *event,
85 static void connect_signals (ModestMainWindow *self);
87 static void modest_main_window_disconnect_signals (ModestWindow *self);
89 static void restore_settings (ModestMainWindow *self,
90 gboolean do_folder_view_too);
92 static void save_state (ModestWindow *self);
94 static void update_menus (ModestMainWindow* self);
96 static void modest_main_window_show_toolbar (ModestWindow *window,
97 gboolean show_toolbar);
99 static void cancel_progressbar (GtkToolButton *toolbutton,
100 ModestMainWindow *self);
102 static void on_queue_changed (ModestMailOperationQueue *queue,
103 ModestMailOperation *mail_op,
104 ModestMailOperationQueueNotification type,
105 ModestMainWindow *self);
107 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
110 on_account_inserted (TnyAccountStore *accoust_store,
115 on_account_removed (TnyAccountStore *accoust_store,
119 static void on_default_account_changed (ModestAccountMgr* mgr,
122 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
126 static void on_configuration_key_changed (ModestConf* conf,
128 ModestConfEvent event,
129 ModestConfNotificationId id,
130 ModestMainWindow *self);
132 static void set_toolbar_mode (ModestMainWindow *self,
133 ModestToolBarModes mode);
135 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
137 static void on_show_account_action_toggled (GtkToggleAction *action,
140 static void on_refresh_account_action_activated (GtkAction *action,
143 static void on_account_updated (ModestAccountMgr* mgr, gchar* account_name,
146 static void on_send_receive_csm_activated (GtkMenuItem *item,
149 static void on_msg_count_changed (ModestHeaderView *header_view,
151 TnyFolderChange *change,
152 ModestMainWindow *main_window);
154 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
157 static GtkWidget * create_empty_view (void);
159 static gboolean on_folder_view_focus_in (GtkWidget *widget,
160 GdkEventFocus *event,
163 static gboolean on_header_view_focus_in (GtkWidget *widget,
164 GdkEventFocus *event,
167 static void on_folder_selection_changed (ModestFolderView *folder_view,
168 TnyFolderStore *folder_store,
170 ModestMainWindow *main_window);
172 static void set_at_least_one_account_visible(ModestMainWindow *self);
174 static void on_updating_msg_list (ModestHeaderView *header_view,
178 static gboolean restore_paned_timeout_handler (gpointer *data);
180 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
181 struct _ModestMainWindowPrivate {
182 GtkWidget *msg_paned;
183 GtkWidget *main_paned;
184 GtkWidget *main_vbox;
185 GtkWidget *contents_widget;
186 GtkWidget *empty_view;
188 /* Progress observers */
189 GtkWidget *progress_bar;
190 GSList *progress_widgets;
193 GtkWidget *progress_toolitem;
194 GtkWidget *cancel_toolitem;
195 GtkWidget *sort_toolitem;
196 GtkWidget *refresh_toolitem;
197 ModestToolBarModes current_toolbar_mode;
199 /* Merge ids used to add/remove accounts to the ViewMenu*/
200 GByteArray *merge_ids;
201 GtkActionGroup *view_additions_group;
203 /* On-demand widgets */
204 GtkWidget *accounts_popup;
205 GtkWidget *details_widget;
207 /* Optimized view enabled */
208 gboolean optimized_view;
210 /* Optimized view enabled */
211 gboolean send_receive_in_progress;
213 ModestHeaderView *header_view;
214 ModestFolderView *folder_view;
216 ModestMainWindowStyle style;
217 ModestMainWindowContentsStyle contents_style;
219 guint progress_bar_timeout;
220 guint restore_paned_timeout;
222 /* Signal handler UIDs */
223 GList *queue_err_signals;
226 /* "Updating" banner for header view */
227 GtkWidget *updating_banner;
228 guint updating_banner_timeout;
230 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
231 MODEST_TYPE_MAIN_WINDOW, \
232 ModestMainWindowPrivate))
234 typedef struct _GetMsgAsyncHelper {
235 ModestMainWindowPrivate *main_window_private;
237 ModestTnyMsgReplyType reply_type;
238 ModestTnyMsgForwardType forward_type;
245 static GtkWindowClass *parent_class = NULL;
248 /* Private actions */
249 /* This is the context sensitive menu: */
250 static const GtkActionEntry modest_folder_view_action_entries [] = {
252 /* Folder View CSM actions */
253 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
254 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
255 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
256 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
257 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
258 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
261 static const GtkActionEntry modest_header_view_action_entries [] = {
263 /* Header View CSM actions */
264 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
265 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
266 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
267 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
268 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
269 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
270 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
271 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
272 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
273 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
276 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
277 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
280 /************************************************************************/
283 modest_main_window_get_type (void)
285 static GType my_type = 0;
287 static const GTypeInfo my_info = {
288 sizeof(ModestMainWindowClass),
289 NULL, /* base init */
290 NULL, /* base finalize */
291 (GClassInitFunc) modest_main_window_class_init,
292 NULL, /* class finalize */
293 NULL, /* class data */
294 sizeof(ModestMainWindow),
296 (GInstanceInitFunc) modest_main_window_init,
299 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
307 modest_main_window_class_init (ModestMainWindowClass *klass)
309 GObjectClass *gobject_class;
310 gobject_class = (GObjectClass*) klass;
311 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
313 parent_class = g_type_class_peek_parent (klass);
314 gobject_class->finalize = modest_main_window_finalize;
316 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
318 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
319 modest_window_class->save_state_func = save_state;
320 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
321 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
322 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
326 modest_main_window_init (ModestMainWindow *obj)
328 ModestMainWindowPrivate *priv;
330 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
332 priv->queue_err_signals = NULL;
333 priv->msg_paned = NULL;
334 priv->main_paned = NULL;
335 priv->main_vbox = NULL;
336 priv->header_view = NULL;
337 priv->folder_view = NULL;
338 priv->contents_widget = NULL;
339 priv->accounts_popup = NULL;
340 priv->details_widget = NULL;
341 priv->empty_view = NULL;
342 priv->progress_widgets = NULL;
343 priv->progress_bar = NULL;
344 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
345 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
346 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
347 priv->merge_ids = NULL;
348 priv->optimized_view = FALSE;
349 priv->send_receive_in_progress = FALSE;
350 priv->progress_bar_timeout = 0;
351 priv->restore_paned_timeout = 0;
352 priv->sighandlers = NULL;
353 priv->updating_banner = NULL;
354 priv->updating_banner_timeout = 0;
356 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
358 "applications_email_mainview");
362 modest_main_window_finalize (GObject *obj)
364 ModestMainWindowPrivate *priv;
366 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
368 /* Sanity check: shouldn't be needed, the window mgr should
369 call this function before */
370 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
371 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
373 g_slist_free (priv->progress_widgets);
375 g_byte_array_free (priv->merge_ids, TRUE);
377 if (priv->progress_bar_timeout > 0) {
378 g_source_remove (priv->progress_bar_timeout);
379 priv->progress_bar_timeout = 0;
382 if (priv->updating_banner_timeout > 0) {
383 g_source_remove (priv->updating_banner_timeout);
384 priv->updating_banner_timeout = 0;
387 if (priv->updating_banner) {
388 gtk_widget_destroy (priv->updating_banner);
389 priv->updating_banner = NULL;
392 if (priv->restore_paned_timeout > 0) {
393 g_source_remove (priv->restore_paned_timeout);
394 priv->restore_paned_timeout = 0;
397 G_OBJECT_CLASS(parent_class)->finalize (obj);
401 modest_main_window_get_child_widget (ModestMainWindow *self,
402 ModestMainWindowWidgetType widget_type)
404 ModestMainWindowPrivate *priv;
407 g_return_val_if_fail (self, NULL);
408 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
411 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
413 switch (widget_type) {
414 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
415 widget = (GtkWidget*)priv->header_view; break;
416 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
417 widget = (GtkWidget*)priv->folder_view; break;
422 return widget ? GTK_WIDGET(widget) : NULL;
426 restore_paned_timeout_handler (gpointer *data)
428 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
429 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
432 /* Timeouts are outside the main lock */
433 gdk_threads_enter ();
434 if (GTK_WIDGET_VISIBLE (main_window)) {
435 conf = modest_runtime_get_conf ();
436 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
437 MODEST_CONF_MAIN_PANED_KEY);
439 gdk_threads_leave ();
446 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
449 ModestMainWindowPrivate *priv;
451 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
453 conf = modest_runtime_get_conf ();
455 modest_widget_memory_restore (conf, G_OBJECT(self),
456 MODEST_CONF_MAIN_WINDOW_KEY);
458 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
459 MODEST_CONF_HEADER_VIEW_KEY);
461 if (do_folder_view_too)
462 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
463 MODEST_CONF_FOLDER_VIEW_KEY);
465 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
466 MODEST_CONF_MAIN_PANED_KEY);
468 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
470 /* We need to force a redraw here in order to get the right
471 position of the horizontal paned separator */
472 gtk_widget_show (GTK_WIDGET (self));
477 save_state (ModestWindow *window)
480 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
484 conf = modest_runtime_get_conf ();
486 modest_widget_memory_save (conf,G_OBJECT(self),
487 MODEST_CONF_MAIN_WINDOW_KEY);
488 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
489 MODEST_CONF_MAIN_PANED_KEY);
490 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
491 // MODEST_CONF_HEADER_VIEW_KEY);
492 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
493 MODEST_CONF_FOLDER_VIEW_KEY);
497 compare_display_names (ModestAccountSettings *a,
498 ModestAccountSettings *b)
500 return strcmp (modest_account_settings_get_display_name (a),
501 modest_account_settings_get_display_name (b));
505 update_menus (ModestMainWindow* self)
507 GSList *account_names, *iter, *accounts;
508 ModestMainWindowPrivate *priv;
509 ModestWindowPrivate *parent_priv;
510 ModestAccountMgr *mgr;
511 gint i, num_accounts;
513 gchar *default_account;
514 const gchar *active_account_name;
515 GtkWidget *send_receive_button, *item;
516 GtkAction *send_receive_all = NULL;
519 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
520 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
522 /* Get enabled account IDs */
523 mgr = modest_runtime_get_account_mgr ();
524 account_names = modest_account_mgr_account_names (mgr, TRUE);
525 iter = account_names;
529 ModestAccountSettings *settings =
530 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
531 accounts = g_slist_prepend (accounts, settings);
535 modest_account_mgr_free_account_names (account_names);
536 account_names = NULL;
538 /* Order the list of accounts by its display name */
539 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
540 num_accounts = g_slist_length (accounts);
542 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
543 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
544 gtk_action_set_visible (send_receive_all, num_accounts > 0);
546 /* Delete old send&receive popup items. We can not just do a
547 menu_detach because it does not work well with
549 if (priv->accounts_popup)
550 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
551 (GtkCallback) gtk_widget_destroy, NULL);
553 /* Delete old entries in the View menu. Do not free groups, it
555 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
557 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
558 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
559 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
560 GTK_ACTION_GROUP (groups->data));
563 if (priv->merge_ids) {
564 for (i = 0; i < priv->merge_ids->len; i++)
565 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
566 g_byte_array_free (priv->merge_ids, TRUE);
568 /* We need to call this in order to ensure
569 that the new actions are added in the right
570 order (alphabetical) */
571 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
573 groups = g_list_next (groups);
575 priv->merge_ids = g_byte_array_sized_new (num_accounts);
577 /* Get send receive button */
578 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
579 "/ToolBar/ToolbarSendReceive");
581 /* Create the menu */
582 if (num_accounts > 1) {
583 if (!priv->accounts_popup)
584 priv->accounts_popup = gtk_menu_new ();
585 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
586 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
587 g_signal_connect (G_OBJECT (item),
589 G_CALLBACK (on_send_receive_csm_activated),
591 item = gtk_separator_menu_item_new ();
592 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
595 /* Create a new action group */
596 default_account = modest_account_mgr_get_default_account (mgr);
597 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
599 if (!active_account_name)
600 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
602 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
604 for (i = 0; i < num_accounts; i++) {
605 gchar *display_name = NULL;
606 const gchar *account_name;
607 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
610 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
613 account_name = modest_account_settings_get_account_name (settings);
615 if (default_account && account_name &&
616 !(strcmp (default_account, account_name) == 0)) {
617 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
618 modest_account_settings_get_display_name (settings));
620 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
621 modest_account_settings_get_display_name (settings));
624 /* Create action and add it to the action group. The
625 action name must be the account name, this way we
626 could know in the handlers the account to show */
627 if (settings && account_name) {
628 gchar* item_name, *refresh_action_name;
630 GtkAction *view_account_action, *refresh_account_action;
632 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
633 display_name, NULL, NULL, 0));
634 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
635 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
636 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
638 if (active_account_name) {
639 if (active_account_name && account_name &&
640 (strcmp (active_account_name, account_name) == 0)) {
641 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
645 /* Add ui from account data. We allow 2^9-1 account
646 changes in a single execution because we're
647 downcasting the guint to a guint8 in order to use a
648 GByteArray. It should be enough. */
649 item_name = g_strconcat (account_name, "Menu", NULL);
650 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
651 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
652 gtk_ui_manager_add_ui (parent_priv->ui_manager,
654 "/MenuBar/ViewMenu/ViewMenuAdditions",
657 GTK_UI_MANAGER_MENUITEM,
660 /* Connect the action signal "activate" */
661 g_signal_connect_after (G_OBJECT (view_account_action),
663 G_CALLBACK (on_show_account_action_toggled),
666 /* Create the items for the Tools->Send&Receive submenu */
667 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
668 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
669 display_name, NULL, NULL);
670 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
672 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
673 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
674 gtk_ui_manager_add_ui (parent_priv->ui_manager,
676 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
679 GTK_UI_MANAGER_MENUITEM,
681 g_free (refresh_action_name);
683 g_signal_connect_data (G_OBJECT (refresh_account_action),
685 G_CALLBACK (on_refresh_account_action_activated),
686 g_strdup (account_name),
687 (GClosureNotify) g_free,
690 /* Create item and add it to the send&receive
691 CSM. If there is only one account then
693 if (priv->accounts_popup) {
694 GtkWidget *label = gtk_label_new(NULL);
695 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
696 if (default_account && (strcmp(account_name, default_account) == 0))
698 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
699 gtk_label_set_markup (GTK_LABEL (label), escaped);
704 gtk_label_set_text (GTK_LABEL (label), display_name);
707 item = gtk_menu_item_new ();
708 gtk_container_add (GTK_CONTAINER (item), label);
710 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
711 g_signal_connect_data (G_OBJECT (item),
713 G_CALLBACK (on_send_receive_csm_activated),
714 g_strdup (account_name),
715 (GClosureNotify) g_free,
722 g_free (display_name);
725 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
727 /* We cannot do this in the loop above because this relies on the action
728 * group being inserted. This makes the default account appear in bold.
729 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
730 for (i = 0; i < num_accounts; i++) {
731 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
732 const gchar *account_name;
734 account_name = modest_account_settings_get_account_name (settings);
736 if(account_name && default_account &&
737 strcmp (account_name, default_account) == 0) {
738 gchar *item_name = g_strconcat (account_name, "Menu", NULL);
740 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
741 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
745 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
746 if (GTK_IS_LABEL (child)) {
747 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
748 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
749 gtk_label_set_markup (GTK_LABEL (child), bold_name);
754 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
755 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
759 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
760 if (GTK_IS_LABEL (child)) {
761 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
762 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
763 gtk_label_set_markup (GTK_LABEL (child), bold_name);
771 g_object_unref (settings);
774 if (priv->accounts_popup) {
775 /* Mandatory in order to view the menu contents */
776 gtk_widget_show_all (priv->accounts_popup);
778 /* Setup tap_and_hold just if was not done before*/
779 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
780 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
784 g_slist_free (accounts);
785 g_free (default_account);
788 /* Make sure that at least one account is viewed if there are any
789 * accounts, for instance when adding the first account: */
790 set_at_least_one_account_visible (self);
794 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
796 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
797 gtk_scrolled_window_add_with_viewport
798 (GTK_SCROLLED_WINDOW(win), widget);
800 gtk_container_add (GTK_CONTAINER(win),
811 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
813 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
815 GList *oerrsignals = priv->queue_err_signals;
816 while (oerrsignals) {
817 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
818 g_signal_handler_disconnect (esignal->queue, esignal->signal);
819 g_slice_free (QueueErrorSignal, esignal);
820 oerrsignals = g_list_next (oerrsignals);
822 g_list_free (priv->queue_err_signals);
823 priv->queue_err_signals = NULL;
828 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
830 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
833 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
837 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
839 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
841 /* Update visibility */
844 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
848 modest_main_window_disconnect_signals (ModestWindow *self)
850 ModestMainWindowPrivate *priv;
851 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
853 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
854 priv->sighandlers = NULL;
858 connect_signals (ModestMainWindow *self)
860 ModestWindowPrivate *parent_priv;
861 ModestMainWindowPrivate *priv;
864 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
865 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
870 modest_signal_mgr_connect (priv->sighandlers,
871 G_OBJECT(priv->folder_view), "key-press-event",
872 G_CALLBACK(on_inner_widgets_key_pressed), self);
874 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
875 "folder_selection_changed",
876 G_CALLBACK (on_folder_selection_changed),
879 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
880 "folder-display-name-changed",
881 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
884 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
886 G_CALLBACK (on_folder_view_focus_in),
889 /* Folder view CSM */
890 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
891 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
892 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
893 G_CALLBACK(_folder_view_csm_menu_activated),
897 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
898 G_CALLBACK(modest_ui_actions_on_header_selected), self);
900 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
901 G_CALLBACK(modest_ui_actions_on_header_activated), self);
903 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
904 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
906 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
907 G_CALLBACK(on_inner_widgets_key_pressed), self);
909 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
910 G_CALLBACK(on_msg_count_changed), self);
912 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
913 G_CALLBACK (on_header_view_focus_in), self);
915 modest_signal_mgr_connect (priv->sighandlers,
916 G_OBJECT (priv->header_view),
918 G_CALLBACK (on_updating_msg_list),
921 /* Header view CSM */
922 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
923 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
925 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
926 G_CALLBACK(_header_view_csm_menu_activated),
931 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
932 G_CALLBACK (modest_main_window_window_state_event),
935 /* Mail Operation Queue */
937 modest_signal_mgr_connect (priv->sighandlers,
938 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
940 G_CALLBACK (on_queue_changed), self);
942 /* Track changes in the device name */
944 modest_signal_mgr_connect (priv->sighandlers,
945 G_OBJECT(modest_runtime_get_conf ()),
947 G_CALLBACK (on_configuration_key_changed),
950 /* Track account changes. We need to refresh the toolbar */
952 modest_signal_mgr_connect (priv->sighandlers,
953 G_OBJECT (modest_runtime_get_account_store ()),
955 G_CALLBACK (on_account_inserted),
958 modest_signal_mgr_connect (priv->sighandlers,
959 G_OBJECT (modest_runtime_get_account_store ()),
961 G_CALLBACK (on_account_removed),
964 /* We need to refresh the send & receive menu to change the bold
965 * account when the default account changes. */
967 modest_signal_mgr_connect (priv->sighandlers,
968 G_OBJECT (modest_runtime_get_account_mgr ()),
969 "default_account_changed",
970 G_CALLBACK (on_default_account_changed),
974 modest_signal_mgr_connect (priv->sighandlers,
975 G_OBJECT (modest_runtime_get_account_mgr ()),
977 G_CALLBACK (on_account_updated),
981 modest_signal_mgr_connect (priv->sighandlers,
982 G_OBJECT (modest_runtime_get_account_store()),
983 "password_requested",
984 G_CALLBACK (modest_ui_actions_on_password_requested),
989 /** Idle handler, to send/receive at startup .*/
991 sync_accounts_cb (ModestMainWindow *win)
993 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
994 return FALSE; /* Do not call this idle handler again. */
999 on_hildon_program_is_topmost_notify(GObject *self,
1000 GParamSpec *propert_param, gpointer user_data)
1002 HildonProgram *app = HILDON_PROGRAM (self);
1005 ModestWindow* self = MODEST_WINDOW(user_data);
1008 /* Note that use of hildon_program_set_can_hibernate()
1009 * is generally referred to as "setting the killable flag",
1010 * though hibernation does not seem equal to death.
1013 if (hildon_program_get_is_topmost (app)) {
1014 /* Prevent hibernation when the progam comes to the foreground,
1015 * because hibernation should only happen when the application
1016 * is in the background: */
1017 hildon_program_set_can_hibernate (app, FALSE);
1019 /* Allow hibernation if the program has gone to the background: */
1021 /* However, prevent hibernation while the settings are being changed: */
1022 const gboolean hibernation_prevented =
1023 modest_window_mgr_get_hibernation_is_prevented (
1024 modest_runtime_get_window_mgr ());
1026 if (hibernation_prevented)
1027 hildon_program_set_can_hibernate (app, FALSE);
1029 /* Allow hibernation, after saving the state: */
1030 modest_osso_save_state();
1031 hildon_program_set_can_hibernate (app, TRUE);
1038 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1040 GtkWidget *folder_win = (GtkWidget *) user_data;
1041 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1043 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1044 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1046 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1048 /* Connect signals */
1049 connect_signals (MODEST_MAIN_WINDOW (self));
1051 /* Set account store */
1052 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1053 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1055 /* Load previous osso state, for instance if we are being restored from
1057 modest_osso_load_state ();
1059 /* Restore window & widget settings */
1060 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1062 /* Check if accounts exist and show the account wizard if not */
1063 gboolean accounts_exist =
1064 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1066 if (!accounts_exist) {
1067 /* This is necessary to have the main window shown behind the dialog
1068 It's an ugly hack... jschmid */
1069 gtk_widget_show_all(GTK_WIDGET(self));
1070 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1073 GtkAction *send_receive_all;
1074 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1075 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1076 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1077 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1078 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1079 modest_account_mgr_free_account_names (accounts);
1080 update_menus (MODEST_MAIN_WINDOW (self));
1085 modest_main_window_new (void)
1087 ModestMainWindow *self = NULL;
1088 ModestMainWindowPrivate *priv = NULL;
1089 ModestWindowPrivate *parent_priv = NULL;
1090 GtkWidget *folder_win = NULL;
1091 ModestDimmingRulesGroup *menu_rules_group = NULL;
1092 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1093 GtkActionGroup *action_group = NULL;
1094 GError *error = NULL;
1096 ModestConf *conf = NULL;
1097 GtkAction *action = NULL;
1098 GdkPixbuf *window_icon;
1100 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1101 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1102 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1104 parent_priv->ui_manager = gtk_ui_manager_new();
1105 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1107 action_group = gtk_action_group_new ("ModestMainWindowActions");
1108 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1110 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1111 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1113 /* Add common actions */
1114 gtk_action_group_add_actions (action_group,
1115 modest_action_entries,
1116 G_N_ELEMENTS (modest_action_entries),
1119 gtk_action_group_add_actions (action_group,
1120 modest_folder_view_action_entries,
1121 G_N_ELEMENTS (modest_folder_view_action_entries),
1124 gtk_action_group_add_actions (action_group,
1125 modest_header_view_action_entries,
1126 G_N_ELEMENTS (modest_header_view_action_entries),
1129 gtk_action_group_add_toggle_actions (action_group,
1130 modest_toggle_action_entries,
1131 G_N_ELEMENTS (modest_toggle_action_entries),
1134 gtk_action_group_add_toggle_actions (action_group,
1135 modest_main_window_toggle_action_entries,
1136 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1139 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1140 g_object_unref (action_group);
1142 /* Load the UI definition */
1143 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1144 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1145 if (error != NULL) {
1146 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1147 g_error_free (error);
1151 /* Add common dimming rules */
1152 modest_dimming_rules_group_add_rules (menu_rules_group,
1153 modest_main_window_menu_dimming_entries,
1154 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1155 MODEST_WINDOW (self));
1156 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1157 modest_main_window_toolbar_dimming_entries,
1158 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1159 MODEST_WINDOW (self));
1161 /* Insert dimming rules group for this window */
1162 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1163 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1164 g_object_unref (menu_rules_group);
1165 g_object_unref (toolbar_rules_group);
1167 /* Add accelerators */
1168 gtk_window_add_accel_group (GTK_WINDOW (self),
1169 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1171 /* Menubar. Update the state of some toggles */
1172 parent_priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
1173 conf = modest_runtime_get_conf ();
1174 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1175 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1176 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1177 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1178 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1179 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1180 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1181 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1182 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1183 gtk_widget_show (parent_priv->menubar);
1185 /* Get device name */
1186 modest_maemo_utils_get_device_name ();
1190 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1191 if (!priv->header_view)
1192 g_printerr ("modest: cannot instantiate header view\n");
1193 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1194 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1195 MODEST_CONF_HEADER_VIEW_KEY);
1197 /* Other style properties of header view */
1198 g_object_set (G_OBJECT (priv->header_view),
1199 "rules-hint", FALSE,
1201 /* gtk_widget_show (priv->header_view); */
1204 priv->empty_view = create_empty_view ();
1205 gtk_widget_show (priv->empty_view);
1207 /* Create scrolled windows */
1208 folder_win = gtk_scrolled_window_new (NULL, NULL);
1209 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1210 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1212 GTK_POLICY_AUTOMATIC);
1213 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1215 GTK_POLICY_AUTOMATIC);
1216 /* gtk_widget_show (priv->contents_widget); */
1219 priv->main_paned = gtk_hpaned_new ();
1220 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1221 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1222 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1224 /* putting it all together... */
1225 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1226 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1227 gtk_widget_show (priv->main_vbox);
1229 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1231 app = hildon_program_get_instance ();
1232 hildon_program_add_window (app, HILDON_WINDOW (self));
1234 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1235 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1237 g_signal_connect (G_OBJECT(self), "show",
1238 G_CALLBACK (modest_main_window_on_show), folder_win);
1240 /* Set window icon */
1241 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1243 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1244 g_object_unref (window_icon);
1247 /* Dont't restore settings here,
1248 * because it requires a gtk_widget_show(),
1249 * and we don't want to do that until later,
1250 * so that the UI is not visible for non-menu D-Bus activation.
1252 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1254 return MODEST_WINDOW(self);
1258 modest_main_window_set_style (ModestMainWindow *self,
1259 ModestMainWindowStyle style)
1261 ModestMainWindowPrivate *priv;
1262 ModestWindowPrivate *parent_priv;
1266 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1268 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1269 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1271 /* no change -> nothing to do */
1272 if (priv->style == style)
1275 /* Get toggle button and update the state if needed. This will
1276 happen only when the set_style is not invoked from the UI,
1277 for example when it's called from widget memory */
1278 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1279 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1280 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1281 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1282 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1283 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1284 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1287 priv->style = style;
1289 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1290 /* Remove main paned */
1291 g_object_ref (priv->main_paned);
1292 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1294 /* Reparent the contents widget to the main vbox */
1295 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1298 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1299 /* Remove header view */
1300 g_object_ref (priv->contents_widget);
1301 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1303 /* Reparent the main paned */
1304 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1305 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1309 g_return_if_reached ();
1312 /* Let header view grab the focus if it's being shown */
1313 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1314 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1316 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1319 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1322 ModestMainWindowStyle
1323 modest_main_window_get_style (ModestMainWindow *self)
1325 ModestMainWindowPrivate *priv;
1327 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1329 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1336 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1338 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1339 ModestWindowPrivate *parent_priv;
1340 ModestWindowMgr *mgr;
1341 gboolean is_fullscreen;
1342 GtkAction *fs_toggle_action;
1345 mgr = modest_runtime_get_window_mgr ();
1347 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1349 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1351 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1352 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1353 if (is_fullscreen != active) {
1354 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1363 set_homogeneous (GtkWidget *widget,
1366 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1367 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1371 modest_main_window_show_toolbar (ModestWindow *self,
1372 gboolean show_toolbar)
1374 ModestMainWindowPrivate *priv = NULL;
1375 ModestWindowPrivate *parent_priv = NULL;
1376 GtkWidget *reply_button = NULL, *menu = NULL;
1377 GtkWidget *placeholder = NULL;
1379 const gchar *action_name;
1382 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1383 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1384 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1386 /* Set optimized view status */
1387 priv->optimized_view = !show_toolbar;
1389 if (!parent_priv->toolbar) {
1390 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1392 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1394 /* Set homogeneous toolbar */
1395 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1396 set_homogeneous, NULL);
1398 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1399 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1400 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1401 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1402 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1403 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1404 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1405 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1407 /* Add ProgressBar (Transfer toolbar) */
1408 priv->progress_bar = modest_progress_bar_widget_new ();
1409 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1410 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1411 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1412 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1413 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1415 /* Connect cancel 'clicked' signal to abort progress mode */
1416 g_signal_connect(priv->cancel_toolitem, "clicked",
1417 G_CALLBACK(cancel_progressbar),
1420 /* Add it to the observers list */
1421 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1424 hildon_window_add_toolbar (HILDON_WINDOW (self),
1425 GTK_TOOLBAR (parent_priv->toolbar));
1427 /* Set reply button tap and hold menu */
1428 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1429 "/ToolBar/ToolbarMessageReply");
1430 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1431 "/ToolbarReplyCSM");
1432 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1434 /* Set send & receive button tap and hold menu */
1435 update_menus (MODEST_MAIN_WINDOW (self));
1439 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1440 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1441 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1443 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1444 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1445 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1447 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1449 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1453 /* Update also the actions (to update the toggles in the
1454 menus), we have to do it manually because some other window
1455 of the same time could have changed it (remember that the
1456 toolbar fullscreen mode is shared by all the windows of the
1458 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1459 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1461 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1463 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1464 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1469 on_account_inserted (TnyAccountStore *accoust_store,
1470 TnyAccount *account,
1473 update_menus (MODEST_MAIN_WINDOW (user_data));
1477 on_default_account_changed (ModestAccountMgr* mgr,
1480 update_menus (MODEST_MAIN_WINDOW (user_data));
1484 on_account_removed (TnyAccountStore *accoust_store,
1485 TnyAccount *account,
1488 update_menus (MODEST_MAIN_WINDOW (user_data));
1492 on_account_updated (ModestAccountMgr* mgr,
1493 gchar* account_name,
1496 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1498 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) {
1499 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1504 * This function manages the key events used to navigate between
1505 * header and folder views (when the window is in split view)
1508 * -------------------------------------------------
1509 * HeaderView GDK_Left Move focus to folder view
1510 * FolderView GDK_Right Move focus to header view
1512 * There is no need to scroll to selected row, the widgets will be the
1513 * responsibles of doing that (probably managing the focus-in event
1516 on_inner_widgets_key_pressed (GtkWidget *widget,
1520 ModestMainWindowPrivate *priv;
1522 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1524 /* Do nothing if we're in SIMPLE style */
1525 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1528 if (MODEST_IS_HEADER_VIEW (widget)) {
1529 if (event->keyval == GDK_Left)
1530 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1531 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1532 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1533 if (selected_headers > 1) {
1534 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1538 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1539 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1545 set_alignment (GtkWidget *widget,
1548 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1549 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1553 create_empty_view (void)
1555 GtkLabel *label = NULL;
1556 GtkWidget *align = NULL;
1558 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1559 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1560 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1561 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1563 return GTK_WIDGET(align);
1567 * Free the returned string
1570 get_gray_color_markup (GtkWidget *styled_widget)
1572 gchar *gray_color_markup = NULL;
1573 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1574 /* Obtain the secondary text color. We need a realized widget, that's why
1575 we get styled_widget from outside */
1577 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1578 gray_color_markup = modest_text_utils_get_color_string (&color);
1579 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1581 if (!gray_color_markup)
1582 gray_color_markup = g_strdup ("#BBBBBB");
1584 return gray_color_markup;
1588 * Free the returned string
1591 create_device_name_visual_string (const gchar *device_name,
1592 const gchar *gray_color_markup)
1596 /* We have to use "" to fill the %s of the translation. We can
1597 not just use the device name because the device name is
1598 shown in a different color, so it could not be included
1599 into the <span> tag */
1600 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1601 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1611 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1613 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1618 gchar *gray_color_markup;
1620 vbox = gtk_vbox_new (FALSE, 0);
1622 gray_color_markup = get_gray_color_markup (styled_widget);
1624 /* Account description: */
1625 if (modest_tny_account_is_virtual_local_folders (account)
1626 || (modest_tny_account_is_memory_card_account (account))) {
1628 /* Get device name */
1629 gchar *device_name = NULL;
1630 if (modest_tny_account_is_virtual_local_folders (account))
1631 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1632 MODEST_CONF_DEVICE_NAME, NULL);
1634 device_name = g_strdup (tny_account_get_name (account));
1636 label = create_device_name_visual_string ((const gchar *) device_name,
1637 (const gchar *) gray_color_markup);
1638 label_w = gtk_label_new (NULL);
1639 gtk_label_set_markup (GTK_LABEL (label_w), label);
1640 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1641 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1642 g_free (device_name);
1645 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1646 gtk_box_pack_start (GTK_BOX (vbox),
1647 gtk_label_new (tny_account_get_name (account)),
1650 /* Other accounts, such as IMAP and POP: */
1655 /* Put proto in uppercase */
1656 proto = g_string_new (tny_account_get_proto (account));
1657 proto = g_string_ascii_up (proto);
1659 /* note: mcen_fi_localroot_description is something like "%s account"
1660 * however, we should display "%s account: %s"... therefore, ugly tmp */
1661 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1662 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1663 gray_color_markup, tmp, tny_account_get_name (account));
1666 label_w = gtk_label_new (NULL);
1667 gtk_label_set_markup (GTK_LABEL (label_w), label);
1668 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1669 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1670 g_string_free (proto, TRUE);
1676 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1677 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1678 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1679 modest_tny_folder_store_get_message_count (folder_store));
1680 label_w = gtk_label_new (NULL);
1681 gtk_label_set_markup (GTK_LABEL (label_w), label);
1682 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1683 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1687 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1689 _("mcen_fi_rootfolder_folders"),
1690 modest_tny_folder_store_get_folder_count (folder_store));
1691 label_w = gtk_label_new (NULL);
1692 gtk_label_set_markup (GTK_LABEL (label_w), label);
1693 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1694 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1698 if (modest_tny_account_is_virtual_local_folders (account)
1699 || modest_tny_account_is_memory_card_account (account)) {
1701 gchar *size = modest_text_utils_get_display_size (
1702 modest_tny_folder_store_get_local_size (folder_store));
1704 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1705 gray_color_markup, _("mcen_fi_rootfolder_size"),
1709 label_w = gtk_label_new (NULL);
1710 gtk_label_set_markup (GTK_LABEL (label_w), label);
1711 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1712 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1714 } else if (TNY_IS_ACCOUNT(folder_store)) {
1715 TnyAccount *account = TNY_ACCOUNT(folder_store);
1717 time_t last_updated;
1718 const gchar *last_updated_string;
1719 /* Get last updated from configuration */
1720 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1721 tny_account_get_id (account));
1723 if (last_updated > 0)
1724 last_updated_string = modest_text_utils_get_display_date(last_updated);
1726 last_updated_string = g_strdup (_("mcen_va_never"));
1728 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1729 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1730 label_w = gtk_label_new (NULL);
1731 gtk_label_set_markup (GTK_LABEL (label_w), label);
1732 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1733 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1737 g_free (gray_color_markup);
1740 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1746 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1748 ModestMainWindowPrivate *priv = NULL;
1750 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1752 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1754 return priv->send_receive_in_progress;
1758 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1760 GtkAction *action = NULL;
1761 GtkWidget *widget = NULL;
1762 ModestMainWindowPrivate *priv = NULL;
1764 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1765 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1767 priv->send_receive_in_progress = TRUE;
1769 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1770 gtk_action_set_sensitive (action, FALSE);
1771 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1772 /* gtk_action_set_sensitive (action, FALSE); */
1773 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1774 gtk_widget_set_sensitive (widget, FALSE);
1778 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1780 GtkAction *action = NULL;
1781 GtkWidget *widget = NULL;
1782 ModestMainWindowPrivate *priv = NULL;
1784 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1785 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1787 priv->send_receive_in_progress = FALSE;
1789 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1790 gtk_action_set_sensitive (action, TRUE);
1791 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1792 /* gtk_action_set_sensitive (action, TRUE); */
1793 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1794 gtk_widget_set_sensitive (widget, TRUE);
1799 on_msg_count_changed (ModestHeaderView *header_view,
1801 TnyFolderChange *change,
1802 ModestMainWindow *main_window)
1804 gboolean folder_empty = FALSE;
1805 gboolean all_marked_as_deleted = FALSE;
1806 TnyFolderChangeChanged changed;
1807 ModestMainWindowPrivate *priv;
1809 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1810 g_return_if_fail (TNY_IS_FOLDER(folder));
1811 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1812 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1814 changed = tny_folder_change_get_changed (change);
1816 /* If something changes */
1817 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1818 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1820 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1822 /* Check header removed (hide marked as DELETED headers) */
1823 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1824 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1827 /* Check if all messages are marked to be deleted */
1828 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1829 folder_empty = folder_empty || all_marked_as_deleted ;
1831 /* Set contents style of headers view */
1833 modest_main_window_set_contents_style (main_window,
1834 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1835 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1838 modest_main_window_set_contents_style (main_window,
1839 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1845 modest_main_window_set_contents_style (ModestMainWindow *self,
1846 ModestMainWindowContentsStyle style)
1848 ModestMainWindowPrivate *priv;
1850 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1852 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1854 /* We allow to set the same content style than the previously
1855 set if there are details, because it could happen when we're
1856 selecting different accounts consecutively */
1857 if ((priv->contents_style == style) &&
1858 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1861 /* Remove previous child. Delete it if it was an account
1863 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1865 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1866 g_object_ref (content);
1867 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1868 g_object_ref (priv->empty_view);
1869 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1872 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1875 priv->contents_style = style;
1877 switch (priv->contents_style) {
1878 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1879 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1880 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1883 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1885 /* if we're started without main win, there may not be a folder
1886 * view. this fixes a GLib-Critical */
1887 if (priv->folder_view) {
1888 TnyFolderStore *selected_folderstore =
1889 modest_folder_view_get_selected (priv->folder_view);
1890 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1891 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1892 TNY_ACCOUNT (selected_folderstore));
1894 wrap_in_scrolled_window (priv->contents_widget,
1895 priv->details_widget);
1897 g_object_unref (selected_folderstore);
1898 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1903 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1904 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1905 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1909 g_return_if_reached ();
1913 gtk_widget_show_all (priv->contents_widget);
1916 ModestMainWindowContentsStyle
1917 modest_main_window_get_contents_style (ModestMainWindow *self)
1919 ModestMainWindowPrivate *priv;
1921 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1923 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1924 return priv->contents_style;
1929 on_configuration_key_changed (ModestConf* conf,
1931 ModestConfEvent event,
1932 ModestConfNotificationId id,
1933 ModestMainWindow *self)
1935 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1936 TnyAccount *account = NULL;
1938 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1941 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1944 if (priv->folder_view)
1945 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1947 if (account && TNY_IS_ACCOUNT (account) &&
1948 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1951 const gchar *device_name;
1952 gchar *new_text, *gray_color_markup;
1955 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1956 label = GTK_LABEL (children->data);
1958 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1959 MODEST_CONF_DEVICE_NAME, NULL);
1961 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1962 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1964 gtk_label_set_markup (label, new_text);
1965 gtk_widget_show (GTK_WIDGET (label));
1967 g_free (gray_color_markup);
1969 g_list_free (children);
1971 g_object_unref (account);
1975 set_toolbar_transfer_mode (ModestMainWindow *self)
1977 ModestMainWindowPrivate *priv = NULL;
1979 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1981 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1983 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1985 if (priv->progress_bar_timeout > 0) {
1986 g_source_remove (priv->progress_bar_timeout);
1987 priv->progress_bar_timeout = 0;
1994 set_toolbar_mode (ModestMainWindow *self,
1995 ModestToolBarModes mode)
1997 ModestWindowPrivate *parent_priv = NULL;
1998 ModestMainWindowPrivate *priv = NULL;
1999 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2001 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2003 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2004 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2006 /* In case this was called before the toolbar exists: */
2007 if (!(parent_priv->toolbar))
2010 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2012 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2013 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2014 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2016 /* Sets current toolbar mode */
2017 priv->current_toolbar_mode = mode;
2019 /* Checks the dimming rules */
2020 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2022 /* Show and hide toolbar items */
2024 case TOOLBAR_MODE_NORMAL:
2026 gtk_action_set_visible (sort_action, TRUE);
2028 gtk_action_set_visible (refresh_action, TRUE);
2029 if (priv->progress_toolitem) {
2030 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2031 gtk_widget_hide (priv->progress_toolitem);
2033 if (priv->progress_bar)
2034 gtk_widget_hide (priv->progress_bar);
2037 gtk_action_set_visible (cancel_action, FALSE);
2039 /* Hide toolbar if optimized view is enabled */
2040 if (priv->optimized_view)
2041 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2043 case TOOLBAR_MODE_TRANSFER:
2045 gtk_action_set_visible (sort_action, FALSE);
2047 gtk_action_set_visible (refresh_action, FALSE);
2049 gtk_action_set_visible (cancel_action, TRUE);
2050 if (priv->progress_bar)
2051 gtk_widget_show (priv->progress_bar);
2052 if (priv->progress_toolitem) {
2053 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2054 gtk_widget_show (priv->progress_toolitem);
2057 /* Show toolbar if it's hiden (optimized view ) */
2058 if (priv->optimized_view)
2059 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2062 g_return_if_reached ();
2067 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2069 ModestMainWindowPrivate *priv;
2071 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2072 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2074 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2078 cancel_progressbar (GtkToolButton *toolbutton,
2079 ModestMainWindow *self)
2082 ModestMainWindowPrivate *priv;
2084 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2086 /* Get operation observers and cancel all the operations */
2087 tmp = priv->progress_widgets;
2089 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2090 tmp=g_slist_next(tmp);
2095 observers_empty (ModestMainWindow *self)
2098 ModestMainWindowPrivate *priv;
2099 gboolean is_empty = TRUE;
2100 guint pending_ops = 0;
2102 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2103 tmp = priv->progress_widgets;
2105 /* Check all observers */
2106 while (tmp && is_empty) {
2107 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2108 is_empty = pending_ops == 0;
2110 tmp = g_slist_next(tmp);
2118 * Gets the toolbar mode needed for each mail operation. It stores in
2119 * @mode_changed if the toolbar mode has changed or not
2121 static ModestToolBarModes
2122 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2123 ModestMailOperation *mail_op,
2124 gboolean *mode_changed)
2126 ModestToolBarModes mode;
2127 ModestMainWindowPrivate *priv;
2129 *mode_changed = FALSE;
2130 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2132 /* Get toolbar mode from operation id*/
2133 switch (modest_mail_operation_get_type_operation (mail_op)) {
2134 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2135 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2136 mode = TOOLBAR_MODE_TRANSFER;
2137 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2138 *mode_changed = TRUE;
2141 mode = TOOLBAR_MODE_NORMAL;
2147 on_mail_operation_started (ModestMailOperation *mail_op,
2150 ModestMainWindow *self;
2151 ModestMailOperationTypeOperation op_type;
2152 ModestMainWindowPrivate *priv;
2153 ModestToolBarModes mode;
2155 gboolean mode_changed = FALSE;
2156 TnyAccount *account;
2158 self = MODEST_MAIN_WINDOW (user_data);
2159 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2161 /* Do not show progress for receiving operations if the
2162 account is the local account or the MMC one */
2163 op_type = modest_mail_operation_get_type_operation (mail_op);
2164 account = modest_mail_operation_get_account (mail_op);
2165 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2168 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2169 modest_tny_account_is_memory_card_account (account));
2170 g_object_unref (account);
2175 /* Get toolbar mode from operation id*/
2176 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2178 /* Add operation observers and change toolbar if neccessary*/
2179 tmp = priv->progress_widgets;
2180 if (mode == TOOLBAR_MODE_TRANSFER) {
2182 set_toolbar_transfer_mode(self);
2185 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2187 tmp = g_slist_next (tmp);
2193 on_mail_operation_finished (ModestMailOperation *mail_op,
2196 ModestToolBarModes mode;
2197 ModestMailOperationTypeOperation op_type;
2199 ModestMainWindow *self;
2200 gboolean mode_changed;
2201 TnyAccount *account;
2202 ModestMainWindowPrivate *priv;
2204 self = MODEST_MAIN_WINDOW (user_data);
2205 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2207 /* The mail operation was not added to the progress objects if
2208 the account was the local account or the MMC one */
2209 op_type = modest_mail_operation_get_type_operation (mail_op);
2210 account = modest_mail_operation_get_account (mail_op);
2211 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2214 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2215 modest_tny_account_is_memory_card_account (account));
2216 g_object_unref (account);
2221 /* Get toolbar mode from operation id*/
2222 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2224 /* Change toolbar mode */
2225 tmp = priv->progress_widgets;
2226 if (mode == TOOLBAR_MODE_TRANSFER) {
2228 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2230 tmp = g_slist_next (tmp);
2233 /* If no more operations are being observed, NORMAL mode is enabled again */
2234 if (observers_empty (self)) {
2235 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2241 on_queue_changed (ModestMailOperationQueue *queue,
2242 ModestMailOperation *mail_op,
2243 ModestMailOperationQueueNotification type,
2244 ModestMainWindow *self)
2246 ModestMainWindowPrivate *priv;
2248 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2250 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2251 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2253 "operation-started",
2254 G_CALLBACK (on_mail_operation_started),
2256 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2258 "operation-finished",
2259 G_CALLBACK (on_mail_operation_finished),
2261 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2262 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2264 "operation-started");
2265 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2267 "operation-finished");
2272 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2274 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2276 ModestAccountMgr *mgr;
2277 ModestAccountSettings *settings;
2278 ModestServerAccountSettings *store_settings = NULL;
2280 /* Get account data */
2281 mgr = modest_runtime_get_account_mgr ();
2282 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2284 store_settings = modest_account_settings_get_store_settings (settings);
2286 /* Set the new visible & active account */
2287 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2288 const gchar *account_name;
2290 account_name = modest_account_settings_get_account_name (settings);
2292 modest_folder_view_set_account_id_of_visible_server_account
2294 modest_server_account_settings_get_account_name (store_settings));
2295 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2296 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2297 if (action != NULL) {
2298 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2299 modest_utils_toggle_action_set_active_block_notify (
2300 GTK_TOGGLE_ACTION (action),
2306 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2311 g_object_unref (store_settings);
2312 g_object_unref (settings);
2316 /* Make sure that at least one account is "viewed": */
2318 set_at_least_one_account_visible(ModestMainWindow *self)
2320 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2321 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2323 if (!(priv->folder_view)) {
2324 /* It is too early to do this. */
2328 const gchar *active_server_account_name =
2329 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2331 if (!active_server_account_name ||
2332 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2334 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2335 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2336 if (default_modest_name) {
2337 set_account_visible (self, default_modest_name);
2338 } else if (first_modest_name) {
2339 set_account_visible (self, first_modest_name);
2341 g_free (first_modest_name);
2342 g_free (default_modest_name);
2347 on_show_account_action_toggled (GtkToggleAction *action,
2350 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2352 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2353 if (gtk_toggle_action_get_active (action))
2354 set_account_visible (self, acc_name);
2358 refresh_account (const gchar *account_name)
2362 /* win must already exists here, obviously */
2363 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2366 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2370 /* If account_name == NULL, we must update all (option All) */
2372 modest_ui_actions_do_send_receive_all (win);
2374 modest_ui_actions_do_send_receive (account_name, win);
2379 on_refresh_account_action_activated (GtkAction *action,
2382 refresh_account ((const gchar*) user_data);
2386 on_send_receive_csm_activated (GtkMenuItem *item,
2389 refresh_account ((const gchar*) user_data);
2393 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2395 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2397 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2403 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2405 ModestMainWindow *main_window = NULL;
2407 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2408 main_window = MODEST_MAIN_WINDOW (userdata);
2410 /* Update toolbar dimming state */
2411 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2417 on_header_view_focus_in (GtkWidget *widget,
2418 GdkEventFocus *event,
2421 ModestMainWindow *main_window = NULL;
2423 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2425 main_window = MODEST_MAIN_WINDOW (userdata);
2427 /* Update toolbar dimming state */
2428 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2434 on_folder_selection_changed (ModestFolderView *folder_view,
2435 TnyFolderStore *folder_store,
2437 ModestMainWindow *main_window)
2439 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2440 GtkAction *action = NULL;
2441 gboolean show_reply = TRUE;
2442 gboolean show_forward = TRUE;
2443 gboolean show_cancel_send = FALSE;
2444 gboolean show_clipboard = TRUE;
2445 gboolean show_delete = TRUE;
2448 if (TNY_IS_ACCOUNT (folder_store)) {
2449 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2450 } else if (TNY_IS_FOLDER (folder_store)) {
2451 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2452 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2453 TNY_FOLDER (folder_store));
2454 switch (folder_type) {
2455 case TNY_FOLDER_TYPE_DRAFTS:
2456 show_clipboard = show_delete = TRUE;
2457 show_reply = show_forward = show_cancel_send = FALSE;
2459 case TNY_FOLDER_TYPE_SENT:
2460 show_forward = show_clipboard = show_delete = TRUE;
2461 show_reply = show_cancel_send = FALSE;
2463 case TNY_FOLDER_TYPE_OUTBOX:
2464 show_clipboard = show_delete = show_cancel_send = TRUE;
2465 show_reply = show_forward = FALSE;
2467 case TNY_FOLDER_TYPE_INVALID:
2468 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2471 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2472 show_cancel_send = FALSE;
2475 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2476 show_cancel_send = FALSE;
2481 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2482 gtk_action_set_visible (action, show_reply);
2483 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2484 gtk_action_set_visible (action, show_reply);
2485 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2486 gtk_action_set_visible (action, show_forward);
2487 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2488 gtk_action_set_visible (action, show_cancel_send);
2489 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2490 gtk_action_set_visible (action, show_delete);
2492 /* We finally call to the ui actions handler, after updating properly
2493 * the header view CSM */
2494 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2498 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2499 GtkTreeModel *model,
2500 GtkTreeRowReference *row_reference,
2501 ModestMainWindow *self)
2503 ModestMainWindowPrivate *priv = NULL;
2504 GtkTreeModel *header_model = NULL;
2505 GtkTreePath *path = NULL;
2507 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2508 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2509 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2511 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2512 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2514 /* Do nothing if we changed the folder in the main view */
2515 if (header_model != model)
2518 /* Select the message in the header view */
2519 path = gtk_tree_row_reference_get_path (row_reference);
2520 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2522 gtk_tree_path_free (path);
2528 show_updating_banner (gpointer user_data)
2530 ModestMainWindowPrivate *priv = NULL;
2532 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2534 if (priv->updating_banner == NULL) {
2536 /* We're outside the main lock */
2537 gdk_threads_enter ();
2538 priv->updating_banner =
2539 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2540 _CS ("ckdg_pb_updating"));
2541 gdk_threads_leave ();
2544 /* Remove timeout */
2545 priv->updating_banner_timeout = 0;
2550 * We use this function to show/hide a progress banner showing
2551 * "Updating" while the header view is being filled. We're not showing
2552 * it unless the update takes more than 2 seconds
2554 * If starting = TRUE then the refresh is starting, otherwise it means
2555 * that is has just finished
2558 on_updating_msg_list (ModestHeaderView *header_view,
2562 ModestMainWindowPrivate *priv = NULL;
2564 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2566 /* Remove old timeout */
2567 if (priv->updating_banner_timeout > 0) {
2568 g_source_remove (priv->updating_banner_timeout);
2569 priv->updating_banner_timeout = 0;
2572 /* Create a new timeout */
2574 priv->updating_banner_timeout =
2575 g_timeout_add (2000, show_updating_banner, user_data);
2577 /* Remove the banner if exists */
2578 if (priv->updating_banner) {
2579 gtk_widget_destroy (priv->updating_banner);
2580 priv->updating_banner = NULL;