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);
109 static void on_account_inserted (TnyAccountStore *accoust_store,
113 static void on_account_removed (TnyAccountStore *accoust_store,
117 static void on_account_changed (TnyAccountStore *account_store,
121 static void on_default_account_changed (ModestAccountMgr* mgr,
124 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
128 static void on_configuration_key_changed (ModestConf* conf,
130 ModestConfEvent event,
131 ModestConfNotificationId id,
132 ModestMainWindow *self);
134 static void set_toolbar_mode (ModestMainWindow *self,
135 ModestToolBarModes mode);
137 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
139 static void on_show_account_action_toggled (GtkToggleAction *action,
142 static void on_refresh_account_action_activated (GtkAction *action,
145 static void on_send_receive_csm_activated (GtkMenuItem *item,
148 static void on_msg_count_changed (ModestHeaderView *header_view,
150 TnyFolderChange *change,
151 ModestMainWindow *main_window);
153 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
156 static GtkWidget * create_empty_view (void);
158 static gboolean on_folder_view_focus_in (GtkWidget *widget,
159 GdkEventFocus *event,
162 static gboolean on_header_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static void on_folder_selection_changed (ModestFolderView *folder_view,
167 TnyFolderStore *folder_store,
169 ModestMainWindow *main_window);
171 static void set_at_least_one_account_visible(ModestMainWindow *self);
173 static void on_updating_msg_list (ModestHeaderView *header_view,
177 static gboolean restore_paned_timeout_handler (gpointer *data);
179 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
180 struct _ModestMainWindowPrivate {
181 GtkWidget *msg_paned;
182 GtkWidget *main_paned;
183 GtkWidget *main_vbox;
184 GtkWidget *contents_widget;
185 GtkWidget *empty_view;
187 /* Progress observers */
188 GtkWidget *progress_bar;
189 GSList *progress_widgets;
192 GtkWidget *progress_toolitem;
193 GtkWidget *cancel_toolitem;
194 GtkWidget *sort_toolitem;
195 GtkWidget *refresh_toolitem;
196 ModestToolBarModes current_toolbar_mode;
198 /* Merge ids used to add/remove accounts to the ViewMenu*/
199 GByteArray *merge_ids;
200 GtkActionGroup *view_additions_group;
202 /* On-demand widgets */
203 GtkWidget *accounts_popup;
204 GtkWidget *details_widget;
206 /* Optimized view enabled */
207 gboolean optimized_view;
209 /* Optimized view enabled */
210 gboolean send_receive_in_progress;
212 ModestHeaderView *header_view;
213 ModestFolderView *folder_view;
215 ModestMainWindowStyle style;
216 ModestMainWindowContentsStyle contents_style;
218 guint progress_bar_timeout;
219 guint restore_paned_timeout;
221 /* Signal handler UIDs */
222 GList *queue_err_signals;
225 /* "Updating" banner for header view */
226 GtkWidget *updating_banner;
227 guint updating_banner_timeout;
229 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
230 MODEST_TYPE_MAIN_WINDOW, \
231 ModestMainWindowPrivate))
233 typedef struct _GetMsgAsyncHelper {
234 ModestMainWindowPrivate *main_window_private;
236 ModestTnyMsgReplyType reply_type;
237 ModestTnyMsgForwardType forward_type;
244 static GtkWindowClass *parent_class = NULL;
247 /* Private actions */
248 /* This is the context sensitive menu: */
249 static const GtkActionEntry modest_folder_view_action_entries [] = {
251 /* Folder View CSM actions */
252 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
253 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
254 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
255 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
256 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
257 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
260 static const GtkActionEntry modest_header_view_action_entries [] = {
262 /* Header View CSM actions */
263 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
264 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
265 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
266 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
267 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
268 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
269 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
270 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
271 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
272 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
275 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
276 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
279 /************************************************************************/
282 modest_main_window_get_type (void)
284 static GType my_type = 0;
286 static const GTypeInfo my_info = {
287 sizeof(ModestMainWindowClass),
288 NULL, /* base init */
289 NULL, /* base finalize */
290 (GClassInitFunc) modest_main_window_class_init,
291 NULL, /* class finalize */
292 NULL, /* class data */
293 sizeof(ModestMainWindow),
295 (GInstanceInitFunc) modest_main_window_init,
298 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
306 modest_main_window_class_init (ModestMainWindowClass *klass)
308 GObjectClass *gobject_class;
309 gobject_class = (GObjectClass*) klass;
310 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
312 parent_class = g_type_class_peek_parent (klass);
313 gobject_class->finalize = modest_main_window_finalize;
315 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
317 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
318 modest_window_class->save_state_func = save_state;
319 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
320 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
321 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
325 modest_main_window_init (ModestMainWindow *obj)
327 ModestMainWindowPrivate *priv;
329 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
331 priv->queue_err_signals = NULL;
332 priv->msg_paned = NULL;
333 priv->main_paned = NULL;
334 priv->main_vbox = NULL;
335 priv->header_view = NULL;
336 priv->folder_view = NULL;
337 priv->contents_widget = NULL;
338 priv->accounts_popup = NULL;
339 priv->details_widget = NULL;
340 priv->empty_view = NULL;
341 priv->progress_widgets = NULL;
342 priv->progress_bar = NULL;
343 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
344 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
345 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
346 priv->merge_ids = NULL;
347 priv->optimized_view = FALSE;
348 priv->send_receive_in_progress = FALSE;
349 priv->progress_bar_timeout = 0;
350 priv->restore_paned_timeout = 0;
351 priv->sighandlers = NULL;
352 priv->updating_banner = NULL;
353 priv->updating_banner_timeout = 0;
355 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
357 "applications_email_mainview");
361 modest_main_window_finalize (GObject *obj)
363 ModestMainWindowPrivate *priv;
365 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
367 /* Sanity check: shouldn't be needed, the window mgr should
368 call this function before */
369 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
370 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
372 g_slist_free (priv->progress_widgets);
374 g_byte_array_free (priv->merge_ids, TRUE);
376 if (priv->progress_bar_timeout > 0) {
377 g_source_remove (priv->progress_bar_timeout);
378 priv->progress_bar_timeout = 0;
381 if (priv->updating_banner_timeout > 0) {
382 g_source_remove (priv->updating_banner_timeout);
383 priv->updating_banner_timeout = 0;
386 if (priv->updating_banner) {
387 gtk_widget_destroy (priv->updating_banner);
388 priv->updating_banner = NULL;
391 if (priv->restore_paned_timeout > 0) {
392 g_source_remove (priv->restore_paned_timeout);
393 priv->restore_paned_timeout = 0;
396 G_OBJECT_CLASS(parent_class)->finalize (obj);
400 modest_main_window_get_child_widget (ModestMainWindow *self,
401 ModestMainWindowWidgetType widget_type)
403 ModestMainWindowPrivate *priv;
406 g_return_val_if_fail (self, NULL);
407 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
410 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
412 switch (widget_type) {
413 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
414 widget = (GtkWidget*)priv->header_view; break;
415 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
416 widget = (GtkWidget*)priv->folder_view; break;
421 return widget ? GTK_WIDGET(widget) : NULL;
425 restore_paned_timeout_handler (gpointer *data)
427 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
428 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
431 /* Timeouts are outside the main lock */
432 gdk_threads_enter ();
433 if (GTK_WIDGET_VISIBLE (main_window)) {
434 conf = modest_runtime_get_conf ();
435 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
436 MODEST_CONF_MAIN_PANED_KEY);
438 gdk_threads_leave ();
445 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
448 ModestMainWindowPrivate *priv;
450 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
452 conf = modest_runtime_get_conf ();
454 modest_widget_memory_restore (conf, G_OBJECT(self),
455 MODEST_CONF_MAIN_WINDOW_KEY);
457 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
458 MODEST_CONF_HEADER_VIEW_KEY);
460 if (do_folder_view_too)
461 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
462 MODEST_CONF_FOLDER_VIEW_KEY);
464 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
465 MODEST_CONF_MAIN_PANED_KEY);
467 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
469 /* We need to force a redraw here in order to get the right
470 position of the horizontal paned separator */
471 gtk_widget_show (GTK_WIDGET (self));
476 save_state (ModestWindow *window)
479 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
480 ModestMainWindowPrivate *priv;
482 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
483 conf = modest_runtime_get_conf ();
485 modest_widget_memory_save (conf,G_OBJECT(self),
486 MODEST_CONF_MAIN_WINDOW_KEY);
487 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
488 MODEST_CONF_MAIN_PANED_KEY);
489 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
490 // MODEST_CONF_HEADER_VIEW_KEY);
491 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
492 MODEST_CONF_FOLDER_VIEW_KEY);
496 compare_display_names (ModestAccountSettings *a,
497 ModestAccountSettings *b)
499 return strcmp (modest_account_settings_get_display_name (a),
500 modest_account_settings_get_display_name (b));
504 update_menus (ModestMainWindow* self)
506 GSList *account_names, *iter, *accounts;
507 ModestMainWindowPrivate *priv;
508 ModestWindowPrivate *parent_priv;
509 ModestAccountMgr *mgr;
510 gint i, num_accounts;
512 gchar *default_account;
513 const gchar *active_account_name;
514 GtkWidget *send_receive_button, *item;
515 GtkAction *send_receive_all = NULL;
518 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
519 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
521 /* Get enabled account IDs */
522 mgr = modest_runtime_get_account_mgr ();
523 account_names = modest_account_mgr_account_names (mgr, TRUE);
524 iter = account_names;
528 ModestAccountSettings *settings =
529 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
530 accounts = g_slist_prepend (accounts, settings);
534 modest_account_mgr_free_account_names (account_names);
535 account_names = NULL;
537 /* Order the list of accounts by its display name */
538 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
539 num_accounts = g_slist_length (accounts);
541 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
542 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
543 gtk_action_set_visible (send_receive_all, num_accounts > 0);
545 /* Delete old send&receive popup items. We can not just do a
546 menu_detach because it does not work well with
548 if (priv->accounts_popup)
549 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
550 (GtkCallback) gtk_widget_destroy, NULL);
552 /* Delete old entries in the View menu. Do not free groups, it
554 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
556 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
557 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
558 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
559 GTK_ACTION_GROUP (groups->data));
562 if (priv->merge_ids) {
563 for (i = 0; i < priv->merge_ids->len; i++)
564 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
565 g_byte_array_free (priv->merge_ids, TRUE);
567 /* We need to call this in order to ensure
568 that the new actions are added in the right
569 order (alphabetical) */
570 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
572 groups = g_list_next (groups);
574 priv->merge_ids = g_byte_array_sized_new (num_accounts);
576 /* Get send receive button */
577 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
578 "/ToolBar/ToolbarSendReceive");
580 /* Create the menu */
581 if (num_accounts > 1) {
582 if (!priv->accounts_popup)
583 priv->accounts_popup = gtk_menu_new ();
584 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
585 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
586 g_signal_connect (G_OBJECT (item),
588 G_CALLBACK (on_send_receive_csm_activated),
590 item = gtk_separator_menu_item_new ();
591 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
594 /* Create a new action group */
595 default_account = modest_account_mgr_get_default_account (mgr);
596 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
598 if (!active_account_name)
599 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
601 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
603 for (i = 0; i < num_accounts; i++) {
604 gchar *display_name = NULL;
605 const gchar *account_name;
606 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
609 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
612 account_name = modest_account_settings_get_account_name (settings);
614 if (default_account && account_name &&
615 !(strcmp (default_account, account_name) == 0)) {
616 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
617 modest_account_settings_get_display_name (settings));
619 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
620 modest_account_settings_get_display_name (settings));
623 /* Create action and add it to the action group. The
624 action name must be the account name, this way we
625 could know in the handlers the account to show */
626 if (settings && account_name) {
627 gchar* item_name, *refresh_action_name;
629 GtkAction *view_account_action, *refresh_account_action;
631 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
632 display_name, NULL, NULL, 0));
633 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
634 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
635 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
637 if (active_account_name) {
638 if (active_account_name && account_name &&
639 (strcmp (active_account_name, account_name) == 0)) {
640 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
644 /* Add ui from account data. We allow 2^9-1 account
645 changes in a single execution because we're
646 downcasting the guint to a guint8 in order to use a
647 GByteArray. It should be enough. */
648 item_name = g_strconcat (account_name, "Menu", NULL);
649 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
650 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
651 gtk_ui_manager_add_ui (parent_priv->ui_manager,
653 "/MenuBar/ViewMenu/ViewMenuAdditions",
656 GTK_UI_MANAGER_MENUITEM,
659 /* Connect the action signal "activate" */
660 g_signal_connect_after (G_OBJECT (view_account_action),
662 G_CALLBACK (on_show_account_action_toggled),
665 /* Create the items for the Tools->Send&Receive submenu */
666 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
667 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
668 display_name, NULL, NULL);
669 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
671 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
672 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
673 gtk_ui_manager_add_ui (parent_priv->ui_manager,
675 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
678 GTK_UI_MANAGER_MENUITEM,
680 g_free (refresh_action_name);
682 g_signal_connect_data (G_OBJECT (refresh_account_action),
684 G_CALLBACK (on_refresh_account_action_activated),
685 g_strdup (account_name),
686 (GClosureNotify) g_free,
689 /* Create item and add it to the send&receive
690 CSM. If there is only one account then
692 if (priv->accounts_popup) {
693 GtkWidget *label = gtk_label_new(NULL);
694 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
695 if (default_account && (strcmp(account_name, default_account) == 0))
697 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
698 gtk_label_set_markup (GTK_LABEL (label), escaped);
703 gtk_label_set_text (GTK_LABEL (label), display_name);
706 item = gtk_menu_item_new ();
707 gtk_container_add (GTK_CONTAINER (item), label);
709 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
710 g_signal_connect_data (G_OBJECT (item),
712 G_CALLBACK (on_send_receive_csm_activated),
713 g_strdup (account_name),
714 (GClosureNotify) g_free,
721 g_free (display_name);
724 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
726 /* We cannot do this in the loop above because this relies on the action
727 * group being inserted. This makes the default account appear in bold.
728 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
729 for (i = 0; i < num_accounts; i++) {
730 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
731 const gchar *account_name;
733 account_name = modest_account_settings_get_account_name (settings);
735 if(account_name && default_account &&
736 strcmp (account_name, default_account) == 0) {
737 gchar *item_name = g_strconcat (account_name, "Menu", NULL);
739 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
740 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
744 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
745 if (GTK_IS_LABEL (child)) {
746 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
747 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
748 gtk_label_set_markup (GTK_LABEL (child), bold_name);
753 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
754 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
758 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
759 if (GTK_IS_LABEL (child)) {
760 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
761 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
762 gtk_label_set_markup (GTK_LABEL (child), bold_name);
770 g_object_unref (settings);
773 if (priv->accounts_popup) {
774 /* Mandatory in order to view the menu contents */
775 gtk_widget_show_all (priv->accounts_popup);
777 /* Setup tap_and_hold just if was not done before*/
778 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
779 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
783 g_slist_free (accounts);
784 g_free (default_account);
787 /* Make sure that at least one account is viewed if there are any
788 * accounts, for instance when adding the first account: */
789 set_at_least_one_account_visible (self);
793 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
795 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
796 gtk_scrolled_window_add_with_viewport
797 (GTK_SCROLLED_WINDOW(win), widget);
799 gtk_container_add (GTK_CONTAINER(win),
810 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
812 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
814 GList *oerrsignals = priv->queue_err_signals;
815 while (oerrsignals) {
816 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
817 g_signal_handler_disconnect (esignal->queue, esignal->signal);
818 g_slice_free (QueueErrorSignal, esignal);
819 oerrsignals = g_list_next (oerrsignals);
821 g_list_free (priv->queue_err_signals);
822 priv->queue_err_signals = NULL;
827 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
829 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
832 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
836 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
838 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
840 /* Update visibility */
843 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
847 modest_main_window_disconnect_signals (ModestWindow *self)
849 ModestMainWindowPrivate *priv;
850 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
852 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
853 priv->sighandlers = NULL;
857 connect_signals (ModestMainWindow *self)
859 ModestWindowPrivate *parent_priv;
860 ModestMainWindowPrivate *priv;
863 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
864 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
869 modest_signal_mgr_connect (priv->sighandlers,
870 G_OBJECT(priv->folder_view), "key-press-event",
871 G_CALLBACK(on_inner_widgets_key_pressed), self);
873 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
874 "folder_selection_changed",
875 G_CALLBACK (on_folder_selection_changed),
878 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
879 "folder-display-name-changed",
880 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
883 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
885 G_CALLBACK (on_folder_view_focus_in),
888 /* Folder view CSM */
889 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
890 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
891 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
892 G_CALLBACK(_folder_view_csm_menu_activated),
896 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
897 G_CALLBACK(modest_ui_actions_on_header_selected), self);
899 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
900 G_CALLBACK(modest_ui_actions_on_header_activated), self);
902 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
903 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
905 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
906 G_CALLBACK(on_inner_widgets_key_pressed), self);
908 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
909 G_CALLBACK(on_msg_count_changed), self);
911 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
912 G_CALLBACK (on_header_view_focus_in), self);
914 modest_signal_mgr_connect (priv->sighandlers,
915 G_OBJECT (priv->header_view),
917 G_CALLBACK (on_updating_msg_list),
920 /* Header view CSM */
921 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
922 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
924 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
925 G_CALLBACK(_header_view_csm_menu_activated),
930 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
931 G_CALLBACK (modest_main_window_window_state_event),
934 /* Mail Operation Queue */
936 modest_signal_mgr_connect (priv->sighandlers,
937 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
939 G_CALLBACK (on_queue_changed), self);
941 /* Track changes in the device name */
943 modest_signal_mgr_connect (priv->sighandlers,
944 G_OBJECT(modest_runtime_get_conf ()),
946 G_CALLBACK (on_configuration_key_changed),
949 /* Track account changes. We need to refresh the toolbar */
951 modest_signal_mgr_connect (priv->sighandlers,
952 G_OBJECT (modest_runtime_get_account_store ()),
954 G_CALLBACK (on_account_inserted),
957 modest_signal_mgr_connect (priv->sighandlers,
958 G_OBJECT (modest_runtime_get_account_store ()),
960 G_CALLBACK (on_account_removed),
963 /* We need to refresh the send & receive menu to change the bold
964 * account when the default account changes. */
966 modest_signal_mgr_connect (priv->sighandlers,
967 G_OBJECT (modest_runtime_get_account_mgr ()),
968 "default_account_changed",
969 G_CALLBACK (on_default_account_changed),
974 modest_signal_mgr_connect (priv->sighandlers,
975 G_OBJECT (modest_runtime_get_account_store ()),
977 G_CALLBACK (on_account_changed),
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 = modest_maemo_utils_get_manager_menubar_as_menu (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, MODEST_ICON_SIZE_BIG);
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_changed (TnyAccountStore *account_store,
1493 TnyAccount *account,
1496 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1498 /* We need to refresh the details widget because it could have changed */
1499 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) {
1500 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1503 /* Update the menus as well, the account name could be changed */
1504 update_menus (MODEST_MAIN_WINDOW (user_data));
1508 * This function manages the key events used to navigate between
1509 * header and folder views (when the window is in split view)
1512 * -------------------------------------------------
1513 * HeaderView GDK_Left Move focus to folder view
1514 * FolderView GDK_Right Move focus to header view
1516 * There is no need to scroll to selected row, the widgets will be the
1517 * responsibles of doing that (probably managing the focus-in event
1520 on_inner_widgets_key_pressed (GtkWidget *widget,
1524 ModestMainWindowPrivate *priv;
1526 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1528 /* Do nothing if we're in SIMPLE style */
1529 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1532 if (MODEST_IS_HEADER_VIEW (widget)) {
1533 if (event->keyval == GDK_Left)
1534 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1535 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1536 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1537 if (selected_headers > 1) {
1538 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1542 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1543 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1549 set_alignment (GtkWidget *widget,
1552 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1553 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1557 create_empty_view (void)
1559 GtkLabel *label = NULL;
1560 GtkWidget *align = NULL;
1562 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1563 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1564 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1565 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1567 return GTK_WIDGET(align);
1571 * Free the returned string
1574 get_gray_color_markup (GtkWidget *styled_widget)
1576 gchar *gray_color_markup = NULL;
1577 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1578 /* Obtain the secondary text color. We need a realized widget, that's why
1579 we get styled_widget from outside */
1581 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1582 gray_color_markup = modest_text_utils_get_color_string (&color);
1583 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1585 if (!gray_color_markup)
1586 gray_color_markup = g_strdup ("#BBBBBB");
1588 return gray_color_markup;
1592 * Free the returned string
1595 create_device_name_visual_string (const gchar *device_name,
1596 const gchar *gray_color_markup)
1600 /* We have to use "" to fill the %s of the translation. We can
1601 not just use the device name because the device name is
1602 shown in a different color, so it could not be included
1603 into the <span> tag */
1604 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1605 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1615 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1617 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1622 gchar *gray_color_markup;
1624 vbox = gtk_vbox_new (FALSE, 0);
1626 gray_color_markup = get_gray_color_markup (styled_widget);
1628 /* Account description: */
1629 if (modest_tny_account_is_virtual_local_folders (account)
1630 || (modest_tny_account_is_memory_card_account (account))) {
1632 /* Get device name */
1633 gchar *device_name = NULL;
1634 if (modest_tny_account_is_virtual_local_folders (account))
1635 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1636 MODEST_CONF_DEVICE_NAME, NULL);
1638 device_name = g_strdup (tny_account_get_name (account));
1640 label = create_device_name_visual_string ((const gchar *) device_name,
1641 (const gchar *) gray_color_markup);
1642 label_w = gtk_label_new (NULL);
1643 gtk_label_set_markup (GTK_LABEL (label_w), label);
1644 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1645 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1646 g_free (device_name);
1649 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1650 gtk_box_pack_start (GTK_BOX (vbox),
1651 gtk_label_new (tny_account_get_name (account)),
1654 /* Other accounts, such as IMAP and POP: */
1659 /* Put proto in uppercase */
1660 proto = g_string_new (tny_account_get_proto (account));
1661 proto = g_string_ascii_up (proto);
1663 /* note: mcen_fi_localroot_description is something like "%s account"
1664 * however, we should display "%s account: %s"... therefore, ugly tmp */
1665 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1666 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1667 gray_color_markup, tmp, tny_account_get_name (account));
1670 label_w = gtk_label_new (NULL);
1671 gtk_label_set_markup (GTK_LABEL (label_w), label);
1672 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1673 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1674 g_string_free (proto, TRUE);
1680 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1681 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1682 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1683 modest_tny_folder_store_get_message_count (folder_store));
1684 label_w = gtk_label_new (NULL);
1685 gtk_label_set_markup (GTK_LABEL (label_w), label);
1686 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1687 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1691 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1693 _("mcen_fi_rootfolder_folders"),
1694 modest_tny_folder_store_get_folder_count (folder_store));
1695 label_w = gtk_label_new (NULL);
1696 gtk_label_set_markup (GTK_LABEL (label_w), label);
1697 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1698 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1702 if (modest_tny_account_is_virtual_local_folders (account)
1703 || modest_tny_account_is_memory_card_account (account)) {
1705 gchar *size = modest_text_utils_get_display_size (
1706 modest_tny_folder_store_get_local_size (folder_store));
1708 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1709 gray_color_markup, _("mcen_fi_rootfolder_size"),
1713 label_w = gtk_label_new (NULL);
1714 gtk_label_set_markup (GTK_LABEL (label_w), label);
1715 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1716 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1718 } else if (TNY_IS_ACCOUNT(folder_store)) {
1719 TnyAccount *account = TNY_ACCOUNT(folder_store);
1721 time_t last_updated;
1722 const gchar *last_updated_string;
1723 /* Get last updated from configuration */
1724 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1725 tny_account_get_id (account));
1727 if (last_updated > 0)
1728 last_updated_string = modest_text_utils_get_display_date(last_updated);
1730 last_updated_string = g_strdup (_("mcen_va_never"));
1732 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1733 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1734 label_w = gtk_label_new (NULL);
1735 gtk_label_set_markup (GTK_LABEL (label_w), label);
1736 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1737 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1741 g_free (gray_color_markup);
1744 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1750 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1752 ModestMainWindowPrivate *priv = NULL;
1754 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1756 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1758 return priv->send_receive_in_progress;
1762 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1764 GtkAction *action = NULL;
1765 GtkWidget *widget = NULL;
1766 ModestMainWindowPrivate *priv = NULL;
1768 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1769 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1771 priv->send_receive_in_progress = TRUE;
1773 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1774 gtk_action_set_sensitive (action, FALSE);
1775 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1776 /* gtk_action_set_sensitive (action, FALSE); */
1777 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1778 gtk_widget_set_sensitive (widget, FALSE);
1782 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1784 GtkAction *action = NULL;
1785 GtkWidget *widget = NULL;
1786 ModestMainWindowPrivate *priv = NULL;
1788 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1789 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1791 priv->send_receive_in_progress = FALSE;
1793 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1794 gtk_action_set_sensitive (action, TRUE);
1795 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1796 /* gtk_action_set_sensitive (action, TRUE); */
1797 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1798 gtk_widget_set_sensitive (widget, TRUE);
1803 on_msg_count_changed (ModestHeaderView *header_view,
1805 TnyFolderChange *change,
1806 ModestMainWindow *main_window)
1808 gboolean folder_empty = FALSE;
1809 gboolean all_marked_as_deleted = FALSE;
1810 TnyFolderChangeChanged changed;
1811 ModestMainWindowPrivate *priv;
1813 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1814 g_return_if_fail (TNY_IS_FOLDER(folder));
1815 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1816 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1818 changed = tny_folder_change_get_changed (change);
1820 /* If something changes */
1821 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1822 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1824 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1826 /* Check header removed (hide marked as DELETED headers) */
1827 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1828 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1831 /* Check if all messages are marked to be deleted */
1832 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1833 folder_empty = folder_empty || all_marked_as_deleted ;
1835 /* Set contents style of headers view */
1837 modest_main_window_set_contents_style (main_window,
1838 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1839 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1842 modest_main_window_set_contents_style (main_window,
1843 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1849 modest_main_window_set_contents_style (ModestMainWindow *self,
1850 ModestMainWindowContentsStyle style)
1852 ModestMainWindowPrivate *priv;
1854 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1856 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1858 /* We allow to set the same content style than the previously
1859 set if there are details, because it could happen when we're
1860 selecting different accounts consecutively */
1861 if ((priv->contents_style == style) &&
1862 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1865 /* Remove previous child. Delete it if it was an account
1867 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1869 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1870 g_object_ref (content);
1871 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1872 g_object_ref (priv->empty_view);
1873 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1876 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1879 priv->contents_style = style;
1881 switch (priv->contents_style) {
1882 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1883 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1884 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1887 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1889 /* if we're started without main win, there may not be a folder
1890 * view. this fixes a GLib-Critical */
1891 if (priv->folder_view) {
1892 TnyFolderStore *selected_folderstore =
1893 modest_folder_view_get_selected (priv->folder_view);
1894 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1895 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1896 TNY_ACCOUNT (selected_folderstore));
1898 wrap_in_scrolled_window (priv->contents_widget,
1899 priv->details_widget);
1901 g_object_unref (selected_folderstore);
1902 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1907 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1908 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1909 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1913 g_return_if_reached ();
1917 gtk_widget_show_all (priv->contents_widget);
1920 ModestMainWindowContentsStyle
1921 modest_main_window_get_contents_style (ModestMainWindow *self)
1923 ModestMainWindowPrivate *priv;
1925 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1927 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1928 return priv->contents_style;
1933 on_configuration_key_changed (ModestConf* conf,
1935 ModestConfEvent event,
1936 ModestConfNotificationId id,
1937 ModestMainWindow *self)
1939 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1940 TnyAccount *account = NULL;
1942 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1945 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1948 if (priv->folder_view)
1949 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1951 if (account && TNY_IS_ACCOUNT (account) &&
1952 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1955 const gchar *device_name;
1956 gchar *new_text, *gray_color_markup;
1959 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1960 label = GTK_LABEL (children->data);
1962 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1963 MODEST_CONF_DEVICE_NAME, NULL);
1965 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1966 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1968 gtk_label_set_markup (label, new_text);
1969 gtk_widget_show (GTK_WIDGET (label));
1971 g_free (gray_color_markup);
1973 g_list_free (children);
1975 g_object_unref (account);
1979 set_toolbar_transfer_mode (ModestMainWindow *self)
1981 ModestMainWindowPrivate *priv = NULL;
1983 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1985 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1987 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1989 if (priv->progress_bar_timeout > 0) {
1990 g_source_remove (priv->progress_bar_timeout);
1991 priv->progress_bar_timeout = 0;
1998 set_toolbar_mode (ModestMainWindow *self,
1999 ModestToolBarModes mode)
2001 ModestWindowPrivate *parent_priv = NULL;
2002 ModestMainWindowPrivate *priv = NULL;
2003 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2005 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2007 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2008 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2010 /* In case this was called before the toolbar exists: */
2011 if (!(parent_priv->toolbar))
2014 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2016 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2017 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2018 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2020 /* Sets current toolbar mode */
2021 priv->current_toolbar_mode = mode;
2023 /* Checks the dimming rules */
2024 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2026 /* Show and hide toolbar items */
2028 case TOOLBAR_MODE_NORMAL:
2030 gtk_action_set_visible (sort_action, TRUE);
2032 gtk_action_set_visible (refresh_action, TRUE);
2033 if (priv->progress_toolitem) {
2034 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2035 gtk_widget_hide (priv->progress_toolitem);
2037 if (priv->progress_bar)
2038 gtk_widget_hide (priv->progress_bar);
2041 gtk_action_set_visible (cancel_action, FALSE);
2043 /* Hide toolbar if optimized view is enabled */
2044 if (priv->optimized_view)
2045 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2047 case TOOLBAR_MODE_TRANSFER:
2049 gtk_action_set_visible (sort_action, FALSE);
2051 gtk_action_set_visible (refresh_action, FALSE);
2053 gtk_action_set_visible (cancel_action, TRUE);
2054 if (priv->progress_bar)
2055 gtk_widget_show (priv->progress_bar);
2056 if (priv->progress_toolitem) {
2057 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2058 gtk_widget_show (priv->progress_toolitem);
2061 /* Show toolbar if it's hiden (optimized view ) */
2062 if (priv->optimized_view)
2063 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2066 g_return_if_reached ();
2071 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2073 ModestMainWindowPrivate *priv;
2075 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2076 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2078 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2082 cancel_progressbar (GtkToolButton *toolbutton,
2083 ModestMainWindow *self)
2086 ModestMainWindowPrivate *priv;
2088 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2090 /* Get operation observers and cancel all the operations */
2091 tmp = priv->progress_widgets;
2093 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2094 tmp=g_slist_next(tmp);
2099 observers_empty (ModestMainWindow *self)
2102 ModestMainWindowPrivate *priv;
2103 gboolean is_empty = TRUE;
2104 guint pending_ops = 0;
2106 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2107 tmp = priv->progress_widgets;
2109 /* Check all observers */
2110 while (tmp && is_empty) {
2111 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2112 is_empty = pending_ops == 0;
2114 tmp = g_slist_next(tmp);
2122 * Gets the toolbar mode needed for each mail operation. It stores in
2123 * @mode_changed if the toolbar mode has changed or not
2125 static ModestToolBarModes
2126 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2127 ModestMailOperation *mail_op,
2128 gboolean *mode_changed)
2130 ModestToolBarModes mode;
2131 ModestMainWindowPrivate *priv;
2133 *mode_changed = FALSE;
2134 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2136 /* Get toolbar mode from operation id*/
2137 switch (modest_mail_operation_get_type_operation (mail_op)) {
2138 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2139 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2140 mode = TOOLBAR_MODE_TRANSFER;
2141 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2142 *mode_changed = TRUE;
2145 mode = TOOLBAR_MODE_NORMAL;
2151 on_mail_operation_started (ModestMailOperation *mail_op,
2154 ModestMainWindow *self;
2155 ModestMailOperationTypeOperation op_type;
2156 ModestMainWindowPrivate *priv;
2157 ModestToolBarModes mode;
2159 gboolean mode_changed = FALSE;
2160 TnyAccount *account;
2162 self = MODEST_MAIN_WINDOW (user_data);
2163 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2165 /* Do not show progress for receiving operations if the
2166 account is the local account or the MMC one */
2167 op_type = modest_mail_operation_get_type_operation (mail_op);
2168 account = modest_mail_operation_get_account (mail_op);
2169 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2172 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2173 modest_tny_account_is_memory_card_account (account));
2174 g_object_unref (account);
2179 /* Get toolbar mode from operation id*/
2180 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2182 /* Add operation observers and change toolbar if neccessary*/
2183 tmp = priv->progress_widgets;
2184 if (mode == TOOLBAR_MODE_TRANSFER) {
2186 set_toolbar_transfer_mode(self);
2189 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2191 tmp = g_slist_next (tmp);
2197 on_mail_operation_finished (ModestMailOperation *mail_op,
2200 ModestToolBarModes mode;
2201 ModestMailOperationTypeOperation op_type;
2203 ModestMainWindow *self;
2204 gboolean mode_changed;
2205 TnyAccount *account;
2206 ModestMainWindowPrivate *priv;
2208 self = MODEST_MAIN_WINDOW (user_data);
2209 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2211 /* The mail operation was not added to the progress objects if
2212 the account was the local account or the MMC one */
2213 op_type = modest_mail_operation_get_type_operation (mail_op);
2214 account = modest_mail_operation_get_account (mail_op);
2215 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2218 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2219 modest_tny_account_is_memory_card_account (account));
2220 g_object_unref (account);
2225 /* Get toolbar mode from operation id*/
2226 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2228 /* Change toolbar mode */
2229 tmp = priv->progress_widgets;
2230 if (mode == TOOLBAR_MODE_TRANSFER) {
2232 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2234 tmp = g_slist_next (tmp);
2237 /* If no more operations are being observed, NORMAL mode is enabled again */
2238 if (observers_empty (self)) {
2239 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2245 on_queue_changed (ModestMailOperationQueue *queue,
2246 ModestMailOperation *mail_op,
2247 ModestMailOperationQueueNotification type,
2248 ModestMainWindow *self)
2250 ModestMainWindowPrivate *priv;
2252 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2254 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2255 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2257 "operation-started",
2258 G_CALLBACK (on_mail_operation_started),
2260 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2262 "operation-finished",
2263 G_CALLBACK (on_mail_operation_finished),
2265 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2266 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2268 "operation-started");
2269 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2271 "operation-finished");
2276 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2278 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2280 ModestAccountMgr *mgr;
2281 ModestAccountSettings *settings;
2282 ModestServerAccountSettings *store_settings = NULL;
2284 /* Get account data */
2285 mgr = modest_runtime_get_account_mgr ();
2286 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2288 store_settings = modest_account_settings_get_store_settings (settings);
2290 /* Set the new visible & active account */
2291 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2292 const gchar *account_name;
2294 account_name = modest_account_settings_get_account_name (settings);
2296 modest_folder_view_set_account_id_of_visible_server_account
2298 modest_server_account_settings_get_account_name (store_settings));
2299 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2300 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2301 if (action != NULL) {
2302 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2303 modest_utils_toggle_action_set_active_block_notify (
2304 GTK_TOGGLE_ACTION (action),
2310 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2315 g_object_unref (store_settings);
2316 g_object_unref (settings);
2320 /* Make sure that at least one account is "viewed": */
2322 set_at_least_one_account_visible(ModestMainWindow *self)
2324 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2325 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2327 if (!(priv->folder_view)) {
2328 /* It is too early to do this. */
2332 const gchar *active_server_account_name =
2333 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2335 if (!active_server_account_name ||
2336 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2338 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2339 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2340 if (default_modest_name) {
2341 set_account_visible (self, default_modest_name);
2342 } else if (first_modest_name) {
2343 set_account_visible (self, first_modest_name);
2345 g_free (first_modest_name);
2346 g_free (default_modest_name);
2351 on_show_account_action_toggled (GtkToggleAction *action,
2354 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2356 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2357 if (gtk_toggle_action_get_active (action))
2358 set_account_visible (self, acc_name);
2362 refresh_account (const gchar *account_name)
2366 /* win must already exists here, obviously */
2367 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2370 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2374 /* If account_name == NULL, we must update all (option All) */
2376 modest_ui_actions_do_send_receive_all (win);
2378 modest_ui_actions_do_send_receive (account_name, win);
2383 on_refresh_account_action_activated (GtkAction *action,
2386 refresh_account ((const gchar*) user_data);
2390 on_send_receive_csm_activated (GtkMenuItem *item,
2393 refresh_account ((const gchar*) user_data);
2397 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2399 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2401 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2407 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2409 ModestMainWindow *main_window = NULL;
2411 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2412 main_window = MODEST_MAIN_WINDOW (userdata);
2414 /* Update toolbar dimming state */
2415 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2421 on_header_view_focus_in (GtkWidget *widget,
2422 GdkEventFocus *event,
2425 ModestMainWindow *main_window = NULL;
2427 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2429 main_window = MODEST_MAIN_WINDOW (userdata);
2431 /* Update toolbar dimming state */
2432 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2438 on_folder_selection_changed (ModestFolderView *folder_view,
2439 TnyFolderStore *folder_store,
2441 ModestMainWindow *main_window)
2443 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2444 GtkAction *action = NULL;
2445 gboolean show_reply = TRUE;
2446 gboolean show_forward = TRUE;
2447 gboolean show_cancel_send = FALSE;
2448 gboolean show_clipboard = TRUE;
2449 gboolean show_delete = TRUE;
2452 if (TNY_IS_ACCOUNT (folder_store)) {
2453 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2454 } else if (TNY_IS_FOLDER (folder_store)) {
2455 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2456 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2457 TNY_FOLDER (folder_store));
2458 switch (folder_type) {
2459 case TNY_FOLDER_TYPE_DRAFTS:
2460 show_clipboard = show_delete = TRUE;
2461 show_reply = show_forward = show_cancel_send = FALSE;
2463 case TNY_FOLDER_TYPE_SENT:
2464 show_forward = show_clipboard = show_delete = TRUE;
2465 show_reply = show_cancel_send = FALSE;
2467 case TNY_FOLDER_TYPE_OUTBOX:
2468 show_clipboard = show_delete = show_cancel_send = TRUE;
2469 show_reply = show_forward = FALSE;
2471 case TNY_FOLDER_TYPE_INVALID:
2472 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2475 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2476 show_cancel_send = FALSE;
2479 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2480 show_cancel_send = FALSE;
2485 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2486 gtk_action_set_visible (action, show_reply);
2487 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2488 gtk_action_set_visible (action, show_reply);
2489 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2490 gtk_action_set_visible (action, show_forward);
2491 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2492 gtk_action_set_visible (action, show_cancel_send);
2493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2494 gtk_action_set_visible (action, show_delete);
2496 /* We finally call to the ui actions handler, after updating properly
2497 * the header view CSM */
2498 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2502 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2503 GtkTreeModel *model,
2504 GtkTreeRowReference *row_reference,
2505 ModestMainWindow *self)
2507 ModestMainWindowPrivate *priv = NULL;
2508 GtkTreeModel *header_model = NULL;
2509 GtkTreePath *path = NULL;
2511 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2512 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2513 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2515 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2516 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2518 /* Do nothing if we changed the folder in the main view */
2519 if (header_model != model)
2522 /* Select the message in the header view */
2523 path = gtk_tree_row_reference_get_path (row_reference);
2524 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2526 gtk_tree_path_free (path);
2532 show_updating_banner (gpointer user_data)
2534 ModestMainWindowPrivate *priv = NULL;
2536 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2538 if (priv->updating_banner == NULL) {
2540 /* We're outside the main lock */
2541 gdk_threads_enter ();
2542 priv->updating_banner =
2543 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2544 _CS ("ckdg_pb_updating"));
2545 gdk_threads_leave ();
2548 /* Remove timeout */
2549 priv->updating_banner_timeout = 0;
2554 * We use this function to show/hide a progress banner showing
2555 * "Updating" while the header view is being filled. We're not showing
2556 * it unless the update takes more than 2 seconds
2558 * If starting = TRUE then the refresh is starting, otherwise it means
2559 * that is has just finished
2562 on_updating_msg_list (ModestHeaderView *header_view,
2566 ModestMainWindowPrivate *priv = NULL;
2568 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2570 /* Remove old timeout */
2571 if (priv->updating_banner_timeout > 0) {
2572 g_source_remove (priv->updating_banner_timeout);
2573 priv->updating_banner_timeout = 0;
2576 /* Create a new timeout */
2578 priv->updating_banner_timeout =
2579 g_timeout_add (2000, show_updating_banner, user_data);
2581 /* Remove the banner if exists */
2582 if (priv->updating_banner) {
2583 gtk_widget_destroy (priv->updating_banner);
2584 priv->updating_banner = NULL;