1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-utils.h>
57 #include <modest-maemo-utils.h>
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-mail-operation.h"
61 #include "modest-icon-names.h"
62 #include "modest-progress-bar.h"
63 #include "modest-text-utils.h"
64 #include "modest-ui-dimming-manager.h"
65 #include "maemo/modest-osso-state-saving.h"
66 #include "modest-text-utils.h"
67 #include "modest-signal-mgr.h"
69 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
76 /* 'private'/'protected' functions */
77 static void modest_main_window_class_init (ModestMainWindowClass *klass);
78 static void modest_main_window_init (ModestMainWindow *obj);
79 static void modest_main_window_finalize (GObject *obj);
81 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
82 GdkEventWindowState *event,
85 static void connect_signals (ModestMainWindow *self);
87 static void modest_main_window_disconnect_signals (ModestWindow *self);
89 static void restore_settings (ModestMainWindow *self,
90 gboolean do_folder_view_too);
92 static void save_state (ModestWindow *self);
94 static void update_menus (ModestMainWindow* self);
96 static void modest_main_window_show_toolbar (ModestWindow *window,
97 gboolean show_toolbar);
99 static void cancel_progressbar (GtkToolButton *toolbutton,
100 ModestMainWindow *self);
102 static void on_queue_changed (ModestMailOperationQueue *queue,
103 ModestMailOperation *mail_op,
104 ModestMailOperationQueueNotification type,
105 ModestMainWindow *self);
107 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
109 static void on_account_inserted (TnyAccountStore *accoust_store,
113 static void on_account_removed (TnyAccountStore *accoust_store,
117 static void on_account_changed (TnyAccountStore *account_store,
121 static void on_default_account_changed (ModestAccountMgr* mgr,
124 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
128 static void on_configuration_key_changed (ModestConf* conf,
130 ModestConfEvent event,
131 ModestConfNotificationId id,
132 ModestMainWindow *self);
134 static void set_toolbar_mode (ModestMainWindow *self,
135 ModestToolBarModes mode);
137 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
139 static void on_show_account_action_toggled (GtkToggleAction *action,
142 static void on_refresh_account_action_activated (GtkAction *action,
145 static void on_send_receive_csm_activated (GtkMenuItem *item,
148 static void on_msg_count_changed (ModestHeaderView *header_view,
150 TnyFolderChange *change,
151 ModestMainWindow *main_window);
153 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
156 static GtkWidget * create_empty_view (void);
158 static gboolean on_folder_view_focus_in (GtkWidget *widget,
159 GdkEventFocus *event,
162 static gboolean on_header_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static void on_folder_selection_changed (ModestFolderView *folder_view,
167 TnyFolderStore *folder_store,
169 ModestMainWindow *main_window);
171 static void set_at_least_one_account_visible(ModestMainWindow *self);
173 static void on_updating_msg_list (ModestHeaderView *header_view,
177 static gboolean restore_paned_timeout_handler (gpointer *data);
179 static gboolean show_retrieving_banner (gpointer user_data);
181 static void on_window_destroy (GtkObject *widget,
184 static void on_window_hide (GObject *gobject,
188 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
189 struct _ModestMainWindowPrivate {
190 GtkWidget *msg_paned;
191 GtkWidget *main_paned;
192 GtkWidget *main_vbox;
193 GtkWidget *contents_widget;
194 GtkWidget *empty_view;
196 /* Progress observers */
197 GtkWidget *progress_bar;
198 GSList *progress_widgets;
201 GtkWidget *progress_toolitem;
202 GtkWidget *cancel_toolitem;
203 GtkWidget *sort_toolitem;
204 GtkWidget *refresh_toolitem;
205 ModestToolBarModes current_toolbar_mode;
207 /* Merge ids used to add/remove accounts to the ViewMenu*/
208 GByteArray *merge_ids;
209 GtkActionGroup *view_additions_group;
211 /* On-demand widgets */
212 GtkWidget *accounts_popup;
213 GtkWidget *details_widget;
215 /* Optimized view enabled */
216 gboolean optimized_view;
218 /* Optimized view enabled */
219 gboolean send_receive_in_progress;
221 ModestHeaderView *header_view;
222 ModestFolderView *folder_view;
224 ModestMainWindowStyle style;
225 ModestMainWindowContentsStyle contents_style;
226 gboolean wait_for_settings;
228 guint progress_bar_timeout;
229 guint restore_paned_timeout;
231 /* Signal handler UIDs */
232 GList *queue_err_signals;
235 /* "Updating" banner for header view */
236 GtkWidget *updating_banner;
237 guint updating_banner_timeout;
239 /* "Retrieving" banner for header view */
240 GtkWidget *retrieving_banner;
241 guint retrieving_banner_timeout;
244 osso_display_state_t display_state;
246 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
247 MODEST_TYPE_MAIN_WINDOW, \
248 ModestMainWindowPrivate))
250 typedef struct _GetMsgAsyncHelper {
251 ModestMainWindowPrivate *main_window_private;
253 ModestTnyMsgReplyType reply_type;
254 ModestTnyMsgForwardType forward_type;
261 static GtkWindowClass *parent_class = NULL;
264 /* Private actions */
265 /* This is the context sensitive menu: */
266 static const GtkActionEntry modest_folder_view_action_entries [] = {
268 /* Folder View CSM actions */
269 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
270 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
271 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
272 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
273 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
274 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
277 static const GtkActionEntry modest_header_view_action_entries [] = {
279 /* Header View CSM actions */
280 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
281 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
282 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
283 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
284 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
285 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
286 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
287 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
288 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
289 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
292 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
293 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
296 /************************************************************************/
299 modest_main_window_get_type (void)
301 static GType my_type = 0;
303 static const GTypeInfo my_info = {
304 sizeof(ModestMainWindowClass),
305 NULL, /* base init */
306 NULL, /* base finalize */
307 (GClassInitFunc) modest_main_window_class_init,
308 NULL, /* class finalize */
309 NULL, /* class data */
310 sizeof(ModestMainWindow),
312 (GInstanceInitFunc) modest_main_window_init,
315 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
323 modest_main_window_class_init (ModestMainWindowClass *klass)
325 GObjectClass *gobject_class;
326 gobject_class = (GObjectClass*) klass;
327 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
329 parent_class = g_type_class_peek_parent (klass);
330 gobject_class->finalize = modest_main_window_finalize;
332 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
334 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
335 modest_window_class->save_state_func = save_state;
336 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
337 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
338 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
342 modest_main_window_init (ModestMainWindow *obj)
344 ModestMainWindowPrivate *priv;
346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
348 priv->queue_err_signals = NULL;
349 priv->msg_paned = NULL;
350 priv->main_paned = NULL;
351 priv->main_vbox = NULL;
352 priv->header_view = NULL;
353 priv->folder_view = NULL;
354 priv->contents_widget = NULL;
355 priv->accounts_popup = NULL;
356 priv->details_widget = NULL;
357 priv->empty_view = NULL;
358 priv->progress_widgets = NULL;
359 priv->progress_bar = NULL;
360 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
361 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
362 priv->wait_for_settings = TRUE;
363 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
364 priv->merge_ids = NULL;
365 priv->optimized_view = FALSE;
366 priv->send_receive_in_progress = FALSE;
367 priv->progress_bar_timeout = 0;
368 priv->restore_paned_timeout = 0;
369 priv->sighandlers = NULL;
370 priv->updating_banner = NULL;
371 priv->updating_banner_timeout = 0;
372 priv->retrieving_banner = NULL;
373 priv->retrieving_banner_timeout = 0;
374 priv->display_state = OSSO_DISPLAY_ON;
376 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
378 "applications_email_mainview");
382 modest_main_window_finalize (GObject *obj)
384 ModestMainWindowPrivate *priv;
386 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
388 /* Sanity check: shouldn't be needed, the window mgr should
389 call this function before */
390 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
391 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
393 g_slist_free (priv->progress_widgets);
395 g_byte_array_free (priv->merge_ids, TRUE);
397 if (priv->progress_bar_timeout > 0) {
398 g_source_remove (priv->progress_bar_timeout);
399 priv->progress_bar_timeout = 0;
402 if (priv->updating_banner_timeout > 0) {
403 g_source_remove (priv->updating_banner_timeout);
404 priv->updating_banner_timeout = 0;
407 if (priv->updating_banner) {
408 gtk_widget_destroy (priv->updating_banner);
409 priv->updating_banner = NULL;
412 if (priv->retrieving_banner_timeout > 0) {
413 g_source_remove (priv->retrieving_banner_timeout);
414 priv->retrieving_banner_timeout = 0;
417 if (priv->retrieving_banner) {
418 gtk_widget_destroy (priv->retrieving_banner);
419 priv->retrieving_banner = NULL;
422 if (priv->restore_paned_timeout > 0) {
423 g_source_remove (priv->restore_paned_timeout);
424 priv->restore_paned_timeout = 0;
427 G_OBJECT_CLASS(parent_class)->finalize (obj);
431 modest_main_window_get_child_widget (ModestMainWindow *self,
432 ModestMainWindowWidgetType widget_type)
434 ModestMainWindowPrivate *priv;
437 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
438 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
441 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
443 switch (widget_type) {
444 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
445 widget = (GtkWidget*)priv->header_view; break;
446 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
447 widget = (GtkWidget*)priv->folder_view; break;
452 /* Note that the window could have been destroyed, and so
453 their children, but still have some references */
454 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
458 restore_paned_timeout_handler (gpointer *data)
460 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
461 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
464 /* Timeouts are outside the main lock */
465 gdk_threads_enter ();
466 if (GTK_WIDGET_VISIBLE (main_window)) {
467 conf = modest_runtime_get_conf ();
468 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
469 MODEST_CONF_MAIN_PANED_KEY);
471 gdk_threads_leave ();
478 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
485 conf = modest_runtime_get_conf ();
487 modest_widget_memory_restore (conf, G_OBJECT(self),
488 MODEST_CONF_MAIN_WINDOW_KEY);
490 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
491 MODEST_CONF_HEADER_VIEW_KEY);
493 if (do_folder_view_too)
494 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
495 MODEST_CONF_FOLDER_VIEW_KEY);
497 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
498 /* MODEST_CONF_MAIN_PANED_KEY); */
500 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
502 /* We need to force a redraw here in order to get the right
503 position of the horizontal paned separator */
504 gtk_widget_show (GTK_WIDGET (self));
509 save_state (ModestWindow *window)
512 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
513 ModestMainWindowPrivate *priv;
515 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
516 conf = modest_runtime_get_conf ();
518 modest_widget_memory_save (conf,G_OBJECT(self),
519 MODEST_CONF_MAIN_WINDOW_KEY);
520 /* Only save main paned position if we're in split mode */
521 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
522 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
523 MODEST_CONF_MAIN_PANED_KEY);
524 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
525 MODEST_CONF_FOLDER_VIEW_KEY);
529 compare_display_names (ModestAccountSettings *a,
530 ModestAccountSettings *b)
532 return strcmp (modest_account_settings_get_display_name (a),
533 modest_account_settings_get_display_name (b));
536 /* We use this function to prevent the send&receive CSM to be shown
537 when there are less than two account */
539 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
545 update_menus (ModestMainWindow* self)
547 GSList *account_names, *iter, *accounts;
548 ModestMainWindowPrivate *priv;
549 ModestWindowPrivate *parent_priv;
550 ModestAccountMgr *mgr;
551 gint i, num_accounts;
553 gchar *default_account;
554 const gchar *active_account_name;
555 GtkWidget *send_receive_button, *item;
556 GtkAction *send_receive_all = NULL;
559 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
560 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
562 /* Get enabled account IDs */
563 mgr = modest_runtime_get_account_mgr ();
564 account_names = modest_account_mgr_account_names (mgr, TRUE);
565 iter = account_names;
569 ModestAccountSettings *settings =
570 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
571 accounts = g_slist_prepend (accounts, settings);
575 modest_account_mgr_free_account_names (account_names);
576 account_names = NULL;
578 /* Order the list of accounts by its display name */
579 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
580 num_accounts = g_slist_length (accounts);
582 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
583 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
584 gtk_action_set_visible (send_receive_all, num_accounts > 0);
586 /* Delete old send&receive popup items. We can not just do a
587 menu_detach because it does not work well with
589 if (priv->accounts_popup)
590 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
591 (GtkCallback) gtk_widget_destroy, NULL);
593 /* Delete old entries in the View menu. Do not free groups, it
595 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
597 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
598 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
599 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
600 GTK_ACTION_GROUP (groups->data));
603 if (priv->merge_ids) {
604 for (i = 0; i < priv->merge_ids->len; i++)
605 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
606 g_byte_array_free (priv->merge_ids, TRUE);
608 /* We need to call this in order to ensure
609 that the new actions are added in the right
610 order (alphabetical) */
611 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
613 groups = g_list_next (groups);
615 priv->merge_ids = g_byte_array_sized_new (num_accounts);
617 /* Get send receive button */
618 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
619 "/ToolBar/ToolbarSendReceive");
621 /* Create the menu */
622 if (num_accounts > 1) {
623 if (!priv->accounts_popup)
624 priv->accounts_popup = gtk_menu_new ();
625 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
626 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
627 g_signal_connect (G_OBJECT (item),
629 G_CALLBACK (on_send_receive_csm_activated),
631 item = gtk_separator_menu_item_new ();
632 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
635 /* Create a new action group */
636 default_account = modest_account_mgr_get_default_account (mgr);
637 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
639 if (!active_account_name)
640 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
642 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
644 for (i = 0; i < num_accounts; i++) {
645 gchar *display_name = NULL;
646 const gchar *account_name;
647 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
650 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
653 account_name = modest_account_settings_get_account_name (settings);
655 if (default_account && account_name &&
656 !(strcmp (default_account, account_name) == 0)) {
657 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
658 modest_account_settings_get_display_name (settings));
660 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
661 modest_account_settings_get_display_name (settings));
666 /* Create action and add it to the action group. The
667 action name must be the account name, this way we
668 could know in the handlers the account to show */
669 if (settings && account_name) {
670 gchar* item_name, *refresh_action_name;
672 GtkAction *view_account_action, *refresh_account_action;
673 gchar *escaped_display_name;
675 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
677 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
678 escaped_display_name, NULL, NULL, 0));
679 g_free (escaped_display_name);
680 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
681 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
682 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
684 if (active_account_name) {
685 if (active_account_name && account_name &&
686 (strcmp (active_account_name, account_name) == 0)) {
687 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
691 /* Add ui from account data. We allow 2^9-1 account
692 changes in a single execution because we're
693 downcasting the guint to a guint8 in order to use a
694 GByteArray. It should be enough. */
695 item_name = g_strconcat (account_name, "Menu", NULL);
696 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
697 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
698 gtk_ui_manager_add_ui (parent_priv->ui_manager,
700 "/MenuBar/ViewMenu/ViewMenuAdditions",
703 GTK_UI_MANAGER_MENUITEM,
706 /* Connect the action signal "activate" */
707 g_signal_connect_after (G_OBJECT (view_account_action),
709 G_CALLBACK (on_show_account_action_toggled),
712 /* Create the items for the Tools->Send&Receive submenu */
713 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
714 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
715 display_name, NULL, NULL);
716 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
718 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
719 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
720 gtk_ui_manager_add_ui (parent_priv->ui_manager,
722 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
725 GTK_UI_MANAGER_MENUITEM,
727 g_free (refresh_action_name);
729 g_signal_connect_data (G_OBJECT (refresh_account_action),
731 G_CALLBACK (on_refresh_account_action_activated),
732 g_strdup (account_name),
733 (GClosureNotify) g_free,
736 /* Create item and add it to the send&receive
737 CSM. If there is only one account then
739 if (num_accounts > 1) {
740 GtkWidget *label = gtk_label_new(NULL);
741 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
742 if (default_account && (strcmp(account_name, default_account) == 0)) {
743 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
744 gtk_label_set_markup (GTK_LABEL (label), escaped);
747 gtk_label_set_text (GTK_LABEL (label), display_name);
750 item = gtk_menu_item_new ();
751 gtk_container_add (GTK_CONTAINER (item), label);
753 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
754 g_signal_connect_data (G_OBJECT (item),
756 G_CALLBACK (on_send_receive_csm_activated),
757 g_strdup (account_name),
758 (GClosureNotify) g_free,
765 g_free (display_name);
768 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
770 /* We cannot do this in the loop above because this relies on the action
771 * group being inserted. This makes the default account appear in bold.
772 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
773 for (i = 0; i < num_accounts; i++) {
774 gchar *item_name, *path;
776 ModestAccountSettings *settings;
777 const gchar *account_name;
780 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
781 account_name = modest_account_settings_get_account_name (settings);
782 is_default = (account_name && default_account && !strcmp (account_name, default_account));
784 /* Get the item of the view menu */
785 item_name = g_strconcat (account_name, "Menu", NULL);
786 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
787 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
791 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
792 if (GTK_IS_LABEL (child)) {
793 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
795 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
796 gtk_label_set_markup (GTK_LABEL (child), bold_name);
799 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
803 /* Get the item of the tools menu */
804 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
805 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
809 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
810 if (GTK_IS_LABEL (child)) {
811 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
813 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
814 gtk_label_set_markup (GTK_LABEL (child), bold_name);
817 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
822 g_object_unref (settings);
825 if (num_accounts > 1) {
826 /* Disconnect the tap-and-hold-query if it's connected */
827 if (modest_signal_mgr_is_connected (priv->sighandlers,
828 G_OBJECT (send_receive_button),
829 "tap-and-hold-query"))
830 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
831 G_OBJECT (send_receive_button),
832 "tap-and-hold-query");
834 /* Mandatory in order to view the menu contents */
835 gtk_widget_show_all (priv->accounts_popup);
837 /* Setup tap_and_hold just if was not done before*/
838 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
839 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
841 /* Connect the tap-and-hold-query in order not to show the CSM */
842 if (!modest_signal_mgr_is_connected (priv->sighandlers,
843 G_OBJECT (send_receive_button),
844 "tap-and-hold-query"))
845 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
846 G_OBJECT (send_receive_button),
847 "tap-and-hold-query",
848 G_CALLBACK (tap_and_hold_query_cb),
853 g_slist_free (accounts);
854 g_free (default_account);
857 /* Make sure that at least one account is viewed if there are any
858 * accounts, for instance when adding the first account: */
859 set_at_least_one_account_visible (self);
863 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
865 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
866 gtk_scrolled_window_add_with_viewport
867 (GTK_SCROLLED_WINDOW(win), widget);
869 gtk_container_add (GTK_CONTAINER(win),
880 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
882 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
884 GList *oerrsignals = priv->queue_err_signals;
885 while (oerrsignals) {
886 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
887 g_signal_handler_disconnect (esignal->queue, esignal->signal);
888 g_slice_free (QueueErrorSignal, esignal);
889 oerrsignals = g_list_next (oerrsignals);
891 g_list_free (priv->queue_err_signals);
892 priv->queue_err_signals = NULL;
897 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
899 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
902 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
906 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
908 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
910 /* Update visibility */
913 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
917 modest_main_window_disconnect_signals (ModestWindow *self)
919 ModestMainWindowPrivate *priv;
920 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
922 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
923 priv->sighandlers = NULL;
927 connect_signals (ModestMainWindow *self)
929 ModestWindowPrivate *parent_priv;
930 ModestMainWindowPrivate *priv;
933 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
934 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
939 modest_signal_mgr_connect (priv->sighandlers,
940 G_OBJECT(priv->folder_view), "key-press-event",
941 G_CALLBACK(on_inner_widgets_key_pressed), self);
943 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
944 "folder_selection_changed",
945 G_CALLBACK (on_folder_selection_changed),
948 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
949 "folder-display-name-changed",
950 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
953 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
955 G_CALLBACK (on_folder_view_focus_in),
958 /* Folder view CSM */
959 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
960 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
961 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
962 G_CALLBACK(_folder_view_csm_menu_activated),
966 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
967 G_CALLBACK(modest_ui_actions_on_header_selected), self);
969 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
970 G_CALLBACK(modest_ui_actions_on_header_activated), self);
972 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
973 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
975 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
976 G_CALLBACK(on_inner_widgets_key_pressed), self);
978 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
979 G_CALLBACK(on_msg_count_changed), self);
981 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
982 G_CALLBACK (on_header_view_focus_in), self);
984 modest_signal_mgr_connect (priv->sighandlers,
985 G_OBJECT (priv->header_view),
987 G_CALLBACK (on_updating_msg_list),
990 /* Header view CSM */
991 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
992 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
994 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
995 G_CALLBACK(_header_view_csm_menu_activated),
1000 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1001 G_CALLBACK (modest_main_window_window_state_event),
1003 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1004 * in destroy stage */
1005 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1007 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1009 /* Mail Operation Queue */
1011 modest_signal_mgr_connect (priv->sighandlers,
1012 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1014 G_CALLBACK (on_queue_changed), self);
1016 /* Track changes in the device name */
1018 modest_signal_mgr_connect (priv->sighandlers,
1019 G_OBJECT(modest_runtime_get_conf ()),
1021 G_CALLBACK (on_configuration_key_changed),
1024 /* Track account changes. We need to refresh the toolbar */
1026 modest_signal_mgr_connect (priv->sighandlers,
1027 G_OBJECT (modest_runtime_get_account_store ()),
1029 G_CALLBACK (on_account_inserted),
1032 modest_signal_mgr_connect (priv->sighandlers,
1033 G_OBJECT (modest_runtime_get_account_store ()),
1035 G_CALLBACK (on_account_removed),
1038 /* We need to refresh the send & receive menu to change the bold
1039 * account when the default account changes. */
1041 modest_signal_mgr_connect (priv->sighandlers,
1042 G_OBJECT (modest_runtime_get_account_mgr ()),
1043 "default_account_changed",
1044 G_CALLBACK (on_default_account_changed),
1049 modest_signal_mgr_connect (priv->sighandlers,
1050 G_OBJECT (modest_runtime_get_account_store ()),
1052 G_CALLBACK (on_account_changed),
1056 modest_signal_mgr_connect (priv->sighandlers,
1057 G_OBJECT (modest_runtime_get_account_store()),
1058 "password_requested",
1059 G_CALLBACK (modest_ui_actions_on_password_requested),
1064 on_hildon_program_is_topmost_notify(GObject *self,
1065 GParamSpec *propert_param,
1068 HildonProgram *app = HILDON_PROGRAM (self);
1070 /* Note that use of hildon_program_set_can_hibernate()
1071 * is generally referred to as "setting the killable flag",
1072 * though hibernation does not seem equal to death.
1075 if (hildon_program_get_is_topmost (app)) {
1076 /* Prevent hibernation when the progam comes to the foreground,
1077 * because hibernation should only happen when the application
1078 * is in the background: */
1079 hildon_program_set_can_hibernate (app, FALSE);
1081 /* Remove new mail visual notifications */
1082 modest_platform_remove_new_mail_notifications (TRUE);
1084 /* Allow hibernation if the program has gone to the background: */
1086 /* However, prevent hibernation while the settings are being changed: */
1087 const gboolean hibernation_prevented =
1088 modest_window_mgr_get_hibernation_is_prevented (
1089 modest_runtime_get_window_mgr ());
1091 if (hibernation_prevented)
1092 hildon_program_set_can_hibernate (app, FALSE);
1094 /* Allow hibernation, after saving the state: */
1095 modest_osso_save_state();
1096 hildon_program_set_can_hibernate (app, TRUE);
1102 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1104 GtkWidget *folder_win = (GtkWidget *) user_data;
1105 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1107 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1108 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1110 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1112 /* Connect signals */
1113 connect_signals (MODEST_MAIN_WINDOW (self));
1115 /* Set account store */
1116 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1117 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1119 /* Load previous osso state, for instance if we are being restored from
1121 modest_osso_load_state ();
1123 /* Restore window & widget settings */
1124 priv->wait_for_settings = TRUE;
1125 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1126 priv->wait_for_settings = FALSE;
1128 /* Check if accounts exist and show the account wizard if not */
1129 gboolean accounts_exist =
1130 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1132 if (!accounts_exist) {
1133 /* This is necessary to have the main window shown behind the dialog
1134 It's an ugly hack... jschmid */
1135 gtk_widget_show_all(GTK_WIDGET(self));
1136 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1139 GtkAction *send_receive_all;
1140 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1141 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1142 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1143 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1144 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1145 modest_account_mgr_free_account_names (accounts);
1146 update_menus (MODEST_MAIN_WINDOW (self));
1151 osso_display_event_cb (osso_display_state_t state,
1154 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1156 priv->display_state = state;
1158 /* Stop blinking if the screen becomes on */
1159 if (priv->display_state == OSSO_DISPLAY_ON)
1160 modest_platform_remove_new_mail_notifications (TRUE);
1164 modest_main_window_new (void)
1166 ModestMainWindow *self = NULL;
1167 ModestMainWindowPrivate *priv = NULL;
1168 ModestWindowPrivate *parent_priv = NULL;
1169 GtkWidget *folder_win = NULL;
1170 ModestDimmingRulesGroup *menu_rules_group = NULL;
1171 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1172 GtkActionGroup *action_group = NULL;
1173 GError *error = NULL;
1175 ModestConf *conf = NULL;
1176 GtkAction *action = NULL;
1177 GdkPixbuf *window_icon;
1179 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1180 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1181 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1183 parent_priv->ui_manager = gtk_ui_manager_new();
1184 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1186 action_group = gtk_action_group_new ("ModestMainWindowActions");
1187 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1189 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1190 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1192 /* Add common actions */
1193 gtk_action_group_add_actions (action_group,
1194 modest_action_entries,
1195 G_N_ELEMENTS (modest_action_entries),
1198 gtk_action_group_add_actions (action_group,
1199 modest_folder_view_action_entries,
1200 G_N_ELEMENTS (modest_folder_view_action_entries),
1203 gtk_action_group_add_actions (action_group,
1204 modest_header_view_action_entries,
1205 G_N_ELEMENTS (modest_header_view_action_entries),
1208 gtk_action_group_add_toggle_actions (action_group,
1209 modest_toggle_action_entries,
1210 G_N_ELEMENTS (modest_toggle_action_entries),
1213 gtk_action_group_add_toggle_actions (action_group,
1214 modest_main_window_toggle_action_entries,
1215 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1218 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1219 g_object_unref (action_group);
1221 /* Load the UI definition */
1222 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1223 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1224 if (error != NULL) {
1225 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1226 g_error_free (error);
1230 /* Add common dimming rules */
1231 modest_dimming_rules_group_add_rules (menu_rules_group,
1232 modest_main_window_menu_dimming_entries,
1233 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1234 MODEST_WINDOW (self));
1235 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1236 modest_main_window_toolbar_dimming_entries,
1237 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1238 MODEST_WINDOW (self));
1240 /* Insert dimming rules group for this window */
1241 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1242 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1243 g_object_unref (menu_rules_group);
1244 g_object_unref (toolbar_rules_group);
1246 /* Add accelerators */
1247 gtk_window_add_accel_group (GTK_WINDOW (self),
1248 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1250 /* Menubar. Update the state of some toggles */
1251 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1252 conf = modest_runtime_get_conf ();
1253 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1254 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1255 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1256 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1257 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1258 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1259 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1260 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1261 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1262 gtk_widget_show (parent_priv->menubar);
1264 /* Get device name */
1265 modest_maemo_utils_get_device_name ();
1269 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1270 if (!priv->header_view)
1271 g_printerr ("modest: cannot instantiate header view\n");
1272 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1273 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1274 MODEST_CONF_HEADER_VIEW_KEY);
1276 /* Other style properties of header view */
1277 g_object_set (G_OBJECT (priv->header_view),
1278 "rules-hint", FALSE,
1280 /* gtk_widget_show (priv->header_view); */
1283 priv->empty_view = create_empty_view ();
1284 gtk_widget_show (priv->empty_view);
1286 /* Create scrolled windows */
1287 folder_win = gtk_scrolled_window_new (NULL, NULL);
1288 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1289 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1291 GTK_POLICY_AUTOMATIC);
1292 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1294 GTK_POLICY_AUTOMATIC);
1295 /* gtk_widget_show (priv->contents_widget); */
1298 priv->main_paned = gtk_hpaned_new ();
1299 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1300 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1301 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1303 /* putting it all together... */
1304 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1305 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1306 gtk_widget_show (priv->main_vbox);
1308 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1310 app = hildon_program_get_instance ();
1311 hildon_program_add_window (app, HILDON_WINDOW (self));
1313 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1314 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1316 g_signal_connect (G_OBJECT(self), "show",
1317 G_CALLBACK (modest_main_window_on_show), folder_win);
1319 /* Set window icon */
1320 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1322 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1323 g_object_unref (window_icon);
1326 /* Listen for changes in the screen, we don't want to show a
1327 led pattern when the display is on for example */
1328 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1329 osso_display_event_cb,
1332 /* Dont't restore settings here,
1333 * because it requires a gtk_widget_show(),
1334 * and we don't want to do that until later,
1335 * so that the UI is not visible for non-menu D-Bus activation.
1338 return MODEST_WINDOW(self);
1342 modest_main_window_set_style (ModestMainWindow *self,
1343 ModestMainWindowStyle style)
1345 ModestMainWindowPrivate *priv;
1346 ModestWindowPrivate *parent_priv;
1350 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1352 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1353 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1355 /* no change -> nothing to do */
1356 if (priv->style == style)
1359 /* Get toggle button and update the state if needed. This will
1360 happen only when the set_style is not invoked from the UI,
1361 for example when it's called from widget memory */
1362 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1363 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1364 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1365 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1366 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1367 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1368 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1371 priv->style = style;
1373 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1375 if (!priv->wait_for_settings)
1376 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1377 MODEST_CONF_MAIN_PANED_KEY);
1378 /* Remove main paned */
1379 g_object_ref (priv->main_paned);
1380 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1382 /* Reparent the contents widget to the main vbox */
1383 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1386 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1387 /* Remove header view */
1388 g_object_ref (priv->contents_widget);
1389 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1391 /* Reparent the main paned */
1392 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1393 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1395 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1399 g_return_if_reached ();
1402 /* Let header view grab the focus if it's being shown */
1403 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1404 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1406 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1409 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1412 ModestMainWindowStyle
1413 modest_main_window_get_style (ModestMainWindow *self)
1415 ModestMainWindowPrivate *priv;
1417 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1419 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1424 toolbar_resize (ModestMainWindow *self)
1426 ModestMainWindowPrivate *priv = NULL;
1427 ModestWindowPrivate *parent_priv = NULL;
1429 gint static_button_size;
1430 ModestWindowMgr *mgr;
1432 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1433 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1434 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1436 mgr = modest_runtime_get_window_mgr ();
1437 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1439 if (parent_priv->toolbar) {
1440 /* left size buttons */
1441 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1444 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1445 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1448 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1449 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1452 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1453 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1454 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1455 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1456 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1458 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1459 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1460 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1463 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1464 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1473 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1475 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1476 ModestWindowPrivate *parent_priv;
1477 ModestWindowMgr *mgr;
1478 gboolean is_fullscreen;
1479 GtkAction *fs_toggle_action;
1482 mgr = modest_runtime_get_window_mgr ();
1484 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1486 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1488 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1489 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1490 if (is_fullscreen != active) {
1491 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1494 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1502 modest_main_window_show_toolbar (ModestWindow *self,
1503 gboolean show_toolbar)
1505 ModestMainWindowPrivate *priv = NULL;
1506 ModestWindowPrivate *parent_priv = NULL;
1507 GtkWidget *reply_button = NULL, *menu = NULL;
1508 GtkWidget *placeholder = NULL;
1510 const gchar *action_name;
1513 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1514 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1515 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1517 /* Set optimized view status */
1518 priv->optimized_view = !show_toolbar;
1520 if (!parent_priv->toolbar) {
1521 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1523 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1525 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1526 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1527 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1528 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1529 toolbar_resize (MODEST_MAIN_WINDOW (self));
1531 /* Add ProgressBar (Transfer toolbar) */
1532 priv->progress_bar = modest_progress_bar_new ();
1533 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1534 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1535 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1536 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1537 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1539 /* Connect cancel 'clicked' signal to abort progress mode */
1540 g_signal_connect(priv->cancel_toolitem, "clicked",
1541 G_CALLBACK(cancel_progressbar),
1544 /* Add it to the observers list */
1545 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1548 hildon_window_add_toolbar (HILDON_WINDOW (self),
1549 GTK_TOOLBAR (parent_priv->toolbar));
1551 /* Set reply button tap and hold menu */
1552 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1553 "/ToolBar/ToolbarMessageReply");
1554 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1555 "/ToolbarReplyCSM");
1556 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1558 /* Set send & receive button tap and hold menu */
1559 update_menus (MODEST_MAIN_WINDOW (self));
1563 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1564 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1565 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1567 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1568 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1569 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1571 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1573 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1577 /* Update also the actions (to update the toggles in the
1578 menus), we have to do it manually because some other window
1579 of the same time could have changed it (remember that the
1580 toolbar fullscreen mode is shared by all the windows of the
1582 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1583 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1585 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1587 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1588 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1593 on_account_inserted (TnyAccountStore *accoust_store,
1594 TnyAccount *account,
1597 /* Transport accounts and local ones (MMC and the Local
1598 folders account do now cause menu changes */
1599 if (TNY_IS_STORE_ACCOUNT (account) &&
1600 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1602 update_menus (MODEST_MAIN_WINDOW (user_data));
1607 on_default_account_changed (ModestAccountMgr* mgr,
1610 update_menus (MODEST_MAIN_WINDOW (user_data));
1614 on_account_removed (TnyAccountStore *accoust_store,
1615 TnyAccount *account,
1618 /* Transport accounts and local ones (MMC and the Local
1619 folders account do now cause menu changes */
1620 if (TNY_IS_STORE_ACCOUNT (account) &&
1621 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1622 update_menus (MODEST_MAIN_WINDOW (user_data));
1626 on_account_changed (TnyAccountStore *account_store,
1627 TnyAccount *account,
1630 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1632 /* Transport accounts and local ones (MMC and the Local
1633 folders account do now cause menu changes */
1634 if (TNY_IS_STORE_ACCOUNT (account)) {
1635 /* We need to refresh the details widget because it could have changed */
1636 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1637 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1639 /* Update the menus as well, name could change */
1640 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1641 update_menus (MODEST_MAIN_WINDOW (user_data));
1646 * This function manages the key events used to navigate between
1647 * header and folder views (when the window is in split view)
1650 * -------------------------------------------------
1651 * HeaderView GDK_Left Move focus to folder view
1652 * FolderView GDK_Right Move focus to header view
1654 * There is no need to scroll to selected row, the widgets will be the
1655 * responsibles of doing that (probably managing the focus-in event
1658 on_inner_widgets_key_pressed (GtkWidget *widget,
1662 ModestMainWindowPrivate *priv;
1664 if (event->type == GDK_KEY_RELEASE)
1667 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1669 /* Do nothing if we're in SIMPLE style */
1670 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1673 if (MODEST_IS_HEADER_VIEW (widget)) {
1674 if (event->keyval == GDK_Left)
1675 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1676 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1677 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1678 if (selected_headers > 1) {
1679 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1683 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1684 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1690 set_alignment (GtkWidget *widget,
1693 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1694 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1698 create_empty_view (void)
1700 GtkLabel *label = NULL;
1701 GtkWidget *align = NULL;
1703 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1704 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1705 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1706 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1708 return GTK_WIDGET(align);
1712 * Free the returned string
1715 get_gray_color_markup (GtkWidget *styled_widget)
1717 gchar *gray_color_markup = NULL;
1718 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1719 /* Obtain the secondary text color. We need a realized widget, that's why
1720 we get styled_widget from outside */
1722 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1723 gray_color_markup = modest_text_utils_get_color_string (&color);
1724 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1726 if (!gray_color_markup)
1727 gray_color_markup = g_strdup ("#BBBBBB");
1729 return gray_color_markup;
1733 * Free the returned string
1736 create_device_name_visual_string (const gchar *device_name,
1737 const gchar *gray_color_markup)
1741 /* We have to use "" to fill the %s of the translation. We can
1742 not just use the device name because the device name is
1743 shown in a different color, so it could not be included
1744 into the <span> tag */
1745 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1746 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1756 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1758 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1763 gchar *gray_color_markup;
1765 vbox = gtk_vbox_new (FALSE, 0);
1767 gray_color_markup = get_gray_color_markup (styled_widget);
1769 /* Account description: */
1770 if (modest_tny_account_is_virtual_local_folders (account)
1771 || (modest_tny_account_is_memory_card_account (account))) {
1773 /* Get device name */
1774 gchar *device_name = NULL;
1775 if (modest_tny_account_is_virtual_local_folders (account))
1776 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1777 MODEST_CONF_DEVICE_NAME, NULL);
1779 device_name = g_strdup (tny_account_get_name (account));
1781 label = create_device_name_visual_string ((const gchar *) device_name,
1782 (const gchar *) gray_color_markup);
1783 label_w = gtk_label_new (NULL);
1784 gtk_label_set_markup (GTK_LABEL (label_w), label);
1785 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1786 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1787 g_free (device_name);
1790 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1791 gtk_box_pack_start (GTK_BOX (vbox),
1792 gtk_label_new (tny_account_get_name (account)),
1795 /* Other accounts, such as IMAP and POP: */
1800 /* Put proto in uppercase */
1801 proto = g_string_new (tny_account_get_proto (account));
1802 proto = g_string_ascii_up (proto);
1804 /* note: mcen_fi_localroot_description is something like "%s account"
1805 * however, we should display "%s account: %s"... therefore, ugly tmp */
1806 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1807 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1808 gray_color_markup, tmp, tny_account_get_name (account));
1811 label_w = gtk_label_new (NULL);
1812 gtk_label_set_markup (GTK_LABEL (label_w), label);
1813 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1814 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1815 g_string_free (proto, TRUE);
1821 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1822 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1823 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1824 modest_tny_folder_store_get_message_count (folder_store));
1825 label_w = gtk_label_new (NULL);
1826 gtk_label_set_markup (GTK_LABEL (label_w), label);
1827 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1828 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1832 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1834 _("mcen_fi_rootfolder_folders"),
1835 modest_tny_folder_store_get_folder_count (folder_store));
1836 label_w = gtk_label_new (NULL);
1837 gtk_label_set_markup (GTK_LABEL (label_w), label);
1838 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1839 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1843 if (modest_tny_account_is_virtual_local_folders (account)
1844 || modest_tny_account_is_memory_card_account (account)) {
1846 gchar *size = modest_text_utils_get_display_size (
1847 modest_tny_folder_store_get_local_size (folder_store));
1849 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1850 gray_color_markup, _("mcen_fi_rootfolder_size"),
1854 label_w = gtk_label_new (NULL);
1855 gtk_label_set_markup (GTK_LABEL (label_w), label);
1856 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1857 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1859 } else if (TNY_IS_ACCOUNT(folder_store)) {
1860 TnyAccount *account = TNY_ACCOUNT(folder_store);
1862 time_t last_updated;
1863 const gchar *last_updated_string;
1864 /* Get last updated from configuration */
1865 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1866 tny_account_get_id (account));
1868 if (last_updated > 0)
1869 last_updated_string = modest_text_utils_get_display_date(last_updated);
1871 last_updated_string = g_strdup (_("mcen_va_never"));
1873 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1874 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1875 label_w = gtk_label_new (NULL);
1876 gtk_label_set_markup (GTK_LABEL (label_w), label);
1877 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1878 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1882 g_free (gray_color_markup);
1885 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1891 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1893 ModestMainWindowPrivate *priv = NULL;
1895 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1897 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1899 return priv->send_receive_in_progress;
1903 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1905 GtkAction *action = NULL;
1906 GtkWidget *widget = NULL;
1907 ModestMainWindowPrivate *priv = NULL;
1909 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1910 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1912 priv->send_receive_in_progress = TRUE;
1914 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1915 gtk_action_set_sensitive (action, FALSE);
1916 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1917 /* gtk_action_set_sensitive (action, FALSE); */
1918 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1919 gtk_widget_set_sensitive (widget, FALSE);
1923 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1925 GtkAction *action = NULL;
1926 GtkWidget *widget = NULL;
1927 ModestMainWindowPrivate *priv = NULL;
1929 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1930 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1932 priv->send_receive_in_progress = FALSE;
1934 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1935 gtk_action_set_sensitive (action, TRUE);
1936 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1937 /* gtk_action_set_sensitive (action, TRUE); */
1938 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1939 gtk_widget_set_sensitive (widget, TRUE);
1944 on_msg_count_changed (ModestHeaderView *header_view,
1946 TnyFolderChange *change,
1947 ModestMainWindow *main_window)
1949 gboolean refilter = FALSE;
1950 gboolean folder_empty = FALSE;
1951 gboolean all_marked_as_deleted = FALSE;
1952 ModestMainWindowPrivate *priv;
1954 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1955 g_return_if_fail (TNY_IS_FOLDER(folder));
1956 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1958 if (change != NULL) {
1959 TnyFolderChangeChanged changed;
1961 changed = tny_folder_change_get_changed (change);
1962 /* If something changes */
1963 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1964 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1966 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1968 /* Play a sound (if configured) and make the LED blink */
1969 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1970 modest_platform_push_email_notification ();
1973 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1976 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1979 /* Check if all messages are marked to be deleted */
1980 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1981 folder_empty = folder_empty || all_marked_as_deleted;
1983 /* Set contents style of headers view */
1985 modest_main_window_set_contents_style (main_window,
1986 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1987 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1989 modest_main_window_set_contents_style (main_window,
1990 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1994 modest_header_view_refilter (header_view);
1999 modest_main_window_set_contents_style (ModestMainWindow *self,
2000 ModestMainWindowContentsStyle style)
2002 ModestMainWindowPrivate *priv;
2004 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2006 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2008 /* We allow to set the same content style than the previously
2009 set if there are details, because it could happen when we're
2010 selecting different accounts consecutively */
2011 if ((priv->contents_style == style) &&
2012 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2015 /* Remove previous child. Delete it if it was an account
2017 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2019 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2020 g_object_ref (content);
2021 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2022 g_object_ref (priv->empty_view);
2023 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2026 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2029 priv->contents_style = style;
2031 switch (priv->contents_style) {
2032 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2033 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2034 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2037 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2039 /* if we're started without main win, there may not be a folder
2040 * view. this fixes a GLib-Critical */
2041 if (priv->folder_view) {
2042 TnyFolderStore *selected_folderstore =
2043 modest_folder_view_get_selected (priv->folder_view);
2044 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2045 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2046 TNY_ACCOUNT (selected_folderstore));
2048 wrap_in_scrolled_window (priv->contents_widget,
2049 priv->details_widget);
2051 g_object_unref (selected_folderstore);
2052 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2057 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2058 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2059 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2063 g_return_if_reached ();
2067 gtk_widget_show_all (priv->contents_widget);
2070 ModestMainWindowContentsStyle
2071 modest_main_window_get_contents_style (ModestMainWindow *self)
2073 ModestMainWindowPrivate *priv;
2075 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2077 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2078 return priv->contents_style;
2083 on_configuration_key_changed (ModestConf* conf,
2085 ModestConfEvent event,
2086 ModestConfNotificationId id,
2087 ModestMainWindow *self)
2089 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2090 TnyAccount *account = NULL;
2092 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2095 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2098 if (priv->folder_view)
2099 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2101 if (account && TNY_IS_ACCOUNT (account) &&
2102 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2105 const gchar *device_name;
2106 gchar *new_text, *gray_color_markup;
2109 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2110 label = GTK_LABEL (children->data);
2112 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2113 MODEST_CONF_DEVICE_NAME, NULL);
2115 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2116 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2118 gtk_label_set_markup (label, new_text);
2119 gtk_widget_show (GTK_WIDGET (label));
2121 g_free (gray_color_markup);
2123 g_list_free (children);
2125 g_object_unref (account);
2129 set_toolbar_transfer_mode (ModestMainWindow *self)
2131 ModestMainWindowPrivate *priv = NULL;
2133 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2135 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2137 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2139 if (priv->progress_bar_timeout > 0) {
2140 g_source_remove (priv->progress_bar_timeout);
2141 priv->progress_bar_timeout = 0;
2148 set_toolbar_mode (ModestMainWindow *self,
2149 ModestToolBarModes mode)
2151 ModestWindowPrivate *parent_priv = NULL;
2152 ModestMainWindowPrivate *priv = NULL;
2153 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2155 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2157 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2158 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2160 /* In case this was called before the toolbar exists: */
2161 if (!(parent_priv->toolbar))
2164 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2166 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2167 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2168 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2170 /* Sets current toolbar mode */
2171 priv->current_toolbar_mode = mode;
2173 /* Checks the dimming rules */
2174 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2175 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2177 /* Show and hide toolbar items */
2179 case TOOLBAR_MODE_NORMAL:
2181 gtk_action_set_visible (sort_action, TRUE);
2183 gtk_action_set_visible (refresh_action, TRUE);
2184 if (priv->progress_toolitem) {
2185 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2186 gtk_widget_hide (priv->progress_toolitem);
2188 if (priv->progress_bar)
2189 gtk_widget_hide (priv->progress_bar);
2192 gtk_action_set_visible (cancel_action, FALSE);
2194 /* Hide toolbar if optimized view is enabled */
2195 if (priv->optimized_view)
2196 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2198 case TOOLBAR_MODE_TRANSFER:
2200 gtk_action_set_visible (sort_action, FALSE);
2202 gtk_action_set_visible (refresh_action, FALSE);
2204 gtk_action_set_visible (cancel_action, TRUE);
2205 if (priv->progress_bar)
2206 gtk_widget_show (priv->progress_bar);
2207 if (priv->progress_toolitem) {
2208 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2209 gtk_widget_show (priv->progress_toolitem);
2212 /* Show toolbar if it's hiden (optimized view ) */
2213 if (priv->optimized_view)
2214 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2217 g_return_if_reached ();
2222 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2224 ModestMainWindowPrivate *priv;
2226 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2227 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2229 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2233 cancel_progressbar (GtkToolButton *toolbutton,
2234 ModestMainWindow *self)
2237 ModestMainWindowPrivate *priv;
2239 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2241 /* Get operation observers and cancel all the operations */
2242 tmp = priv->progress_widgets;
2244 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2245 tmp=g_slist_next(tmp);
2250 observers_empty (ModestMainWindow *self)
2253 ModestMainWindowPrivate *priv;
2254 gboolean is_empty = TRUE;
2255 guint pending_ops = 0;
2257 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2258 tmp = priv->progress_widgets;
2260 /* Check all observers */
2261 while (tmp && is_empty) {
2262 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2263 is_empty = pending_ops == 0;
2265 tmp = g_slist_next(tmp);
2273 * Gets the toolbar mode needed for each mail operation. It stores in
2274 * @mode_changed if the toolbar mode has changed or not
2276 static ModestToolBarModes
2277 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2278 ModestMailOperation *mail_op,
2279 gboolean *mode_changed)
2281 ModestToolBarModes mode;
2282 ModestMainWindowPrivate *priv;
2284 *mode_changed = FALSE;
2285 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2287 /* Get toolbar mode from operation id*/
2288 switch (modest_mail_operation_get_type_operation (mail_op)) {
2289 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2290 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2291 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2292 mode = TOOLBAR_MODE_TRANSFER;
2293 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2294 *mode_changed = TRUE;
2297 mode = TOOLBAR_MODE_NORMAL;
2303 on_mail_operation_started (ModestMailOperation *mail_op,
2306 ModestMainWindow *self;
2307 ModestMailOperationTypeOperation op_type;
2308 ModestMainWindowPrivate *priv;
2309 ModestToolBarModes mode;
2311 gboolean mode_changed = FALSE;
2312 TnyAccount *account = NULL;
2314 self = MODEST_MAIN_WINDOW (user_data);
2315 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2317 /* Do not show progress for receiving operations if the
2318 account is the local account or the MMC one */
2319 op_type = modest_mail_operation_get_type_operation (mail_op);
2320 account = modest_mail_operation_get_account (mail_op);
2321 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2324 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2325 modest_tny_account_is_memory_card_account (account));
2327 g_object_unref (account);
2331 /* Show information banner. Remove old timeout */
2332 if (priv->retrieving_banner_timeout > 0) {
2333 g_source_remove (priv->retrieving_banner_timeout);
2334 priv->retrieving_banner_timeout = 0;
2336 /* Create a new timeout */
2337 priv->retrieving_banner_timeout =
2338 g_timeout_add (2000, show_retrieving_banner, self);
2341 /* Not every mail operation has account, noop does not */
2343 g_object_unref (account);
2345 /* Get toolbar mode from operation id*/
2346 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2348 /* Add operation observers and change toolbar if neccessary*/
2349 tmp = priv->progress_widgets;
2350 if (mode == TOOLBAR_MODE_TRANSFER) {
2352 GObject *source = modest_mail_operation_get_source(mail_op);
2353 if (G_OBJECT (self) == source) {
2354 set_toolbar_transfer_mode(self);
2356 g_object_unref (source);
2360 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2362 tmp = g_slist_next (tmp);
2366 /* Update the main menu as well, we need to explicitely do
2367 this in order to enable/disable accelerators */
2368 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2372 on_mail_operation_finished (ModestMailOperation *mail_op,
2375 ModestToolBarModes mode;
2376 ModestMailOperationTypeOperation op_type;
2378 ModestMainWindow *self;
2379 gboolean mode_changed;
2380 TnyAccount *account = NULL;
2381 ModestMainWindowPrivate *priv;
2383 self = MODEST_MAIN_WINDOW (user_data);
2384 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2386 /* The mail operation was not added to the progress objects if
2387 the account was the local account or the MMC one */
2388 op_type = modest_mail_operation_get_type_operation (mail_op);
2389 account = modest_mail_operation_get_account (mail_op);
2390 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2393 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2394 modest_tny_account_is_memory_card_account (account));
2396 g_object_unref (account);
2400 /* Remove old timeout */
2401 if (priv->retrieving_banner_timeout > 0) {
2402 g_source_remove (priv->retrieving_banner_timeout);
2403 priv->retrieving_banner_timeout = 0;
2406 /* Remove the banner if exists */
2407 if (priv->retrieving_banner) {
2408 gtk_widget_destroy (priv->retrieving_banner);
2409 priv->retrieving_banner = NULL;
2413 /* Not every mail operation has account, noop does not */
2415 g_object_unref (account);
2417 /* Get toolbar mode from operation id*/
2418 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2420 /* Change toolbar mode */
2421 tmp = priv->progress_widgets;
2422 if (mode == TOOLBAR_MODE_TRANSFER) {
2424 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2426 tmp = g_slist_next (tmp);
2429 /* If no more operations are being observed, NORMAL mode is enabled again */
2430 if (observers_empty (self)) {
2431 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2437 on_queue_changed (ModestMailOperationQueue *queue,
2438 ModestMailOperation *mail_op,
2439 ModestMailOperationQueueNotification type,
2440 ModestMainWindow *self)
2442 ModestMainWindowPrivate *priv;
2444 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2446 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2447 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2449 "operation-started",
2450 G_CALLBACK (on_mail_operation_started),
2452 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2454 "operation-finished",
2455 G_CALLBACK (on_mail_operation_finished),
2457 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2458 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2460 "operation-started");
2461 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2463 "operation-finished");
2468 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2470 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2472 ModestAccountMgr *mgr;
2473 ModestAccountSettings *settings;
2474 ModestServerAccountSettings *store_settings = NULL;
2476 /* Get account data */
2477 mgr = modest_runtime_get_account_mgr ();
2478 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2480 store_settings = modest_account_settings_get_store_settings (settings);
2482 /* Set the new visible & active account */
2483 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2484 const gchar *account_name;
2486 account_name = modest_account_settings_get_account_name (settings);
2488 modest_folder_view_set_account_id_of_visible_server_account
2490 modest_server_account_settings_get_account_name (store_settings));
2491 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2492 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2493 if (action != NULL) {
2494 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2495 modest_utils_toggle_action_set_active_block_notify (
2496 GTK_TOGGLE_ACTION (action),
2502 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2507 g_object_unref (store_settings);
2508 g_object_unref (settings);
2512 /* Make sure that at least one account is "viewed": */
2514 set_at_least_one_account_visible(ModestMainWindow *self)
2516 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2517 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2519 if (!(priv->folder_view)) {
2520 /* It is too early to do this. */
2524 const gchar *active_server_account_name =
2525 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2527 if (!active_server_account_name ||
2528 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2530 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2531 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2532 if (default_modest_name) {
2533 set_account_visible (self, default_modest_name);
2534 } else if (first_modest_name) {
2535 set_account_visible (self, first_modest_name);
2537 g_free (first_modest_name);
2538 g_free (default_modest_name);
2543 on_show_account_action_toggled (GtkToggleAction *action,
2546 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2548 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2549 if (gtk_toggle_action_get_active (action))
2550 set_account_visible (self, acc_name);
2554 refresh_account (const gchar *account_name)
2558 /* win must already exists here, obviously */
2559 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2562 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2566 /* If account_name == NULL, we must update all (option All) */
2568 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2570 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2575 on_refresh_account_action_activated (GtkAction *action,
2578 refresh_account ((const gchar*) user_data);
2582 on_send_receive_csm_activated (GtkMenuItem *item,
2585 refresh_account ((const gchar*) user_data);
2589 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2591 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2593 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2599 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2601 ModestMainWindow *main_window = NULL;
2603 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2604 main_window = MODEST_MAIN_WINDOW (userdata);
2606 /* Update toolbar dimming state */
2607 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2608 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2614 on_header_view_focus_in (GtkWidget *widget,
2615 GdkEventFocus *event,
2618 ModestMainWindow *main_window = NULL;
2620 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2622 main_window = MODEST_MAIN_WINDOW (userdata);
2624 /* Update toolbar dimming state */
2625 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2626 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2632 on_folder_selection_changed (ModestFolderView *folder_view,
2633 TnyFolderStore *folder_store,
2635 ModestMainWindow *main_window)
2637 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2638 GtkAction *action = NULL;
2639 gboolean show_reply = TRUE;
2640 gboolean show_forward = TRUE;
2641 gboolean show_cancel_send = FALSE;
2642 gboolean show_clipboard = TRUE;
2643 gboolean show_delete = TRUE;
2646 if (TNY_IS_ACCOUNT (folder_store)) {
2647 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2648 } else if (TNY_IS_FOLDER (folder_store)) {
2649 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2650 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2651 TNY_FOLDER (folder_store));
2652 switch (folder_type) {
2653 case TNY_FOLDER_TYPE_DRAFTS:
2654 show_clipboard = show_delete = TRUE;
2655 show_reply = show_forward = show_cancel_send = FALSE;
2657 case TNY_FOLDER_TYPE_SENT:
2658 show_forward = show_clipboard = show_delete = TRUE;
2659 show_reply = show_cancel_send = FALSE;
2661 case TNY_FOLDER_TYPE_OUTBOX:
2662 show_clipboard = show_delete = show_cancel_send = TRUE;
2663 show_reply = show_forward = FALSE;
2665 case TNY_FOLDER_TYPE_INVALID:
2666 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2669 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2670 show_cancel_send = FALSE;
2673 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2674 show_cancel_send = FALSE;
2679 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2680 gtk_action_set_visible (action, show_reply);
2681 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2682 gtk_action_set_visible (action, show_reply);
2683 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2684 gtk_action_set_visible (action, show_forward);
2685 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2686 gtk_action_set_visible (action, show_cancel_send);
2687 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2688 gtk_action_set_visible (action, show_delete);
2690 /* We finally call to the ui actions handler, after updating properly
2691 * the header view CSM */
2692 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2696 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2697 GtkTreeModel *model,
2698 GtkTreeRowReference *row_reference,
2699 ModestMainWindow *self)
2701 ModestMainWindowPrivate *priv = NULL;
2702 GtkTreeModel *header_model = NULL;
2703 GtkTreePath *path = NULL;
2705 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2706 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2707 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2709 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2710 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2712 /* Do nothing if we changed the folder in the main view */
2713 if (header_model != model)
2716 /* Select the message in the header view */
2717 path = gtk_tree_row_reference_get_path (row_reference);
2718 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2720 gtk_tree_path_free (path);
2726 show_updating_banner (gpointer user_data)
2728 ModestMainWindowPrivate *priv = NULL;
2730 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2732 if (priv->updating_banner == NULL) {
2734 /* We're outside the main lock */
2735 gdk_threads_enter ();
2736 priv->updating_banner =
2737 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2738 _CS ("ckdg_pb_updating"));
2739 gdk_threads_leave ();
2742 /* Remove timeout */
2743 priv->updating_banner_timeout = 0;
2748 * We use this function to show/hide a progress banner showing
2749 * "Updating" while the header view is being filled. We're not showing
2750 * it unless the update takes more than 2 seconds
2752 * If starting = TRUE then the refresh is starting, otherwise it means
2753 * that is has just finished
2756 on_updating_msg_list (ModestHeaderView *header_view,
2760 ModestMainWindowPrivate *priv = NULL;
2762 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2764 /* Remove old timeout */
2765 if (priv->updating_banner_timeout > 0) {
2766 g_source_remove (priv->updating_banner_timeout);
2767 priv->updating_banner_timeout = 0;
2770 /* Create a new timeout */
2772 priv->updating_banner_timeout =
2773 g_timeout_add (2000, show_updating_banner, user_data);
2775 /* Remove the banner if exists */
2776 if (priv->updating_banner) {
2777 gtk_widget_destroy (priv->updating_banner);
2778 priv->updating_banner = NULL;
2784 modest_main_window_screen_is_on (ModestMainWindow *self)
2786 ModestMainWindowPrivate *priv = NULL;
2788 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2790 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2792 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2796 remove_banners (ModestMainWindow *window)
2798 ModestMainWindowPrivate *priv;
2800 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2802 if (priv->retrieving_banner_timeout > 0) {
2803 g_source_remove (priv->retrieving_banner_timeout);
2804 priv->retrieving_banner_timeout = 0;
2807 if (priv->retrieving_banner != NULL) {
2808 gtk_widget_destroy (priv->retrieving_banner);
2809 priv->retrieving_banner = NULL;
2812 if (priv->updating_banner_timeout > 0) {
2813 g_source_remove (priv->updating_banner_timeout);
2814 priv->updating_banner_timeout = 0;
2817 if (priv->updating_banner != NULL) {
2818 gtk_widget_destroy (priv->updating_banner);
2819 priv->updating_banner = NULL;
2825 on_window_hide (GObject *gobject,
2829 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
2831 if (!GTK_WIDGET_VISIBLE (user_data))
2832 remove_banners (MODEST_MAIN_WINDOW (user_data));
2836 on_window_destroy (GtkObject *widget,
2839 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
2841 remove_banners (MODEST_MAIN_WINDOW (user_data));
2845 show_retrieving_banner (gpointer user_data)
2847 ModestMainWindowPrivate *priv = NULL;
2849 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2851 if (priv->retrieving_banner == NULL) {
2853 /* We're outside the main lock */
2854 gdk_threads_enter ();
2855 priv->retrieving_banner =
2856 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2857 _("mcen_ib_getting_items"));
2858 gdk_threads_leave ();
2861 /* Remove timeout */
2862 priv->retrieving_banner_timeout = 0;