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.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 static gboolean show_retrieving_banner (gpointer user_data);
181 static void on_window_destroy (GtkObject *widget,
184 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
185 struct _ModestMainWindowPrivate {
186 GtkWidget *msg_paned;
187 GtkWidget *main_paned;
188 GtkWidget *main_vbox;
189 GtkWidget *contents_widget;
190 GtkWidget *empty_view;
192 /* Progress observers */
193 GtkWidget *progress_bar;
194 GSList *progress_widgets;
197 GtkWidget *progress_toolitem;
198 GtkWidget *cancel_toolitem;
199 GtkWidget *sort_toolitem;
200 GtkWidget *refresh_toolitem;
201 ModestToolBarModes current_toolbar_mode;
203 /* Merge ids used to add/remove accounts to the ViewMenu*/
204 GByteArray *merge_ids;
205 GtkActionGroup *view_additions_group;
207 /* On-demand widgets */
208 GtkWidget *accounts_popup;
209 GtkWidget *details_widget;
211 /* Optimized view enabled */
212 gboolean optimized_view;
214 /* Optimized view enabled */
215 gboolean send_receive_in_progress;
217 ModestHeaderView *header_view;
218 ModestFolderView *folder_view;
220 ModestMainWindowStyle style;
221 ModestMainWindowContentsStyle contents_style;
222 gboolean wait_for_settings;
224 guint progress_bar_timeout;
225 guint restore_paned_timeout;
227 /* Signal handler UIDs */
228 GList *queue_err_signals;
231 /* "Updating" banner for header view */
232 GtkWidget *updating_banner;
233 guint updating_banner_timeout;
235 /* "Retrieving" banner for header view */
236 GtkWidget *retrieving_banner;
237 guint retrieving_banner_timeout;
240 osso_display_state_t display_state;
242 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
243 MODEST_TYPE_MAIN_WINDOW, \
244 ModestMainWindowPrivate))
246 typedef struct _GetMsgAsyncHelper {
247 ModestMainWindowPrivate *main_window_private;
249 ModestTnyMsgReplyType reply_type;
250 ModestTnyMsgForwardType forward_type;
257 static GtkWindowClass *parent_class = NULL;
260 /* Private actions */
261 /* This is the context sensitive menu: */
262 static const GtkActionEntry modest_folder_view_action_entries [] = {
264 /* Folder View CSM actions */
265 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
266 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
267 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
268 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
269 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
270 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
273 static const GtkActionEntry modest_header_view_action_entries [] = {
275 /* Header View CSM actions */
276 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
277 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
278 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
279 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
280 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
281 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
282 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
283 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
284 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
285 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
288 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
289 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
292 /************************************************************************/
295 modest_main_window_get_type (void)
297 static GType my_type = 0;
299 static const GTypeInfo my_info = {
300 sizeof(ModestMainWindowClass),
301 NULL, /* base init */
302 NULL, /* base finalize */
303 (GClassInitFunc) modest_main_window_class_init,
304 NULL, /* class finalize */
305 NULL, /* class data */
306 sizeof(ModestMainWindow),
308 (GInstanceInitFunc) modest_main_window_init,
311 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
319 modest_main_window_class_init (ModestMainWindowClass *klass)
321 GObjectClass *gobject_class;
322 gobject_class = (GObjectClass*) klass;
323 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
325 parent_class = g_type_class_peek_parent (klass);
326 gobject_class->finalize = modest_main_window_finalize;
328 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
330 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
331 modest_window_class->save_state_func = save_state;
332 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
333 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
334 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
338 modest_main_window_init (ModestMainWindow *obj)
340 ModestMainWindowPrivate *priv;
342 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
344 priv->queue_err_signals = NULL;
345 priv->msg_paned = NULL;
346 priv->main_paned = NULL;
347 priv->main_vbox = NULL;
348 priv->header_view = NULL;
349 priv->folder_view = NULL;
350 priv->contents_widget = NULL;
351 priv->accounts_popup = NULL;
352 priv->details_widget = NULL;
353 priv->empty_view = NULL;
354 priv->progress_widgets = NULL;
355 priv->progress_bar = NULL;
356 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
357 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
358 priv->wait_for_settings = TRUE;
359 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
360 priv->merge_ids = NULL;
361 priv->optimized_view = FALSE;
362 priv->send_receive_in_progress = FALSE;
363 priv->progress_bar_timeout = 0;
364 priv->restore_paned_timeout = 0;
365 priv->sighandlers = NULL;
366 priv->updating_banner = NULL;
367 priv->updating_banner_timeout = 0;
368 priv->retrieving_banner = NULL;
369 priv->retrieving_banner_timeout = 0;
370 priv->display_state = OSSO_DISPLAY_ON;
372 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
374 "applications_email_mainview");
378 modest_main_window_finalize (GObject *obj)
380 ModestMainWindowPrivate *priv;
382 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
384 /* Sanity check: shouldn't be needed, the window mgr should
385 call this function before */
386 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
387 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
389 g_slist_free (priv->progress_widgets);
391 g_byte_array_free (priv->merge_ids, TRUE);
393 if (priv->progress_bar_timeout > 0) {
394 g_source_remove (priv->progress_bar_timeout);
395 priv->progress_bar_timeout = 0;
398 if (priv->updating_banner_timeout > 0) {
399 g_source_remove (priv->updating_banner_timeout);
400 priv->updating_banner_timeout = 0;
403 if (priv->updating_banner) {
404 gtk_widget_destroy (priv->updating_banner);
405 priv->updating_banner = NULL;
408 if (priv->retrieving_banner_timeout > 0) {
409 g_source_remove (priv->retrieving_banner_timeout);
410 priv->retrieving_banner_timeout = 0;
413 if (priv->retrieving_banner) {
414 gtk_widget_destroy (priv->retrieving_banner);
415 priv->retrieving_banner = NULL;
418 if (priv->restore_paned_timeout > 0) {
419 g_source_remove (priv->restore_paned_timeout);
420 priv->restore_paned_timeout = 0;
423 G_OBJECT_CLASS(parent_class)->finalize (obj);
427 modest_main_window_get_child_widget (ModestMainWindow *self,
428 ModestMainWindowWidgetType widget_type)
430 ModestMainWindowPrivate *priv;
433 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
434 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
437 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
439 switch (widget_type) {
440 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
441 widget = (GtkWidget*)priv->header_view; break;
442 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
443 widget = (GtkWidget*)priv->folder_view; break;
448 return widget ? GTK_WIDGET(widget) : NULL;
452 restore_paned_timeout_handler (gpointer *data)
454 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
455 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
458 /* Timeouts are outside the main lock */
459 gdk_threads_enter ();
460 if (GTK_WIDGET_VISIBLE (main_window)) {
461 conf = modest_runtime_get_conf ();
462 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
463 MODEST_CONF_MAIN_PANED_KEY);
465 gdk_threads_leave ();
472 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
475 ModestMainWindowPrivate *priv;
477 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
479 conf = modest_runtime_get_conf ();
481 modest_widget_memory_restore (conf, G_OBJECT(self),
482 MODEST_CONF_MAIN_WINDOW_KEY);
484 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
485 MODEST_CONF_HEADER_VIEW_KEY);
487 if (do_folder_view_too)
488 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
489 MODEST_CONF_FOLDER_VIEW_KEY);
491 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
492 /* MODEST_CONF_MAIN_PANED_KEY); */
494 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
496 /* We need to force a redraw here in order to get the right
497 position of the horizontal paned separator */
498 gtk_widget_show (GTK_WIDGET (self));
503 save_state (ModestWindow *window)
506 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
507 ModestMainWindowPrivate *priv;
509 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
510 conf = modest_runtime_get_conf ();
512 modest_widget_memory_save (conf,G_OBJECT(self),
513 MODEST_CONF_MAIN_WINDOW_KEY);
514 /* Only save main paned position if we're in split mode */
515 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
516 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
517 MODEST_CONF_MAIN_PANED_KEY);
518 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
519 MODEST_CONF_FOLDER_VIEW_KEY);
523 compare_display_names (ModestAccountSettings *a,
524 ModestAccountSettings *b)
526 return strcmp (modest_account_settings_get_display_name (a),
527 modest_account_settings_get_display_name (b));
530 /* We use this function to prevent the send&receive CSM to be shown
531 when there are less than two account */
533 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
539 update_menus (ModestMainWindow* self)
541 GSList *account_names, *iter, *accounts;
542 ModestMainWindowPrivate *priv;
543 ModestWindowPrivate *parent_priv;
544 ModestAccountMgr *mgr;
545 gint i, num_accounts;
547 gchar *default_account;
548 const gchar *active_account_name;
549 GtkWidget *send_receive_button, *item;
550 GtkAction *send_receive_all = NULL;
553 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
554 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
556 /* Get enabled account IDs */
557 mgr = modest_runtime_get_account_mgr ();
558 account_names = modest_account_mgr_account_names (mgr, TRUE);
559 iter = account_names;
563 ModestAccountSettings *settings =
564 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
565 accounts = g_slist_prepend (accounts, settings);
569 modest_account_mgr_free_account_names (account_names);
570 account_names = NULL;
572 /* Order the list of accounts by its display name */
573 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
574 num_accounts = g_slist_length (accounts);
576 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
577 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
578 gtk_action_set_visible (send_receive_all, num_accounts > 0);
580 /* Delete old send&receive popup items. We can not just do a
581 menu_detach because it does not work well with
583 if (priv->accounts_popup)
584 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
585 (GtkCallback) gtk_widget_destroy, NULL);
587 /* Delete old entries in the View menu. Do not free groups, it
589 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
591 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
592 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
593 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
594 GTK_ACTION_GROUP (groups->data));
597 if (priv->merge_ids) {
598 for (i = 0; i < priv->merge_ids->len; i++)
599 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
600 g_byte_array_free (priv->merge_ids, TRUE);
602 /* We need to call this in order to ensure
603 that the new actions are added in the right
604 order (alphabetical) */
605 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
607 groups = g_list_next (groups);
609 priv->merge_ids = g_byte_array_sized_new (num_accounts);
611 /* Get send receive button */
612 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
613 "/ToolBar/ToolbarSendReceive");
615 /* Create the menu */
616 if (num_accounts > 1) {
617 if (!priv->accounts_popup)
618 priv->accounts_popup = gtk_menu_new ();
619 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
620 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
621 g_signal_connect (G_OBJECT (item),
623 G_CALLBACK (on_send_receive_csm_activated),
625 item = gtk_separator_menu_item_new ();
626 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
629 /* Create a new action group */
630 default_account = modest_account_mgr_get_default_account (mgr);
631 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
633 if (!active_account_name)
634 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
636 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
638 for (i = 0; i < num_accounts; i++) {
639 gchar *display_name = NULL;
640 const gchar *account_name;
641 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
644 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
647 account_name = modest_account_settings_get_account_name (settings);
649 if (default_account && account_name &&
650 !(strcmp (default_account, account_name) == 0)) {
651 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
652 modest_account_settings_get_display_name (settings));
654 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
655 modest_account_settings_get_display_name (settings));
660 /* Create action and add it to the action group. The
661 action name must be the account name, this way we
662 could know in the handlers the account to show */
663 if (settings && account_name) {
664 gchar* item_name, *refresh_action_name;
666 GtkAction *view_account_action, *refresh_account_action;
667 gchar *escaped_display_name;
669 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
671 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
672 escaped_display_name, NULL, NULL, 0));
673 g_free (escaped_display_name);
674 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
675 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
676 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
678 if (active_account_name) {
679 if (active_account_name && account_name &&
680 (strcmp (active_account_name, account_name) == 0)) {
681 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
685 /* Add ui from account data. We allow 2^9-1 account
686 changes in a single execution because we're
687 downcasting the guint to a guint8 in order to use a
688 GByteArray. It should be enough. */
689 item_name = g_strconcat (account_name, "Menu", NULL);
690 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
691 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
692 gtk_ui_manager_add_ui (parent_priv->ui_manager,
694 "/MenuBar/ViewMenu/ViewMenuAdditions",
697 GTK_UI_MANAGER_MENUITEM,
700 /* Connect the action signal "activate" */
701 g_signal_connect_after (G_OBJECT (view_account_action),
703 G_CALLBACK (on_show_account_action_toggled),
706 /* Create the items for the Tools->Send&Receive submenu */
707 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
708 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
709 display_name, NULL, NULL);
710 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
712 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
713 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
714 gtk_ui_manager_add_ui (parent_priv->ui_manager,
716 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
719 GTK_UI_MANAGER_MENUITEM,
721 g_free (refresh_action_name);
723 g_signal_connect_data (G_OBJECT (refresh_account_action),
725 G_CALLBACK (on_refresh_account_action_activated),
726 g_strdup (account_name),
727 (GClosureNotify) g_free,
730 /* Create item and add it to the send&receive
731 CSM. If there is only one account then
733 if (num_accounts > 1) {
734 GtkWidget *label = gtk_label_new(NULL);
735 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
736 if (default_account && (strcmp(account_name, default_account) == 0)) {
737 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
738 gtk_label_set_markup (GTK_LABEL (label), escaped);
741 gtk_label_set_text (GTK_LABEL (label), display_name);
744 item = gtk_menu_item_new ();
745 gtk_container_add (GTK_CONTAINER (item), label);
747 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
748 g_signal_connect_data (G_OBJECT (item),
750 G_CALLBACK (on_send_receive_csm_activated),
751 g_strdup (account_name),
752 (GClosureNotify) g_free,
759 g_free (display_name);
762 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
764 /* We cannot do this in the loop above because this relies on the action
765 * group being inserted. This makes the default account appear in bold.
766 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
767 for (i = 0; i < num_accounts; i++) {
768 gchar *item_name, *path;
770 ModestAccountSettings *settings;
771 const gchar *account_name;
774 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
775 account_name = modest_account_settings_get_account_name (settings);
776 is_default = (account_name && default_account && !strcmp (account_name, default_account));
778 /* Get the item of the view menu */
779 item_name = g_strconcat (account_name, "Menu", NULL);
780 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
781 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
785 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
786 if (GTK_IS_LABEL (child)) {
787 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
789 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
790 gtk_label_set_markup (GTK_LABEL (child), bold_name);
793 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
797 /* Get the item of the tools menu */
798 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
799 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
803 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
804 if (GTK_IS_LABEL (child)) {
805 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
807 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
808 gtk_label_set_markup (GTK_LABEL (child), bold_name);
811 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
816 g_object_unref (settings);
819 if (num_accounts > 1) {
820 /* Disconnect the tap-and-hold-query if it's connected */
821 if (modest_signal_mgr_is_connected (priv->sighandlers,
822 G_OBJECT (send_receive_button),
823 "tap-and-hold-query"))
824 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
825 G_OBJECT (send_receive_button),
826 "tap-and-hold-query");
828 /* Mandatory in order to view the menu contents */
829 gtk_widget_show_all (priv->accounts_popup);
831 /* Setup tap_and_hold just if was not done before*/
832 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
833 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
835 /* Connect the tap-and-hold-query in order not to show the CSM */
836 if (!modest_signal_mgr_is_connected (priv->sighandlers,
837 G_OBJECT (send_receive_button),
838 "tap-and-hold-query"))
839 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
840 G_OBJECT (send_receive_button),
841 "tap-and-hold-query",
842 G_CALLBACK (tap_and_hold_query_cb),
847 g_slist_free (accounts);
848 g_free (default_account);
851 /* Make sure that at least one account is viewed if there are any
852 * accounts, for instance when adding the first account: */
853 set_at_least_one_account_visible (self);
857 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
859 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
860 gtk_scrolled_window_add_with_viewport
861 (GTK_SCROLLED_WINDOW(win), widget);
863 gtk_container_add (GTK_CONTAINER(win),
874 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
876 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
878 GList *oerrsignals = priv->queue_err_signals;
879 while (oerrsignals) {
880 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
881 g_signal_handler_disconnect (esignal->queue, esignal->signal);
882 g_slice_free (QueueErrorSignal, esignal);
883 oerrsignals = g_list_next (oerrsignals);
885 g_list_free (priv->queue_err_signals);
886 priv->queue_err_signals = NULL;
891 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
893 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
896 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
900 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
902 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
904 /* Update visibility */
907 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
911 modest_main_window_disconnect_signals (ModestWindow *self)
913 ModestMainWindowPrivate *priv;
914 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
916 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
917 priv->sighandlers = NULL;
921 connect_signals (ModestMainWindow *self)
923 ModestWindowPrivate *parent_priv;
924 ModestMainWindowPrivate *priv;
927 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
928 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
933 modest_signal_mgr_connect (priv->sighandlers,
934 G_OBJECT(priv->folder_view), "key-press-event",
935 G_CALLBACK(on_inner_widgets_key_pressed), self);
937 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
938 "folder_selection_changed",
939 G_CALLBACK (on_folder_selection_changed),
942 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
943 "folder-display-name-changed",
944 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
947 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
949 G_CALLBACK (on_folder_view_focus_in),
952 /* Folder view CSM */
953 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
954 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
955 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
956 G_CALLBACK(_folder_view_csm_menu_activated),
960 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
961 G_CALLBACK(modest_ui_actions_on_header_selected), self);
963 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
964 G_CALLBACK(modest_ui_actions_on_header_activated), self);
966 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
967 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
969 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
970 G_CALLBACK(on_inner_widgets_key_pressed), self);
972 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
973 G_CALLBACK(on_msg_count_changed), self);
975 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
976 G_CALLBACK (on_header_view_focus_in), self);
978 modest_signal_mgr_connect (priv->sighandlers,
979 G_OBJECT (priv->header_view),
981 G_CALLBACK (on_updating_msg_list),
984 /* Header view CSM */
985 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
986 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
988 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
989 G_CALLBACK(_header_view_csm_menu_activated),
994 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
995 G_CALLBACK (modest_main_window_window_state_event),
997 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
998 * in destroy stage */
999 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1001 /* Mail Operation Queue */
1003 modest_signal_mgr_connect (priv->sighandlers,
1004 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1006 G_CALLBACK (on_queue_changed), self);
1008 /* Track changes in the device name */
1010 modest_signal_mgr_connect (priv->sighandlers,
1011 G_OBJECT(modest_runtime_get_conf ()),
1013 G_CALLBACK (on_configuration_key_changed),
1016 /* Track account changes. We need to refresh the toolbar */
1018 modest_signal_mgr_connect (priv->sighandlers,
1019 G_OBJECT (modest_runtime_get_account_store ()),
1021 G_CALLBACK (on_account_inserted),
1024 modest_signal_mgr_connect (priv->sighandlers,
1025 G_OBJECT (modest_runtime_get_account_store ()),
1027 G_CALLBACK (on_account_removed),
1030 /* We need to refresh the send & receive menu to change the bold
1031 * account when the default account changes. */
1033 modest_signal_mgr_connect (priv->sighandlers,
1034 G_OBJECT (modest_runtime_get_account_mgr ()),
1035 "default_account_changed",
1036 G_CALLBACK (on_default_account_changed),
1041 modest_signal_mgr_connect (priv->sighandlers,
1042 G_OBJECT (modest_runtime_get_account_store ()),
1044 G_CALLBACK (on_account_changed),
1048 modest_signal_mgr_connect (priv->sighandlers,
1049 G_OBJECT (modest_runtime_get_account_store()),
1050 "password_requested",
1051 G_CALLBACK (modest_ui_actions_on_password_requested),
1056 on_hildon_program_is_topmost_notify(GObject *self,
1057 GParamSpec *propert_param,
1060 HildonProgram *app = HILDON_PROGRAM (self);
1062 /* Note that use of hildon_program_set_can_hibernate()
1063 * is generally referred to as "setting the killable flag",
1064 * though hibernation does not seem equal to death.
1067 if (hildon_program_get_is_topmost (app)) {
1068 /* Prevent hibernation when the progam comes to the foreground,
1069 * because hibernation should only happen when the application
1070 * is in the background: */
1071 hildon_program_set_can_hibernate (app, FALSE);
1073 /* Remove new mail visual notifications */
1074 modest_platform_remove_new_mail_notifications (TRUE);
1076 /* Allow hibernation if the program has gone to the background: */
1078 /* However, prevent hibernation while the settings are being changed: */
1079 const gboolean hibernation_prevented =
1080 modest_window_mgr_get_hibernation_is_prevented (
1081 modest_runtime_get_window_mgr ());
1083 if (hibernation_prevented)
1084 hildon_program_set_can_hibernate (app, FALSE);
1086 /* Allow hibernation, after saving the state: */
1087 modest_osso_save_state();
1088 hildon_program_set_can_hibernate (app, TRUE);
1094 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1096 GtkWidget *folder_win = (GtkWidget *) user_data;
1097 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1099 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1100 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1102 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1104 /* Connect signals */
1105 connect_signals (MODEST_MAIN_WINDOW (self));
1107 /* Set account store */
1108 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1109 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1111 /* Load previous osso state, for instance if we are being restored from
1113 modest_osso_load_state ();
1115 /* Restore window & widget settings */
1116 priv->wait_for_settings = TRUE;
1117 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1118 priv->wait_for_settings = FALSE;
1120 /* Check if accounts exist and show the account wizard if not */
1121 gboolean accounts_exist =
1122 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1124 if (!accounts_exist) {
1125 /* This is necessary to have the main window shown behind the dialog
1126 It's an ugly hack... jschmid */
1127 gtk_widget_show_all(GTK_WIDGET(self));
1128 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1131 GtkAction *send_receive_all;
1132 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1133 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1134 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1135 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1136 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1137 modest_account_mgr_free_account_names (accounts);
1138 update_menus (MODEST_MAIN_WINDOW (self));
1143 osso_display_event_cb (osso_display_state_t state,
1146 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1148 priv->display_state = state;
1150 /* Stop blinking if the screen becomes on */
1151 if (priv->display_state == OSSO_DISPLAY_ON)
1152 modest_platform_remove_new_mail_notifications (TRUE);
1156 modest_main_window_new (void)
1158 ModestMainWindow *self = NULL;
1159 ModestMainWindowPrivate *priv = NULL;
1160 ModestWindowPrivate *parent_priv = NULL;
1161 GtkWidget *folder_win = NULL;
1162 ModestDimmingRulesGroup *menu_rules_group = NULL;
1163 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1164 GtkActionGroup *action_group = NULL;
1165 GError *error = NULL;
1167 ModestConf *conf = NULL;
1168 GtkAction *action = NULL;
1169 GdkPixbuf *window_icon;
1171 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1172 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1173 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1175 parent_priv->ui_manager = gtk_ui_manager_new();
1176 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1178 action_group = gtk_action_group_new ("ModestMainWindowActions");
1179 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1181 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1182 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1184 /* Add common actions */
1185 gtk_action_group_add_actions (action_group,
1186 modest_action_entries,
1187 G_N_ELEMENTS (modest_action_entries),
1190 gtk_action_group_add_actions (action_group,
1191 modest_folder_view_action_entries,
1192 G_N_ELEMENTS (modest_folder_view_action_entries),
1195 gtk_action_group_add_actions (action_group,
1196 modest_header_view_action_entries,
1197 G_N_ELEMENTS (modest_header_view_action_entries),
1200 gtk_action_group_add_toggle_actions (action_group,
1201 modest_toggle_action_entries,
1202 G_N_ELEMENTS (modest_toggle_action_entries),
1205 gtk_action_group_add_toggle_actions (action_group,
1206 modest_main_window_toggle_action_entries,
1207 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1210 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1211 g_object_unref (action_group);
1213 /* Load the UI definition */
1214 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1215 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1216 if (error != NULL) {
1217 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1218 g_error_free (error);
1222 /* Add common dimming rules */
1223 modest_dimming_rules_group_add_rules (menu_rules_group,
1224 modest_main_window_menu_dimming_entries,
1225 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1226 MODEST_WINDOW (self));
1227 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1228 modest_main_window_toolbar_dimming_entries,
1229 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1230 MODEST_WINDOW (self));
1232 /* Insert dimming rules group for this window */
1233 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1234 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1235 g_object_unref (menu_rules_group);
1236 g_object_unref (toolbar_rules_group);
1238 /* Add accelerators */
1239 gtk_window_add_accel_group (GTK_WINDOW (self),
1240 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1242 /* Menubar. Update the state of some toggles */
1243 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1244 conf = modest_runtime_get_conf ();
1245 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1246 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1247 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1248 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1249 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1250 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1251 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1252 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1253 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1254 gtk_widget_show (parent_priv->menubar);
1256 /* Get device name */
1257 modest_maemo_utils_get_device_name ();
1261 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1262 if (!priv->header_view)
1263 g_printerr ("modest: cannot instantiate header view\n");
1264 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1265 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1266 MODEST_CONF_HEADER_VIEW_KEY);
1268 /* Other style properties of header view */
1269 g_object_set (G_OBJECT (priv->header_view),
1270 "rules-hint", FALSE,
1272 /* gtk_widget_show (priv->header_view); */
1275 priv->empty_view = create_empty_view ();
1276 gtk_widget_show (priv->empty_view);
1278 /* Create scrolled windows */
1279 folder_win = gtk_scrolled_window_new (NULL, NULL);
1280 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1281 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1283 GTK_POLICY_AUTOMATIC);
1284 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1286 GTK_POLICY_AUTOMATIC);
1287 /* gtk_widget_show (priv->contents_widget); */
1290 priv->main_paned = gtk_hpaned_new ();
1291 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1292 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1293 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1295 /* putting it all together... */
1296 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1297 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1298 gtk_widget_show (priv->main_vbox);
1300 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1302 app = hildon_program_get_instance ();
1303 hildon_program_add_window (app, HILDON_WINDOW (self));
1305 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1306 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1308 g_signal_connect (G_OBJECT(self), "show",
1309 G_CALLBACK (modest_main_window_on_show), folder_win);
1311 /* Set window icon */
1312 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1314 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1315 g_object_unref (window_icon);
1318 /* Listen for changes in the screen, we don't want to show a
1319 led pattern when the display is on for example */
1320 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1321 osso_display_event_cb,
1324 /* Dont't restore settings here,
1325 * because it requires a gtk_widget_show(),
1326 * and we don't want to do that until later,
1327 * so that the UI is not visible for non-menu D-Bus activation.
1330 return MODEST_WINDOW(self);
1334 modest_main_window_set_style (ModestMainWindow *self,
1335 ModestMainWindowStyle style)
1337 ModestMainWindowPrivate *priv;
1338 ModestWindowPrivate *parent_priv;
1342 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1344 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1345 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1347 /* no change -> nothing to do */
1348 if (priv->style == style)
1351 /* Get toggle button and update the state if needed. This will
1352 happen only when the set_style is not invoked from the UI,
1353 for example when it's called from widget memory */
1354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1355 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1356 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1357 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1358 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1359 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1360 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1363 priv->style = style;
1365 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1367 if (!priv->wait_for_settings)
1368 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1369 MODEST_CONF_MAIN_PANED_KEY);
1370 /* Remove main paned */
1371 g_object_ref (priv->main_paned);
1372 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1374 /* Reparent the contents widget to the main vbox */
1375 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1378 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1379 /* Remove header view */
1380 g_object_ref (priv->contents_widget);
1381 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1383 /* Reparent the main paned */
1384 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1385 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1387 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1391 g_return_if_reached ();
1394 /* Let header view grab the focus if it's being shown */
1395 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1396 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1398 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1401 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1404 ModestMainWindowStyle
1405 modest_main_window_get_style (ModestMainWindow *self)
1407 ModestMainWindowPrivate *priv;
1409 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1411 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1416 toolbar_resize (ModestMainWindow *self)
1418 ModestMainWindowPrivate *priv = NULL;
1419 ModestWindowPrivate *parent_priv = NULL;
1421 gint static_button_size;
1422 ModestWindowMgr *mgr;
1424 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1425 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1426 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1428 mgr = modest_runtime_get_window_mgr ();
1429 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1431 if (parent_priv->toolbar) {
1432 /* left size buttons */
1433 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1434 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1435 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1436 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1437 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1438 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1439 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1440 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1441 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1444 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1445 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1448 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1454 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1455 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1456 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1457 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1465 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1467 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1468 ModestWindowPrivate *parent_priv;
1469 ModestWindowMgr *mgr;
1470 gboolean is_fullscreen;
1471 GtkAction *fs_toggle_action;
1474 mgr = modest_runtime_get_window_mgr ();
1476 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1478 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1480 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1481 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1482 if (is_fullscreen != active) {
1483 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1486 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1494 modest_main_window_show_toolbar (ModestWindow *self,
1495 gboolean show_toolbar)
1497 ModestMainWindowPrivate *priv = NULL;
1498 ModestWindowPrivate *parent_priv = NULL;
1499 GtkWidget *reply_button = NULL, *menu = NULL;
1500 GtkWidget *placeholder = NULL;
1502 const gchar *action_name;
1505 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1506 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1507 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1509 /* Set optimized view status */
1510 priv->optimized_view = !show_toolbar;
1512 if (!parent_priv->toolbar) {
1513 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1515 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1517 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1518 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1519 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1520 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1521 toolbar_resize (MODEST_MAIN_WINDOW (self));
1523 /* Add ProgressBar (Transfer toolbar) */
1524 priv->progress_bar = modest_progress_bar_new ();
1525 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1526 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1527 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1528 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1529 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1531 /* Connect cancel 'clicked' signal to abort progress mode */
1532 g_signal_connect(priv->cancel_toolitem, "clicked",
1533 G_CALLBACK(cancel_progressbar),
1536 /* Add it to the observers list */
1537 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1540 hildon_window_add_toolbar (HILDON_WINDOW (self),
1541 GTK_TOOLBAR (parent_priv->toolbar));
1543 /* Set reply button tap and hold menu */
1544 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1545 "/ToolBar/ToolbarMessageReply");
1546 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1547 "/ToolbarReplyCSM");
1548 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1550 /* Set send & receive button tap and hold menu */
1551 update_menus (MODEST_MAIN_WINDOW (self));
1555 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1556 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1557 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1559 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1560 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1561 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1563 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1565 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1569 /* Update also the actions (to update the toggles in the
1570 menus), we have to do it manually because some other window
1571 of the same time could have changed it (remember that the
1572 toolbar fullscreen mode is shared by all the windows of the
1574 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1575 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1577 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1579 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1580 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1585 * Counts the number of remote accounts in a list
1588 num_remote_accounts (TnyList *accounts)
1593 iter = tny_list_create_iterator (accounts);
1594 while (!tny_iterator_is_done (iter)) {
1595 TnyAccount *account = (TnyAccount *) tny_iterator_get_current (iter);
1596 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1598 tny_iterator_next (iter);
1600 g_object_unref (iter);
1606 on_account_inserted (TnyAccountStore *accoust_store,
1607 TnyAccount *account,
1610 /* Transport accounts and local ones (MMC and the Local
1611 folders account do now cause menu changes */
1612 if (TNY_IS_STORE_ACCOUNT (account) &&
1613 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1614 TnyList *list = tny_simple_list_new ();
1617 update_menus (MODEST_MAIN_WINDOW (user_data));
1619 /* Perform a send&receive if there are more than 1
1620 remote account , if this is the first remote
1621 account the folder view will automatically select
1623 tny_account_store_get_accounts (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1624 list, TNY_ACCOUNT_STORE_STORE_ACCOUNTS);
1625 if (num_remote_accounts (list) > 1) {
1626 const gchar *account_name =
1627 modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1628 modest_ui_actions_do_send_receive (account_name, FALSE, MODEST_WINDOW (user_data));
1631 g_object_unref (list);
1636 on_default_account_changed (ModestAccountMgr* mgr,
1639 update_menus (MODEST_MAIN_WINDOW (user_data));
1643 on_account_removed (TnyAccountStore *accoust_store,
1644 TnyAccount *account,
1647 /* Transport accounts and local ones (MMC and the Local
1648 folders account do now cause menu changes */
1649 if (TNY_IS_STORE_ACCOUNT (account) &&
1650 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1651 update_menus (MODEST_MAIN_WINDOW (user_data));
1655 on_account_changed (TnyAccountStore *account_store,
1656 TnyAccount *account,
1659 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1661 /* We need to refresh the details widget because it could have changed */
1662 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) {
1663 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1666 /* Update the menus as well, the account name could be
1667 changed. Transport accounts and local ones (MMC and the
1668 Local folders account do now cause menu changes */
1669 if (TNY_IS_STORE_ACCOUNT (account) &&
1670 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1671 update_menus (MODEST_MAIN_WINDOW (user_data));
1675 * This function manages the key events used to navigate between
1676 * header and folder views (when the window is in split view)
1679 * -------------------------------------------------
1680 * HeaderView GDK_Left Move focus to folder view
1681 * FolderView GDK_Right Move focus to header view
1683 * There is no need to scroll to selected row, the widgets will be the
1684 * responsibles of doing that (probably managing the focus-in event
1687 on_inner_widgets_key_pressed (GtkWidget *widget,
1691 ModestMainWindowPrivate *priv;
1693 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1695 /* Do nothing if we're in SIMPLE style */
1696 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1699 if (MODEST_IS_HEADER_VIEW (widget)) {
1700 if (event->keyval == GDK_Left)
1701 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1702 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1703 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1704 if (selected_headers > 1) {
1705 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1709 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1710 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1716 set_alignment (GtkWidget *widget,
1719 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1720 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1724 create_empty_view (void)
1726 GtkLabel *label = NULL;
1727 GtkWidget *align = NULL;
1729 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1730 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1731 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1732 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1734 return GTK_WIDGET(align);
1738 * Free the returned string
1741 get_gray_color_markup (GtkWidget *styled_widget)
1743 gchar *gray_color_markup = NULL;
1744 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1745 /* Obtain the secondary text color. We need a realized widget, that's why
1746 we get styled_widget from outside */
1748 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1749 gray_color_markup = modest_text_utils_get_color_string (&color);
1750 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1752 if (!gray_color_markup)
1753 gray_color_markup = g_strdup ("#BBBBBB");
1755 return gray_color_markup;
1759 * Free the returned string
1762 create_device_name_visual_string (const gchar *device_name,
1763 const gchar *gray_color_markup)
1767 /* We have to use "" to fill the %s of the translation. We can
1768 not just use the device name because the device name is
1769 shown in a different color, so it could not be included
1770 into the <span> tag */
1771 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1772 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1782 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1784 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1789 gchar *gray_color_markup;
1791 vbox = gtk_vbox_new (FALSE, 0);
1793 gray_color_markup = get_gray_color_markup (styled_widget);
1795 /* Account description: */
1796 if (modest_tny_account_is_virtual_local_folders (account)
1797 || (modest_tny_account_is_memory_card_account (account))) {
1799 /* Get device name */
1800 gchar *device_name = NULL;
1801 if (modest_tny_account_is_virtual_local_folders (account))
1802 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1803 MODEST_CONF_DEVICE_NAME, NULL);
1805 device_name = g_strdup (tny_account_get_name (account));
1807 label = create_device_name_visual_string ((const gchar *) device_name,
1808 (const gchar *) gray_color_markup);
1809 label_w = gtk_label_new (NULL);
1810 gtk_label_set_markup (GTK_LABEL (label_w), label);
1811 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1812 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1813 g_free (device_name);
1816 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1817 gtk_box_pack_start (GTK_BOX (vbox),
1818 gtk_label_new (tny_account_get_name (account)),
1821 /* Other accounts, such as IMAP and POP: */
1826 /* Put proto in uppercase */
1827 proto = g_string_new (tny_account_get_proto (account));
1828 proto = g_string_ascii_up (proto);
1830 /* note: mcen_fi_localroot_description is something like "%s account"
1831 * however, we should display "%s account: %s"... therefore, ugly tmp */
1832 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1833 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1834 gray_color_markup, tmp, tny_account_get_name (account));
1837 label_w = gtk_label_new (NULL);
1838 gtk_label_set_markup (GTK_LABEL (label_w), label);
1839 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1840 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1841 g_string_free (proto, TRUE);
1847 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1848 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1849 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1850 modest_tny_folder_store_get_message_count (folder_store));
1851 label_w = gtk_label_new (NULL);
1852 gtk_label_set_markup (GTK_LABEL (label_w), label);
1853 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1854 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1858 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1860 _("mcen_fi_rootfolder_folders"),
1861 modest_tny_folder_store_get_folder_count (folder_store));
1862 label_w = gtk_label_new (NULL);
1863 gtk_label_set_markup (GTK_LABEL (label_w), label);
1864 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1865 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1869 if (modest_tny_account_is_virtual_local_folders (account)
1870 || modest_tny_account_is_memory_card_account (account)) {
1872 gchar *size = modest_text_utils_get_display_size (
1873 modest_tny_folder_store_get_local_size (folder_store));
1875 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1876 gray_color_markup, _("mcen_fi_rootfolder_size"),
1880 label_w = gtk_label_new (NULL);
1881 gtk_label_set_markup (GTK_LABEL (label_w), label);
1882 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1883 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1885 } else if (TNY_IS_ACCOUNT(folder_store)) {
1886 TnyAccount *account = TNY_ACCOUNT(folder_store);
1888 time_t last_updated;
1889 const gchar *last_updated_string;
1890 /* Get last updated from configuration */
1891 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1892 tny_account_get_id (account));
1894 if (last_updated > 0)
1895 last_updated_string = modest_text_utils_get_display_date(last_updated);
1897 last_updated_string = g_strdup (_("mcen_va_never"));
1899 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1900 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1901 label_w = gtk_label_new (NULL);
1902 gtk_label_set_markup (GTK_LABEL (label_w), label);
1903 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1904 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1908 g_free (gray_color_markup);
1911 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1917 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1919 ModestMainWindowPrivate *priv = NULL;
1921 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1923 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1925 return priv->send_receive_in_progress;
1929 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1931 GtkAction *action = NULL;
1932 GtkWidget *widget = NULL;
1933 ModestMainWindowPrivate *priv = NULL;
1935 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1936 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1938 priv->send_receive_in_progress = TRUE;
1940 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1941 gtk_action_set_sensitive (action, FALSE);
1942 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1943 /* gtk_action_set_sensitive (action, FALSE); */
1944 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1945 gtk_widget_set_sensitive (widget, FALSE);
1949 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1951 GtkAction *action = NULL;
1952 GtkWidget *widget = NULL;
1953 ModestMainWindowPrivate *priv = NULL;
1955 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1956 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1958 priv->send_receive_in_progress = FALSE;
1960 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1961 gtk_action_set_sensitive (action, TRUE);
1962 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1963 /* gtk_action_set_sensitive (action, TRUE); */
1964 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1965 gtk_widget_set_sensitive (widget, TRUE);
1970 on_msg_count_changed (ModestHeaderView *header_view,
1972 TnyFolderChange *change,
1973 ModestMainWindow *main_window)
1975 gboolean refilter = FALSE;
1976 gboolean folder_empty = FALSE;
1977 gboolean all_marked_as_deleted = FALSE;
1978 ModestMainWindowPrivate *priv;
1980 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1981 g_return_if_fail (TNY_IS_FOLDER(folder));
1982 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1984 if (change != NULL) {
1985 TnyFolderChangeChanged changed;
1987 changed = tny_folder_change_get_changed (change);
1988 /* If something changes */
1989 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1990 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1992 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1994 /* Play a sound (if configured) and make the LED blink */
1995 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1996 modest_platform_push_email_notification ();
1999 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2002 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2005 /* Check if all messages are marked to be deleted */
2006 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2007 folder_empty = folder_empty || all_marked_as_deleted;
2009 /* Set contents style of headers view */
2011 modest_main_window_set_contents_style (main_window,
2012 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2013 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2015 modest_main_window_set_contents_style (main_window,
2016 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2020 modest_header_view_refilter (header_view);
2025 modest_main_window_set_contents_style (ModestMainWindow *self,
2026 ModestMainWindowContentsStyle style)
2028 ModestMainWindowPrivate *priv;
2030 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2032 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2034 /* We allow to set the same content style than the previously
2035 set if there are details, because it could happen when we're
2036 selecting different accounts consecutively */
2037 if ((priv->contents_style == style) &&
2038 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2041 /* Remove previous child. Delete it if it was an account
2043 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2045 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2046 g_object_ref (content);
2047 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2048 g_object_ref (priv->empty_view);
2049 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2052 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2055 priv->contents_style = style;
2057 switch (priv->contents_style) {
2058 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2059 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2060 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2063 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2065 /* if we're started without main win, there may not be a folder
2066 * view. this fixes a GLib-Critical */
2067 if (priv->folder_view) {
2068 TnyFolderStore *selected_folderstore =
2069 modest_folder_view_get_selected (priv->folder_view);
2070 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2071 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2072 TNY_ACCOUNT (selected_folderstore));
2074 wrap_in_scrolled_window (priv->contents_widget,
2075 priv->details_widget);
2077 g_object_unref (selected_folderstore);
2078 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2083 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2084 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2085 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2089 g_return_if_reached ();
2093 gtk_widget_show_all (priv->contents_widget);
2096 ModestMainWindowContentsStyle
2097 modest_main_window_get_contents_style (ModestMainWindow *self)
2099 ModestMainWindowPrivate *priv;
2101 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2103 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2104 return priv->contents_style;
2109 on_configuration_key_changed (ModestConf* conf,
2111 ModestConfEvent event,
2112 ModestConfNotificationId id,
2113 ModestMainWindow *self)
2115 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2116 TnyAccount *account = NULL;
2118 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2121 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2124 if (priv->folder_view)
2125 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2127 if (account && TNY_IS_ACCOUNT (account) &&
2128 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2131 const gchar *device_name;
2132 gchar *new_text, *gray_color_markup;
2135 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2136 label = GTK_LABEL (children->data);
2138 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2139 MODEST_CONF_DEVICE_NAME, NULL);
2141 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2142 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2144 gtk_label_set_markup (label, new_text);
2145 gtk_widget_show (GTK_WIDGET (label));
2147 g_free (gray_color_markup);
2149 g_list_free (children);
2151 g_object_unref (account);
2155 set_toolbar_transfer_mode (ModestMainWindow *self)
2157 ModestMainWindowPrivate *priv = NULL;
2159 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2161 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2163 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2165 if (priv->progress_bar_timeout > 0) {
2166 g_source_remove (priv->progress_bar_timeout);
2167 priv->progress_bar_timeout = 0;
2174 set_toolbar_mode (ModestMainWindow *self,
2175 ModestToolBarModes mode)
2177 ModestWindowPrivate *parent_priv = NULL;
2178 ModestMainWindowPrivate *priv = NULL;
2179 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2181 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2183 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2184 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2186 /* In case this was called before the toolbar exists: */
2187 if (!(parent_priv->toolbar))
2190 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2192 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2193 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2194 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2196 /* Sets current toolbar mode */
2197 priv->current_toolbar_mode = mode;
2199 /* Checks the dimming rules */
2200 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2202 /* Show and hide toolbar items */
2204 case TOOLBAR_MODE_NORMAL:
2206 gtk_action_set_visible (sort_action, TRUE);
2208 gtk_action_set_visible (refresh_action, TRUE);
2209 if (priv->progress_toolitem) {
2210 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2211 gtk_widget_hide (priv->progress_toolitem);
2213 if (priv->progress_bar)
2214 gtk_widget_hide (priv->progress_bar);
2217 gtk_action_set_visible (cancel_action, FALSE);
2219 /* Hide toolbar if optimized view is enabled */
2220 if (priv->optimized_view)
2221 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2223 case TOOLBAR_MODE_TRANSFER:
2225 gtk_action_set_visible (sort_action, FALSE);
2227 gtk_action_set_visible (refresh_action, FALSE);
2229 gtk_action_set_visible (cancel_action, TRUE);
2230 if (priv->progress_bar)
2231 gtk_widget_show (priv->progress_bar);
2232 if (priv->progress_toolitem) {
2233 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2234 gtk_widget_show (priv->progress_toolitem);
2237 /* Show toolbar if it's hiden (optimized view ) */
2238 if (priv->optimized_view)
2239 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2242 g_return_if_reached ();
2247 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2249 ModestMainWindowPrivate *priv;
2251 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2252 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2254 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2258 cancel_progressbar (GtkToolButton *toolbutton,
2259 ModestMainWindow *self)
2262 ModestMainWindowPrivate *priv;
2264 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2266 /* Get operation observers and cancel all the operations */
2267 tmp = priv->progress_widgets;
2269 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2270 tmp=g_slist_next(tmp);
2275 observers_empty (ModestMainWindow *self)
2278 ModestMainWindowPrivate *priv;
2279 gboolean is_empty = TRUE;
2280 guint pending_ops = 0;
2282 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2283 tmp = priv->progress_widgets;
2285 /* Check all observers */
2286 while (tmp && is_empty) {
2287 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2288 is_empty = pending_ops == 0;
2290 tmp = g_slist_next(tmp);
2298 * Gets the toolbar mode needed for each mail operation. It stores in
2299 * @mode_changed if the toolbar mode has changed or not
2301 static ModestToolBarModes
2302 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2303 ModestMailOperation *mail_op,
2304 gboolean *mode_changed)
2306 ModestToolBarModes mode;
2307 ModestMainWindowPrivate *priv;
2309 *mode_changed = FALSE;
2310 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2312 /* Get toolbar mode from operation id*/
2313 switch (modest_mail_operation_get_type_operation (mail_op)) {
2314 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2315 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2316 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2317 mode = TOOLBAR_MODE_TRANSFER;
2318 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2319 *mode_changed = TRUE;
2322 mode = TOOLBAR_MODE_NORMAL;
2328 on_mail_operation_started (ModestMailOperation *mail_op,
2331 ModestMainWindow *self;
2332 ModestMailOperationTypeOperation op_type;
2333 ModestMainWindowPrivate *priv;
2334 ModestToolBarModes mode;
2336 gboolean mode_changed = FALSE;
2337 TnyAccount *account;
2339 self = MODEST_MAIN_WINDOW (user_data);
2340 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2342 /* Do not show progress for receiving operations if the
2343 account is the local account or the MMC one */
2344 op_type = modest_mail_operation_get_type_operation (mail_op);
2345 account = modest_mail_operation_get_account (mail_op);
2346 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2349 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2350 modest_tny_account_is_memory_card_account (account));
2352 g_object_unref (account);
2356 /* Show information banner. Remove old timeout */
2357 if (priv->retrieving_banner_timeout > 0) {
2358 g_source_remove (priv->retrieving_banner_timeout);
2359 priv->retrieving_banner_timeout = 0;
2361 /* Create a new timeout */
2362 priv->retrieving_banner_timeout =
2363 g_timeout_add (2000, show_retrieving_banner, self);
2365 g_object_unref (account);
2367 /* Get toolbar mode from operation id*/
2368 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2370 /* Add operation observers and change toolbar if neccessary*/
2371 tmp = priv->progress_widgets;
2372 if (mode == TOOLBAR_MODE_TRANSFER) {
2374 GObject *source = modest_mail_operation_get_source(mail_op);
2375 if (G_OBJECT (self) == source) {
2376 set_toolbar_transfer_mode(self);
2378 g_object_unref (source);
2382 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2384 tmp = g_slist_next (tmp);
2388 /* Update the main menu as well, we need to explicitely do
2389 this in order to enable/disable accelerators */
2390 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2394 on_mail_operation_finished (ModestMailOperation *mail_op,
2397 ModestToolBarModes mode;
2398 ModestMailOperationTypeOperation op_type;
2400 ModestMainWindow *self;
2401 gboolean mode_changed;
2402 TnyAccount *account;
2403 ModestMainWindowPrivate *priv;
2405 self = MODEST_MAIN_WINDOW (user_data);
2406 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2408 /* The mail operation was not added to the progress objects if
2409 the account was the local account or the MMC one */
2410 op_type = modest_mail_operation_get_type_operation (mail_op);
2411 account = modest_mail_operation_get_account (mail_op);
2412 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2415 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2416 modest_tny_account_is_memory_card_account (account));
2418 g_object_unref (account);
2422 /* Remove old timeout */
2423 if (priv->retrieving_banner_timeout > 0) {
2424 g_source_remove (priv->retrieving_banner_timeout);
2425 priv->retrieving_banner_timeout = 0;
2428 /* Remove the banner if exists */
2429 if (priv->retrieving_banner) {
2430 gtk_widget_destroy (priv->retrieving_banner);
2431 priv->retrieving_banner = NULL;
2434 g_object_unref (account);
2436 /* Get toolbar mode from operation id*/
2437 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2439 /* Change toolbar mode */
2440 tmp = priv->progress_widgets;
2441 if (mode == TOOLBAR_MODE_TRANSFER) {
2443 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2445 tmp = g_slist_next (tmp);
2448 /* If no more operations are being observed, NORMAL mode is enabled again */
2449 if (observers_empty (self)) {
2450 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2456 on_queue_changed (ModestMailOperationQueue *queue,
2457 ModestMailOperation *mail_op,
2458 ModestMailOperationQueueNotification type,
2459 ModestMainWindow *self)
2461 ModestMainWindowPrivate *priv;
2463 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2465 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2466 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2468 "operation-started",
2469 G_CALLBACK (on_mail_operation_started),
2471 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2473 "operation-finished",
2474 G_CALLBACK (on_mail_operation_finished),
2476 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2477 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2479 "operation-started");
2480 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2482 "operation-finished");
2487 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2489 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2491 ModestAccountMgr *mgr;
2492 ModestAccountSettings *settings;
2493 ModestServerAccountSettings *store_settings = NULL;
2495 /* Get account data */
2496 mgr = modest_runtime_get_account_mgr ();
2497 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2499 store_settings = modest_account_settings_get_store_settings (settings);
2501 /* Set the new visible & active account */
2502 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2503 const gchar *account_name;
2505 account_name = modest_account_settings_get_account_name (settings);
2507 modest_folder_view_set_account_id_of_visible_server_account
2509 modest_server_account_settings_get_account_name (store_settings));
2510 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2511 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2512 if (action != NULL) {
2513 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2514 modest_utils_toggle_action_set_active_block_notify (
2515 GTK_TOGGLE_ACTION (action),
2521 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2526 g_object_unref (store_settings);
2527 g_object_unref (settings);
2531 /* Make sure that at least one account is "viewed": */
2533 set_at_least_one_account_visible(ModestMainWindow *self)
2535 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2536 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2538 if (!(priv->folder_view)) {
2539 /* It is too early to do this. */
2543 const gchar *active_server_account_name =
2544 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2546 if (!active_server_account_name ||
2547 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2549 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2550 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2551 if (default_modest_name) {
2552 set_account_visible (self, default_modest_name);
2553 } else if (first_modest_name) {
2554 set_account_visible (self, first_modest_name);
2556 g_free (first_modest_name);
2557 g_free (default_modest_name);
2562 on_show_account_action_toggled (GtkToggleAction *action,
2565 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2567 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2568 if (gtk_toggle_action_get_active (action))
2569 set_account_visible (self, acc_name);
2573 refresh_account (const gchar *account_name)
2577 /* win must already exists here, obviously */
2578 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2581 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2585 /* If account_name == NULL, we must update all (option All) */
2587 modest_ui_actions_do_send_receive_all (win, TRUE);
2589 modest_ui_actions_do_send_receive (account_name, TRUE, win);
2594 on_refresh_account_action_activated (GtkAction *action,
2597 refresh_account ((const gchar*) user_data);
2601 on_send_receive_csm_activated (GtkMenuItem *item,
2604 refresh_account ((const gchar*) user_data);
2608 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2610 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2612 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2618 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2620 ModestMainWindow *main_window = NULL;
2622 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2623 main_window = MODEST_MAIN_WINDOW (userdata);
2625 /* Update toolbar dimming state */
2626 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2632 on_header_view_focus_in (GtkWidget *widget,
2633 GdkEventFocus *event,
2636 ModestMainWindow *main_window = NULL;
2638 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2640 main_window = MODEST_MAIN_WINDOW (userdata);
2642 /* Update toolbar dimming state */
2643 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2649 on_folder_selection_changed (ModestFolderView *folder_view,
2650 TnyFolderStore *folder_store,
2652 ModestMainWindow *main_window)
2654 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2655 GtkAction *action = NULL;
2656 gboolean show_reply = TRUE;
2657 gboolean show_forward = TRUE;
2658 gboolean show_cancel_send = FALSE;
2659 gboolean show_clipboard = TRUE;
2660 gboolean show_delete = TRUE;
2663 if (TNY_IS_ACCOUNT (folder_store)) {
2664 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2665 } else if (TNY_IS_FOLDER (folder_store)) {
2666 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2667 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2668 TNY_FOLDER (folder_store));
2669 switch (folder_type) {
2670 case TNY_FOLDER_TYPE_DRAFTS:
2671 show_clipboard = show_delete = TRUE;
2672 show_reply = show_forward = show_cancel_send = FALSE;
2674 case TNY_FOLDER_TYPE_SENT:
2675 show_forward = show_clipboard = show_delete = TRUE;
2676 show_reply = show_cancel_send = FALSE;
2678 case TNY_FOLDER_TYPE_OUTBOX:
2679 show_clipboard = show_delete = show_cancel_send = TRUE;
2680 show_reply = show_forward = FALSE;
2682 case TNY_FOLDER_TYPE_INVALID:
2683 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2686 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2687 show_cancel_send = FALSE;
2690 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2691 show_cancel_send = FALSE;
2696 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2697 gtk_action_set_visible (action, show_reply);
2698 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2699 gtk_action_set_visible (action, show_reply);
2700 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2701 gtk_action_set_visible (action, show_forward);
2702 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2703 gtk_action_set_visible (action, show_cancel_send);
2704 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2705 gtk_action_set_visible (action, show_delete);
2707 /* We finally call to the ui actions handler, after updating properly
2708 * the header view CSM */
2709 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2713 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2714 GtkTreeModel *model,
2715 GtkTreeRowReference *row_reference,
2716 ModestMainWindow *self)
2718 ModestMainWindowPrivate *priv = NULL;
2719 GtkTreeModel *header_model = NULL;
2720 GtkTreePath *path = NULL;
2722 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2723 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2724 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2726 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2727 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2729 /* Do nothing if we changed the folder in the main view */
2730 if (header_model != model)
2733 /* Select the message in the header view */
2734 path = gtk_tree_row_reference_get_path (row_reference);
2735 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2737 gtk_tree_path_free (path);
2743 show_updating_banner (gpointer user_data)
2745 ModestMainWindowPrivate *priv = NULL;
2747 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2749 if (priv->updating_banner == NULL) {
2751 /* We're outside the main lock */
2752 gdk_threads_enter ();
2753 priv->updating_banner =
2754 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2755 _CS ("ckdg_pb_updating"));
2756 gdk_threads_leave ();
2759 /* Remove timeout */
2760 priv->updating_banner_timeout = 0;
2765 * We use this function to show/hide a progress banner showing
2766 * "Updating" while the header view is being filled. We're not showing
2767 * it unless the update takes more than 2 seconds
2769 * If starting = TRUE then the refresh is starting, otherwise it means
2770 * that is has just finished
2773 on_updating_msg_list (ModestHeaderView *header_view,
2777 ModestMainWindowPrivate *priv = NULL;
2779 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2781 /* Remove old timeout */
2782 if (priv->updating_banner_timeout > 0) {
2783 g_source_remove (priv->updating_banner_timeout);
2784 priv->updating_banner_timeout = 0;
2787 /* Create a new timeout */
2789 priv->updating_banner_timeout =
2790 g_timeout_add (2000, show_updating_banner, user_data);
2792 /* Remove the banner if exists */
2793 if (priv->updating_banner) {
2794 gtk_widget_destroy (priv->updating_banner);
2795 priv->updating_banner = NULL;
2801 modest_main_window_screen_is_on (ModestMainWindow *self)
2803 ModestMainWindowPrivate *priv = NULL;
2805 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2807 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2809 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2813 on_window_destroy (GtkObject *widget, gpointer userdata)
2815 ModestMainWindowPrivate *priv;
2817 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (widget);
2819 if (priv->retrieving_banner_timeout > 0) {
2820 g_source_remove (priv->retrieving_banner_timeout);
2821 priv->retrieving_banner_timeout = 0;
2824 if (priv->retrieving_banner != NULL) {
2825 gtk_widget_destroy (priv->retrieving_banner);
2826 priv->retrieving_banner = NULL;
2829 if (priv->updating_banner_timeout > 0) {
2830 g_source_remove (priv->updating_banner_timeout);
2831 priv->updating_banner_timeout = 0;
2834 if (priv->updating_banner != NULL) {
2835 gtk_widget_destroy (priv->updating_banner);
2836 priv->updating_banner = NULL;
2842 show_retrieving_banner (gpointer user_data)
2844 ModestMainWindowPrivate *priv = NULL;
2846 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2848 if (priv->retrieving_banner == NULL) {
2850 /* We're outside the main lock */
2851 gdk_threads_enter ();
2852 priv->retrieving_banner =
2853 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2854 _("mcen_ib_getting_items"));
2855 gdk_threads_leave ();
2858 /* Remove timeout */
2859 priv->retrieving_banner_timeout = 0;