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_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),
1056 modest_signal_mgr_connect (priv->sighandlers,
1057 G_OBJECT (modest_runtime_get_account_store()),
1058 "password_requested",
1059 G_CALLBACK (modest_ui_actions_on_password_requested),
1064 on_hildon_program_is_topmost_notify(GObject *self,
1065 GParamSpec *propert_param,
1068 HildonProgram *app = HILDON_PROGRAM (self);
1070 /* Note that use of hildon_program_set_can_hibernate()
1071 * is generally referred to as "setting the killable flag",
1072 * though hibernation does not seem equal to death.
1075 if (hildon_program_get_is_topmost (app)) {
1076 /* Prevent hibernation when the progam comes to the foreground,
1077 * because hibernation should only happen when the application
1078 * is in the background: */
1079 hildon_program_set_can_hibernate (app, FALSE);
1081 /* Remove new mail visual notifications */
1082 modest_platform_remove_new_mail_notifications (TRUE);
1084 /* Allow hibernation if the program has gone to the background: */
1086 /* However, prevent hibernation while the settings are being changed: */
1087 const gboolean hibernation_prevented =
1088 modest_window_mgr_get_hibernation_is_prevented (
1089 modest_runtime_get_window_mgr ());
1091 if (hibernation_prevented)
1092 hildon_program_set_can_hibernate (app, FALSE);
1094 /* Allow hibernation, after saving the state: */
1095 modest_osso_save_state();
1096 hildon_program_set_can_hibernate (app, TRUE);
1102 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1104 GtkWidget *folder_win = (GtkWidget *) user_data;
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));
1151 osso_display_event_cb (osso_display_state_t state,
1154 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1156 priv->display_state = state;
1158 /* Stop blinking if the screen becomes on */
1159 if (priv->display_state == OSSO_DISPLAY_ON)
1160 modest_platform_remove_new_mail_notifications (TRUE);
1164 modest_main_window_new (void)
1166 ModestMainWindow *self = NULL;
1167 ModestMainWindowPrivate *priv = NULL;
1168 ModestWindowPrivate *parent_priv = NULL;
1169 GtkWidget *folder_win = NULL;
1170 ModestDimmingRulesGroup *menu_rules_group = NULL;
1171 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1172 GtkActionGroup *action_group = NULL;
1173 GError *error = NULL;
1175 ModestConf *conf = NULL;
1176 GtkAction *action = NULL;
1177 GdkPixbuf *window_icon;
1179 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1180 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1181 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1183 parent_priv->ui_manager = gtk_ui_manager_new();
1184 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1186 action_group = gtk_action_group_new ("ModestMainWindowActions");
1187 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1189 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1190 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1192 /* Add common actions */
1193 gtk_action_group_add_actions (action_group,
1194 modest_action_entries,
1195 G_N_ELEMENTS (modest_action_entries),
1198 gtk_action_group_add_actions (action_group,
1199 modest_folder_view_action_entries,
1200 G_N_ELEMENTS (modest_folder_view_action_entries),
1203 gtk_action_group_add_actions (action_group,
1204 modest_header_view_action_entries,
1205 G_N_ELEMENTS (modest_header_view_action_entries),
1208 gtk_action_group_add_toggle_actions (action_group,
1209 modest_toggle_action_entries,
1210 G_N_ELEMENTS (modest_toggle_action_entries),
1213 gtk_action_group_add_toggle_actions (action_group,
1214 modest_main_window_toggle_action_entries,
1215 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1218 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1219 g_object_unref (action_group);
1221 /* Load the UI definition */
1222 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1223 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1224 if (error != NULL) {
1225 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1226 g_error_free (error);
1230 /* Add common dimming rules */
1231 modest_dimming_rules_group_add_rules (menu_rules_group,
1232 modest_main_window_menu_dimming_entries,
1233 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1234 MODEST_WINDOW (self));
1235 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1236 modest_main_window_toolbar_dimming_entries,
1237 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1238 MODEST_WINDOW (self));
1240 /* Insert dimming rules group for this window */
1241 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1242 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1243 g_object_unref (menu_rules_group);
1244 g_object_unref (toolbar_rules_group);
1246 /* Add accelerators */
1247 gtk_window_add_accel_group (GTK_WINDOW (self),
1248 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1250 /* Menubar. Update the state of some toggles */
1251 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1252 conf = modest_runtime_get_conf ();
1253 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1254 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1255 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1256 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1257 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1258 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1259 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1260 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1261 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1262 gtk_widget_show (parent_priv->menubar);
1264 /* Get device name */
1265 modest_maemo_utils_get_device_name ();
1269 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1270 if (!priv->header_view)
1271 g_printerr ("modest: cannot instantiate header view\n");
1272 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1273 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1274 MODEST_CONF_HEADER_VIEW_KEY);
1276 /* Other style properties of header view */
1277 g_object_set (G_OBJECT (priv->header_view),
1278 "rules-hint", FALSE,
1280 /* gtk_widget_show (priv->header_view); */
1283 priv->empty_view = create_empty_view ();
1284 gtk_widget_show (priv->empty_view);
1286 /* Create scrolled windows */
1287 folder_win = gtk_scrolled_window_new (NULL, NULL);
1288 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1289 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1291 GTK_POLICY_AUTOMATIC);
1292 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1294 GTK_POLICY_AUTOMATIC);
1295 /* gtk_widget_show (priv->contents_widget); */
1298 priv->main_paned = gtk_hpaned_new ();
1299 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1300 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1301 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1303 /* putting it all together... */
1304 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1305 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1306 gtk_widget_show (priv->main_vbox);
1308 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1310 app = hildon_program_get_instance ();
1311 hildon_program_add_window (app, HILDON_WINDOW (self));
1313 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1314 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1316 g_signal_connect (G_OBJECT(self), "show",
1317 G_CALLBACK (modest_main_window_on_show), folder_win);
1319 /* Set window icon */
1320 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1322 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1323 g_object_unref (window_icon);
1326 /* Listen for changes in the screen, we don't want to show a
1327 led pattern when the display is on for example */
1328 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1329 osso_display_event_cb,
1332 /* Dont't restore settings here,
1333 * because it requires a gtk_widget_show(),
1334 * and we don't want to do that until later,
1335 * so that the UI is not visible for non-menu D-Bus activation.
1338 return MODEST_WINDOW(self);
1342 modest_main_window_set_style (ModestMainWindow *self,
1343 ModestMainWindowStyle style)
1345 ModestMainWindowPrivate *priv;
1346 ModestWindowPrivate *parent_priv;
1350 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1352 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1353 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1355 /* no change -> nothing to do */
1356 if (priv->style == style)
1359 /* Get toggle button and update the state if needed. This will
1360 happen only when the set_style is not invoked from the UI,
1361 for example when it's called from widget memory */
1362 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1363 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1364 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1365 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1366 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1367 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1368 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1371 priv->style = style;
1373 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1375 if (!priv->wait_for_settings)
1376 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1377 MODEST_CONF_MAIN_PANED_KEY);
1378 /* Remove main paned */
1379 g_object_ref (priv->main_paned);
1380 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1382 /* Reparent the contents widget to the main vbox */
1383 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1386 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1387 /* Remove header view */
1388 g_object_ref (priv->contents_widget);
1389 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1391 /* Reparent the main paned */
1392 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1393 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1395 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1399 g_return_if_reached ();
1402 /* Let header view grab the focus if it's being shown */
1403 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1404 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1406 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1409 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1412 ModestMainWindowStyle
1413 modest_main_window_get_style (ModestMainWindow *self)
1415 ModestMainWindowPrivate *priv;
1417 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1419 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1424 toolbar_resize (ModestMainWindow *self)
1426 ModestMainWindowPrivate *priv = NULL;
1427 ModestWindowPrivate *parent_priv = NULL;
1429 gint static_button_size;
1430 ModestWindowMgr *mgr;
1432 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1433 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1434 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1436 mgr = modest_runtime_get_window_mgr ();
1437 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1439 if (parent_priv->toolbar) {
1440 /* left size buttons */
1441 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1444 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1445 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1448 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1449 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1452 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1453 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
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);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1459 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1460 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1473 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1475 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1476 ModestWindowPrivate *parent_priv;
1477 ModestWindowMgr *mgr;
1478 gboolean is_fullscreen;
1479 GtkAction *fs_toggle_action;
1482 mgr = modest_runtime_get_window_mgr ();
1484 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1486 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1488 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1489 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1490 if (is_fullscreen != active) {
1491 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1494 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1502 modest_main_window_show_toolbar (ModestWindow *self,
1503 gboolean show_toolbar)
1505 ModestMainWindowPrivate *priv = NULL;
1506 ModestWindowPrivate *parent_priv = NULL;
1507 GtkWidget *reply_button = NULL, *menu = NULL;
1508 GtkWidget *placeholder = NULL;
1510 const gchar *action_name;
1513 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1514 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1515 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1517 /* Set optimized view status */
1518 priv->optimized_view = !show_toolbar;
1520 if (!parent_priv->toolbar) {
1521 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1523 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1525 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1526 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1527 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1528 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1529 toolbar_resize (MODEST_MAIN_WINDOW (self));
1531 /* Add ProgressBar (Transfer toolbar) */
1532 priv->progress_bar = modest_progress_bar_new ();
1533 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1534 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1535 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1536 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1537 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1539 /* Connect cancel 'clicked' signal to abort progress mode */
1540 g_signal_connect(priv->cancel_toolitem, "clicked",
1541 G_CALLBACK(cancel_progressbar),
1544 /* Add it to the observers list */
1545 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1548 hildon_window_add_toolbar (HILDON_WINDOW (self),
1549 GTK_TOOLBAR (parent_priv->toolbar));
1551 /* Set reply button tap and hold menu */
1552 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1553 "/ToolBar/ToolbarMessageReply");
1554 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1555 "/ToolbarReplyCSM");
1556 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1558 /* Set send & receive button tap and hold menu */
1559 update_menus (MODEST_MAIN_WINDOW (self));
1563 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1564 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1565 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1567 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1568 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1569 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1571 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1573 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1577 /* Update also the actions (to update the toggles in the
1578 menus), we have to do it manually because some other window
1579 of the same time could have changed it (remember that the
1580 toolbar fullscreen mode is shared by all the windows of the
1582 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1583 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1585 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1587 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1588 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1593 on_account_inserted (TnyAccountStore *accoust_store,
1594 TnyAccount *account,
1597 /* Transport accounts and local ones (MMC and the Local
1598 folders account do now cause menu changes */
1599 if (TNY_IS_STORE_ACCOUNT (account) &&
1600 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1602 update_menus (MODEST_MAIN_WINDOW (user_data));
1607 on_default_account_changed (ModestAccountMgr* mgr,
1610 update_menus (MODEST_MAIN_WINDOW (user_data));
1614 on_account_removed (TnyAccountStore *accoust_store,
1615 TnyAccount *account,
1618 /* Transport accounts and local ones (MMC and the Local
1619 folders account do now cause menu changes */
1620 if (TNY_IS_STORE_ACCOUNT (account) &&
1621 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1622 update_menus (MODEST_MAIN_WINDOW (user_data));
1626 on_account_changed (TnyAccountStore *account_store,
1627 TnyAccount *account,
1630 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1632 /* Transport accounts and local ones (MMC and the Local
1633 folders account do now cause menu changes */
1634 if (TNY_IS_STORE_ACCOUNT (account)) {
1635 /* We need to refresh the details widget because it could have changed */
1636 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1637 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1639 /* Update the menus as well, name could change */
1640 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1641 update_menus (MODEST_MAIN_WINDOW (user_data));
1646 * This function manages the key events used to navigate between
1647 * header and folder views (when the window is in split view)
1650 * -------------------------------------------------
1651 * HeaderView GDK_Left Move focus to folder view
1652 * FolderView GDK_Right Move focus to header view
1654 * There is no need to scroll to selected row, the widgets will be the
1655 * responsibles of doing that (probably managing the focus-in event
1658 on_inner_widgets_key_pressed (GtkWidget *widget,
1662 ModestMainWindowPrivate *priv;
1664 if (event->type == GDK_KEY_RELEASE)
1667 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1669 /* Do nothing if we're in SIMPLE style */
1670 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1673 if (MODEST_IS_HEADER_VIEW (widget)) {
1674 if (event->keyval == GDK_Left)
1675 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1676 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1677 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1678 if (selected_headers > 1) {
1679 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1682 GtkTreePath * cursor_path;
1683 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1684 if (cursor_path == NULL) {
1685 GtkTreeSelection *selection;
1687 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1688 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1691 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1692 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1697 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1698 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1704 set_alignment (GtkWidget *widget,
1707 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1708 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1712 create_empty_view (void)
1714 GtkLabel *label = NULL;
1715 GtkWidget *align = NULL;
1717 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1718 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1719 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1720 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1722 return GTK_WIDGET(align);
1726 * Free the returned string
1729 get_gray_color_markup (GtkWidget *styled_widget)
1731 gchar *gray_color_markup = NULL;
1732 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1733 /* Obtain the secondary text color. We need a realized widget, that's why
1734 we get styled_widget from outside */
1736 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1737 gray_color_markup = modest_text_utils_get_color_string (&color);
1738 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1740 if (!gray_color_markup)
1741 gray_color_markup = g_strdup ("#BBBBBB");
1743 return gray_color_markup;
1747 * Free the returned string
1750 create_device_name_visual_string (const gchar *device_name,
1751 const gchar *gray_color_markup)
1755 /* We have to use "" to fill the %s of the translation. We can
1756 not just use the device name because the device name is
1757 shown in a different color, so it could not be included
1758 into the <span> tag */
1759 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1760 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1770 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1772 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1777 gchar *gray_color_markup;
1779 vbox = gtk_vbox_new (FALSE, 0);
1781 gray_color_markup = get_gray_color_markup (styled_widget);
1783 /* Account description: */
1784 if (modest_tny_account_is_virtual_local_folders (account)
1785 || (modest_tny_account_is_memory_card_account (account))) {
1787 /* Get device name */
1788 gchar *device_name = NULL;
1789 if (modest_tny_account_is_virtual_local_folders (account))
1790 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1791 MODEST_CONF_DEVICE_NAME, NULL);
1793 device_name = g_strdup (tny_account_get_name (account));
1795 label = create_device_name_visual_string ((const gchar *) device_name,
1796 (const gchar *) gray_color_markup);
1797 label_w = gtk_label_new (NULL);
1798 gtk_label_set_markup (GTK_LABEL (label_w), label);
1799 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1800 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1801 g_free (device_name);
1804 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1805 gtk_box_pack_start (GTK_BOX (vbox),
1806 gtk_label_new (tny_account_get_name (account)),
1809 /* Other accounts, such as IMAP and POP: */
1814 /* Put proto in uppercase */
1815 proto = g_string_new (tny_account_get_proto (account));
1816 proto = g_string_ascii_up (proto);
1818 /* note: mcen_fi_localroot_description is something like "%s account"
1819 * however, we should display "%s account: %s"... therefore, ugly tmp */
1820 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1821 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1822 gray_color_markup, tmp, tny_account_get_name (account));
1825 label_w = gtk_label_new (NULL);
1826 gtk_label_set_markup (GTK_LABEL (label_w), label);
1827 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1828 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1829 g_string_free (proto, TRUE);
1835 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1836 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1837 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1838 modest_tny_folder_store_get_message_count (folder_store));
1839 label_w = gtk_label_new (NULL);
1840 gtk_label_set_markup (GTK_LABEL (label_w), label);
1841 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1842 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1846 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1848 _("mcen_fi_rootfolder_folders"),
1849 modest_tny_folder_store_get_folder_count (folder_store));
1850 label_w = gtk_label_new (NULL);
1851 gtk_label_set_markup (GTK_LABEL (label_w), label);
1852 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1853 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1857 if (modest_tny_account_is_virtual_local_folders (account)
1858 || modest_tny_account_is_memory_card_account (account)) {
1860 gchar *size = modest_text_utils_get_display_size (
1861 modest_tny_folder_store_get_local_size (folder_store));
1863 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1864 gray_color_markup, _("mcen_fi_rootfolder_size"),
1868 label_w = gtk_label_new (NULL);
1869 gtk_label_set_markup (GTK_LABEL (label_w), label);
1870 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1871 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1873 } else if (TNY_IS_ACCOUNT(folder_store)) {
1874 TnyAccount *account = TNY_ACCOUNT(folder_store);
1876 time_t last_updated;
1877 const gchar *last_updated_string;
1878 /* Get last updated from configuration */
1879 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1880 tny_account_get_id (account));
1882 if (last_updated > 0)
1883 last_updated_string = modest_text_utils_get_display_date(last_updated);
1885 last_updated_string = g_strdup (_("mcen_va_never"));
1887 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1888 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1889 label_w = gtk_label_new (NULL);
1890 gtk_label_set_markup (GTK_LABEL (label_w), label);
1891 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1892 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1896 g_free (gray_color_markup);
1899 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1905 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1907 ModestMainWindowPrivate *priv = NULL;
1909 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1911 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1913 return priv->send_receive_in_progress;
1917 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1919 GtkAction *action = NULL;
1920 GtkWidget *widget = NULL;
1921 ModestMainWindowPrivate *priv = NULL;
1923 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1924 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1926 priv->send_receive_in_progress = TRUE;
1928 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1929 gtk_action_set_sensitive (action, FALSE);
1930 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1931 /* gtk_action_set_sensitive (action, FALSE); */
1932 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1933 gtk_widget_set_sensitive (widget, FALSE);
1937 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1939 GtkAction *action = NULL;
1940 GtkWidget *widget = NULL;
1941 ModestMainWindowPrivate *priv = NULL;
1943 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1944 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1946 priv->send_receive_in_progress = FALSE;
1948 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1949 gtk_action_set_sensitive (action, TRUE);
1950 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1951 /* gtk_action_set_sensitive (action, TRUE); */
1952 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1953 gtk_widget_set_sensitive (widget, TRUE);
1958 on_msg_count_changed (ModestHeaderView *header_view,
1960 TnyFolderChange *change,
1961 ModestMainWindow *main_window)
1963 gboolean refilter = FALSE;
1964 gboolean folder_empty = FALSE;
1965 gboolean all_marked_as_deleted = FALSE;
1966 ModestMainWindowPrivate *priv;
1968 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1969 g_return_if_fail (TNY_IS_FOLDER(folder));
1970 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1972 if (change != NULL) {
1973 TnyFolderChangeChanged changed;
1975 changed = tny_folder_change_get_changed (change);
1976 /* If something changes */
1977 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1978 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1980 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1982 /* Play a sound (if configured) and make the LED blink */
1983 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1984 modest_platform_push_email_notification ();
1987 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1990 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1993 /* Check if all messages are marked to be deleted */
1994 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1995 folder_empty = folder_empty || all_marked_as_deleted;
1997 /* Set contents style of headers view */
1999 modest_main_window_set_contents_style (main_window,
2000 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2001 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2003 modest_main_window_set_contents_style (main_window,
2004 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2008 modest_header_view_refilter (header_view);
2013 modest_main_window_set_contents_style (ModestMainWindow *self,
2014 ModestMainWindowContentsStyle style)
2016 ModestMainWindowPrivate *priv;
2018 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2020 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2022 /* We allow to set the same content style than the previously
2023 set if there are details, because it could happen when we're
2024 selecting different accounts consecutively */
2025 if ((priv->contents_style == style) &&
2026 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2029 /* Remove previous child. Delete it if it was an account
2031 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2033 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2034 g_object_ref (content);
2035 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2036 g_object_ref (priv->empty_view);
2037 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2040 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2043 priv->contents_style = style;
2045 switch (priv->contents_style) {
2046 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2047 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2048 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2051 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2053 /* if we're started without main win, there may not be a folder
2054 * view. this fixes a GLib-Critical */
2055 if (priv->folder_view) {
2056 TnyFolderStore *selected_folderstore =
2057 modest_folder_view_get_selected (priv->folder_view);
2058 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2059 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2060 TNY_ACCOUNT (selected_folderstore));
2062 wrap_in_scrolled_window (priv->contents_widget,
2063 priv->details_widget);
2065 g_object_unref (selected_folderstore);
2066 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2071 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2072 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2073 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2077 g_return_if_reached ();
2081 gtk_widget_show_all (priv->contents_widget);
2084 ModestMainWindowContentsStyle
2085 modest_main_window_get_contents_style (ModestMainWindow *self)
2087 ModestMainWindowPrivate *priv;
2089 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2091 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2092 return priv->contents_style;
2097 on_configuration_key_changed (ModestConf* conf,
2099 ModestConfEvent event,
2100 ModestConfNotificationId id,
2101 ModestMainWindow *self)
2103 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2104 TnyAccount *account = NULL;
2106 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2109 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2112 if (priv->folder_view)
2113 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2115 if (account && TNY_IS_ACCOUNT (account) &&
2116 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2119 const gchar *device_name;
2120 gchar *new_text, *gray_color_markup;
2123 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2124 label = GTK_LABEL (children->data);
2126 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2127 MODEST_CONF_DEVICE_NAME, NULL);
2129 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2130 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2132 gtk_label_set_markup (label, new_text);
2133 gtk_widget_show (GTK_WIDGET (label));
2135 g_free (gray_color_markup);
2137 g_list_free (children);
2139 g_object_unref (account);
2143 set_toolbar_transfer_mode (ModestMainWindow *self)
2145 ModestMainWindowPrivate *priv = NULL;
2147 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2149 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2151 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2153 if (priv->progress_bar_timeout > 0) {
2154 g_source_remove (priv->progress_bar_timeout);
2155 priv->progress_bar_timeout = 0;
2162 set_toolbar_mode (ModestMainWindow *self,
2163 ModestToolBarModes mode)
2165 ModestWindowPrivate *parent_priv = NULL;
2166 ModestMainWindowPrivate *priv = NULL;
2167 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2169 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2171 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2172 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2174 /* In case this was called before the toolbar exists: */
2175 if (!(parent_priv->toolbar))
2178 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2180 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2181 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2182 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2184 /* Sets current toolbar mode */
2185 priv->current_toolbar_mode = mode;
2187 /* Checks the dimming rules */
2188 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2189 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2191 /* Show and hide toolbar items */
2193 case TOOLBAR_MODE_NORMAL:
2195 gtk_action_set_visible (sort_action, TRUE);
2197 gtk_action_set_visible (refresh_action, TRUE);
2198 if (priv->progress_toolitem) {
2199 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2200 gtk_widget_hide (priv->progress_toolitem);
2202 if (priv->progress_bar)
2203 gtk_widget_hide (priv->progress_bar);
2206 gtk_action_set_visible (cancel_action, FALSE);
2208 /* Hide toolbar if optimized view is enabled */
2209 if (priv->optimized_view)
2210 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2212 case TOOLBAR_MODE_TRANSFER:
2214 gtk_action_set_visible (sort_action, FALSE);
2216 gtk_action_set_visible (refresh_action, FALSE);
2218 gtk_action_set_visible (cancel_action, TRUE);
2219 if (priv->progress_bar)
2220 gtk_widget_show (priv->progress_bar);
2221 if (priv->progress_toolitem) {
2222 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2223 gtk_widget_show (priv->progress_toolitem);
2226 /* Show toolbar if it's hiden (optimized view ) */
2227 if (priv->optimized_view)
2228 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2231 g_return_if_reached ();
2236 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2238 ModestMainWindowPrivate *priv;
2240 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2241 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2243 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2247 cancel_progressbar (GtkToolButton *toolbutton,
2248 ModestMainWindow *self)
2251 ModestMainWindowPrivate *priv;
2253 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2255 /* Get operation observers and cancel all the operations */
2256 tmp = priv->progress_widgets;
2258 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2259 tmp=g_slist_next(tmp);
2264 observers_empty (ModestMainWindow *self)
2267 ModestMainWindowPrivate *priv;
2268 gboolean is_empty = TRUE;
2269 guint pending_ops = 0;
2271 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2272 tmp = priv->progress_widgets;
2274 /* Check all observers */
2275 while (tmp && is_empty) {
2276 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2277 is_empty = pending_ops == 0;
2279 tmp = g_slist_next(tmp);
2287 * Gets the toolbar mode needed for each mail operation. It stores in
2288 * @mode_changed if the toolbar mode has changed or not
2290 static ModestToolBarModes
2291 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2292 ModestMailOperation *mail_op,
2293 gboolean *mode_changed)
2295 ModestToolBarModes mode;
2296 ModestMainWindowPrivate *priv;
2298 *mode_changed = FALSE;
2299 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2301 /* Get toolbar mode from operation id*/
2302 switch (modest_mail_operation_get_type_operation (mail_op)) {
2303 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2304 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2305 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2306 mode = TOOLBAR_MODE_TRANSFER;
2307 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2308 *mode_changed = TRUE;
2311 mode = TOOLBAR_MODE_NORMAL;
2317 on_mail_operation_started (ModestMailOperation *mail_op,
2320 ModestMainWindow *self;
2321 ModestMailOperationTypeOperation op_type;
2322 ModestMainWindowPrivate *priv;
2323 ModestToolBarModes mode;
2325 gboolean mode_changed = FALSE;
2326 TnyAccount *account = NULL;
2328 self = MODEST_MAIN_WINDOW (user_data);
2329 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2331 /* Do not show progress for receiving operations if the
2332 account is the local account or the MMC one */
2333 op_type = modest_mail_operation_get_type_operation (mail_op);
2334 account = modest_mail_operation_get_account (mail_op);
2335 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2338 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2339 modest_tny_account_is_memory_card_account (account));
2341 g_object_unref (account);
2345 /* Show information banner. Remove old timeout */
2346 if (priv->retrieving_banner_timeout > 0) {
2347 g_source_remove (priv->retrieving_banner_timeout);
2348 priv->retrieving_banner_timeout = 0;
2350 /* Create a new timeout */
2351 priv->retrieving_banner_timeout =
2352 g_timeout_add (2000, show_retrieving_banner, self);
2355 /* Not every mail operation has account, noop does not */
2357 g_object_unref (account);
2359 /* Get toolbar mode from operation id*/
2360 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2362 /* Add operation observers and change toolbar if neccessary*/
2363 tmp = priv->progress_widgets;
2364 if (mode == TOOLBAR_MODE_TRANSFER) {
2366 GObject *source = modest_mail_operation_get_source(mail_op);
2367 if (G_OBJECT (self) == source) {
2368 set_toolbar_transfer_mode(self);
2370 g_object_unref (source);
2374 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2376 tmp = g_slist_next (tmp);
2380 /* Update the main menu as well, we need to explicitely do
2381 this in order to enable/disable accelerators */
2382 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2386 on_mail_operation_finished (ModestMailOperation *mail_op,
2389 ModestToolBarModes mode;
2390 ModestMailOperationTypeOperation op_type;
2392 ModestMainWindow *self;
2393 gboolean mode_changed;
2394 TnyAccount *account = NULL;
2395 ModestMainWindowPrivate *priv;
2397 self = MODEST_MAIN_WINDOW (user_data);
2398 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2400 /* The mail operation was not added to the progress objects if
2401 the account was the local account or the MMC one */
2402 op_type = modest_mail_operation_get_type_operation (mail_op);
2403 account = modest_mail_operation_get_account (mail_op);
2404 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2407 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2408 modest_tny_account_is_memory_card_account (account));
2410 g_object_unref (account);
2414 /* Remove old timeout */
2415 if (priv->retrieving_banner_timeout > 0) {
2416 g_source_remove (priv->retrieving_banner_timeout);
2417 priv->retrieving_banner_timeout = 0;
2420 /* Remove the banner if exists */
2421 if (priv->retrieving_banner) {
2422 gtk_widget_destroy (priv->retrieving_banner);
2423 priv->retrieving_banner = NULL;
2427 /* Not every mail operation has account, noop does not */
2429 g_object_unref (account);
2431 /* Get toolbar mode from operation id*/
2432 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2434 /* Change toolbar mode */
2435 tmp = priv->progress_widgets;
2436 if (mode == TOOLBAR_MODE_TRANSFER) {
2438 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2440 tmp = g_slist_next (tmp);
2443 /* If no more operations are being observed, NORMAL mode is enabled again */
2444 if (observers_empty (self)) {
2445 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2451 on_queue_changed (ModestMailOperationQueue *queue,
2452 ModestMailOperation *mail_op,
2453 ModestMailOperationQueueNotification type,
2454 ModestMainWindow *self)
2456 ModestMainWindowPrivate *priv;
2458 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2460 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2461 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2463 "operation-started",
2464 G_CALLBACK (on_mail_operation_started),
2466 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2468 "operation-finished",
2469 G_CALLBACK (on_mail_operation_finished),
2471 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2472 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2474 "operation-started");
2475 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2477 "operation-finished");
2482 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2484 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2486 ModestAccountMgr *mgr;
2487 ModestAccountSettings *settings;
2488 ModestServerAccountSettings *store_settings = NULL;
2490 /* Get account data */
2491 mgr = modest_runtime_get_account_mgr ();
2492 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2494 store_settings = modest_account_settings_get_store_settings (settings);
2496 /* Set the new visible & active account */
2497 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2498 const gchar *account_name;
2500 account_name = modest_account_settings_get_account_name (settings);
2502 modest_folder_view_set_account_id_of_visible_server_account
2504 modest_server_account_settings_get_account_name (store_settings));
2505 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2506 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2507 if (action != NULL) {
2508 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2509 modest_utils_toggle_action_set_active_block_notify (
2510 GTK_TOGGLE_ACTION (action),
2516 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2521 g_object_unref (store_settings);
2522 g_object_unref (settings);
2526 /* Make sure that at least one account is "viewed": */
2528 set_at_least_one_account_visible(ModestMainWindow *self)
2530 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2531 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2533 if (!(priv->folder_view)) {
2534 /* It is too early to do this. */
2538 const gchar *active_server_account_name =
2539 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2541 if (!active_server_account_name ||
2542 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2544 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2545 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2546 if (default_modest_name) {
2547 set_account_visible (self, default_modest_name);
2548 } else if (first_modest_name) {
2549 set_account_visible (self, first_modest_name);
2551 g_free (first_modest_name);
2552 g_free (default_modest_name);
2557 on_show_account_action_toggled (GtkToggleAction *action,
2560 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2562 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2563 if (gtk_toggle_action_get_active (action))
2564 set_account_visible (self, acc_name);
2568 refresh_account (const gchar *account_name)
2572 /* win must already exists here, obviously */
2573 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2576 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2580 /* If account_name == NULL, we must update all (option All) */
2582 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2584 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2589 on_refresh_account_action_activated (GtkAction *action,
2592 refresh_account ((const gchar*) user_data);
2596 on_send_receive_csm_activated (GtkMenuItem *item,
2599 refresh_account ((const gchar*) user_data);
2603 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2605 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2607 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2613 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2615 ModestMainWindow *main_window = NULL;
2617 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2618 main_window = MODEST_MAIN_WINDOW (userdata);
2620 /* Update toolbar dimming state */
2621 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2622 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2628 on_header_view_focus_in (GtkWidget *widget,
2629 GdkEventFocus *event,
2632 ModestMainWindow *main_window = NULL;
2634 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2636 main_window = MODEST_MAIN_WINDOW (userdata);
2638 /* Update toolbar dimming state */
2639 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2640 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2646 on_folder_selection_changed (ModestFolderView *folder_view,
2647 TnyFolderStore *folder_store,
2649 ModestMainWindow *main_window)
2651 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2652 GtkAction *action = NULL;
2653 gboolean show_reply = TRUE;
2654 gboolean show_forward = TRUE;
2655 gboolean show_cancel_send = FALSE;
2656 gboolean show_clipboard = TRUE;
2657 gboolean show_delete = TRUE;
2660 if (TNY_IS_ACCOUNT (folder_store)) {
2661 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2662 } else if (TNY_IS_FOLDER (folder_store)) {
2663 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2664 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2665 TNY_FOLDER (folder_store));
2666 switch (folder_type) {
2667 case TNY_FOLDER_TYPE_DRAFTS:
2668 show_clipboard = show_delete = TRUE;
2669 show_reply = show_forward = show_cancel_send = FALSE;
2671 case TNY_FOLDER_TYPE_SENT:
2672 show_forward = show_clipboard = show_delete = TRUE;
2673 show_reply = show_cancel_send = FALSE;
2675 case TNY_FOLDER_TYPE_OUTBOX:
2676 show_clipboard = show_delete = show_cancel_send = TRUE;
2677 show_reply = show_forward = FALSE;
2679 case TNY_FOLDER_TYPE_INVALID:
2680 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2683 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2684 show_cancel_send = FALSE;
2687 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2688 show_cancel_send = FALSE;
2693 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2694 gtk_action_set_visible (action, show_reply);
2695 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2696 gtk_action_set_visible (action, show_reply);
2697 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2698 gtk_action_set_visible (action, show_forward);
2699 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2700 gtk_action_set_visible (action, show_cancel_send);
2701 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2702 gtk_action_set_visible (action, show_delete);
2704 /* We finally call to the ui actions handler, after updating properly
2705 * the header view CSM */
2706 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2710 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2711 GtkTreeModel *model,
2712 GtkTreeRowReference *row_reference,
2713 ModestMainWindow *self)
2715 ModestMainWindowPrivate *priv = NULL;
2716 GtkTreeModel *header_model = NULL;
2717 GtkTreePath *path = NULL;
2719 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2720 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2721 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2723 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2724 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2726 /* Do nothing if we changed the folder in the main view */
2727 if (header_model != model)
2730 /* Select the message in the header view */
2731 path = gtk_tree_row_reference_get_path (row_reference);
2732 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2734 gtk_tree_path_free (path);
2740 show_updating_banner (gpointer user_data)
2742 ModestMainWindowPrivate *priv = NULL;
2744 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2746 if (priv->updating_banner == NULL) {
2748 /* We're outside the main lock */
2749 gdk_threads_enter ();
2750 priv->updating_banner =
2751 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2752 _CS ("ckdg_pb_updating"));
2753 gdk_threads_leave ();
2756 /* Remove timeout */
2757 priv->updating_banner_timeout = 0;
2762 * We use this function to show/hide a progress banner showing
2763 * "Updating" while the header view is being filled. We're not showing
2764 * it unless the update takes more than 2 seconds
2766 * If starting = TRUE then the refresh is starting, otherwise it means
2767 * that is has just finished
2770 on_updating_msg_list (ModestHeaderView *header_view,
2774 ModestMainWindowPrivate *priv = NULL;
2776 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2778 /* Remove old timeout */
2779 if (priv->updating_banner_timeout > 0) {
2780 g_source_remove (priv->updating_banner_timeout);
2781 priv->updating_banner_timeout = 0;
2784 /* Create a new timeout */
2786 priv->updating_banner_timeout =
2787 g_timeout_add (2000, show_updating_banner, user_data);
2789 /* Remove the banner if exists */
2790 if (priv->updating_banner) {
2791 gtk_widget_destroy (priv->updating_banner);
2792 priv->updating_banner = NULL;
2798 modest_main_window_screen_is_on (ModestMainWindow *self)
2800 ModestMainWindowPrivate *priv = NULL;
2802 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2804 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2806 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2810 remove_banners (ModestMainWindow *window)
2812 ModestMainWindowPrivate *priv;
2814 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2816 if (priv->retrieving_banner_timeout > 0) {
2817 g_source_remove (priv->retrieving_banner_timeout);
2818 priv->retrieving_banner_timeout = 0;
2821 if (priv->retrieving_banner != NULL) {
2822 gtk_widget_destroy (priv->retrieving_banner);
2823 priv->retrieving_banner = NULL;
2826 if (priv->updating_banner_timeout > 0) {
2827 g_source_remove (priv->updating_banner_timeout);
2828 priv->updating_banner_timeout = 0;
2831 if (priv->updating_banner != NULL) {
2832 gtk_widget_destroy (priv->updating_banner);
2833 priv->updating_banner = NULL;
2839 on_window_hide (GObject *gobject,
2843 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2845 if (!GTK_WIDGET_VISIBLE (gobject)) {
2846 TnyFolderStore *folder_store;
2847 ModestMainWindowPrivate *priv;
2849 /* Remove the currently shown banners */
2850 remove_banners (MODEST_MAIN_WINDOW (gobject));
2852 /* Force the folder view to sync the currently selected folder
2853 to save the read/unread status and to expunge messages */
2854 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2855 folder_store = modest_folder_view_get_selected (priv->folder_view);
2856 if (TNY_IS_FOLDER (folder_store)) {
2857 ModestMailOperation *mail_op;
2859 mail_op = modest_mail_operation_new (NULL);
2860 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2862 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2863 g_object_unref (mail_op);
2869 on_window_destroy (GtkObject *widget,
2872 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2874 remove_banners (MODEST_MAIN_WINDOW (widget));
2878 show_retrieving_banner (gpointer user_data)
2880 ModestMainWindowPrivate *priv = NULL;
2882 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2884 if (priv->retrieving_banner == NULL) {
2886 /* We're outside the main lock */
2887 gdk_threads_enter ();
2888 priv->retrieving_banner =
2889 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2890 _("mcen_ib_getting_items"));
2891 gdk_threads_leave ();
2894 /* Remove timeout */
2895 priv->retrieving_banner_timeout = 0;