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 static void on_window_hide (GObject *gobject,
188 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
189 struct _ModestMainWindowPrivate {
190 GtkWidget *msg_paned;
191 GtkWidget *main_paned;
192 GtkWidget *main_vbox;
193 GtkWidget *contents_widget;
194 GtkWidget *empty_view;
196 /* Progress observers */
197 GtkWidget *progress_bar;
198 GSList *progress_widgets;
201 GtkWidget *progress_toolitem;
202 GtkWidget *cancel_toolitem;
203 GtkWidget *sort_toolitem;
204 GtkWidget *refresh_toolitem;
205 ModestToolBarModes current_toolbar_mode;
207 /* Merge ids used to add/remove accounts to the ViewMenu*/
208 GByteArray *merge_ids;
209 GtkActionGroup *view_additions_group;
211 /* On-demand widgets */
212 GtkWidget *accounts_popup;
213 GtkWidget *details_widget;
215 /* Optimized view enabled */
216 gboolean optimized_view;
218 /* Optimized view enabled */
219 gboolean send_receive_in_progress;
221 ModestHeaderView *header_view;
222 ModestFolderView *folder_view;
224 ModestMainWindowStyle style;
225 ModestMainWindowContentsStyle contents_style;
226 gboolean wait_for_settings;
228 guint progress_bar_timeout;
229 guint restore_paned_timeout;
231 /* Signal handler UIDs */
232 GList *queue_err_signals;
235 /* "Updating" banner for header view */
236 GtkWidget *updating_banner;
237 guint updating_banner_timeout;
239 /* "Retrieving" banner for header view */
240 GtkWidget *retrieving_banner;
241 guint retrieving_banner_timeout;
244 osso_display_state_t display_state;
246 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
247 MODEST_TYPE_MAIN_WINDOW, \
248 ModestMainWindowPrivate))
250 typedef struct _GetMsgAsyncHelper {
251 ModestMainWindowPrivate *main_window_private;
253 ModestTnyMsgReplyType reply_type;
254 ModestTnyMsgForwardType forward_type;
261 static GtkWindowClass *parent_class = NULL;
264 /* Private actions */
265 /* This is the context sensitive menu: */
266 static const GtkActionEntry modest_folder_view_action_entries [] = {
268 /* Folder View CSM actions */
269 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
270 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
271 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
272 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
273 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
274 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
277 static const GtkActionEntry modest_header_view_action_entries [] = {
279 /* Header View CSM actions */
280 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
281 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
282 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
283 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
284 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
285 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
286 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
287 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
288 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
289 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
292 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
293 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
296 /************************************************************************/
299 modest_main_window_get_type (void)
301 static GType my_type = 0;
303 static const GTypeInfo my_info = {
304 sizeof(ModestMainWindowClass),
305 NULL, /* base init */
306 NULL, /* base finalize */
307 (GClassInitFunc) modest_main_window_class_init,
308 NULL, /* class finalize */
309 NULL, /* class data */
310 sizeof(ModestMainWindow),
312 (GInstanceInitFunc) modest_main_window_init,
315 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
323 modest_main_window_class_init (ModestMainWindowClass *klass)
325 GObjectClass *gobject_class;
326 gobject_class = (GObjectClass*) klass;
327 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
329 parent_class = g_type_class_peek_parent (klass);
330 gobject_class->finalize = modest_main_window_finalize;
332 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
334 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
335 modest_window_class->save_state_func = save_state;
336 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
337 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
338 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
342 modest_main_window_init (ModestMainWindow *obj)
344 ModestMainWindowPrivate *priv;
346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
348 priv->queue_err_signals = NULL;
349 priv->msg_paned = NULL;
350 priv->main_paned = NULL;
351 priv->main_vbox = NULL;
352 priv->header_view = NULL;
353 priv->folder_view = NULL;
354 priv->contents_widget = NULL;
355 priv->accounts_popup = NULL;
356 priv->details_widget = NULL;
357 priv->empty_view = NULL;
358 priv->progress_widgets = NULL;
359 priv->progress_bar = NULL;
360 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
361 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
362 priv->wait_for_settings = TRUE;
363 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
364 priv->merge_ids = NULL;
365 priv->optimized_view = FALSE;
366 priv->send_receive_in_progress = FALSE;
367 priv->progress_bar_timeout = 0;
368 priv->restore_paned_timeout = 0;
369 priv->sighandlers = NULL;
370 priv->updating_banner = NULL;
371 priv->updating_banner_timeout = 0;
372 priv->retrieving_banner = NULL;
373 priv->retrieving_banner_timeout = 0;
374 priv->display_state = OSSO_DISPLAY_ON;
376 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
378 "applications_email_mainview");
382 modest_main_window_finalize (GObject *obj)
384 ModestMainWindowPrivate *priv;
386 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
388 /* Sanity check: shouldn't be needed, the window mgr should
389 call this function before */
390 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
391 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
393 g_slist_free (priv->progress_widgets);
395 g_byte_array_free (priv->merge_ids, TRUE);
397 if (priv->progress_bar_timeout > 0) {
398 g_source_remove (priv->progress_bar_timeout);
399 priv->progress_bar_timeout = 0;
402 if (priv->updating_banner_timeout > 0) {
403 g_source_remove (priv->updating_banner_timeout);
404 priv->updating_banner_timeout = 0;
407 if (priv->updating_banner) {
408 gtk_widget_destroy (priv->updating_banner);
409 priv->updating_banner = NULL;
412 if (priv->retrieving_banner_timeout > 0) {
413 g_source_remove (priv->retrieving_banner_timeout);
414 priv->retrieving_banner_timeout = 0;
417 if (priv->retrieving_banner) {
418 gtk_widget_destroy (priv->retrieving_banner);
419 priv->retrieving_banner = NULL;
422 if (priv->restore_paned_timeout > 0) {
423 g_source_remove (priv->restore_paned_timeout);
424 priv->restore_paned_timeout = 0;
427 G_OBJECT_CLASS(parent_class)->finalize (obj);
431 modest_main_window_get_child_widget (ModestMainWindow *self,
432 ModestMainWindowWidgetType widget_type)
434 ModestMainWindowPrivate *priv;
437 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
438 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
441 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
443 switch (widget_type) {
444 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
445 widget = (GtkWidget*)priv->header_view; break;
446 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
447 widget = (GtkWidget*)priv->folder_view; break;
452 /* Note that the window could have been destroyed, and so
453 their children, but still have some references */
454 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
458 restore_paned_timeout_handler (gpointer *data)
460 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
461 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
464 /* Timeouts are outside the main lock */
465 gdk_threads_enter ();
466 if (GTK_WIDGET_VISIBLE (main_window)) {
467 conf = modest_runtime_get_conf ();
468 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
469 MODEST_CONF_MAIN_PANED_KEY);
471 gdk_threads_leave ();
478 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
485 conf = modest_runtime_get_conf ();
487 modest_widget_memory_restore (conf, G_OBJECT(self),
488 MODEST_CONF_MAIN_WINDOW_KEY);
490 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
491 MODEST_CONF_HEADER_VIEW_KEY);
493 if (do_folder_view_too)
494 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
495 MODEST_CONF_FOLDER_VIEW_KEY);
497 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
498 /* MODEST_CONF_MAIN_PANED_KEY); */
500 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
502 /* We need to force a redraw here in order to get the right
503 position of the horizontal paned separator */
504 gtk_widget_show (GTK_WIDGET (self));
509 save_state (ModestWindow *window)
512 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
513 ModestMainWindowPrivate *priv;
515 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
516 conf = modest_runtime_get_conf ();
518 modest_widget_memory_save (conf,G_OBJECT(self),
519 MODEST_CONF_MAIN_WINDOW_KEY);
520 /* Only save main paned position if we're in split mode */
521 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
522 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
523 MODEST_CONF_MAIN_PANED_KEY);
524 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
525 MODEST_CONF_FOLDER_VIEW_KEY);
529 compare_display_names (ModestAccountSettings *a,
530 ModestAccountSettings *b)
532 return strcmp (modest_account_settings_get_display_name (a),
533 modest_account_settings_get_display_name (b));
536 /* We use this function to prevent the send&receive CSM to be shown
537 when there are less than two account */
539 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
545 update_menus (ModestMainWindow* self)
547 GSList *account_names, *iter, *accounts;
548 ModestMainWindowPrivate *priv;
549 ModestWindowPrivate *parent_priv;
550 ModestAccountMgr *mgr;
551 gint i, num_accounts;
553 gchar *default_account;
554 const gchar *active_account_name;
555 GtkWidget *send_receive_button, *item;
556 GtkAction *send_receive_all = NULL;
559 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
560 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
562 /* Get enabled account IDs */
563 mgr = modest_runtime_get_account_mgr ();
564 account_names = modest_account_mgr_account_names (mgr, TRUE);
565 iter = account_names;
569 ModestAccountSettings *settings =
570 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
571 accounts = g_slist_prepend (accounts, settings);
575 modest_account_mgr_free_account_names (account_names);
576 account_names = NULL;
578 /* Order the list of accounts by its display name */
579 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
580 num_accounts = g_slist_length (accounts);
582 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
583 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
584 gtk_action_set_visible (send_receive_all, num_accounts > 0);
586 /* Delete old send&receive popup items. We can not just do a
587 menu_detach because it does not work well with
589 if (priv->accounts_popup)
590 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
591 (GtkCallback) gtk_widget_destroy, NULL);
593 /* Delete old entries in the View menu. Do not free groups, it
595 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
597 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
598 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
599 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
600 GTK_ACTION_GROUP (groups->data));
603 if (priv->merge_ids) {
604 for (i = 0; i < priv->merge_ids->len; i++)
605 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
606 g_byte_array_free (priv->merge_ids, TRUE);
608 /* We need to call this in order to ensure
609 that the new actions are added in the right
610 order (alphabetical) */
611 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
613 groups = g_list_next (groups);
615 priv->merge_ids = g_byte_array_sized_new (num_accounts);
617 /* Get send receive button */
618 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
619 "/ToolBar/ToolbarSendReceive");
621 /* Create the menu */
622 if (num_accounts > 1) {
623 if (!priv->accounts_popup)
624 priv->accounts_popup = gtk_menu_new ();
625 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
626 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
627 g_signal_connect (G_OBJECT (item),
629 G_CALLBACK (on_send_receive_csm_activated),
631 item = gtk_separator_menu_item_new ();
632 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
635 /* Create a new action group */
636 default_account = modest_account_mgr_get_default_account (mgr);
637 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
639 if (!active_account_name)
640 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
642 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
644 for (i = 0; i < num_accounts; i++) {
645 gchar *display_name = NULL;
646 const gchar *account_name;
647 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
650 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
653 account_name = modest_account_settings_get_account_name (settings);
655 if (default_account && account_name &&
656 !(strcmp (default_account, account_name) == 0)) {
657 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
658 modest_account_settings_get_display_name (settings));
660 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
661 modest_account_settings_get_display_name (settings));
666 /* Create action and add it to the action group. The
667 action name must be the account name, this way we
668 could know in the handlers the account to show */
669 if (settings && account_name) {
670 gchar* item_name, *refresh_action_name;
672 GtkAction *view_account_action, *refresh_account_action;
673 gchar *escaped_display_name;
675 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
677 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
678 escaped_display_name, NULL, NULL, 0));
679 g_free (escaped_display_name);
680 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
681 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
682 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
684 if (active_account_name) {
685 if (active_account_name && account_name &&
686 (strcmp (active_account_name, account_name) == 0)) {
687 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
691 /* Add ui from account data. We allow 2^9-1 account
692 changes in a single execution because we're
693 downcasting the guint to a guint8 in order to use a
694 GByteArray. It should be enough. */
695 item_name = g_strconcat (account_name, "Menu", NULL);
696 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
697 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
698 gtk_ui_manager_add_ui (parent_priv->ui_manager,
700 "/MenuBar/ViewMenu/ViewMenuAdditions",
703 GTK_UI_MANAGER_MENUITEM,
706 /* Connect the action signal "activate" */
707 g_signal_connect_after (G_OBJECT (view_account_action),
709 G_CALLBACK (on_show_account_action_toggled),
712 /* Create the items for the Tools->Send&Receive submenu */
713 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
714 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
715 display_name, NULL, NULL);
716 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
718 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
719 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
720 gtk_ui_manager_add_ui (parent_priv->ui_manager,
722 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
725 GTK_UI_MANAGER_MENUITEM,
727 g_free (refresh_action_name);
729 g_signal_connect_data (G_OBJECT (refresh_account_action),
731 G_CALLBACK (on_refresh_account_action_activated),
732 g_strdup (account_name),
733 (GClosureNotify) g_free,
736 /* Create item and add it to the send&receive
737 CSM. If there is only one account then
739 if (num_accounts > 1) {
740 GtkWidget *label = gtk_label_new(NULL);
741 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
742 if (default_account && (strcmp(account_name, default_account) == 0)) {
743 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
744 gtk_label_set_markup (GTK_LABEL (label), escaped);
747 gtk_label_set_text (GTK_LABEL (label), display_name);
750 item = gtk_menu_item_new ();
751 gtk_container_add (GTK_CONTAINER (item), label);
753 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
754 g_signal_connect_data (G_OBJECT (item),
756 G_CALLBACK (on_send_receive_csm_activated),
757 g_strdup (account_name),
758 (GClosureNotify) g_free,
765 g_free (display_name);
768 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
770 /* We cannot do this in the loop above because this relies on the action
771 * group being inserted. This makes the default account appear in bold.
772 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
773 for (i = 0; i < num_accounts; i++) {
774 gchar *item_name, *path;
776 ModestAccountSettings *settings;
777 const gchar *account_name;
780 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
781 account_name = modest_account_settings_get_account_name (settings);
782 is_default = (account_name && default_account && !strcmp (account_name, default_account));
784 /* Get the item of the view menu */
785 item_name = g_strconcat (account_name, "Menu", NULL);
786 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
787 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
791 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
792 if (GTK_IS_LABEL (child)) {
793 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
795 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
796 gtk_label_set_markup (GTK_LABEL (child), bold_name);
799 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
803 /* Get the item of the tools menu */
804 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
805 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
809 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
810 if (GTK_IS_LABEL (child)) {
811 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
813 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
814 gtk_label_set_markup (GTK_LABEL (child), bold_name);
817 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
822 g_object_unref (settings);
825 if (num_accounts > 1) {
826 /* Disconnect the tap-and-hold-query if it's connected */
827 if (modest_signal_mgr_is_connected (priv->sighandlers,
828 G_OBJECT (send_receive_button),
829 "tap-and-hold-query"))
830 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
831 G_OBJECT (send_receive_button),
832 "tap-and-hold-query");
834 /* Mandatory in order to view the menu contents */
835 gtk_widget_show_all (priv->accounts_popup);
837 /* Setup tap_and_hold just if was not done before*/
838 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
839 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
841 /* Connect the tap-and-hold-query in order not to show the CSM */
842 if (!modest_signal_mgr_is_connected (priv->sighandlers,
843 G_OBJECT (send_receive_button),
844 "tap-and-hold-query"))
845 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
846 G_OBJECT (send_receive_button),
847 "tap-and-hold-query",
848 G_CALLBACK (tap_and_hold_query_cb),
853 g_slist_free (accounts);
854 g_free (default_account);
857 /* Make sure that at least one account is viewed if there are any
858 * accounts, for instance when adding the first account: */
859 set_at_least_one_account_visible (self);
863 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
865 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
866 gtk_scrolled_window_add_with_viewport
867 (GTK_SCROLLED_WINDOW(win), widget);
869 gtk_container_add (GTK_CONTAINER(win),
880 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
882 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
884 GList *oerrsignals = priv->queue_err_signals;
885 while (oerrsignals) {
886 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
887 g_signal_handler_disconnect (esignal->queue, esignal->signal);
888 g_slice_free (QueueErrorSignal, esignal);
889 oerrsignals = g_list_next (oerrsignals);
891 g_list_free (priv->queue_err_signals);
892 priv->queue_err_signals = NULL;
897 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
899 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
902 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
906 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
908 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
910 /* Update visibility */
913 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
917 modest_main_window_disconnect_signals (ModestWindow *self)
919 ModestMainWindowPrivate *priv;
920 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
922 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
923 priv->sighandlers = NULL;
927 connect_signals (ModestMainWindow *self)
929 ModestWindowPrivate *parent_priv;
930 ModestMainWindowPrivate *priv;
933 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
934 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
939 modest_signal_mgr_connect (priv->sighandlers,
940 G_OBJECT(priv->folder_view), "key-press-event",
941 G_CALLBACK(on_inner_widgets_key_pressed), self);
943 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
944 "folder_selection_changed",
945 G_CALLBACK (on_folder_selection_changed),
948 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
949 "folder-display-name-changed",
950 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
953 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
955 G_CALLBACK (on_folder_view_focus_in),
958 /* Folder view CSM */
959 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
960 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
961 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
962 G_CALLBACK(_folder_view_csm_menu_activated),
966 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
967 G_CALLBACK(modest_ui_actions_on_header_selected), self);
969 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
970 G_CALLBACK(modest_ui_actions_on_header_activated), self);
972 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
973 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
975 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
976 G_CALLBACK(on_inner_widgets_key_pressed), self);
978 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
979 G_CALLBACK(on_msg_count_changed), self);
981 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
982 G_CALLBACK (on_header_view_focus_in), self);
984 modest_signal_mgr_connect (priv->sighandlers,
985 G_OBJECT (priv->header_view),
987 G_CALLBACK (on_updating_msg_list),
990 /* Header view CSM */
991 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
992 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
994 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
995 G_CALLBACK(_header_view_csm_menu_activated),
1000 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1001 G_CALLBACK (modest_main_window_window_state_event),
1003 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1004 * in destroy stage */
1005 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1007 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1009 /* Mail Operation Queue */
1011 modest_signal_mgr_connect (priv->sighandlers,
1012 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1014 G_CALLBACK (on_queue_changed), self);
1016 /* Track changes in the device name */
1018 modest_signal_mgr_connect (priv->sighandlers,
1019 G_OBJECT(modest_runtime_get_conf ()),
1021 G_CALLBACK (on_configuration_key_changed),
1024 /* Track account changes. We need to refresh the toolbar */
1026 modest_signal_mgr_connect (priv->sighandlers,
1027 G_OBJECT (modest_runtime_get_account_store ()),
1029 G_CALLBACK (on_account_inserted),
1032 modest_signal_mgr_connect (priv->sighandlers,
1033 G_OBJECT (modest_runtime_get_account_store ()),
1035 G_CALLBACK (on_account_removed),
1038 /* We need to refresh the send & receive menu to change the bold
1039 * account when the default account changes. */
1041 modest_signal_mgr_connect (priv->sighandlers,
1042 G_OBJECT (modest_runtime_get_account_mgr ()),
1043 "default_account_changed",
1044 G_CALLBACK (on_default_account_changed),
1049 modest_signal_mgr_connect (priv->sighandlers,
1050 G_OBJECT (modest_runtime_get_account_store ()),
1052 G_CALLBACK (on_account_changed),
1057 on_hildon_program_is_topmost_notify(GObject *self,
1058 GParamSpec *propert_param,
1061 HildonProgram *app = HILDON_PROGRAM (self);
1063 /* Note that use of hildon_program_set_can_hibernate()
1064 * is generally referred to as "setting the killable flag",
1065 * though hibernation does not seem equal to death.
1068 if (hildon_program_get_is_topmost (app)) {
1069 /* Prevent hibernation when the progam comes to the foreground,
1070 * because hibernation should only happen when the application
1071 * is in the background: */
1072 hildon_program_set_can_hibernate (app, FALSE);
1074 /* Remove new mail visual notifications */
1075 modest_platform_remove_new_mail_notifications (TRUE);
1077 /* Allow hibernation if the program has gone to the background: */
1079 /* However, prevent hibernation while the settings are being changed: */
1080 const gboolean hibernation_prevented =
1081 modest_window_mgr_get_hibernation_is_prevented (
1082 modest_runtime_get_window_mgr ());
1084 if (hibernation_prevented)
1085 hildon_program_set_can_hibernate (app, FALSE);
1087 /* Allow hibernation, after saving the state: */
1088 modest_osso_save_state();
1089 hildon_program_set_can_hibernate (app, TRUE);
1096 GtkWidget *folder_win;
1101 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1103 ShowHelper *helper = (ShowHelper *) user_data;
1104 GtkWidget *folder_win = helper->folder_win;
1105 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1107 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1108 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1110 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1112 /* Connect signals */
1113 connect_signals (MODEST_MAIN_WINDOW (self));
1115 /* Set account store */
1116 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1117 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1119 /* Load previous osso state, for instance if we are being restored from
1121 modest_osso_load_state ();
1123 /* Restore window & widget settings */
1124 priv->wait_for_settings = TRUE;
1125 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1126 priv->wait_for_settings = FALSE;
1128 /* Check if accounts exist and show the account wizard if not */
1129 gboolean accounts_exist =
1130 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1132 if (!accounts_exist) {
1133 /* This is necessary to have the main window shown behind the dialog
1134 It's an ugly hack... jschmid */
1135 gtk_widget_show_all(GTK_WIDGET(self));
1136 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1139 GtkAction *send_receive_all;
1140 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1141 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1142 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1143 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1144 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1145 modest_account_mgr_free_account_names (accounts);
1146 update_menus (MODEST_MAIN_WINDOW (self));
1149 /* Never call this function again (NOTE that it could happen
1150 as we hide the main window instead of closing it while
1151 there are operations ongoing) and free the helper */
1152 g_signal_handler_disconnect (self, helper->handler_id);
1153 g_slice_free (ShowHelper, helper);
1157 osso_display_event_cb (osso_display_state_t state,
1160 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1162 priv->display_state = state;
1164 /* Stop blinking if the screen becomes on */
1165 if (priv->display_state == OSSO_DISPLAY_ON)
1166 modest_platform_remove_new_mail_notifications (TRUE);
1170 modest_main_window_new (void)
1172 ModestMainWindow *self = NULL;
1173 ModestMainWindowPrivate *priv = NULL;
1174 ModestWindowPrivate *parent_priv = NULL;
1175 GtkWidget *folder_win = NULL;
1176 ModestDimmingRulesGroup *menu_rules_group = NULL;
1177 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1178 GtkActionGroup *action_group = NULL;
1179 GError *error = NULL;
1181 ModestConf *conf = NULL;
1182 GtkAction *action = NULL;
1183 GdkPixbuf *window_icon;
1186 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1187 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1188 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1190 parent_priv->ui_manager = gtk_ui_manager_new();
1191 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1193 action_group = gtk_action_group_new ("ModestMainWindowActions");
1194 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1196 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1197 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1199 /* Add common actions */
1200 gtk_action_group_add_actions (action_group,
1201 modest_action_entries,
1202 G_N_ELEMENTS (modest_action_entries),
1205 gtk_action_group_add_actions (action_group,
1206 modest_folder_view_action_entries,
1207 G_N_ELEMENTS (modest_folder_view_action_entries),
1210 gtk_action_group_add_actions (action_group,
1211 modest_header_view_action_entries,
1212 G_N_ELEMENTS (modest_header_view_action_entries),
1215 gtk_action_group_add_toggle_actions (action_group,
1216 modest_toggle_action_entries,
1217 G_N_ELEMENTS (modest_toggle_action_entries),
1220 gtk_action_group_add_toggle_actions (action_group,
1221 modest_main_window_toggle_action_entries,
1222 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1225 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1226 g_object_unref (action_group);
1228 /* Load the UI definition */
1229 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1230 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1231 if (error != NULL) {
1232 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1233 g_error_free (error);
1237 /* Add common dimming rules */
1238 modest_dimming_rules_group_add_rules (menu_rules_group,
1239 modest_main_window_menu_dimming_entries,
1240 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1241 MODEST_WINDOW (self));
1242 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1243 modest_main_window_toolbar_dimming_entries,
1244 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1245 MODEST_WINDOW (self));
1247 /* Insert dimming rules group for this window */
1248 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1249 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1250 g_object_unref (menu_rules_group);
1251 g_object_unref (toolbar_rules_group);
1253 /* Add accelerators */
1254 gtk_window_add_accel_group (GTK_WINDOW (self),
1255 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1257 /* Menubar. Update the state of some toggles */
1258 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1259 conf = modest_runtime_get_conf ();
1260 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1261 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1262 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1263 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1264 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1265 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1266 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1267 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1268 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1269 gtk_widget_show (parent_priv->menubar);
1271 /* Get device name */
1272 modest_maemo_utils_get_device_name ();
1276 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1277 if (!priv->header_view)
1278 g_printerr ("modest: cannot instantiate header view\n");
1279 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1280 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1281 MODEST_CONF_HEADER_VIEW_KEY);
1283 /* Other style properties of header view */
1284 g_object_set (G_OBJECT (priv->header_view),
1285 "rules-hint", FALSE,
1287 /* gtk_widget_show (priv->header_view); */
1290 priv->empty_view = create_empty_view ();
1291 gtk_widget_show (priv->empty_view);
1293 /* Create scrolled windows */
1294 folder_win = gtk_scrolled_window_new (NULL, NULL);
1295 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1296 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1298 GTK_POLICY_AUTOMATIC);
1299 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1301 GTK_POLICY_AUTOMATIC);
1302 /* gtk_widget_show (priv->contents_widget); */
1305 priv->main_paned = gtk_hpaned_new ();
1306 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1307 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1308 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1310 /* putting it all together... */
1311 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1312 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1313 gtk_widget_show (priv->main_vbox);
1315 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1317 app = hildon_program_get_instance ();
1318 hildon_program_add_window (app, HILDON_WINDOW (self));
1320 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1321 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1323 /* Connect to "show" action. We delay the creation of some
1324 elements until that moment */
1325 helper = g_slice_new0 (ShowHelper);
1326 helper->folder_win = folder_win;
1327 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1328 G_CALLBACK (modest_main_window_on_show),
1331 /* Set window icon */
1332 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1334 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1335 g_object_unref (window_icon);
1338 /* Listen for changes in the screen, we don't want to show a
1339 led pattern when the display is on for example */
1340 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1341 osso_display_event_cb,
1344 /* Dont't restore settings here,
1345 * because it requires a gtk_widget_show(),
1346 * and we don't want to do that until later,
1347 * so that the UI is not visible for non-menu D-Bus activation.
1350 return MODEST_WINDOW(self);
1354 modest_main_window_set_style (ModestMainWindow *self,
1355 ModestMainWindowStyle style)
1357 ModestMainWindowPrivate *priv;
1358 ModestWindowPrivate *parent_priv;
1362 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1364 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1365 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1367 /* no change -> nothing to do */
1368 if (priv->style == style)
1371 /* Get toggle button and update the state if needed. This will
1372 happen only when the set_style is not invoked from the UI,
1373 for example when it's called from widget memory */
1374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1375 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1376 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1377 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1378 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1379 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1380 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1383 priv->style = style;
1385 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1387 if (!priv->wait_for_settings)
1388 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1389 MODEST_CONF_MAIN_PANED_KEY);
1390 /* Remove main paned */
1391 g_object_ref (priv->main_paned);
1392 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1394 /* Reparent the contents widget to the main vbox */
1395 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1398 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1399 /* Remove header view */
1400 g_object_ref (priv->contents_widget);
1401 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1403 /* Reparent the main paned */
1404 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1405 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1407 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1411 g_return_if_reached ();
1414 /* Let header view grab the focus if it's being shown */
1415 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1416 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1418 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1421 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1424 ModestMainWindowStyle
1425 modest_main_window_get_style (ModestMainWindow *self)
1427 ModestMainWindowPrivate *priv;
1429 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1431 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1436 toolbar_resize (ModestMainWindow *self)
1438 ModestMainWindowPrivate *priv = NULL;
1439 ModestWindowPrivate *parent_priv = NULL;
1441 gint static_button_size;
1442 ModestWindowMgr *mgr;
1444 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1445 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1446 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1448 mgr = modest_runtime_get_window_mgr ();
1449 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1451 if (parent_priv->toolbar) {
1452 /* left size buttons */
1453 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1456 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1457 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1458 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1459 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1460 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1461 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1462 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1463 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1464 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1465 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1466 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1467 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1468 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1470 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1471 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1472 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1475 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1476 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1477 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1485 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1487 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1488 ModestWindowPrivate *parent_priv;
1489 ModestWindowMgr *mgr;
1490 gboolean is_fullscreen;
1491 GtkAction *fs_toggle_action;
1494 mgr = modest_runtime_get_window_mgr ();
1496 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1498 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1500 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1501 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1502 if (is_fullscreen != active) {
1503 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1506 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1514 modest_main_window_show_toolbar (ModestWindow *self,
1515 gboolean show_toolbar)
1517 ModestMainWindowPrivate *priv = NULL;
1518 ModestWindowPrivate *parent_priv = NULL;
1519 GtkWidget *reply_button = NULL, *menu = NULL;
1520 GtkWidget *placeholder = NULL;
1522 const gchar *action_name;
1525 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1526 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1527 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1529 /* Set optimized view status */
1530 priv->optimized_view = !show_toolbar;
1532 if (!parent_priv->toolbar) {
1533 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1535 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1537 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1538 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1539 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1540 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1541 toolbar_resize (MODEST_MAIN_WINDOW (self));
1543 /* Add ProgressBar (Transfer toolbar) */
1544 priv->progress_bar = modest_progress_bar_new ();
1545 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1546 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1547 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1548 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1549 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1551 /* Connect cancel 'clicked' signal to abort progress mode */
1552 g_signal_connect(priv->cancel_toolitem, "clicked",
1553 G_CALLBACK(cancel_progressbar),
1556 /* Add it to the observers list */
1557 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1560 hildon_window_add_toolbar (HILDON_WINDOW (self),
1561 GTK_TOOLBAR (parent_priv->toolbar));
1563 /* Set reply button tap and hold menu */
1564 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1565 "/ToolBar/ToolbarMessageReply");
1566 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1567 "/ToolbarReplyCSM");
1568 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1570 /* Set send & receive button tap and hold menu */
1571 update_menus (MODEST_MAIN_WINDOW (self));
1575 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1576 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1577 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1579 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1580 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1581 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1583 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1585 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1589 /* Update also the actions (to update the toggles in the
1590 menus), we have to do it manually because some other window
1591 of the same time could have changed it (remember that the
1592 toolbar fullscreen mode is shared by all the windows of the
1594 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1595 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1597 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1599 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1600 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1605 on_account_inserted (TnyAccountStore *accoust_store,
1606 TnyAccount *account,
1609 /* Transport accounts and local ones (MMC and the Local
1610 folders account do now cause menu changes */
1611 if (TNY_IS_STORE_ACCOUNT (account) &&
1612 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1614 update_menus (MODEST_MAIN_WINDOW (user_data));
1619 on_default_account_changed (ModestAccountMgr* mgr,
1622 update_menus (MODEST_MAIN_WINDOW (user_data));
1626 on_account_removed (TnyAccountStore *accoust_store,
1627 TnyAccount *account,
1630 /* Transport accounts and local ones (MMC and the Local
1631 folders account do now cause menu changes */
1632 if (TNY_IS_STORE_ACCOUNT (account) &&
1633 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1634 update_menus (MODEST_MAIN_WINDOW (user_data));
1638 on_account_changed (TnyAccountStore *account_store,
1639 TnyAccount *account,
1642 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1644 /* Transport accounts and local ones (MMC and the Local
1645 folders account do now cause menu changes */
1646 if (TNY_IS_STORE_ACCOUNT (account)) {
1647 /* We need to refresh the details widget because it could have changed */
1648 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1649 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1651 /* Update the menus as well, name could change */
1652 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1653 update_menus (MODEST_MAIN_WINDOW (user_data));
1658 * This function manages the key events used to navigate between
1659 * header and folder views (when the window is in split view)
1662 * -------------------------------------------------
1663 * HeaderView GDK_Left Move focus to folder view
1664 * FolderView GDK_Right Move focus to header view
1666 * There is no need to scroll to selected row, the widgets will be the
1667 * responsibles of doing that (probably managing the focus-in event
1670 on_inner_widgets_key_pressed (GtkWidget *widget,
1674 ModestMainWindowPrivate *priv;
1676 if (event->type == GDK_KEY_RELEASE)
1679 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1681 /* Do nothing if we're in SIMPLE style */
1682 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1685 if (MODEST_IS_HEADER_VIEW (widget)) {
1686 if (event->keyval == GDK_Left)
1687 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1688 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1689 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1690 if (selected_headers > 1) {
1691 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1694 GtkTreePath * cursor_path;
1695 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1696 if (cursor_path == NULL) {
1697 GtkTreeSelection *selection;
1699 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1700 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1703 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1704 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
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));
2201 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2203 /* Show and hide toolbar items */
2205 case TOOLBAR_MODE_NORMAL:
2207 gtk_action_set_visible (sort_action, TRUE);
2209 gtk_action_set_visible (refresh_action, TRUE);
2210 if (priv->progress_toolitem) {
2211 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2212 gtk_widget_hide (priv->progress_toolitem);
2214 if (priv->progress_bar)
2215 gtk_widget_hide (priv->progress_bar);
2218 gtk_action_set_visible (cancel_action, FALSE);
2220 /* Hide toolbar if optimized view is enabled */
2221 if (priv->optimized_view)
2222 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2224 case TOOLBAR_MODE_TRANSFER:
2226 gtk_action_set_visible (sort_action, FALSE);
2228 gtk_action_set_visible (refresh_action, FALSE);
2230 gtk_action_set_visible (cancel_action, TRUE);
2231 if (priv->progress_bar)
2232 gtk_widget_show (priv->progress_bar);
2233 if (priv->progress_toolitem) {
2234 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2235 gtk_widget_show (priv->progress_toolitem);
2238 /* Show toolbar if it's hiden (optimized view ) */
2239 if (priv->optimized_view)
2240 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2243 g_return_if_reached ();
2248 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2250 ModestMainWindowPrivate *priv;
2252 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2253 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2255 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2259 cancel_progressbar (GtkToolButton *toolbutton,
2260 ModestMainWindow *self)
2263 ModestMainWindowPrivate *priv;
2265 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2267 /* Get operation observers and cancel all the operations */
2268 tmp = priv->progress_widgets;
2270 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2271 tmp=g_slist_next(tmp);
2276 observers_empty (ModestMainWindow *self)
2279 ModestMainWindowPrivate *priv;
2280 gboolean is_empty = TRUE;
2281 guint pending_ops = 0;
2283 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2284 tmp = priv->progress_widgets;
2286 /* Check all observers */
2287 while (tmp && is_empty) {
2288 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2289 is_empty = pending_ops == 0;
2291 tmp = g_slist_next(tmp);
2299 * Gets the toolbar mode needed for each mail operation. It stores in
2300 * @mode_changed if the toolbar mode has changed or not
2302 static ModestToolBarModes
2303 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2304 ModestMailOperation *mail_op,
2305 gboolean *mode_changed)
2307 ModestToolBarModes mode;
2308 ModestMainWindowPrivate *priv;
2310 *mode_changed = FALSE;
2311 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2313 /* Get toolbar mode from operation id*/
2314 switch (modest_mail_operation_get_type_operation (mail_op)) {
2315 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2316 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2317 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2318 mode = TOOLBAR_MODE_TRANSFER;
2319 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2320 *mode_changed = TRUE;
2323 mode = TOOLBAR_MODE_NORMAL;
2329 on_mail_operation_started (ModestMailOperation *mail_op,
2332 ModestMainWindow *self;
2333 ModestMailOperationTypeOperation op_type;
2334 ModestMainWindowPrivate *priv;
2335 ModestToolBarModes mode;
2337 gboolean mode_changed = FALSE;
2338 TnyAccount *account = NULL;
2340 self = MODEST_MAIN_WINDOW (user_data);
2341 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2343 /* Do not show progress for receiving operations if the
2344 account is the local account or the MMC one */
2345 op_type = modest_mail_operation_get_type_operation (mail_op);
2346 account = modest_mail_operation_get_account (mail_op);
2347 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2350 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2351 modest_tny_account_is_memory_card_account (account));
2353 g_object_unref (account);
2357 /* Show information banner. Remove old timeout */
2358 if (priv->retrieving_banner_timeout > 0) {
2359 g_source_remove (priv->retrieving_banner_timeout);
2360 priv->retrieving_banner_timeout = 0;
2362 /* Create a new timeout */
2363 priv->retrieving_banner_timeout =
2364 g_timeout_add (2000, show_retrieving_banner, self);
2367 /* Not every mail operation has account, noop does not */
2369 g_object_unref (account);
2371 /* Get toolbar mode from operation id*/
2372 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2374 /* Add operation observers and change toolbar if neccessary*/
2375 tmp = priv->progress_widgets;
2376 if (mode == TOOLBAR_MODE_TRANSFER) {
2378 GObject *source = modest_mail_operation_get_source(mail_op);
2379 if (G_OBJECT (self) == source) {
2380 set_toolbar_transfer_mode(self);
2382 g_object_unref (source);
2386 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2388 tmp = g_slist_next (tmp);
2392 /* Update the main menu as well, we need to explicitely do
2393 this in order to enable/disable accelerators */
2394 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2398 on_mail_operation_finished (ModestMailOperation *mail_op,
2401 ModestToolBarModes mode;
2402 ModestMailOperationTypeOperation op_type;
2404 ModestMainWindow *self;
2405 gboolean mode_changed;
2406 TnyAccount *account = NULL;
2407 ModestMainWindowPrivate *priv;
2409 self = MODEST_MAIN_WINDOW (user_data);
2410 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2412 /* The mail operation was not added to the progress objects if
2413 the account was the local account or the MMC one */
2414 op_type = modest_mail_operation_get_type_operation (mail_op);
2415 account = modest_mail_operation_get_account (mail_op);
2416 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2419 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2420 modest_tny_account_is_memory_card_account (account));
2422 g_object_unref (account);
2426 /* Remove old timeout */
2427 if (priv->retrieving_banner_timeout > 0) {
2428 g_source_remove (priv->retrieving_banner_timeout);
2429 priv->retrieving_banner_timeout = 0;
2432 /* Remove the banner if exists */
2433 if (priv->retrieving_banner) {
2434 gtk_widget_destroy (priv->retrieving_banner);
2435 priv->retrieving_banner = NULL;
2439 /* Not every mail operation has account, noop does not */
2441 g_object_unref (account);
2443 /* Get toolbar mode from operation id*/
2444 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2446 /* Change toolbar mode */
2447 tmp = priv->progress_widgets;
2448 if (mode == TOOLBAR_MODE_TRANSFER) {
2450 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2452 tmp = g_slist_next (tmp);
2455 /* If no more operations are being observed, NORMAL mode is enabled again */
2456 if (observers_empty (self)) {
2457 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2463 on_queue_changed (ModestMailOperationQueue *queue,
2464 ModestMailOperation *mail_op,
2465 ModestMailOperationQueueNotification type,
2466 ModestMainWindow *self)
2468 ModestMainWindowPrivate *priv;
2470 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2472 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2473 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2475 "operation-started",
2476 G_CALLBACK (on_mail_operation_started),
2478 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2480 "operation-finished",
2481 G_CALLBACK (on_mail_operation_finished),
2483 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2484 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2486 "operation-started");
2487 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2489 "operation-finished");
2494 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2496 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2498 ModestAccountMgr *mgr;
2499 ModestAccountSettings *settings;
2500 ModestServerAccountSettings *store_settings = NULL;
2502 /* Get account data */
2503 mgr = modest_runtime_get_account_mgr ();
2504 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2506 store_settings = modest_account_settings_get_store_settings (settings);
2508 /* Set the new visible & active account */
2509 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2510 const gchar *account_name;
2512 account_name = modest_account_settings_get_account_name (settings);
2514 modest_folder_view_set_account_id_of_visible_server_account
2516 modest_server_account_settings_get_account_name (store_settings));
2517 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2518 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2520 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2521 if (action != NULL) {
2522 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2523 modest_utils_toggle_action_set_active_block_notify (
2524 GTK_TOGGLE_ACTION (action),
2532 g_object_unref (store_settings);
2533 g_object_unref (settings);
2537 /* Make sure that at least one account is "viewed": */
2539 set_at_least_one_account_visible(ModestMainWindow *self)
2541 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2542 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2544 if (!(priv->folder_view)) {
2545 /* It is too early to do this. */
2549 const gchar *active_server_account_name =
2550 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2552 if (!active_server_account_name ||
2553 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2555 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2556 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2557 if (default_modest_name) {
2558 set_account_visible (self, default_modest_name);
2559 } else if (first_modest_name) {
2560 set_account_visible (self, first_modest_name);
2562 g_free (first_modest_name);
2563 g_free (default_modest_name);
2568 on_show_account_action_toggled (GtkToggleAction *action,
2571 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2573 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2574 if (gtk_toggle_action_get_active (action))
2575 set_account_visible (self, acc_name);
2579 refresh_account (const gchar *account_name)
2583 /* win must already exists here, obviously */
2584 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2587 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2591 /* If account_name == NULL, we must update all (option All) */
2593 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2595 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2600 on_refresh_account_action_activated (GtkAction *action,
2603 refresh_account ((const gchar*) user_data);
2607 on_send_receive_csm_activated (GtkMenuItem *item,
2610 refresh_account ((const gchar*) user_data);
2614 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2616 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2618 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2624 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2626 ModestMainWindow *main_window = NULL;
2628 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2629 main_window = MODEST_MAIN_WINDOW (userdata);
2631 /* Update toolbar dimming state */
2632 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2633 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2639 on_header_view_focus_in (GtkWidget *widget,
2640 GdkEventFocus *event,
2643 ModestMainWindow *main_window = NULL;
2645 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2647 main_window = MODEST_MAIN_WINDOW (userdata);
2649 /* Update toolbar dimming state */
2650 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2651 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2657 on_folder_selection_changed (ModestFolderView *folder_view,
2658 TnyFolderStore *folder_store,
2660 ModestMainWindow *main_window)
2662 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2663 GtkAction *action = NULL;
2664 gboolean show_reply = TRUE;
2665 gboolean show_forward = TRUE;
2666 gboolean show_cancel_send = FALSE;
2667 gboolean show_clipboard = TRUE;
2668 gboolean show_delete = TRUE;
2671 if (TNY_IS_ACCOUNT (folder_store)) {
2672 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2673 } else if (TNY_IS_FOLDER (folder_store)) {
2674 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2675 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2676 TNY_FOLDER (folder_store));
2677 switch (folder_type) {
2678 case TNY_FOLDER_TYPE_DRAFTS:
2679 show_clipboard = show_delete = TRUE;
2680 show_reply = show_forward = show_cancel_send = FALSE;
2682 case TNY_FOLDER_TYPE_SENT:
2683 show_forward = show_clipboard = show_delete = TRUE;
2684 show_reply = show_cancel_send = FALSE;
2686 case TNY_FOLDER_TYPE_OUTBOX:
2687 show_clipboard = show_delete = show_cancel_send = TRUE;
2688 show_reply = show_forward = FALSE;
2690 case TNY_FOLDER_TYPE_INVALID:
2691 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2694 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2695 show_cancel_send = FALSE;
2698 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2699 show_cancel_send = FALSE;
2704 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2705 gtk_action_set_visible (action, show_reply);
2706 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2707 gtk_action_set_visible (action, show_reply);
2708 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2709 gtk_action_set_visible (action, show_forward);
2710 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2711 gtk_action_set_visible (action, show_cancel_send);
2712 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2713 gtk_action_set_visible (action, show_delete);
2715 /* We finally call to the ui actions handler, after updating properly
2716 * the header view CSM */
2717 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2721 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2722 GtkTreeModel *model,
2723 GtkTreeRowReference *row_reference,
2724 ModestMainWindow *self)
2726 ModestMainWindowPrivate *priv = NULL;
2727 GtkTreeModel *header_model = NULL;
2728 GtkTreePath *path = NULL;
2730 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2731 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2732 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2734 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2735 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2737 /* Do nothing if we changed the folder in the main view */
2738 if (header_model != model)
2741 /* Select the message in the header view */
2742 path = gtk_tree_row_reference_get_path (row_reference);
2743 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2745 gtk_tree_path_free (path);
2751 show_updating_banner (gpointer user_data)
2753 ModestMainWindowPrivate *priv = NULL;
2755 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2757 if (priv->updating_banner == NULL) {
2759 /* We're outside the main lock */
2760 gdk_threads_enter ();
2761 priv->updating_banner =
2762 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2763 _CS ("ckdg_pb_updating"));
2764 gdk_threads_leave ();
2767 /* Remove timeout */
2768 priv->updating_banner_timeout = 0;
2773 * We use this function to show/hide a progress banner showing
2774 * "Updating" while the header view is being filled. We're not showing
2775 * it unless the update takes more than 2 seconds
2777 * If starting = TRUE then the refresh is starting, otherwise it means
2778 * that is has just finished
2781 on_updating_msg_list (ModestHeaderView *header_view,
2785 ModestMainWindowPrivate *priv = NULL;
2787 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2789 /* Remove old timeout */
2790 if (priv->updating_banner_timeout > 0) {
2791 g_source_remove (priv->updating_banner_timeout);
2792 priv->updating_banner_timeout = 0;
2795 /* Create a new timeout */
2797 priv->updating_banner_timeout =
2798 g_timeout_add (2000, show_updating_banner, user_data);
2800 /* Remove the banner if exists */
2801 if (priv->updating_banner) {
2802 gtk_widget_destroy (priv->updating_banner);
2803 priv->updating_banner = NULL;
2809 modest_main_window_screen_is_on (ModestMainWindow *self)
2811 ModestMainWindowPrivate *priv = NULL;
2813 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2815 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2817 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2821 remove_banners (ModestMainWindow *window)
2823 ModestMainWindowPrivate *priv;
2825 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2827 if (priv->retrieving_banner_timeout > 0) {
2828 g_source_remove (priv->retrieving_banner_timeout);
2829 priv->retrieving_banner_timeout = 0;
2832 if (priv->retrieving_banner != NULL) {
2833 gtk_widget_destroy (priv->retrieving_banner);
2834 priv->retrieving_banner = NULL;
2837 if (priv->updating_banner_timeout > 0) {
2838 g_source_remove (priv->updating_banner_timeout);
2839 priv->updating_banner_timeout = 0;
2842 if (priv->updating_banner != NULL) {
2843 gtk_widget_destroy (priv->updating_banner);
2844 priv->updating_banner = NULL;
2850 on_window_hide (GObject *gobject,
2854 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2856 if (!GTK_WIDGET_VISIBLE (gobject)) {
2857 TnyFolderStore *folder_store;
2858 ModestMainWindowPrivate *priv;
2860 /* Remove the currently shown banners */
2861 remove_banners (MODEST_MAIN_WINDOW (gobject));
2863 /* Force the folder view to sync the currently selected folder
2864 to save the read/unread status and to expunge messages */
2865 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2866 folder_store = modest_folder_view_get_selected (priv->folder_view);
2867 if (TNY_IS_FOLDER (folder_store)) {
2868 ModestMailOperation *mail_op;
2870 mail_op = modest_mail_operation_new (NULL);
2871 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2873 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2874 g_object_unref (mail_op);
2880 on_window_destroy (GtkObject *widget,
2883 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2885 remove_banners (MODEST_MAIN_WINDOW (widget));
2889 show_retrieving_banner (gpointer user_data)
2891 ModestMainWindowPrivate *priv = NULL;
2893 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2895 if (priv->retrieving_banner == NULL) {
2897 /* We're outside the main lock */
2898 gdk_threads_enter ();
2899 priv->retrieving_banner =
2900 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2901 _("mcen_ib_getting_items"));
2902 gdk_threads_leave ();
2905 /* Remove timeout */
2906 priv->retrieving_banner_timeout = 0;