1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-utils.h>
57 #include <modest-maemo-utils.h>
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-mail-operation.h"
61 #include "modest-icon-names.h"
62 #include "modest-progress-bar.h"
63 #include "modest-text-utils.h"
64 #include "modest-ui-dimming-manager.h"
65 #include "maemo/modest-osso-state-saving.h"
66 #include "modest-text-utils.h"
67 #include "modest-signal-mgr.h"
69 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
76 /* 'private'/'protected' functions */
77 static void modest_main_window_class_init (ModestMainWindowClass *klass);
78 static void modest_main_window_init (ModestMainWindow *obj);
79 static void modest_main_window_finalize (GObject *obj);
81 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
82 GdkEventWindowState *event,
85 static void connect_signals (ModestMainWindow *self);
87 static void modest_main_window_disconnect_signals (ModestWindow *self);
89 static void restore_settings (ModestMainWindow *self,
90 gboolean do_folder_view_too);
92 static void save_state (ModestWindow *self);
94 static void update_menus (ModestMainWindow* self);
96 static void modest_main_window_show_toolbar (ModestWindow *window,
97 gboolean show_toolbar);
99 static void cancel_progressbar (GtkToolButton *toolbutton,
100 ModestMainWindow *self);
102 static void on_queue_changed (ModestMailOperationQueue *queue,
103 ModestMailOperation *mail_op,
104 ModestMailOperationQueueNotification type,
105 ModestMainWindow *self);
107 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
109 static void on_account_inserted (TnyAccountStore *accoust_store,
113 static void on_account_removed (TnyAccountStore *accoust_store,
117 static void on_account_changed (TnyAccountStore *account_store,
121 static void on_default_account_changed (ModestAccountMgr* mgr,
124 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
128 static void on_configuration_key_changed (ModestConf* conf,
130 ModestConfEvent event,
131 ModestConfNotificationId id,
132 ModestMainWindow *self);
134 static void set_toolbar_mode (ModestMainWindow *self,
135 ModestToolBarModes mode);
137 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
139 static void on_show_account_action_toggled (GtkToggleAction *action,
142 static void on_refresh_account_action_activated (GtkAction *action,
145 static void on_send_receive_csm_activated (GtkMenuItem *item,
148 static void on_msg_count_changed (ModestHeaderView *header_view,
150 TnyFolderChange *change,
151 ModestMainWindow *main_window);
153 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
156 static GtkWidget * create_empty_view (void);
158 static gboolean on_folder_view_focus_in (GtkWidget *widget,
159 GdkEventFocus *event,
162 static gboolean on_header_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static void on_folder_selection_changed (ModestFolderView *folder_view,
167 TnyFolderStore *folder_store,
169 ModestMainWindow *main_window);
171 static void set_at_least_one_account_visible(ModestMainWindow *self);
173 static void on_updating_msg_list (ModestHeaderView *header_view,
177 static gboolean restore_paned_timeout_handler (gpointer *data);
179 static gboolean show_retrieving_banner (gpointer user_data);
181 static void on_window_destroy (GtkObject *widget,
184 static void on_window_hide (GObject *gobject,
188 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
189 struct _ModestMainWindowPrivate {
190 GtkWidget *msg_paned;
191 GtkWidget *main_paned;
192 GtkWidget *main_vbox;
193 GtkWidget *contents_widget;
194 GtkWidget *empty_view;
196 /* Progress observers */
197 GtkWidget *progress_bar;
198 GSList *progress_widgets;
201 GtkWidget *progress_toolitem;
202 GtkWidget *cancel_toolitem;
203 GtkWidget *sort_toolitem;
204 GtkWidget *refresh_toolitem;
205 ModestToolBarModes current_toolbar_mode;
207 /* Merge ids used to add/remove accounts to the ViewMenu*/
208 GByteArray *merge_ids;
209 GtkActionGroup *view_additions_group;
211 /* On-demand widgets */
212 GtkWidget *accounts_popup;
213 GtkWidget *details_widget;
215 /* Optimized view enabled */
216 gboolean optimized_view;
218 /* Optimized view enabled */
219 gboolean send_receive_in_progress;
221 ModestHeaderView *header_view;
222 ModestFolderView *folder_view;
224 ModestMainWindowStyle style;
225 ModestMainWindowContentsStyle contents_style;
226 gboolean wait_for_settings;
228 guint progress_bar_timeout;
229 guint restore_paned_timeout;
231 /* Signal handler UIDs */
232 GList *queue_err_signals;
235 /* "Updating" banner for header view */
236 GtkWidget *updating_banner;
237 guint updating_banner_timeout;
239 /* "Retrieving" banner for header view */
240 GtkWidget *retrieving_banner;
241 guint retrieving_banner_timeout;
244 osso_display_state_t display_state;
246 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
247 MODEST_TYPE_MAIN_WINDOW, \
248 ModestMainWindowPrivate))
250 typedef struct _GetMsgAsyncHelper {
251 ModestMainWindowPrivate *main_window_private;
253 ModestTnyMsgReplyType reply_type;
254 ModestTnyMsgForwardType forward_type;
261 static GtkWindowClass *parent_class = NULL;
264 /* Private actions */
265 /* This is the context sensitive menu: */
266 static const GtkActionEntry modest_folder_view_action_entries [] = {
268 /* Folder View CSM actions */
269 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
270 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
271 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
272 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
273 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
274 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
277 static const GtkActionEntry modest_header_view_action_entries [] = {
279 /* Header View CSM actions */
280 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
281 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
282 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
283 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
284 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
285 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
286 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
287 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
288 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
289 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
292 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
293 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
296 /************************************************************************/
299 modest_main_window_get_type (void)
301 static GType my_type = 0;
303 static const GTypeInfo my_info = {
304 sizeof(ModestMainWindowClass),
305 NULL, /* base init */
306 NULL, /* base finalize */
307 (GClassInitFunc) modest_main_window_class_init,
308 NULL, /* class finalize */
309 NULL, /* class data */
310 sizeof(ModestMainWindow),
312 (GInstanceInitFunc) modest_main_window_init,
315 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
323 modest_main_window_class_init (ModestMainWindowClass *klass)
325 GObjectClass *gobject_class;
326 gobject_class = (GObjectClass*) klass;
327 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
329 parent_class = g_type_class_peek_parent (klass);
330 gobject_class->finalize = modest_main_window_finalize;
332 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
334 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
335 modest_window_class->save_state_func = save_state;
336 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
337 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
338 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
342 modest_main_window_init (ModestMainWindow *obj)
344 ModestMainWindowPrivate *priv;
346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
348 priv->queue_err_signals = NULL;
349 priv->msg_paned = NULL;
350 priv->main_paned = NULL;
351 priv->main_vbox = NULL;
352 priv->header_view = NULL;
353 priv->folder_view = NULL;
354 priv->contents_widget = NULL;
355 priv->accounts_popup = NULL;
356 priv->details_widget = NULL;
357 priv->empty_view = NULL;
358 priv->progress_widgets = NULL;
359 priv->progress_bar = NULL;
360 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
361 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
362 priv->wait_for_settings = TRUE;
363 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
364 priv->merge_ids = NULL;
365 priv->optimized_view = FALSE;
366 priv->send_receive_in_progress = FALSE;
367 priv->progress_bar_timeout = 0;
368 priv->restore_paned_timeout = 0;
369 priv->sighandlers = NULL;
370 priv->updating_banner = NULL;
371 priv->updating_banner_timeout = 0;
372 priv->retrieving_banner = NULL;
373 priv->retrieving_banner_timeout = 0;
374 priv->display_state = OSSO_DISPLAY_ON;
376 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
378 "applications_email_mainview");
382 modest_main_window_finalize (GObject *obj)
384 ModestMainWindowPrivate *priv;
386 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
388 /* Sanity check: shouldn't be needed, the window mgr should
389 call this function before */
390 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
391 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
393 g_slist_free (priv->progress_widgets);
395 g_byte_array_free (priv->merge_ids, TRUE);
397 if (priv->progress_bar_timeout > 0) {
398 g_source_remove (priv->progress_bar_timeout);
399 priv->progress_bar_timeout = 0;
402 if (priv->updating_banner_timeout > 0) {
403 g_source_remove (priv->updating_banner_timeout);
404 priv->updating_banner_timeout = 0;
407 if (priv->updating_banner) {
408 gtk_widget_destroy (priv->updating_banner);
409 priv->updating_banner = NULL;
412 if (priv->retrieving_banner_timeout > 0) {
413 g_source_remove (priv->retrieving_banner_timeout);
414 priv->retrieving_banner_timeout = 0;
417 if (priv->retrieving_banner) {
418 gtk_widget_destroy (priv->retrieving_banner);
419 priv->retrieving_banner = NULL;
422 if (priv->restore_paned_timeout > 0) {
423 g_source_remove (priv->restore_paned_timeout);
424 priv->restore_paned_timeout = 0;
427 G_OBJECT_CLASS(parent_class)->finalize (obj);
431 modest_main_window_get_child_widget (ModestMainWindow *self,
432 ModestMainWindowWidgetType widget_type)
434 ModestMainWindowPrivate *priv;
437 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
438 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
441 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
443 switch (widget_type) {
444 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
445 widget = (GtkWidget*)priv->header_view; break;
446 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
447 widget = (GtkWidget*)priv->folder_view; break;
452 /* Note that the window could have been destroyed, and so
453 their children, but still have some references */
454 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
458 restore_paned_timeout_handler (gpointer *data)
460 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
461 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
464 /* Timeouts are outside the main lock */
465 gdk_threads_enter ();
466 if (GTK_WIDGET_VISIBLE (main_window)) {
467 conf = modest_runtime_get_conf ();
468 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
469 MODEST_CONF_MAIN_PANED_KEY);
471 gdk_threads_leave ();
478 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
485 conf = modest_runtime_get_conf ();
487 modest_widget_memory_restore (conf, G_OBJECT(self),
488 MODEST_CONF_MAIN_WINDOW_KEY);
490 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
491 MODEST_CONF_HEADER_VIEW_KEY);
493 if (do_folder_view_too)
494 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
495 MODEST_CONF_FOLDER_VIEW_KEY);
497 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
498 /* MODEST_CONF_MAIN_PANED_KEY); */
500 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
502 /* We need to force a redraw here in order to get the right
503 position of the horizontal paned separator */
504 gtk_widget_show (GTK_WIDGET (self));
509 save_state (ModestWindow *window)
512 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
513 ModestMainWindowPrivate *priv;
515 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
516 conf = modest_runtime_get_conf ();
518 modest_widget_memory_save (conf,G_OBJECT(self),
519 MODEST_CONF_MAIN_WINDOW_KEY);
520 /* Only save main paned position if we're in split mode */
521 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
522 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
523 MODEST_CONF_MAIN_PANED_KEY);
524 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
525 MODEST_CONF_FOLDER_VIEW_KEY);
529 compare_display_names (ModestAccountSettings *a,
530 ModestAccountSettings *b)
532 return strcmp (modest_account_settings_get_display_name (a),
533 modest_account_settings_get_display_name (b));
536 /* We use this function to prevent the send&receive CSM to be shown
537 when there are less than two account */
539 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
545 update_menus (ModestMainWindow* self)
547 GSList *account_names, *iter, *accounts;
548 ModestMainWindowPrivate *priv;
549 ModestWindowPrivate *parent_priv;
550 ModestAccountMgr *mgr;
551 gint i, num_accounts;
553 gchar *default_account;
554 const gchar *active_account_name;
555 GtkWidget *send_receive_button, *item;
556 GtkAction *send_receive_all = NULL;
559 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
560 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
562 /* Get enabled account IDs */
563 mgr = modest_runtime_get_account_mgr ();
564 account_names = modest_account_mgr_account_names (mgr, TRUE);
565 iter = account_names;
569 ModestAccountSettings *settings =
570 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
571 accounts = g_slist_prepend (accounts, settings);
575 modest_account_mgr_free_account_names (account_names);
576 account_names = NULL;
578 /* Order the list of accounts by its display name */
579 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
580 num_accounts = g_slist_length (accounts);
582 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
583 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
584 gtk_action_set_visible (send_receive_all, num_accounts > 0);
586 /* Delete old send&receive popup items. We can not just do a
587 menu_detach because it does not work well with
589 if (priv->accounts_popup)
590 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
591 (GtkCallback) gtk_widget_destroy, NULL);
593 /* Delete old entries in the View menu. Do not free groups, it
595 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
597 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
598 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
599 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
600 GTK_ACTION_GROUP (groups->data));
603 if (priv->merge_ids) {
604 for (i = 0; i < priv->merge_ids->len; i++)
605 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
606 g_byte_array_free (priv->merge_ids, TRUE);
608 /* We need to call this in order to ensure
609 that the new actions are added in the right
610 order (alphabetical) */
611 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
613 groups = g_list_next (groups);
615 priv->merge_ids = g_byte_array_sized_new (num_accounts);
617 /* Get send receive button */
618 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
619 "/ToolBar/ToolbarSendReceive");
621 /* Create the menu */
622 if (num_accounts > 1) {
623 if (!priv->accounts_popup)
624 priv->accounts_popup = gtk_menu_new ();
625 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
626 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
627 g_signal_connect (G_OBJECT (item),
629 G_CALLBACK (on_send_receive_csm_activated),
631 item = gtk_separator_menu_item_new ();
632 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
635 /* Create a new action group */
636 default_account = modest_account_mgr_get_default_account (mgr);
637 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
639 if (!active_account_name)
640 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
642 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
644 for (i = 0; i < num_accounts; i++) {
645 gchar *display_name = NULL;
646 const gchar *account_name;
647 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
650 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
653 account_name = modest_account_settings_get_account_name (settings);
655 if (default_account && account_name &&
656 !(strcmp (default_account, account_name) == 0)) {
657 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
658 modest_account_settings_get_display_name (settings));
660 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
661 modest_account_settings_get_display_name (settings));
666 /* Create action and add it to the action group. The
667 action name must be the account name, this way we
668 could know in the handlers the account to show */
669 if (settings && account_name) {
670 gchar* item_name, *refresh_action_name;
672 GtkAction *view_account_action, *refresh_account_action;
673 gchar *escaped_display_name;
675 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
677 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
678 escaped_display_name, NULL, NULL, 0));
679 g_free (escaped_display_name);
680 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
681 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
682 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
684 if (active_account_name) {
685 if (active_account_name && account_name &&
686 (strcmp (active_account_name, account_name) == 0)) {
687 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
691 /* Add ui from account data. We allow 2^9-1 account
692 changes in a single execution because we're
693 downcasting the guint to a guint8 in order to use a
694 GByteArray. It should be enough. */
695 item_name = g_strconcat (account_name, "Menu", NULL);
696 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
697 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
698 gtk_ui_manager_add_ui (parent_priv->ui_manager,
700 "/MenuBar/ViewMenu/ViewMenuAdditions",
703 GTK_UI_MANAGER_MENUITEM,
706 /* Connect the action signal "activate" */
707 g_signal_connect_after (G_OBJECT (view_account_action),
709 G_CALLBACK (on_show_account_action_toggled),
712 /* Create the items for the Tools->Send&Receive submenu */
713 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
714 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
715 display_name, NULL, NULL);
716 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
718 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
719 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
720 gtk_ui_manager_add_ui (parent_priv->ui_manager,
722 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
725 GTK_UI_MANAGER_MENUITEM,
727 g_free (refresh_action_name);
729 g_signal_connect_data (G_OBJECT (refresh_account_action),
731 G_CALLBACK (on_refresh_account_action_activated),
732 g_strdup (account_name),
733 (GClosureNotify) g_free,
736 /* Create item and add it to the send&receive
737 CSM. If there is only one account then
739 if (num_accounts > 1) {
740 GtkWidget *label = gtk_label_new(NULL);
741 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
742 if (default_account && (strcmp(account_name, default_account) == 0)) {
743 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
744 gtk_label_set_markup (GTK_LABEL (label), escaped);
747 gtk_label_set_text (GTK_LABEL (label), display_name);
750 item = gtk_menu_item_new ();
751 gtk_container_add (GTK_CONTAINER (item), label);
753 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
754 g_signal_connect_data (G_OBJECT (item),
756 G_CALLBACK (on_send_receive_csm_activated),
757 g_strdup (account_name),
758 (GClosureNotify) g_free,
765 g_free (display_name);
768 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
770 /* We cannot do this in the loop above because this relies on the action
771 * group being inserted. This makes the default account appear in bold.
772 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
773 for (i = 0; i < num_accounts; i++) {
774 gchar *item_name, *path;
776 ModestAccountSettings *settings;
777 const gchar *account_name;
780 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
781 account_name = modest_account_settings_get_account_name (settings);
782 is_default = (account_name && default_account && !strcmp (account_name, default_account));
784 /* Get the item of the view menu */
785 item_name = g_strconcat (account_name, "Menu", NULL);
786 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
787 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
791 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
792 if (GTK_IS_LABEL (child)) {
793 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
795 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
796 gtk_label_set_markup (GTK_LABEL (child), bold_name);
799 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
803 /* Get the item of the tools menu */
804 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
805 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
809 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
810 if (GTK_IS_LABEL (child)) {
811 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
813 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
814 gtk_label_set_markup (GTK_LABEL (child), bold_name);
817 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
822 g_object_unref (settings);
825 if (num_accounts > 1) {
826 /* Disconnect the tap-and-hold-query if it's connected */
827 if (modest_signal_mgr_is_connected (priv->sighandlers,
828 G_OBJECT (send_receive_button),
829 "tap-and-hold-query"))
830 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
831 G_OBJECT (send_receive_button),
832 "tap-and-hold-query");
834 /* Mandatory in order to view the menu contents */
835 gtk_widget_show_all (priv->accounts_popup);
837 /* Setup tap_and_hold just if was not done before*/
838 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
839 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
841 /* Connect the tap-and-hold-query in order not to show the CSM */
842 if (!modest_signal_mgr_is_connected (priv->sighandlers,
843 G_OBJECT (send_receive_button),
844 "tap-and-hold-query"))
845 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
846 G_OBJECT (send_receive_button),
847 "tap-and-hold-query",
848 G_CALLBACK (tap_and_hold_query_cb),
853 g_slist_free (accounts);
854 g_free (default_account);
857 /* Make sure that at least one account is viewed if there are any
858 * accounts, for instance when adding the first account: */
859 set_at_least_one_account_visible (self);
863 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
865 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
866 gtk_scrolled_window_add_with_viewport
867 (GTK_SCROLLED_WINDOW(win), widget);
869 gtk_container_add (GTK_CONTAINER(win),
880 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
882 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
884 GList *oerrsignals = priv->queue_err_signals;
885 while (oerrsignals) {
886 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
887 g_signal_handler_disconnect (esignal->queue, esignal->signal);
888 g_slice_free (QueueErrorSignal, esignal);
889 oerrsignals = g_list_next (oerrsignals);
891 g_list_free (priv->queue_err_signals);
892 priv->queue_err_signals = NULL;
897 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
899 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
902 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
906 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
908 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
910 /* Update visibility */
913 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
917 modest_main_window_disconnect_signals (ModestWindow *self)
919 ModestMainWindowPrivate *priv;
920 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
922 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
923 priv->sighandlers = NULL;
927 connect_signals (ModestMainWindow *self)
929 ModestWindowPrivate *parent_priv;
930 ModestMainWindowPrivate *priv;
933 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
934 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
939 modest_signal_mgr_connect (priv->sighandlers,
940 G_OBJECT(priv->folder_view), "key-press-event",
941 G_CALLBACK(on_inner_widgets_key_pressed), self);
943 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
944 "folder_selection_changed",
945 G_CALLBACK (on_folder_selection_changed),
948 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
949 "folder-display-name-changed",
950 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
953 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
955 G_CALLBACK (on_folder_view_focus_in),
958 /* Folder view CSM */
959 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
960 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
961 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
962 G_CALLBACK(_folder_view_csm_menu_activated),
966 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
967 G_CALLBACK(modest_ui_actions_on_header_selected), self);
969 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
970 G_CALLBACK(modest_ui_actions_on_header_activated), self);
972 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
973 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
975 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
976 G_CALLBACK(on_inner_widgets_key_pressed), self);
978 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
979 G_CALLBACK(on_msg_count_changed), self);
981 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
982 G_CALLBACK (on_header_view_focus_in), self);
984 modest_signal_mgr_connect (priv->sighandlers,
985 G_OBJECT (priv->header_view),
987 G_CALLBACK (on_updating_msg_list),
990 /* Header view CSM */
991 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
992 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
994 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
995 G_CALLBACK(_header_view_csm_menu_activated),
1000 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1001 G_CALLBACK (modest_main_window_window_state_event),
1003 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1004 * in destroy stage */
1005 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1007 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1009 /* Mail Operation Queue */
1011 modest_signal_mgr_connect (priv->sighandlers,
1012 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1014 G_CALLBACK (on_queue_changed), self);
1016 /* Track changes in the device name */
1018 modest_signal_mgr_connect (priv->sighandlers,
1019 G_OBJECT(modest_runtime_get_conf ()),
1021 G_CALLBACK (on_configuration_key_changed),
1024 /* Track account changes. We need to refresh the toolbar */
1026 modest_signal_mgr_connect (priv->sighandlers,
1027 G_OBJECT (modest_runtime_get_account_store ()),
1029 G_CALLBACK (on_account_inserted),
1032 modest_signal_mgr_connect (priv->sighandlers,
1033 G_OBJECT (modest_runtime_get_account_store ()),
1035 G_CALLBACK (on_account_removed),
1038 /* We need to refresh the send & receive menu to change the bold
1039 * account when the default account changes. */
1041 modest_signal_mgr_connect (priv->sighandlers,
1042 G_OBJECT (modest_runtime_get_account_mgr ()),
1043 "default_account_changed",
1044 G_CALLBACK (on_default_account_changed),
1049 modest_signal_mgr_connect (priv->sighandlers,
1050 G_OBJECT (modest_runtime_get_account_store ()),
1052 G_CALLBACK (on_account_changed),
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);
1103 GtkWidget *folder_win;
1108 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1110 ShowHelper *helper = (ShowHelper *) user_data;
1111 GtkWidget *folder_win = helper->folder_win;
1112 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1114 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1115 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1117 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1119 /* Connect signals */
1120 connect_signals (MODEST_MAIN_WINDOW (self));
1122 /* Set account store */
1123 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1124 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1126 /* Load previous osso state, for instance if we are being restored from
1128 modest_osso_load_state ();
1130 /* Restore window & widget settings */
1131 priv->wait_for_settings = TRUE;
1132 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1133 priv->wait_for_settings = FALSE;
1135 /* Check if accounts exist and show the account wizard if not */
1136 gboolean accounts_exist =
1137 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1139 if (!accounts_exist) {
1140 /* This is necessary to have the main window shown behind the dialog
1141 It's an ugly hack... jschmid */
1142 gtk_widget_show_all(GTK_WIDGET(self));
1143 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1146 GtkAction *send_receive_all;
1147 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1148 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1149 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1150 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1151 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1152 modest_account_mgr_free_account_names (accounts);
1153 update_menus (MODEST_MAIN_WINDOW (self));
1156 /* Never call this function again (NOTE that it could happen
1157 as we hide the main window instead of closing it while
1158 there are operations ongoing) and free the helper */
1159 g_signal_handler_disconnect (self, helper->handler_id);
1160 g_slice_free (ShowHelper, helper);
1164 osso_display_event_cb (osso_display_state_t state,
1167 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1169 priv->display_state = state;
1171 /* Stop blinking if the screen becomes on */
1172 if (priv->display_state == OSSO_DISPLAY_ON)
1173 modest_platform_remove_new_mail_notifications (TRUE);
1177 modest_main_window_new (void)
1179 ModestMainWindow *self = NULL;
1180 ModestMainWindowPrivate *priv = NULL;
1181 ModestWindowPrivate *parent_priv = NULL;
1182 GtkWidget *folder_win = NULL;
1183 ModestDimmingRulesGroup *menu_rules_group = NULL;
1184 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1185 GtkActionGroup *action_group = NULL;
1186 GError *error = NULL;
1188 ModestConf *conf = NULL;
1189 GtkAction *action = NULL;
1190 GdkPixbuf *window_icon;
1193 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1194 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1195 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1197 parent_priv->ui_manager = gtk_ui_manager_new();
1198 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1200 action_group = gtk_action_group_new ("ModestMainWindowActions");
1201 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1203 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1204 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1206 /* Add common actions */
1207 gtk_action_group_add_actions (action_group,
1208 modest_action_entries,
1209 G_N_ELEMENTS (modest_action_entries),
1212 gtk_action_group_add_actions (action_group,
1213 modest_folder_view_action_entries,
1214 G_N_ELEMENTS (modest_folder_view_action_entries),
1217 gtk_action_group_add_actions (action_group,
1218 modest_header_view_action_entries,
1219 G_N_ELEMENTS (modest_header_view_action_entries),
1222 gtk_action_group_add_toggle_actions (action_group,
1223 modest_toggle_action_entries,
1224 G_N_ELEMENTS (modest_toggle_action_entries),
1227 gtk_action_group_add_toggle_actions (action_group,
1228 modest_main_window_toggle_action_entries,
1229 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1232 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1233 g_object_unref (action_group);
1235 /* Load the UI definition */
1236 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1237 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1238 if (error != NULL) {
1239 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1240 g_error_free (error);
1244 /* Add common dimming rules */
1245 modest_dimming_rules_group_add_rules (menu_rules_group,
1246 modest_main_window_menu_dimming_entries,
1247 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1248 MODEST_WINDOW (self));
1249 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1250 modest_main_window_toolbar_dimming_entries,
1251 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1252 MODEST_WINDOW (self));
1254 /* Insert dimming rules group for this window */
1255 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1256 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1257 g_object_unref (menu_rules_group);
1258 g_object_unref (toolbar_rules_group);
1260 /* Add accelerators */
1261 gtk_window_add_accel_group (GTK_WINDOW (self),
1262 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1264 /* Menubar. Update the state of some toggles */
1265 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1266 conf = modest_runtime_get_conf ();
1267 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1268 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1269 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1270 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1271 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1272 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1273 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1274 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1275 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1276 gtk_widget_show (parent_priv->menubar);
1278 /* Get device name */
1279 modest_maemo_utils_get_device_name ();
1283 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1284 if (!priv->header_view)
1285 g_printerr ("modest: cannot instantiate header view\n");
1286 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1287 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1288 MODEST_CONF_HEADER_VIEW_KEY);
1290 /* Other style properties of header view */
1291 g_object_set (G_OBJECT (priv->header_view),
1292 "rules-hint", FALSE,
1294 /* gtk_widget_show (priv->header_view); */
1297 priv->empty_view = create_empty_view ();
1298 gtk_widget_show (priv->empty_view);
1300 /* Create scrolled windows */
1301 folder_win = gtk_scrolled_window_new (NULL, NULL);
1302 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1303 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1305 GTK_POLICY_AUTOMATIC);
1306 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1308 GTK_POLICY_AUTOMATIC);
1309 /* gtk_widget_show (priv->contents_widget); */
1312 priv->main_paned = gtk_hpaned_new ();
1313 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1314 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1315 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1317 /* putting it all together... */
1318 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1319 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1320 gtk_widget_show (priv->main_vbox);
1322 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1324 app = hildon_program_get_instance ();
1325 hildon_program_add_window (app, HILDON_WINDOW (self));
1327 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1328 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1330 /* Connect to "show" action. We delay the creation of some
1331 elements until that moment */
1332 helper = g_slice_new0 (ShowHelper);
1333 helper->folder_win = folder_win;
1334 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1335 G_CALLBACK (modest_main_window_on_show),
1338 /* Set window icon */
1339 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1341 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1342 g_object_unref (window_icon);
1345 /* Listen for changes in the screen, we don't want to show a
1346 led pattern when the display is on for example */
1347 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1348 osso_display_event_cb,
1351 /* Dont't restore settings here,
1352 * because it requires a gtk_widget_show(),
1353 * and we don't want to do that until later,
1354 * so that the UI is not visible for non-menu D-Bus activation.
1357 return MODEST_WINDOW(self);
1361 modest_main_window_set_style (ModestMainWindow *self,
1362 ModestMainWindowStyle style)
1364 ModestMainWindowPrivate *priv;
1365 ModestWindowPrivate *parent_priv;
1369 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1371 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1372 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1374 /* no change -> nothing to do */
1375 if (priv->style == style)
1378 /* Get toggle button and update the state if needed. This will
1379 happen only when the set_style is not invoked from the UI,
1380 for example when it's called from widget memory */
1381 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1382 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1383 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1384 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1385 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1386 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1387 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1390 priv->style = style;
1392 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1394 if (!priv->wait_for_settings)
1395 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1396 MODEST_CONF_MAIN_PANED_KEY);
1397 /* Remove main paned */
1398 g_object_ref (priv->main_paned);
1399 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1401 /* Reparent the contents widget to the main vbox */
1402 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1405 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1406 /* Remove header view */
1407 g_object_ref (priv->contents_widget);
1408 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1410 /* Reparent the main paned */
1411 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1412 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1414 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1418 g_return_if_reached ();
1421 /* Let header view grab the focus if it's being shown */
1422 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1423 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1425 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1428 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1431 ModestMainWindowStyle
1432 modest_main_window_get_style (ModestMainWindow *self)
1434 ModestMainWindowPrivate *priv;
1436 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1438 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1443 toolbar_resize (ModestMainWindow *self)
1445 ModestMainWindowPrivate *priv = NULL;
1446 ModestWindowPrivate *parent_priv = NULL;
1448 gint static_button_size;
1449 ModestWindowMgr *mgr;
1451 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1452 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1453 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1455 mgr = modest_runtime_get_window_mgr ();
1456 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1458 if (parent_priv->toolbar) {
1459 /* left size buttons */
1460 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1463 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1464 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1467 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1468 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1469 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1470 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1471 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1472 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1475 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1478 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1479 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1480 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1482 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1483 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1484 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1492 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1494 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1495 ModestWindowPrivate *parent_priv;
1496 ModestWindowMgr *mgr;
1497 gboolean is_fullscreen;
1498 GtkAction *fs_toggle_action;
1501 mgr = modest_runtime_get_window_mgr ();
1503 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1505 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1507 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1508 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1509 if (is_fullscreen != active) {
1510 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1513 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1521 modest_main_window_show_toolbar (ModestWindow *self,
1522 gboolean show_toolbar)
1524 ModestMainWindowPrivate *priv = NULL;
1525 ModestWindowPrivate *parent_priv = NULL;
1526 GtkWidget *reply_button = NULL, *menu = NULL;
1527 GtkWidget *placeholder = NULL;
1529 const gchar *action_name;
1532 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1533 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1534 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1536 /* Set optimized view status */
1537 priv->optimized_view = !show_toolbar;
1539 if (!parent_priv->toolbar) {
1540 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1542 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1544 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1545 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1546 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1547 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1548 toolbar_resize (MODEST_MAIN_WINDOW (self));
1550 /* Add ProgressBar (Transfer toolbar) */
1551 priv->progress_bar = modest_progress_bar_new ();
1552 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1553 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1554 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1555 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1556 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1558 /* Connect cancel 'clicked' signal to abort progress mode */
1559 g_signal_connect(priv->cancel_toolitem, "clicked",
1560 G_CALLBACK(cancel_progressbar),
1563 /* Add it to the observers list */
1564 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1567 hildon_window_add_toolbar (HILDON_WINDOW (self),
1568 GTK_TOOLBAR (parent_priv->toolbar));
1570 /* Set reply button tap and hold menu */
1571 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1572 "/ToolBar/ToolbarMessageReply");
1573 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1574 "/ToolbarReplyCSM");
1575 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1577 /* Set send & receive button tap and hold menu */
1578 update_menus (MODEST_MAIN_WINDOW (self));
1582 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1583 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1584 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1586 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1587 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1588 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1590 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1592 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1596 /* Update also the actions (to update the toggles in the
1597 menus), we have to do it manually because some other window
1598 of the same time could have changed it (remember that the
1599 toolbar fullscreen mode is shared by all the windows of the
1601 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1602 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1604 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1606 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1607 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1612 on_account_inserted (TnyAccountStore *accoust_store,
1613 TnyAccount *account,
1616 /* Transport accounts and local ones (MMC and the Local
1617 folders account do now cause menu changes */
1618 if (TNY_IS_STORE_ACCOUNT (account) &&
1619 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1621 update_menus (MODEST_MAIN_WINDOW (user_data));
1626 on_default_account_changed (ModestAccountMgr* mgr,
1629 update_menus (MODEST_MAIN_WINDOW (user_data));
1633 on_account_removed (TnyAccountStore *accoust_store,
1634 TnyAccount *account,
1637 /* Transport accounts and local ones (MMC and the Local
1638 folders account do now cause menu changes */
1639 if (TNY_IS_STORE_ACCOUNT (account) &&
1640 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1641 update_menus (MODEST_MAIN_WINDOW (user_data));
1645 on_account_changed (TnyAccountStore *account_store,
1646 TnyAccount *account,
1649 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1651 /* Transport accounts and local ones (MMC and the Local
1652 folders account do now cause menu changes */
1653 if (TNY_IS_STORE_ACCOUNT (account)) {
1654 /* We need to refresh the details widget because it could have changed */
1655 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1656 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1658 /* Update the menus as well, name could change */
1659 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1660 update_menus (MODEST_MAIN_WINDOW (user_data));
1665 * This function manages the key events used to navigate between
1666 * header and folder views (when the window is in split view)
1669 * -------------------------------------------------
1670 * HeaderView GDK_Left Move focus to folder view
1671 * FolderView GDK_Right Move focus to header view
1673 * There is no need to scroll to selected row, the widgets will be the
1674 * responsibles of doing that (probably managing the focus-in event
1677 on_inner_widgets_key_pressed (GtkWidget *widget,
1681 ModestMainWindowPrivate *priv;
1683 if (event->type == GDK_KEY_RELEASE)
1686 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1688 /* Do nothing if we're in SIMPLE style */
1689 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1692 if (MODEST_IS_HEADER_VIEW (widget)) {
1693 if (event->keyval == GDK_Left)
1694 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1695 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1696 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1697 if (selected_headers > 1) {
1698 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1701 GtkTreePath * cursor_path;
1702 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1703 if (cursor_path == NULL) {
1704 GtkTreeSelection *selection;
1706 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1707 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1710 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1711 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1716 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1717 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1723 set_alignment (GtkWidget *widget,
1726 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1727 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1731 create_empty_view (void)
1733 GtkLabel *label = NULL;
1734 GtkWidget *align = NULL;
1736 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1737 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1738 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1739 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1741 return GTK_WIDGET(align);
1745 * Free the returned string
1748 get_gray_color_markup (GtkWidget *styled_widget)
1750 gchar *gray_color_markup = NULL;
1751 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1752 /* Obtain the secondary text color. We need a realized widget, that's why
1753 we get styled_widget from outside */
1755 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1756 gray_color_markup = modest_text_utils_get_color_string (&color);
1757 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1759 if (!gray_color_markup)
1760 gray_color_markup = g_strdup ("#BBBBBB");
1762 return gray_color_markup;
1766 * Free the returned string
1769 create_device_name_visual_string (const gchar *device_name,
1770 const gchar *gray_color_markup)
1774 /* We have to use "" to fill the %s of the translation. We can
1775 not just use the device name because the device name is
1776 shown in a different color, so it could not be included
1777 into the <span> tag */
1778 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1779 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1789 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1791 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1796 gchar *gray_color_markup;
1798 vbox = gtk_vbox_new (FALSE, 0);
1800 gray_color_markup = get_gray_color_markup (styled_widget);
1802 /* Account description: */
1803 if (modest_tny_account_is_virtual_local_folders (account)
1804 || (modest_tny_account_is_memory_card_account (account))) {
1806 /* Get device name */
1807 gchar *device_name = NULL;
1808 if (modest_tny_account_is_virtual_local_folders (account))
1809 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1810 MODEST_CONF_DEVICE_NAME, NULL);
1812 device_name = g_strdup (tny_account_get_name (account));
1814 label = create_device_name_visual_string ((const gchar *) device_name,
1815 (const gchar *) gray_color_markup);
1816 label_w = gtk_label_new (NULL);
1817 gtk_label_set_markup (GTK_LABEL (label_w), label);
1818 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1819 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1820 g_free (device_name);
1823 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1824 gtk_box_pack_start (GTK_BOX (vbox),
1825 gtk_label_new (tny_account_get_name (account)),
1828 /* Other accounts, such as IMAP and POP: */
1833 /* Put proto in uppercase */
1834 proto = g_string_new (tny_account_get_proto (account));
1835 proto = g_string_ascii_up (proto);
1837 /* note: mcen_fi_localroot_description is something like "%s account"
1838 * however, we should display "%s account: %s"... therefore, ugly tmp */
1839 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1840 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1841 gray_color_markup, tmp, tny_account_get_name (account));
1844 label_w = gtk_label_new (NULL);
1845 gtk_label_set_markup (GTK_LABEL (label_w), label);
1846 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1847 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1848 g_string_free (proto, TRUE);
1854 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1855 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1856 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1857 modest_tny_folder_store_get_message_count (folder_store));
1858 label_w = gtk_label_new (NULL);
1859 gtk_label_set_markup (GTK_LABEL (label_w), label);
1860 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1861 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1865 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1867 _("mcen_fi_rootfolder_folders"),
1868 modest_tny_folder_store_get_folder_count (folder_store));
1869 label_w = gtk_label_new (NULL);
1870 gtk_label_set_markup (GTK_LABEL (label_w), label);
1871 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1872 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1876 if (modest_tny_account_is_virtual_local_folders (account)
1877 || modest_tny_account_is_memory_card_account (account)) {
1879 gchar *size = modest_text_utils_get_display_size (
1880 modest_tny_folder_store_get_local_size (folder_store));
1882 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1883 gray_color_markup, _("mcen_fi_rootfolder_size"),
1887 label_w = gtk_label_new (NULL);
1888 gtk_label_set_markup (GTK_LABEL (label_w), label);
1889 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1890 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1892 } else if (TNY_IS_ACCOUNT(folder_store)) {
1893 TnyAccount *account = TNY_ACCOUNT(folder_store);
1895 time_t last_updated;
1896 const gchar *last_updated_string;
1897 /* Get last updated from configuration */
1898 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1899 tny_account_get_id (account));
1901 if (last_updated > 0)
1902 last_updated_string = modest_text_utils_get_display_date(last_updated);
1904 last_updated_string = g_strdup (_("mcen_va_never"));
1906 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1907 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1908 label_w = gtk_label_new (NULL);
1909 gtk_label_set_markup (GTK_LABEL (label_w), label);
1910 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1911 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1915 g_free (gray_color_markup);
1918 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1924 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1926 ModestMainWindowPrivate *priv = NULL;
1928 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1930 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1932 return priv->send_receive_in_progress;
1936 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1938 GtkAction *action = NULL;
1939 GtkWidget *widget = NULL;
1940 ModestMainWindowPrivate *priv = NULL;
1942 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1943 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1945 priv->send_receive_in_progress = TRUE;
1947 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1948 gtk_action_set_sensitive (action, FALSE);
1949 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1950 /* gtk_action_set_sensitive (action, FALSE); */
1951 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1952 gtk_widget_set_sensitive (widget, FALSE);
1956 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1958 GtkAction *action = NULL;
1959 GtkWidget *widget = NULL;
1960 ModestMainWindowPrivate *priv = NULL;
1962 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1963 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1965 priv->send_receive_in_progress = FALSE;
1967 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1968 gtk_action_set_sensitive (action, TRUE);
1969 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1970 /* gtk_action_set_sensitive (action, TRUE); */
1971 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1972 gtk_widget_set_sensitive (widget, TRUE);
1977 on_msg_count_changed (ModestHeaderView *header_view,
1979 TnyFolderChange *change,
1980 ModestMainWindow *main_window)
1982 gboolean refilter = FALSE;
1983 gboolean folder_empty = FALSE;
1984 gboolean all_marked_as_deleted = FALSE;
1985 ModestMainWindowPrivate *priv;
1987 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1988 g_return_if_fail (TNY_IS_FOLDER(folder));
1989 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1991 if (change != NULL) {
1992 TnyFolderChangeChanged changed;
1994 changed = tny_folder_change_get_changed (change);
1995 /* If something changes */
1996 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1997 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1999 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2001 /* Play a sound (if configured) and make the LED blink */
2002 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2003 modest_platform_push_email_notification ();
2006 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2009 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2012 /* Check if all messages are marked to be deleted */
2013 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2014 folder_empty = folder_empty || all_marked_as_deleted;
2016 /* Set contents style of headers view */
2018 modest_main_window_set_contents_style (main_window,
2019 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2020 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2022 modest_main_window_set_contents_style (main_window,
2023 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2027 modest_header_view_refilter (header_view);
2032 modest_main_window_set_contents_style (ModestMainWindow *self,
2033 ModestMainWindowContentsStyle style)
2035 ModestMainWindowPrivate *priv;
2037 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2039 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2041 /* We allow to set the same content style than the previously
2042 set if there are details, because it could happen when we're
2043 selecting different accounts consecutively */
2044 if ((priv->contents_style == style) &&
2045 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2048 /* Remove previous child. Delete it if it was an account
2050 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2052 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2053 g_object_ref (content);
2054 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2055 g_object_ref (priv->empty_view);
2056 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2059 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2062 priv->contents_style = style;
2064 switch (priv->contents_style) {
2065 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2066 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2067 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2070 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2072 /* if we're started without main win, there may not be a folder
2073 * view. this fixes a GLib-Critical */
2074 if (priv->folder_view) {
2075 TnyFolderStore *selected_folderstore =
2076 modest_folder_view_get_selected (priv->folder_view);
2077 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2078 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2079 TNY_ACCOUNT (selected_folderstore));
2081 wrap_in_scrolled_window (priv->contents_widget,
2082 priv->details_widget);
2084 g_object_unref (selected_folderstore);
2085 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2090 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2091 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2092 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2096 g_return_if_reached ();
2100 gtk_widget_show_all (priv->contents_widget);
2103 ModestMainWindowContentsStyle
2104 modest_main_window_get_contents_style (ModestMainWindow *self)
2106 ModestMainWindowPrivate *priv;
2108 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2110 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2111 return priv->contents_style;
2116 on_configuration_key_changed (ModestConf* conf,
2118 ModestConfEvent event,
2119 ModestConfNotificationId id,
2120 ModestMainWindow *self)
2122 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2123 TnyAccount *account = NULL;
2125 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2128 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2131 if (priv->folder_view)
2132 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2134 if (account && TNY_IS_ACCOUNT (account) &&
2135 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2138 const gchar *device_name;
2139 gchar *new_text, *gray_color_markup;
2142 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2143 label = GTK_LABEL (children->data);
2145 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2146 MODEST_CONF_DEVICE_NAME, NULL);
2148 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2149 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2151 gtk_label_set_markup (label, new_text);
2152 gtk_widget_show (GTK_WIDGET (label));
2154 g_free (gray_color_markup);
2156 g_list_free (children);
2158 g_object_unref (account);
2162 set_toolbar_transfer_mode (ModestMainWindow *self)
2164 ModestMainWindowPrivate *priv = NULL;
2166 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2168 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2170 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2172 if (priv->progress_bar_timeout > 0) {
2173 g_source_remove (priv->progress_bar_timeout);
2174 priv->progress_bar_timeout = 0;
2181 set_toolbar_mode (ModestMainWindow *self,
2182 ModestToolBarModes mode)
2184 ModestWindowPrivate *parent_priv = NULL;
2185 ModestMainWindowPrivate *priv = NULL;
2186 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2188 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2190 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2191 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2193 /* In case this was called before the toolbar exists: */
2194 if (!(parent_priv->toolbar))
2197 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2199 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2200 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2201 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2203 /* Sets current toolbar mode */
2204 priv->current_toolbar_mode = mode;
2206 /* Checks the dimming rules */
2207 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2208 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2210 /* Show and hide toolbar items */
2212 case TOOLBAR_MODE_NORMAL:
2214 gtk_action_set_visible (sort_action, TRUE);
2216 gtk_action_set_visible (refresh_action, TRUE);
2217 if (priv->progress_toolitem) {
2218 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2219 gtk_widget_hide (priv->progress_toolitem);
2221 if (priv->progress_bar)
2222 gtk_widget_hide (priv->progress_bar);
2225 gtk_action_set_visible (cancel_action, FALSE);
2227 /* Hide toolbar if optimized view is enabled */
2228 if (priv->optimized_view)
2229 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2231 case TOOLBAR_MODE_TRANSFER:
2233 gtk_action_set_visible (sort_action, FALSE);
2235 gtk_action_set_visible (refresh_action, FALSE);
2237 gtk_action_set_visible (cancel_action, TRUE);
2238 if (priv->progress_bar)
2239 gtk_widget_show (priv->progress_bar);
2240 if (priv->progress_toolitem) {
2241 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2242 gtk_widget_show (priv->progress_toolitem);
2245 /* Show toolbar if it's hiden (optimized view ) */
2246 if (priv->optimized_view)
2247 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2250 g_return_if_reached ();
2255 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2257 ModestMainWindowPrivate *priv;
2259 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2260 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2262 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2266 cancel_progressbar (GtkToolButton *toolbutton,
2267 ModestMainWindow *self)
2270 ModestMainWindowPrivate *priv;
2272 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2274 /* Get operation observers and cancel all the operations */
2275 tmp = priv->progress_widgets;
2277 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2278 tmp=g_slist_next(tmp);
2283 observers_empty (ModestMainWindow *self)
2286 ModestMainWindowPrivate *priv;
2287 gboolean is_empty = TRUE;
2288 guint pending_ops = 0;
2290 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2291 tmp = priv->progress_widgets;
2293 /* Check all observers */
2294 while (tmp && is_empty) {
2295 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2296 is_empty = pending_ops == 0;
2298 tmp = g_slist_next(tmp);
2306 * Gets the toolbar mode needed for each mail operation. It stores in
2307 * @mode_changed if the toolbar mode has changed or not
2309 static ModestToolBarModes
2310 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2311 ModestMailOperation *mail_op,
2312 gboolean *mode_changed)
2314 ModestToolBarModes mode;
2315 ModestMainWindowPrivate *priv;
2317 *mode_changed = FALSE;
2318 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2320 /* Get toolbar mode from operation id*/
2321 switch (modest_mail_operation_get_type_operation (mail_op)) {
2322 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2323 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2324 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2325 mode = TOOLBAR_MODE_TRANSFER;
2326 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2327 *mode_changed = TRUE;
2330 mode = TOOLBAR_MODE_NORMAL;
2336 on_mail_operation_started (ModestMailOperation *mail_op,
2339 ModestMainWindow *self;
2340 ModestMailOperationTypeOperation op_type;
2341 ModestMainWindowPrivate *priv;
2342 ModestToolBarModes mode;
2344 gboolean mode_changed = FALSE;
2345 TnyAccount *account = NULL;
2347 self = MODEST_MAIN_WINDOW (user_data);
2348 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2350 /* Do not show progress for receiving operations if the
2351 account is the local account or the MMC one */
2352 op_type = modest_mail_operation_get_type_operation (mail_op);
2353 account = modest_mail_operation_get_account (mail_op);
2354 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2357 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2358 modest_tny_account_is_memory_card_account (account));
2360 g_object_unref (account);
2364 /* Show information banner. Remove old timeout */
2365 if (priv->retrieving_banner_timeout > 0) {
2366 g_source_remove (priv->retrieving_banner_timeout);
2367 priv->retrieving_banner_timeout = 0;
2369 /* Create a new timeout */
2370 priv->retrieving_banner_timeout =
2371 g_timeout_add (2000, show_retrieving_banner, self);
2374 /* Not every mail operation has account, noop does not */
2376 g_object_unref (account);
2378 /* Get toolbar mode from operation id*/
2379 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2381 /* Add operation observers and change toolbar if neccessary*/
2382 tmp = priv->progress_widgets;
2383 if (mode == TOOLBAR_MODE_TRANSFER) {
2385 GObject *source = modest_mail_operation_get_source(mail_op);
2386 if (G_OBJECT (self) == source) {
2387 set_toolbar_transfer_mode(self);
2389 g_object_unref (source);
2393 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2395 tmp = g_slist_next (tmp);
2399 /* Update the main menu as well, we need to explicitely do
2400 this in order to enable/disable accelerators */
2401 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2405 on_mail_operation_finished (ModestMailOperation *mail_op,
2408 ModestToolBarModes mode;
2409 ModestMailOperationTypeOperation op_type;
2411 ModestMainWindow *self;
2412 gboolean mode_changed;
2413 TnyAccount *account = NULL;
2414 ModestMainWindowPrivate *priv;
2416 self = MODEST_MAIN_WINDOW (user_data);
2417 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2419 /* The mail operation was not added to the progress objects if
2420 the account was the local account or the MMC one */
2421 op_type = modest_mail_operation_get_type_operation (mail_op);
2422 account = modest_mail_operation_get_account (mail_op);
2423 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2426 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2427 modest_tny_account_is_memory_card_account (account));
2429 g_object_unref (account);
2433 /* Remove old timeout */
2434 if (priv->retrieving_banner_timeout > 0) {
2435 g_source_remove (priv->retrieving_banner_timeout);
2436 priv->retrieving_banner_timeout = 0;
2439 /* Remove the banner if exists */
2440 if (priv->retrieving_banner) {
2441 gtk_widget_destroy (priv->retrieving_banner);
2442 priv->retrieving_banner = NULL;
2446 /* Not every mail operation has account, noop does not */
2448 g_object_unref (account);
2450 /* Get toolbar mode from operation id*/
2451 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2453 /* Change toolbar mode */
2454 tmp = priv->progress_widgets;
2455 if (mode == TOOLBAR_MODE_TRANSFER) {
2457 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2459 tmp = g_slist_next (tmp);
2462 /* If no more operations are being observed, NORMAL mode is enabled again */
2463 if (observers_empty (self)) {
2464 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2470 on_queue_changed (ModestMailOperationQueue *queue,
2471 ModestMailOperation *mail_op,
2472 ModestMailOperationQueueNotification type,
2473 ModestMainWindow *self)
2475 ModestMainWindowPrivate *priv;
2477 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2479 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2480 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2482 "operation-started",
2483 G_CALLBACK (on_mail_operation_started),
2485 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2487 "operation-finished",
2488 G_CALLBACK (on_mail_operation_finished),
2490 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2491 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2493 "operation-started");
2494 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2496 "operation-finished");
2501 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2503 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2505 ModestAccountMgr *mgr;
2506 ModestAccountSettings *settings;
2507 ModestServerAccountSettings *store_settings = NULL;
2509 /* Get account data */
2510 mgr = modest_runtime_get_account_mgr ();
2511 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2513 store_settings = modest_account_settings_get_store_settings (settings);
2515 /* Set the new visible & active account */
2516 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2517 const gchar *account_name;
2519 account_name = modest_account_settings_get_account_name (settings);
2521 modest_folder_view_set_account_id_of_visible_server_account
2523 modest_server_account_settings_get_account_name (store_settings));
2524 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2525 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2526 if (action != NULL) {
2527 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2528 modest_utils_toggle_action_set_active_block_notify (
2529 GTK_TOGGLE_ACTION (action),
2535 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2540 g_object_unref (store_settings);
2541 g_object_unref (settings);
2545 /* Make sure that at least one account is "viewed": */
2547 set_at_least_one_account_visible(ModestMainWindow *self)
2549 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2550 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2552 if (!(priv->folder_view)) {
2553 /* It is too early to do this. */
2557 const gchar *active_server_account_name =
2558 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2560 if (!active_server_account_name ||
2561 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2563 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2564 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2565 if (default_modest_name) {
2566 set_account_visible (self, default_modest_name);
2567 } else if (first_modest_name) {
2568 set_account_visible (self, first_modest_name);
2570 g_free (first_modest_name);
2571 g_free (default_modest_name);
2576 on_show_account_action_toggled (GtkToggleAction *action,
2579 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2581 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2582 if (gtk_toggle_action_get_active (action))
2583 set_account_visible (self, acc_name);
2587 refresh_account (const gchar *account_name)
2591 /* win must already exists here, obviously */
2592 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2595 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2599 /* If account_name == NULL, we must update all (option All) */
2601 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2603 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2608 on_refresh_account_action_activated (GtkAction *action,
2611 refresh_account ((const gchar*) user_data);
2615 on_send_receive_csm_activated (GtkMenuItem *item,
2618 refresh_account ((const gchar*) user_data);
2622 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2624 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2626 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2632 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2634 ModestMainWindow *main_window = NULL;
2636 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2637 main_window = MODEST_MAIN_WINDOW (userdata);
2639 /* Update toolbar dimming state */
2640 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2641 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2647 on_header_view_focus_in (GtkWidget *widget,
2648 GdkEventFocus *event,
2651 ModestMainWindow *main_window = NULL;
2653 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2655 main_window = MODEST_MAIN_WINDOW (userdata);
2657 /* Update toolbar dimming state */
2658 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2659 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2665 on_folder_selection_changed (ModestFolderView *folder_view,
2666 TnyFolderStore *folder_store,
2668 ModestMainWindow *main_window)
2670 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2671 GtkAction *action = NULL;
2672 gboolean show_reply = TRUE;
2673 gboolean show_forward = TRUE;
2674 gboolean show_cancel_send = FALSE;
2675 gboolean show_clipboard = TRUE;
2676 gboolean show_delete = TRUE;
2679 if (TNY_IS_ACCOUNT (folder_store)) {
2680 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2681 } else if (TNY_IS_FOLDER (folder_store)) {
2682 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2683 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2684 TNY_FOLDER (folder_store));
2685 switch (folder_type) {
2686 case TNY_FOLDER_TYPE_DRAFTS:
2687 show_clipboard = show_delete = TRUE;
2688 show_reply = show_forward = show_cancel_send = FALSE;
2690 case TNY_FOLDER_TYPE_SENT:
2691 show_forward = show_clipboard = show_delete = TRUE;
2692 show_reply = show_cancel_send = FALSE;
2694 case TNY_FOLDER_TYPE_OUTBOX:
2695 show_clipboard = show_delete = show_cancel_send = TRUE;
2696 show_reply = show_forward = FALSE;
2698 case TNY_FOLDER_TYPE_INVALID:
2699 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2702 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2703 show_cancel_send = FALSE;
2706 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2707 show_cancel_send = FALSE;
2712 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2713 gtk_action_set_visible (action, show_reply);
2714 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2715 gtk_action_set_visible (action, show_reply);
2716 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2717 gtk_action_set_visible (action, show_forward);
2718 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2719 gtk_action_set_visible (action, show_cancel_send);
2720 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2721 gtk_action_set_visible (action, show_delete);
2723 /* We finally call to the ui actions handler, after updating properly
2724 * the header view CSM */
2725 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2729 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2730 GtkTreeModel *model,
2731 GtkTreeRowReference *row_reference,
2732 ModestMainWindow *self)
2734 ModestMainWindowPrivate *priv = NULL;
2735 GtkTreeModel *header_model = NULL;
2736 GtkTreePath *path = NULL;
2738 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2739 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2740 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2742 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2743 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2745 /* Do nothing if we changed the folder in the main view */
2746 if (header_model != model)
2749 /* Select the message in the header view */
2750 path = gtk_tree_row_reference_get_path (row_reference);
2751 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2753 gtk_tree_path_free (path);
2759 show_updating_banner (gpointer user_data)
2761 ModestMainWindowPrivate *priv = NULL;
2763 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2765 if (priv->updating_banner == NULL) {
2767 /* We're outside the main lock */
2768 gdk_threads_enter ();
2769 priv->updating_banner =
2770 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2771 _CS ("ckdg_pb_updating"));
2772 gdk_threads_leave ();
2775 /* Remove timeout */
2776 priv->updating_banner_timeout = 0;
2781 * We use this function to show/hide a progress banner showing
2782 * "Updating" while the header view is being filled. We're not showing
2783 * it unless the update takes more than 2 seconds
2785 * If starting = TRUE then the refresh is starting, otherwise it means
2786 * that is has just finished
2789 on_updating_msg_list (ModestHeaderView *header_view,
2793 ModestMainWindowPrivate *priv = NULL;
2795 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2797 /* Remove old timeout */
2798 if (priv->updating_banner_timeout > 0) {
2799 g_source_remove (priv->updating_banner_timeout);
2800 priv->updating_banner_timeout = 0;
2803 /* Create a new timeout */
2805 priv->updating_banner_timeout =
2806 g_timeout_add (2000, show_updating_banner, user_data);
2808 /* Remove the banner if exists */
2809 if (priv->updating_banner) {
2810 gtk_widget_destroy (priv->updating_banner);
2811 priv->updating_banner = NULL;
2817 modest_main_window_screen_is_on (ModestMainWindow *self)
2819 ModestMainWindowPrivate *priv = NULL;
2821 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2823 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2825 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2829 remove_banners (ModestMainWindow *window)
2831 ModestMainWindowPrivate *priv;
2833 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2835 if (priv->retrieving_banner_timeout > 0) {
2836 g_source_remove (priv->retrieving_banner_timeout);
2837 priv->retrieving_banner_timeout = 0;
2840 if (priv->retrieving_banner != NULL) {
2841 gtk_widget_destroy (priv->retrieving_banner);
2842 priv->retrieving_banner = NULL;
2845 if (priv->updating_banner_timeout > 0) {
2846 g_source_remove (priv->updating_banner_timeout);
2847 priv->updating_banner_timeout = 0;
2850 if (priv->updating_banner != NULL) {
2851 gtk_widget_destroy (priv->updating_banner);
2852 priv->updating_banner = NULL;
2858 on_window_hide (GObject *gobject,
2862 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2864 if (!GTK_WIDGET_VISIBLE (gobject)) {
2865 TnyFolderStore *folder_store;
2866 ModestMainWindowPrivate *priv;
2868 /* Remove the currently shown banners */
2869 remove_banners (MODEST_MAIN_WINDOW (gobject));
2871 /* Force the folder view to sync the currently selected folder
2872 to save the read/unread status and to expunge messages */
2873 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2874 folder_store = modest_folder_view_get_selected (priv->folder_view);
2875 if (TNY_IS_FOLDER (folder_store)) {
2876 ModestMailOperation *mail_op;
2878 mail_op = modest_mail_operation_new (NULL);
2879 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2881 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2882 g_object_unref (mail_op);
2888 on_window_destroy (GtkObject *widget,
2891 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2893 remove_banners (MODEST_MAIN_WINDOW (widget));
2897 show_retrieving_banner (gpointer user_data)
2899 ModestMainWindowPrivate *priv = NULL;
2901 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2903 if (priv->retrieving_banner == NULL) {
2905 /* We're outside the main lock */
2906 gdk_threads_enter ();
2907 priv->retrieving_banner =
2908 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2909 _("mcen_ib_getting_items"));
2910 gdk_threads_leave ();
2913 /* Remove timeout */
2914 priv->retrieving_banner_timeout = 0;