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 #ifdef MODEST_HAVE_HILDON0_WIDGETS
70 #include <hildon-widgets/hildon-program.h>
72 #include <hildon/hildon-program.h>
73 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
75 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
82 /* 'private'/'protected' functions */
83 static void modest_main_window_class_init (ModestMainWindowClass *klass);
84 static void modest_main_window_init (ModestMainWindow *obj);
85 static void modest_main_window_finalize (GObject *obj);
87 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
88 GdkEventWindowState *event,
91 static void connect_signals (ModestMainWindow *self);
93 static void modest_main_window_disconnect_signals (ModestWindow *self);
95 static void restore_settings (ModestMainWindow *self,
96 gboolean do_folder_view_too);
98 static void save_state (ModestWindow *self);
100 static void update_menus (ModestMainWindow* self);
102 static void modest_main_window_show_toolbar (ModestWindow *window,
103 gboolean show_toolbar);
105 static void cancel_progressbar (GtkToolButton *toolbutton,
106 ModestMainWindow *self);
108 static void on_queue_changed (ModestMailOperationQueue *queue,
109 ModestMailOperation *mail_op,
110 ModestMailOperationQueueNotification type,
111 ModestMainWindow *self);
113 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
116 on_account_inserted (TnyAccountStore *accoust_store,
121 on_account_removed (TnyAccountStore *accoust_store,
125 static void on_default_account_changed (ModestAccountMgr* mgr,
128 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
132 static void on_configuration_key_changed (ModestConf* conf,
134 ModestConfEvent event,
135 ModestConfNotificationId id,
136 ModestMainWindow *self);
138 static void set_toolbar_mode (ModestMainWindow *self,
139 ModestToolBarModes mode);
141 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
143 static void on_show_account_action_toggled (GtkToggleAction *action,
146 static void on_refresh_account_action_activated (GtkAction *action,
149 static void on_account_updated (ModestAccountMgr* mgr, gchar* account_name,
152 static void on_send_receive_csm_activated (GtkMenuItem *item,
155 static void on_msg_count_changed (ModestHeaderView *header_view,
157 TnyFolderChange *change,
158 ModestMainWindow *main_window);
160 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
163 static GtkWidget * create_empty_view (void);
165 static gboolean on_folder_view_focus_in (GtkWidget *widget,
166 GdkEventFocus *event,
169 static gboolean on_header_view_focus_in (GtkWidget *widget,
170 GdkEventFocus *event,
173 static void on_folder_selection_changed (ModestFolderView *folder_view,
174 TnyFolderStore *folder_store,
176 ModestMainWindow *main_window);
178 static void set_at_least_one_account_visible(ModestMainWindow *self);
180 static void on_updating_msg_list (ModestHeaderView *header_view,
184 static gboolean restore_paned_timeout_handler (gpointer *data);
186 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
187 struct _ModestMainWindowPrivate {
188 GtkWidget *msg_paned;
189 GtkWidget *main_paned;
190 GtkWidget *main_vbox;
191 GtkWidget *contents_widget;
192 GtkWidget *empty_view;
194 /* Progress observers */
195 GtkWidget *progress_bar;
196 GSList *progress_widgets;
199 GtkWidget *progress_toolitem;
200 GtkWidget *cancel_toolitem;
201 GtkWidget *sort_toolitem;
202 GtkWidget *refresh_toolitem;
203 ModestToolBarModes current_toolbar_mode;
205 /* Merge ids used to add/remove accounts to the ViewMenu*/
206 GByteArray *merge_ids;
207 GtkActionGroup *view_additions_group;
209 /* On-demand widgets */
210 GtkWidget *accounts_popup;
211 GtkWidget *details_widget;
213 /* Optimized view enabled */
214 gboolean optimized_view;
216 /* Optimized view enabled */
217 gboolean send_receive_in_progress;
219 ModestHeaderView *header_view;
220 ModestFolderView *folder_view;
222 ModestMainWindowStyle style;
223 ModestMainWindowContentsStyle contents_style;
225 guint progress_bar_timeout;
226 guint restore_paned_timeout;
228 /* Signal handler UIDs */
229 GList *queue_err_signals;
232 /* "Updating" banner for header view */
233 GtkWidget *updating_banner;
234 guint updating_banner_timeout;
236 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
237 MODEST_TYPE_MAIN_WINDOW, \
238 ModestMainWindowPrivate))
240 typedef struct _GetMsgAsyncHelper {
241 ModestMainWindowPrivate *main_window_private;
243 ModestTnyMsgReplyType reply_type;
244 ModestTnyMsgForwardType forward_type;
251 static GtkWindowClass *parent_class = NULL;
254 /* Private actions */
255 /* This is the context sensitive menu: */
256 static const GtkActionEntry modest_folder_view_action_entries [] = {
258 /* Folder View CSM actions */
259 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
260 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
261 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
262 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
263 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
264 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
267 static const GtkActionEntry modest_header_view_action_entries [] = {
269 /* Header View CSM actions */
270 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
271 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
272 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
273 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
274 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
275 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
276 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
277 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
278 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
279 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
282 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
283 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
286 /************************************************************************/
289 modest_main_window_get_type (void)
291 static GType my_type = 0;
293 static const GTypeInfo my_info = {
294 sizeof(ModestMainWindowClass),
295 NULL, /* base init */
296 NULL, /* base finalize */
297 (GClassInitFunc) modest_main_window_class_init,
298 NULL, /* class finalize */
299 NULL, /* class data */
300 sizeof(ModestMainWindow),
302 (GInstanceInitFunc) modest_main_window_init,
305 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
313 modest_main_window_class_init (ModestMainWindowClass *klass)
315 GObjectClass *gobject_class;
316 gobject_class = (GObjectClass*) klass;
317 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
319 parent_class = g_type_class_peek_parent (klass);
320 gobject_class->finalize = modest_main_window_finalize;
322 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
324 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
325 modest_window_class->save_state_func = save_state;
326 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
327 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
328 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
332 modest_main_window_init (ModestMainWindow *obj)
334 ModestMainWindowPrivate *priv;
336 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
338 priv->queue_err_signals = NULL;
339 priv->msg_paned = NULL;
340 priv->main_paned = NULL;
341 priv->main_vbox = NULL;
342 priv->header_view = NULL;
343 priv->folder_view = NULL;
344 priv->contents_widget = NULL;
345 priv->accounts_popup = NULL;
346 priv->details_widget = NULL;
347 priv->empty_view = NULL;
348 priv->progress_widgets = NULL;
349 priv->progress_bar = NULL;
350 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
351 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
352 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
353 priv->merge_ids = NULL;
354 priv->optimized_view = FALSE;
355 priv->send_receive_in_progress = FALSE;
356 priv->progress_bar_timeout = 0;
357 priv->restore_paned_timeout = 0;
358 priv->sighandlers = NULL;
359 priv->updating_banner = NULL;
360 priv->updating_banner_timeout = 0;
362 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
364 "applications_email_mainview");
368 modest_main_window_finalize (GObject *obj)
370 ModestMainWindowPrivate *priv;
372 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
374 /* Sanity check: shouldn't be needed, the window mgr should
375 call this function before */
376 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
378 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
380 g_slist_free (priv->progress_widgets);
382 g_byte_array_free (priv->merge_ids, TRUE);
384 if (priv->progress_bar_timeout > 0) {
385 g_source_remove (priv->progress_bar_timeout);
386 priv->progress_bar_timeout = 0;
389 if (priv->updating_banner_timeout > 0) {
390 g_source_remove (priv->updating_banner_timeout);
391 priv->updating_banner_timeout = 0;
394 if (priv->updating_banner) {
395 gtk_widget_destroy (priv->updating_banner);
396 priv->updating_banner = NULL;
399 if (priv->restore_paned_timeout > 0) {
400 g_source_remove (priv->restore_paned_timeout);
401 priv->restore_paned_timeout = 0;
404 G_OBJECT_CLASS(parent_class)->finalize (obj);
408 modest_main_window_get_child_widget (ModestMainWindow *self,
409 ModestMainWindowWidgetType widget_type)
411 ModestMainWindowPrivate *priv;
414 g_return_val_if_fail (self, NULL);
415 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
418 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
420 switch (widget_type) {
421 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
422 widget = (GtkWidget*)priv->header_view; break;
423 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
424 widget = (GtkWidget*)priv->folder_view; break;
429 return widget ? GTK_WIDGET(widget) : NULL;
433 restore_paned_timeout_handler (gpointer *data)
435 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
436 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
439 /* Timeouts are outside the main lock */
440 gdk_threads_enter ();
441 if (GTK_WIDGET_VISIBLE (main_window)) {
442 conf = modest_runtime_get_conf ();
443 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
444 MODEST_CONF_MAIN_PANED_KEY);
446 gdk_threads_leave ();
453 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
456 ModestMainWindowPrivate *priv;
458 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
460 conf = modest_runtime_get_conf ();
462 modest_widget_memory_restore (conf, G_OBJECT(self),
463 MODEST_CONF_MAIN_WINDOW_KEY);
465 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
466 MODEST_CONF_HEADER_VIEW_KEY);
468 if (do_folder_view_too)
469 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
470 MODEST_CONF_FOLDER_VIEW_KEY);
472 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
473 MODEST_CONF_MAIN_PANED_KEY);
475 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
477 /* We need to force a redraw here in order to get the right
478 position of the horizontal paned separator */
479 gtk_widget_show (GTK_WIDGET (self));
484 save_state (ModestWindow *window)
487 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
488 ModestMainWindowPrivate *priv;
490 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
491 conf = modest_runtime_get_conf ();
493 modest_widget_memory_save (conf,G_OBJECT(self),
494 MODEST_CONF_MAIN_WINDOW_KEY);
495 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
496 MODEST_CONF_MAIN_PANED_KEY);
497 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
498 // MODEST_CONF_HEADER_VIEW_KEY);
499 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
500 MODEST_CONF_FOLDER_VIEW_KEY);
504 compare_display_names (ModestAccountSettings *a,
505 ModestAccountSettings *b)
507 return strcmp (modest_account_settings_get_display_name (a),
508 modest_account_settings_get_display_name (b));
512 update_menus (ModestMainWindow* self)
514 GSList *account_names, *iter, *accounts;
515 ModestMainWindowPrivate *priv;
516 ModestWindowPrivate *parent_priv;
517 ModestAccountMgr *mgr;
518 gint i, num_accounts;
520 gchar *default_account;
521 const gchar *active_account_name;
522 GtkWidget *send_receive_button, *item;
523 GtkAction *send_receive_all = NULL;
526 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
527 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
529 /* Get enabled account IDs */
530 mgr = modest_runtime_get_account_mgr ();
531 account_names = modest_account_mgr_account_names (mgr, TRUE);
532 iter = account_names;
536 ModestAccountSettings *settings =
537 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
538 accounts = g_slist_prepend (accounts, settings);
542 modest_account_mgr_free_account_names (account_names);
543 account_names = NULL;
545 /* Order the list of accounts by its display name */
546 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
547 num_accounts = g_slist_length (accounts);
549 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
550 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
551 gtk_action_set_visible (send_receive_all, num_accounts > 0);
553 /* Delete old send&receive popup items. We can not just do a
554 menu_detach because it does not work well with
556 if (priv->accounts_popup)
557 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
558 (GtkCallback) gtk_widget_destroy, NULL);
560 /* Delete old entries in the View menu. Do not free groups, it
562 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
564 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
565 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
566 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
567 GTK_ACTION_GROUP (groups->data));
570 if (priv->merge_ids) {
571 for (i = 0; i < priv->merge_ids->len; i++)
572 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
573 g_byte_array_free (priv->merge_ids, TRUE);
575 /* We need to call this in order to ensure
576 that the new actions are added in the right
577 order (alphabetical) */
578 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
580 groups = g_list_next (groups);
582 priv->merge_ids = g_byte_array_sized_new (num_accounts);
584 /* Get send receive button */
585 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
586 "/ToolBar/ToolbarSendReceive");
588 /* Create the menu */
589 if (num_accounts > 1) {
590 if (!priv->accounts_popup)
591 priv->accounts_popup = gtk_menu_new ();
592 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
593 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
594 g_signal_connect (G_OBJECT (item),
596 G_CALLBACK (on_send_receive_csm_activated),
598 item = gtk_separator_menu_item_new ();
599 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
602 /* Create a new action group */
603 default_account = modest_account_mgr_get_default_account (mgr);
604 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
606 if (!active_account_name)
607 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
609 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
611 for (i = 0; i < num_accounts; i++) {
612 gchar *display_name = NULL;
613 const gchar *account_name;
614 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
617 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
620 account_name = modest_account_settings_get_account_name (settings);
622 if (default_account && account_name &&
623 !(strcmp (default_account, account_name) == 0)) {
624 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
625 modest_account_settings_get_display_name (settings));
627 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
628 modest_account_settings_get_display_name (settings));
631 /* Create action and add it to the action group. The
632 action name must be the account name, this way we
633 could know in the handlers the account to show */
634 if (settings && account_name) {
635 gchar* item_name, *refresh_action_name;
637 GtkAction *view_account_action, *refresh_account_action;
639 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
640 display_name, NULL, NULL, 0));
641 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
642 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
643 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
645 if (active_account_name) {
646 if (active_account_name && account_name &&
647 (strcmp (active_account_name, account_name) == 0)) {
648 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
652 /* Add ui from account data. We allow 2^9-1 account
653 changes in a single execution because we're
654 downcasting the guint to a guint8 in order to use a
655 GByteArray. It should be enough. */
656 item_name = g_strconcat (account_name, "Menu", NULL);
657 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
658 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
659 gtk_ui_manager_add_ui (parent_priv->ui_manager,
661 "/MenuBar/ViewMenu/ViewMenuAdditions",
664 GTK_UI_MANAGER_MENUITEM,
667 /* Connect the action signal "activate" */
668 g_signal_connect_after (G_OBJECT (view_account_action),
670 G_CALLBACK (on_show_account_action_toggled),
673 /* Create the items for the Tools->Send&Receive submenu */
674 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
675 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
676 display_name, NULL, NULL);
677 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
679 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
680 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
681 gtk_ui_manager_add_ui (parent_priv->ui_manager,
683 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
686 GTK_UI_MANAGER_MENUITEM,
688 g_free (refresh_action_name);
690 g_signal_connect_data (G_OBJECT (refresh_account_action),
692 G_CALLBACK (on_refresh_account_action_activated),
693 g_strdup (account_name),
694 (GClosureNotify) g_free,
697 /* Create item and add it to the send&receive
698 CSM. If there is only one account then
700 if (priv->accounts_popup) {
701 GtkWidget *label = gtk_label_new(NULL);
702 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
703 if (default_account && (strcmp(account_name, default_account) == 0))
705 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
706 gtk_label_set_markup (GTK_LABEL (label), escaped);
711 gtk_label_set_text (GTK_LABEL (label), display_name);
714 item = gtk_menu_item_new ();
715 gtk_container_add (GTK_CONTAINER (item), label);
717 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
718 g_signal_connect_data (G_OBJECT (item),
720 G_CALLBACK (on_send_receive_csm_activated),
721 g_strdup (account_name),
722 (GClosureNotify) g_free,
729 g_free (display_name);
732 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
734 /* We cannot do this in the loop above because this relies on the action
735 * group being inserted. This makes the default account appear in bold.
736 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
737 for (i = 0; i < num_accounts; i++) {
738 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
739 const gchar *account_name;
741 account_name = modest_account_settings_get_account_name (settings);
743 if(account_name && default_account &&
744 strcmp (account_name, default_account) == 0) {
745 gchar *item_name = g_strconcat (account_name, "Menu", NULL);
747 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
748 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
752 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
753 if (GTK_IS_LABEL (child)) {
754 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
755 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
756 gtk_label_set_markup (GTK_LABEL (child), bold_name);
761 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
762 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
766 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
767 if (GTK_IS_LABEL (child)) {
768 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
769 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
770 gtk_label_set_markup (GTK_LABEL (child), bold_name);
778 g_object_unref (settings);
781 if (priv->accounts_popup) {
782 /* Mandatory in order to view the menu contents */
783 gtk_widget_show_all (priv->accounts_popup);
785 /* Setup tap_and_hold just if was not done before*/
786 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
787 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
791 g_slist_free (accounts);
792 g_free (default_account);
795 /* Make sure that at least one account is viewed if there are any
796 * accounts, for instance when adding the first account: */
797 set_at_least_one_account_visible (self);
801 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
803 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
804 gtk_scrolled_window_add_with_viewport
805 (GTK_SCROLLED_WINDOW(win), widget);
807 gtk_container_add (GTK_CONTAINER(win),
818 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
820 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
822 GList *oerrsignals = priv->queue_err_signals;
823 while (oerrsignals) {
824 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
825 g_signal_handler_disconnect (esignal->queue, esignal->signal);
826 g_slice_free (QueueErrorSignal, esignal);
827 oerrsignals = g_list_next (oerrsignals);
829 g_list_free (priv->queue_err_signals);
830 priv->queue_err_signals = NULL;
835 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
837 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
840 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
844 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
846 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
848 /* Update visibility */
851 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
855 modest_main_window_disconnect_signals (ModestWindow *self)
857 ModestMainWindowPrivate *priv;
858 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
860 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
861 priv->sighandlers = NULL;
865 connect_signals (ModestMainWindow *self)
867 ModestWindowPrivate *parent_priv;
868 ModestMainWindowPrivate *priv;
871 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
872 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
877 modest_signal_mgr_connect (priv->sighandlers,
878 G_OBJECT(priv->folder_view), "key-press-event",
879 G_CALLBACK(on_inner_widgets_key_pressed), self);
881 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
882 "folder_selection_changed",
883 G_CALLBACK (on_folder_selection_changed),
886 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
887 "folder-display-name-changed",
888 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
891 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
893 G_CALLBACK (on_folder_view_focus_in),
896 /* Folder view CSM */
897 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
898 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
899 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
900 G_CALLBACK(_folder_view_csm_menu_activated),
904 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
905 G_CALLBACK(modest_ui_actions_on_header_selected), self);
907 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
908 G_CALLBACK(modest_ui_actions_on_header_activated), self);
910 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
911 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
913 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
914 G_CALLBACK(on_inner_widgets_key_pressed), self);
916 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
917 G_CALLBACK(on_msg_count_changed), self);
919 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
920 G_CALLBACK (on_header_view_focus_in), self);
922 modest_signal_mgr_connect (priv->sighandlers,
923 G_OBJECT (priv->header_view),
925 G_CALLBACK (on_updating_msg_list),
928 /* Header view CSM */
929 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
930 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
932 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
933 G_CALLBACK(_header_view_csm_menu_activated),
938 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
939 G_CALLBACK (modest_main_window_window_state_event),
942 /* Mail Operation Queue */
944 modest_signal_mgr_connect (priv->sighandlers,
945 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
947 G_CALLBACK (on_queue_changed), self);
949 /* Track changes in the device name */
951 modest_signal_mgr_connect (priv->sighandlers,
952 G_OBJECT(modest_runtime_get_conf ()),
954 G_CALLBACK (on_configuration_key_changed),
957 /* Track account changes. We need to refresh the toolbar */
959 modest_signal_mgr_connect (priv->sighandlers,
960 G_OBJECT (modest_runtime_get_account_store ()),
962 G_CALLBACK (on_account_inserted),
965 modest_signal_mgr_connect (priv->sighandlers,
966 G_OBJECT (modest_runtime_get_account_store ()),
968 G_CALLBACK (on_account_removed),
971 /* We need to refresh the send & receive menu to change the bold
972 * account when the default account changes. */
974 modest_signal_mgr_connect (priv->sighandlers,
975 G_OBJECT (modest_runtime_get_account_mgr ()),
976 "default_account_changed",
977 G_CALLBACK (on_default_account_changed),
981 modest_signal_mgr_connect (priv->sighandlers,
982 G_OBJECT (modest_runtime_get_account_mgr ()),
984 G_CALLBACK (on_account_updated),
988 modest_signal_mgr_connect (priv->sighandlers,
989 G_OBJECT (modest_runtime_get_account_store()),
990 "password_requested",
991 G_CALLBACK (modest_ui_actions_on_password_requested),
996 /** Idle handler, to send/receive at startup .*/
998 sync_accounts_cb (ModestMainWindow *win)
1000 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
1001 return FALSE; /* Do not call this idle handler again. */
1006 on_hildon_program_is_topmost_notify(GObject *self,
1007 GParamSpec *propert_param, gpointer user_data)
1009 HildonProgram *app = HILDON_PROGRAM (self);
1012 ModestWindow* self = MODEST_WINDOW(user_data);
1015 /* Note that use of hildon_program_set_can_hibernate()
1016 * is generally referred to as "setting the killable flag",
1017 * though hibernation does not seem equal to death.
1020 if (hildon_program_get_is_topmost (app)) {
1021 /* Prevent hibernation when the progam comes to the foreground,
1022 * because hibernation should only happen when the application
1023 * is in the background: */
1024 hildon_program_set_can_hibernate (app, FALSE);
1026 /* Allow hibernation if the program has gone to the background: */
1028 /* However, prevent hibernation while the settings are being changed: */
1029 const gboolean hibernation_prevented =
1030 modest_window_mgr_get_hibernation_is_prevented (
1031 modest_runtime_get_window_mgr ());
1033 if (hibernation_prevented)
1034 hildon_program_set_can_hibernate (app, FALSE);
1036 /* Allow hibernation, after saving the state: */
1037 modest_osso_save_state();
1038 hildon_program_set_can_hibernate (app, TRUE);
1045 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1047 GtkWidget *folder_win = (GtkWidget *) user_data;
1048 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1050 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1051 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1053 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1055 /* Connect signals */
1056 connect_signals (MODEST_MAIN_WINDOW (self));
1058 /* Set account store */
1059 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1060 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1062 /* Load previous osso state, for instance if we are being restored from
1064 modest_osso_load_state ();
1066 /* Restore window & widget settings */
1067 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1069 /* Check if accounts exist and show the account wizard if not */
1070 gboolean accounts_exist =
1071 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1073 if (!accounts_exist) {
1074 /* This is necessary to have the main window shown behind the dialog
1075 It's an ugly hack... jschmid */
1076 gtk_widget_show_all(GTK_WIDGET(self));
1077 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1080 GtkAction *send_receive_all;
1081 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1082 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1083 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1084 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1085 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1086 modest_account_mgr_free_account_names (accounts);
1087 update_menus (MODEST_MAIN_WINDOW (self));
1092 modest_main_window_new (void)
1094 ModestMainWindow *self = NULL;
1095 ModestMainWindowPrivate *priv = NULL;
1096 ModestWindowPrivate *parent_priv = NULL;
1097 GtkWidget *folder_win = NULL;
1098 ModestDimmingRulesGroup *menu_rules_group = NULL;
1099 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1100 GtkActionGroup *action_group = NULL;
1101 GError *error = NULL;
1102 ModestConf *conf = NULL;
1103 GtkAction *action = NULL;
1104 GdkPixbuf *window_icon;
1106 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1107 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1108 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1110 parent_priv->ui_manager = gtk_ui_manager_new();
1111 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1113 action_group = gtk_action_group_new ("ModestMainWindowActions");
1114 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1116 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1117 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1119 /* Add common actions */
1120 gtk_action_group_add_actions (action_group,
1121 modest_action_entries,
1122 G_N_ELEMENTS (modest_action_entries),
1125 gtk_action_group_add_actions (action_group,
1126 modest_folder_view_action_entries,
1127 G_N_ELEMENTS (modest_folder_view_action_entries),
1130 gtk_action_group_add_actions (action_group,
1131 modest_header_view_action_entries,
1132 G_N_ELEMENTS (modest_header_view_action_entries),
1135 gtk_action_group_add_toggle_actions (action_group,
1136 modest_toggle_action_entries,
1137 G_N_ELEMENTS (modest_toggle_action_entries),
1140 gtk_action_group_add_toggle_actions (action_group,
1141 modest_main_window_toggle_action_entries,
1142 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1145 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1146 g_object_unref (action_group);
1148 /* Load the UI definition */
1149 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1150 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1151 if (error != NULL) {
1152 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1153 g_error_free (error);
1157 /* Add common dimming rules */
1158 modest_dimming_rules_group_add_rules (menu_rules_group,
1159 modest_main_window_menu_dimming_entries,
1160 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1161 MODEST_WINDOW (self));
1162 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1163 modest_main_window_toolbar_dimming_entries,
1164 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1165 MODEST_WINDOW (self));
1167 /* Insert dimming rules group for this window */
1168 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1169 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1170 g_object_unref (menu_rules_group);
1171 g_object_unref (toolbar_rules_group);
1173 /* Add accelerators */
1174 gtk_window_add_accel_group (GTK_WINDOW (self),
1175 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1177 /* Menubar. Update the state of some toggles */
1178 parent_priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
1179 conf = modest_runtime_get_conf ();
1180 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1181 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1182 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1183 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1184 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1185 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1186 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1187 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1188 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1189 gtk_widget_show (parent_priv->menubar);
1191 /* Get device name */
1192 modest_maemo_utils_get_device_name ();
1196 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1197 if (!priv->header_view)
1198 g_printerr ("modest: cannot instantiate header view\n");
1199 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1200 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1201 MODEST_CONF_HEADER_VIEW_KEY);
1203 /* Other style properties of header view */
1204 g_object_set (G_OBJECT (priv->header_view),
1205 "rules-hint", FALSE,
1207 /* gtk_widget_show (priv->header_view); */
1210 priv->empty_view = create_empty_view ();
1211 gtk_widget_show (priv->empty_view);
1213 /* Create scrolled windows */
1214 folder_win = gtk_scrolled_window_new (NULL, NULL);
1215 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1216 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1218 GTK_POLICY_AUTOMATIC);
1219 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1221 GTK_POLICY_AUTOMATIC);
1222 /* gtk_widget_show (priv->contents_widget); */
1225 priv->main_paned = gtk_hpaned_new ();
1226 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1227 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1228 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1230 /* putting it all together... */
1231 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1232 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1233 gtk_widget_show (priv->main_vbox);
1235 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1237 HildonProgram *app = hildon_program_get_instance ();
1238 hildon_program_add_window (app, HILDON_WINDOW (self));
1240 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1241 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1243 g_signal_connect (G_OBJECT(self), "show",
1244 G_CALLBACK (modest_main_window_on_show), folder_win);
1246 /* Set window icon */
1247 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1249 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1250 g_object_unref (window_icon);
1253 /* Dont't restore settings here,
1254 * because it requires a gtk_widget_show(),
1255 * and we don't want to do that until later,
1256 * so that the UI is not visible for non-menu D-Bus activation.
1258 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1260 return MODEST_WINDOW(self);
1264 modest_main_window_set_style (ModestMainWindow *self,
1265 ModestMainWindowStyle style)
1267 ModestMainWindowPrivate *priv;
1268 ModestWindowPrivate *parent_priv;
1272 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1274 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1275 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1277 /* no change -> nothing to do */
1278 if (priv->style == style)
1281 /* Get toggle button and update the state if needed. This will
1282 happen only when the set_style is not invoked from the UI,
1283 for example when it's called from widget memory */
1284 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1285 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1286 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1287 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1288 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1289 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1290 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1293 priv->style = style;
1295 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1296 /* Remove main paned */
1297 g_object_ref (priv->main_paned);
1298 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1300 /* Reparent the contents widget to the main vbox */
1301 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1304 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1305 /* Remove header view */
1306 g_object_ref (priv->contents_widget);
1307 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1309 /* Reparent the main paned */
1310 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1311 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1315 g_return_if_reached ();
1318 /* Let header view grab the focus if it's being shown */
1319 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1320 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1322 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1325 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1328 ModestMainWindowStyle
1329 modest_main_window_get_style (ModestMainWindow *self)
1331 ModestMainWindowPrivate *priv;
1333 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1335 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1342 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1344 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1345 ModestWindowPrivate *parent_priv;
1346 ModestWindowMgr *mgr;
1347 gboolean is_fullscreen;
1348 GtkAction *fs_toggle_action;
1351 mgr = modest_runtime_get_window_mgr ();
1353 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1355 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1357 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1358 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1359 if (is_fullscreen != active) {
1360 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1369 set_homogeneous (GtkWidget *widget,
1372 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1373 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1377 modest_main_window_show_toolbar (ModestWindow *self,
1378 gboolean show_toolbar)
1380 ModestMainWindowPrivate *priv = NULL;
1381 ModestWindowPrivate *parent_priv = NULL;
1382 GtkWidget *reply_button = NULL, *menu = NULL;
1383 GtkWidget *placeholder = NULL;
1385 const gchar *action_name;
1388 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1389 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1390 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1392 /* Set optimized view status */
1393 priv->optimized_view = !show_toolbar;
1395 if (!parent_priv->toolbar) {
1396 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1398 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1400 /* Set homogeneous toolbar */
1401 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1402 set_homogeneous, NULL);
1404 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1405 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1406 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1407 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1408 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1409 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1410 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1411 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1413 /* Add ProgressBar (Transfer toolbar) */
1414 priv->progress_bar = modest_progress_bar_widget_new ();
1415 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1416 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1417 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1418 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1419 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1421 /* Connect cancel 'clicked' signal to abort progress mode */
1422 g_signal_connect(priv->cancel_toolitem, "clicked",
1423 G_CALLBACK(cancel_progressbar),
1426 /* Add it to the observers list */
1427 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1430 hildon_window_add_toolbar (HILDON_WINDOW (self),
1431 GTK_TOOLBAR (parent_priv->toolbar));
1433 /* Set reply button tap and hold menu */
1434 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1435 "/ToolBar/ToolbarMessageReply");
1436 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1437 "/ToolbarReplyCSM");
1438 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1440 /* Set send & receive button tap and hold menu */
1441 update_menus (MODEST_MAIN_WINDOW (self));
1445 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1446 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1447 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1449 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1450 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1451 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1453 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1455 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1459 /* Update also the actions (to update the toggles in the
1460 menus), we have to do it manually because some other window
1461 of the same time could have changed it (remember that the
1462 toolbar fullscreen mode is shared by all the windows of the
1464 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1465 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1467 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1469 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1470 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1475 on_account_inserted (TnyAccountStore *accoust_store,
1476 TnyAccount *account,
1479 update_menus (MODEST_MAIN_WINDOW (user_data));
1483 on_default_account_changed (ModestAccountMgr* mgr,
1486 update_menus (MODEST_MAIN_WINDOW (user_data));
1490 on_account_removed (TnyAccountStore *accoust_store,
1491 TnyAccount *account,
1494 update_menus (MODEST_MAIN_WINDOW (user_data));
1498 on_account_updated (ModestAccountMgr* mgr,
1499 gchar* account_name,
1502 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1504 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) {
1505 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1510 * This function manages the key events used to navigate between
1511 * header and folder views (when the window is in split view)
1514 * -------------------------------------------------
1515 * HeaderView GDK_Left Move focus to folder view
1516 * FolderView GDK_Right Move focus to header view
1518 * There is no need to scroll to selected row, the widgets will be the
1519 * responsibles of doing that (probably managing the focus-in event
1522 on_inner_widgets_key_pressed (GtkWidget *widget,
1526 ModestMainWindowPrivate *priv;
1528 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1530 /* Do nothing if we're in SIMPLE style */
1531 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1534 if (MODEST_IS_HEADER_VIEW (widget)) {
1535 if (event->keyval == GDK_Left)
1536 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1537 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1538 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1539 if (selected_headers > 1) {
1540 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1544 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1545 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1551 set_alignment (GtkWidget *widget,
1554 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1555 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1559 create_empty_view (void)
1561 GtkLabel *label = NULL;
1562 GtkWidget *align = NULL;
1564 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1565 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1566 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1567 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1569 return GTK_WIDGET(align);
1573 * Free the returned string
1576 get_gray_color_markup (GtkWidget *styled_widget)
1578 gchar *gray_color_markup = NULL;
1579 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1580 /* Obtain the secondary text color. We need a realized widget, that's why
1581 we get styled_widget from outside */
1583 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1584 gray_color_markup = modest_text_utils_get_color_string (&color);
1585 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1587 if (!gray_color_markup)
1588 gray_color_markup = g_strdup ("#BBBBBB");
1590 return gray_color_markup;
1594 * Free the returned string
1597 create_device_name_visual_string (const gchar *device_name,
1598 const gchar *gray_color_markup)
1602 /* We have to use "" to fill the %s of the translation. We can
1603 not just use the device name because the device name is
1604 shown in a different color, so it could not be included
1605 into the <span> tag */
1606 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1607 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1617 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1619 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1624 gchar *gray_color_markup;
1626 vbox = gtk_vbox_new (FALSE, 0);
1628 gray_color_markup = get_gray_color_markup (styled_widget);
1630 /* Account description: */
1631 if (modest_tny_account_is_virtual_local_folders (account)
1632 || (modest_tny_account_is_memory_card_account (account))) {
1634 /* Get device name */
1635 gchar *device_name = NULL;
1636 if (modest_tny_account_is_virtual_local_folders (account))
1637 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1638 MODEST_CONF_DEVICE_NAME, NULL);
1640 device_name = g_strdup (tny_account_get_name (account));
1642 label = create_device_name_visual_string ((const gchar *) device_name,
1643 (const gchar *) gray_color_markup);
1644 label_w = gtk_label_new (NULL);
1645 gtk_label_set_markup (GTK_LABEL (label_w), label);
1646 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1647 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1648 g_free (device_name);
1651 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1652 gtk_box_pack_start (GTK_BOX (vbox),
1653 gtk_label_new (tny_account_get_name (account)),
1656 /* Other accounts, such as IMAP and POP: */
1661 /* Put proto in uppercase */
1662 proto = g_string_new (tny_account_get_proto (account));
1663 proto = g_string_ascii_up (proto);
1665 /* note: mcen_fi_localroot_description is something like "%s account"
1666 * however, we should display "%s account: %s"... therefore, ugly tmp */
1667 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1668 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1669 gray_color_markup, tmp, tny_account_get_name (account));
1672 label_w = gtk_label_new (NULL);
1673 gtk_label_set_markup (GTK_LABEL (label_w), label);
1674 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1675 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1676 g_string_free (proto, TRUE);
1682 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1683 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1684 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1685 modest_tny_folder_store_get_message_count (folder_store));
1686 label_w = gtk_label_new (NULL);
1687 gtk_label_set_markup (GTK_LABEL (label_w), label);
1688 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1689 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1693 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1695 _("mcen_fi_rootfolder_folders"),
1696 modest_tny_folder_store_get_folder_count (folder_store));
1697 label_w = gtk_label_new (NULL);
1698 gtk_label_set_markup (GTK_LABEL (label_w), label);
1699 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1700 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1704 if (modest_tny_account_is_virtual_local_folders (account)
1705 || modest_tny_account_is_memory_card_account (account)) {
1707 gchar *size = modest_text_utils_get_display_size (
1708 modest_tny_folder_store_get_local_size (folder_store));
1710 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1711 gray_color_markup, _("mcen_fi_rootfolder_size"),
1715 label_w = gtk_label_new (NULL);
1716 gtk_label_set_markup (GTK_LABEL (label_w), label);
1717 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1718 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1720 } else if (TNY_IS_ACCOUNT(folder_store)) {
1721 TnyAccount *account = TNY_ACCOUNT(folder_store);
1723 time_t last_updated;
1724 const gchar *last_updated_string;
1725 /* Get last updated from configuration */
1726 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1727 tny_account_get_id (account));
1729 if (last_updated > 0)
1730 last_updated_string = modest_text_utils_get_display_date(last_updated);
1732 last_updated_string = g_strdup (_("mcen_va_never"));
1734 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1735 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1736 label_w = gtk_label_new (NULL);
1737 gtk_label_set_markup (GTK_LABEL (label_w), label);
1738 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1739 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1743 g_free (gray_color_markup);
1746 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1752 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1754 ModestMainWindowPrivate *priv = NULL;
1756 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1758 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1760 return priv->send_receive_in_progress;
1764 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1766 GtkAction *action = NULL;
1767 GtkWidget *widget = NULL;
1768 ModestMainWindowPrivate *priv = NULL;
1770 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1771 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1773 priv->send_receive_in_progress = TRUE;
1775 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1776 gtk_action_set_sensitive (action, FALSE);
1777 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1778 /* gtk_action_set_sensitive (action, FALSE); */
1779 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1780 gtk_widget_set_sensitive (widget, FALSE);
1784 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1786 GtkAction *action = NULL;
1787 GtkWidget *widget = NULL;
1788 ModestMainWindowPrivate *priv = NULL;
1790 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1791 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1793 priv->send_receive_in_progress = FALSE;
1795 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1796 gtk_action_set_sensitive (action, TRUE);
1797 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1798 /* gtk_action_set_sensitive (action, TRUE); */
1799 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1800 gtk_widget_set_sensitive (widget, TRUE);
1805 on_msg_count_changed (ModestHeaderView *header_view,
1807 TnyFolderChange *change,
1808 ModestMainWindow *main_window)
1810 gboolean folder_empty = FALSE;
1811 gboolean all_marked_as_deleted = FALSE;
1812 TnyFolderChangeChanged changed;
1813 ModestMainWindowPrivate *priv;
1815 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1816 g_return_if_fail (TNY_IS_FOLDER(folder));
1817 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1818 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1820 changed = tny_folder_change_get_changed (change);
1822 /* If something changes */
1823 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1824 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1826 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1828 /* Check header removed (hide marked as DELETED headers) */
1829 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1830 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1833 /* Check if all messages are marked to be deleted */
1834 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1835 folder_empty = folder_empty || all_marked_as_deleted ;
1837 /* Set contents style of headers view */
1839 modest_main_window_set_contents_style (main_window,
1840 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1841 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1844 modest_main_window_set_contents_style (main_window,
1845 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1851 modest_main_window_set_contents_style (ModestMainWindow *self,
1852 ModestMainWindowContentsStyle style)
1854 ModestMainWindowPrivate *priv;
1856 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1858 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1860 /* We allow to set the same content style than the previously
1861 set if there are details, because it could happen when we're
1862 selecting different accounts consecutively */
1863 if ((priv->contents_style == style) &&
1864 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1867 /* Remove previous child. Delete it if it was an account
1869 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1871 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1872 g_object_ref (content);
1873 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1874 g_object_ref (priv->empty_view);
1875 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1878 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1881 priv->contents_style = style;
1883 switch (priv->contents_style) {
1884 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1885 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1886 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1889 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1891 /* if we're started without main win, there may not be a folder
1892 * view. this fixes a GLib-Critical */
1893 if (priv->folder_view) {
1894 TnyFolderStore *selected_folderstore =
1895 modest_folder_view_get_selected (priv->folder_view);
1896 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1897 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1898 TNY_ACCOUNT (selected_folderstore));
1900 wrap_in_scrolled_window (priv->contents_widget,
1901 priv->details_widget);
1903 g_object_unref (selected_folderstore);
1904 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1909 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1910 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1911 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1915 g_return_if_reached ();
1919 gtk_widget_show_all (priv->contents_widget);
1922 ModestMainWindowContentsStyle
1923 modest_main_window_get_contents_style (ModestMainWindow *self)
1925 ModestMainWindowPrivate *priv;
1927 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1929 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1930 return priv->contents_style;
1935 on_configuration_key_changed (ModestConf* conf,
1937 ModestConfEvent event,
1938 ModestConfNotificationId id,
1939 ModestMainWindow *self)
1941 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1942 TnyAccount *account = NULL;
1944 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1947 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1950 if (priv->folder_view)
1951 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1953 if (account && TNY_IS_ACCOUNT (account) &&
1954 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1957 const gchar *device_name;
1958 gchar *new_text, *gray_color_markup;
1961 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1962 label = GTK_LABEL (children->data);
1964 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1965 MODEST_CONF_DEVICE_NAME, NULL);
1967 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1968 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1970 gtk_label_set_markup (label, new_text);
1971 gtk_widget_show (GTK_WIDGET (label));
1973 g_free (gray_color_markup);
1975 g_list_free (children);
1977 g_object_unref (account);
1981 set_toolbar_transfer_mode (ModestMainWindow *self)
1983 ModestMainWindowPrivate *priv = NULL;
1985 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1987 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1989 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1991 if (priv->progress_bar_timeout > 0) {
1992 g_source_remove (priv->progress_bar_timeout);
1993 priv->progress_bar_timeout = 0;
2000 set_toolbar_mode (ModestMainWindow *self,
2001 ModestToolBarModes mode)
2003 ModestWindowPrivate *parent_priv = NULL;
2004 ModestMainWindowPrivate *priv = NULL;
2005 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2007 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2009 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2010 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2012 /* In case this was called before the toolbar exists: */
2013 if (!(parent_priv->toolbar))
2016 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2018 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2019 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2020 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2022 /* Sets current toolbar mode */
2023 priv->current_toolbar_mode = mode;
2025 /* Checks the dimming rules */
2026 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2028 /* Show and hide toolbar items */
2030 case TOOLBAR_MODE_NORMAL:
2032 gtk_action_set_visible (sort_action, TRUE);
2034 gtk_action_set_visible (refresh_action, TRUE);
2035 if (priv->progress_toolitem) {
2036 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2037 gtk_widget_hide (priv->progress_toolitem);
2039 if (priv->progress_bar)
2040 gtk_widget_hide (priv->progress_bar);
2043 gtk_action_set_visible (cancel_action, FALSE);
2045 /* Hide toolbar if optimized view is enabled */
2046 if (priv->optimized_view)
2047 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2049 case TOOLBAR_MODE_TRANSFER:
2051 gtk_action_set_visible (sort_action, FALSE);
2053 gtk_action_set_visible (refresh_action, FALSE);
2055 gtk_action_set_visible (cancel_action, TRUE);
2056 if (priv->progress_bar)
2057 gtk_widget_show (priv->progress_bar);
2058 if (priv->progress_toolitem) {
2059 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2060 gtk_widget_show (priv->progress_toolitem);
2063 /* Show toolbar if it's hiden (optimized view ) */
2064 if (priv->optimized_view)
2065 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2068 g_return_if_reached ();
2073 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2075 ModestMainWindowPrivate *priv;
2077 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2078 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2080 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2084 cancel_progressbar (GtkToolButton *toolbutton,
2085 ModestMainWindow *self)
2088 ModestMainWindowPrivate *priv;
2090 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2092 /* Get operation observers and cancel all the operations */
2093 tmp = priv->progress_widgets;
2095 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2096 tmp=g_slist_next(tmp);
2101 observers_empty (ModestMainWindow *self)
2104 ModestMainWindowPrivate *priv;
2105 gboolean is_empty = TRUE;
2106 guint pending_ops = 0;
2108 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2109 tmp = priv->progress_widgets;
2111 /* Check all observers */
2112 while (tmp && is_empty) {
2113 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2114 is_empty = pending_ops == 0;
2116 tmp = g_slist_next(tmp);
2124 * Gets the toolbar mode needed for each mail operation. It stores in
2125 * @mode_changed if the toolbar mode has changed or not
2127 static ModestToolBarModes
2128 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2129 ModestMailOperation *mail_op,
2130 gboolean *mode_changed)
2132 ModestToolBarModes mode;
2133 ModestMainWindowPrivate *priv;
2135 *mode_changed = FALSE;
2136 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2138 /* Get toolbar mode from operation id*/
2139 switch (modest_mail_operation_get_type_operation (mail_op)) {
2140 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2141 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2142 mode = TOOLBAR_MODE_TRANSFER;
2143 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2144 *mode_changed = TRUE;
2147 mode = TOOLBAR_MODE_NORMAL;
2153 on_mail_operation_started (ModestMailOperation *mail_op,
2156 ModestMainWindow *self;
2157 ModestMailOperationTypeOperation op_type;
2158 ModestMainWindowPrivate *priv;
2159 ModestToolBarModes mode;
2161 gboolean mode_changed = FALSE;
2162 TnyAccount *account;
2164 self = MODEST_MAIN_WINDOW (user_data);
2165 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2167 /* Do not show progress for receiving operations if the
2168 account is the local account or the MMC one */
2169 op_type = modest_mail_operation_get_type_operation (mail_op);
2170 account = modest_mail_operation_get_account (mail_op);
2171 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2174 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2175 modest_tny_account_is_memory_card_account (account));
2176 g_object_unref (account);
2181 /* Get toolbar mode from operation id*/
2182 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2184 /* Add operation observers and change toolbar if neccessary*/
2185 tmp = priv->progress_widgets;
2186 if (mode == TOOLBAR_MODE_TRANSFER) {
2188 set_toolbar_transfer_mode(self);
2191 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2193 tmp = g_slist_next (tmp);
2199 on_mail_operation_finished (ModestMailOperation *mail_op,
2202 ModestToolBarModes mode;
2203 ModestMailOperationTypeOperation op_type;
2205 ModestMainWindow *self;
2206 gboolean mode_changed;
2207 TnyAccount *account;
2208 ModestMainWindowPrivate *priv;
2210 self = MODEST_MAIN_WINDOW (user_data);
2211 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2213 /* The mail operation was not added to the progress objects if
2214 the account was the local account or the MMC one */
2215 op_type = modest_mail_operation_get_type_operation (mail_op);
2216 account = modest_mail_operation_get_account (mail_op);
2217 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2220 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2221 modest_tny_account_is_memory_card_account (account));
2222 g_object_unref (account);
2227 /* Get toolbar mode from operation id*/
2228 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2230 /* Change toolbar mode */
2231 tmp = priv->progress_widgets;
2232 if (mode == TOOLBAR_MODE_TRANSFER) {
2234 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2236 tmp = g_slist_next (tmp);
2239 /* If no more operations are being observed, NORMAL mode is enabled again */
2240 if (observers_empty (self)) {
2241 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2247 on_queue_changed (ModestMailOperationQueue *queue,
2248 ModestMailOperation *mail_op,
2249 ModestMailOperationQueueNotification type,
2250 ModestMainWindow *self)
2252 ModestMainWindowPrivate *priv;
2254 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2256 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2257 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2259 "operation-started",
2260 G_CALLBACK (on_mail_operation_started),
2262 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2264 "operation-finished",
2265 G_CALLBACK (on_mail_operation_finished),
2267 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2268 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2270 "operation-started");
2271 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2273 "operation-finished");
2278 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2280 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2282 ModestAccountMgr *mgr;
2283 ModestAccountSettings *settings;
2284 ModestServerAccountSettings *store_settings = NULL;
2286 /* Get account data */
2287 mgr = modest_runtime_get_account_mgr ();
2288 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2290 store_settings = modest_account_settings_get_store_settings (settings);
2292 /* Set the new visible & active account */
2293 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2294 const gchar *account_name;
2296 account_name = modest_account_settings_get_account_name (settings);
2298 modest_folder_view_set_account_id_of_visible_server_account
2300 modest_server_account_settings_get_account_name (store_settings));
2301 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2302 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2303 if (action != NULL) {
2304 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2305 modest_utils_toggle_action_set_active_block_notify (
2306 GTK_TOGGLE_ACTION (action),
2312 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2317 g_object_unref (store_settings);
2318 g_object_unref (settings);
2322 /* Make sure that at least one account is "viewed": */
2324 set_at_least_one_account_visible(ModestMainWindow *self)
2326 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2327 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2329 if (!(priv->folder_view)) {
2330 /* It is too early to do this. */
2334 const gchar *active_server_account_name =
2335 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2337 if (!active_server_account_name ||
2338 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2340 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2341 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2342 if (default_modest_name) {
2343 set_account_visible (self, default_modest_name);
2344 } else if (first_modest_name) {
2345 set_account_visible (self, first_modest_name);
2347 g_free (first_modest_name);
2348 g_free (default_modest_name);
2353 on_show_account_action_toggled (GtkToggleAction *action,
2356 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2358 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2359 if (gtk_toggle_action_get_active (action))
2360 set_account_visible (self, acc_name);
2364 refresh_account (const gchar *account_name)
2368 /* win must already exists here, obviously */
2369 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2372 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2376 /* If account_name == NULL, we must update all (option All) */
2378 modest_ui_actions_do_send_receive_all (win);
2380 modest_ui_actions_do_send_receive (account_name, win);
2385 on_refresh_account_action_activated (GtkAction *action,
2388 refresh_account ((const gchar*) user_data);
2392 on_send_receive_csm_activated (GtkMenuItem *item,
2395 refresh_account ((const gchar*) user_data);
2399 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2401 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2403 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2409 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2411 ModestMainWindow *main_window = NULL;
2413 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2414 main_window = MODEST_MAIN_WINDOW (userdata);
2416 /* Update toolbar dimming state */
2417 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2423 on_header_view_focus_in (GtkWidget *widget,
2424 GdkEventFocus *event,
2427 ModestMainWindow *main_window = NULL;
2429 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2431 main_window = MODEST_MAIN_WINDOW (userdata);
2433 /* Update toolbar dimming state */
2434 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2440 on_folder_selection_changed (ModestFolderView *folder_view,
2441 TnyFolderStore *folder_store,
2443 ModestMainWindow *main_window)
2445 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2446 GtkAction *action = NULL;
2447 gboolean show_reply = TRUE;
2448 gboolean show_forward = TRUE;
2449 gboolean show_cancel_send = FALSE;
2450 gboolean show_clipboard = TRUE;
2451 gboolean show_delete = TRUE;
2454 if (TNY_IS_ACCOUNT (folder_store)) {
2455 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2456 } else if (TNY_IS_FOLDER (folder_store)) {
2457 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2458 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2459 TNY_FOLDER (folder_store));
2460 switch (folder_type) {
2461 case TNY_FOLDER_TYPE_DRAFTS:
2462 show_clipboard = show_delete = TRUE;
2463 show_reply = show_forward = show_cancel_send = FALSE;
2465 case TNY_FOLDER_TYPE_SENT:
2466 show_forward = show_clipboard = show_delete = TRUE;
2467 show_reply = show_cancel_send = FALSE;
2469 case TNY_FOLDER_TYPE_OUTBOX:
2470 show_clipboard = show_delete = show_cancel_send = TRUE;
2471 show_reply = show_forward = FALSE;
2473 case TNY_FOLDER_TYPE_INVALID:
2474 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2477 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2478 show_cancel_send = FALSE;
2481 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2482 show_cancel_send = FALSE;
2487 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2488 gtk_action_set_visible (action, show_reply);
2489 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2490 gtk_action_set_visible (action, show_reply);
2491 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2492 gtk_action_set_visible (action, show_forward);
2493 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2494 gtk_action_set_visible (action, show_cancel_send);
2495 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2496 gtk_action_set_visible (action, show_delete);
2498 /* We finally call to the ui actions handler, after updating properly
2499 * the header view CSM */
2500 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2504 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2505 GtkTreeModel *model,
2506 GtkTreeRowReference *row_reference,
2507 ModestMainWindow *self)
2509 ModestMainWindowPrivate *priv = NULL;
2510 GtkTreeModel *header_model = NULL;
2511 GtkTreePath *path = NULL;
2513 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2514 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2515 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2517 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2518 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2520 /* Do nothing if we changed the folder in the main view */
2521 if (header_model != model)
2524 /* Select the message in the header view */
2525 path = gtk_tree_row_reference_get_path (row_reference);
2526 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2528 gtk_tree_path_free (path);
2534 show_updating_banner (gpointer user_data)
2536 ModestMainWindowPrivate *priv = NULL;
2538 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2540 if (priv->updating_banner == NULL) {
2542 /* We're outside the main lock */
2543 gdk_threads_enter ();
2544 priv->updating_banner =
2545 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2546 _CS ("ckdg_pb_updating"));
2547 gdk_threads_leave ();
2550 /* Remove timeout */
2551 priv->updating_banner_timeout = 0;
2556 * We use this function to show/hide a progress banner showing
2557 * "Updating" while the header view is being filled. We're not showing
2558 * it unless the update takes more than 2 seconds
2560 * If starting = TRUE then the refresh is starting, otherwise it means
2561 * that is has just finished
2564 on_updating_msg_list (ModestHeaderView *header_view,
2568 ModestMainWindowPrivate *priv = NULL;
2570 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2572 /* Remove old timeout */
2573 if (priv->updating_banner_timeout > 0) {
2574 g_source_remove (priv->updating_banner_timeout);
2575 priv->updating_banner_timeout = 0;
2578 /* Create a new timeout */
2580 priv->updating_banner_timeout =
2581 g_timeout_add (2000, show_updating_banner, user_data);
2583 /* Remove the banner if exists */
2584 if (priv->updating_banner) {
2585 gtk_widget_destroy (priv->updating_banner);
2586 priv->updating_banner = NULL;