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 if (priv->empty_view) {
394 g_object_unref (priv->empty_view);
395 priv->empty_view = NULL;
398 if (priv->header_view) {
399 g_object_unref (priv->header_view);
400 priv->header_view = NULL;
403 g_slist_free (priv->progress_widgets);
405 g_byte_array_free (priv->merge_ids, TRUE);
407 if (priv->progress_bar_timeout > 0) {
408 g_source_remove (priv->progress_bar_timeout);
409 priv->progress_bar_timeout = 0;
412 if (priv->updating_banner_timeout > 0) {
413 g_source_remove (priv->updating_banner_timeout);
414 priv->updating_banner_timeout = 0;
417 if (priv->updating_banner) {
418 gtk_widget_destroy (priv->updating_banner);
419 priv->updating_banner = NULL;
422 if (priv->retrieving_banner_timeout > 0) {
423 g_source_remove (priv->retrieving_banner_timeout);
424 priv->retrieving_banner_timeout = 0;
427 if (priv->retrieving_banner) {
428 gtk_widget_destroy (priv->retrieving_banner);
429 priv->retrieving_banner = NULL;
432 if (priv->restore_paned_timeout > 0) {
433 g_source_remove (priv->restore_paned_timeout);
434 priv->restore_paned_timeout = 0;
437 G_OBJECT_CLASS(parent_class)->finalize (obj);
441 modest_main_window_get_child_widget (ModestMainWindow *self,
442 ModestMainWindowWidgetType widget_type)
444 ModestMainWindowPrivate *priv;
447 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
448 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
451 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
453 switch (widget_type) {
454 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
455 widget = (GtkWidget*)priv->header_view; break;
456 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
457 widget = (GtkWidget*)priv->folder_view; break;
462 /* Note that the window could have been destroyed, and so
463 their children, but still have some references */
464 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
468 restore_paned_timeout_handler (gpointer *data)
470 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
471 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
474 /* Timeouts are outside the main lock */
475 gdk_threads_enter ();
476 if (GTK_WIDGET_VISIBLE (main_window)) {
477 conf = modest_runtime_get_conf ();
478 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
479 MODEST_CONF_MAIN_PANED_KEY);
481 gdk_threads_leave ();
488 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
491 ModestMainWindowPrivate *priv;
493 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
495 conf = modest_runtime_get_conf ();
497 modest_widget_memory_restore (conf, G_OBJECT(self),
498 MODEST_CONF_MAIN_WINDOW_KEY);
500 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
501 MODEST_CONF_HEADER_VIEW_KEY);
503 if (do_folder_view_too)
504 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
505 MODEST_CONF_FOLDER_VIEW_KEY);
507 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
508 /* MODEST_CONF_MAIN_PANED_KEY); */
510 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
512 /* We need to force a redraw here in order to get the right
513 position of the horizontal paned separator */
514 gtk_widget_show (GTK_WIDGET (self));
519 save_state (ModestWindow *window)
522 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
523 ModestMainWindowPrivate *priv;
525 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
526 conf = modest_runtime_get_conf ();
528 modest_widget_memory_save (conf,G_OBJECT(self),
529 MODEST_CONF_MAIN_WINDOW_KEY);
530 /* Only save main paned position if we're in split mode */
531 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
532 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
533 MODEST_CONF_MAIN_PANED_KEY);
534 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
535 MODEST_CONF_FOLDER_VIEW_KEY);
539 compare_display_names (ModestAccountSettings *a,
540 ModestAccountSettings *b)
542 return strcmp (modest_account_settings_get_display_name (a),
543 modest_account_settings_get_display_name (b));
546 /* We use this function to prevent the send&receive CSM to be shown
547 when there are less than two account */
549 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
555 update_menus (ModestMainWindow* self)
557 GSList *account_names, *iter, *accounts;
558 ModestMainWindowPrivate *priv;
559 ModestWindowPrivate *parent_priv;
560 ModestAccountMgr *mgr;
561 gint i, num_accounts;
563 gchar *default_account;
564 const gchar *active_account_name;
565 GtkWidget *send_receive_button, *item;
566 GtkAction *send_receive_all = NULL;
569 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
570 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
572 /* Get enabled account IDs */
573 mgr = modest_runtime_get_account_mgr ();
574 account_names = modest_account_mgr_account_names (mgr, TRUE);
575 iter = account_names;
579 ModestAccountSettings *settings =
580 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
581 accounts = g_slist_prepend (accounts, settings);
585 modest_account_mgr_free_account_names (account_names);
586 account_names = NULL;
588 /* Order the list of accounts by its display name */
589 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
590 num_accounts = g_slist_length (accounts);
592 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
593 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
594 gtk_action_set_visible (send_receive_all, num_accounts > 0);
596 /* Delete old send&receive popup items. We can not just do a
597 menu_detach because it does not work well with
599 if (priv->accounts_popup)
600 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
601 (GtkCallback) gtk_widget_destroy, NULL);
603 /* Delete old entries in the View menu. Do not free groups, it
605 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
607 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
608 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
609 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
610 GTK_ACTION_GROUP (groups->data));
613 if (priv->merge_ids) {
614 for (i = 0; i < priv->merge_ids->len; i++)
615 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
616 g_byte_array_free (priv->merge_ids, TRUE);
618 /* We need to call this in order to ensure
619 that the new actions are added in the right
620 order (alphabetical) */
621 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
623 groups = g_list_next (groups);
625 priv->merge_ids = g_byte_array_sized_new (num_accounts);
627 /* Get send receive button */
628 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
629 "/ToolBar/ToolbarSendReceive");
631 /* Create the menu */
632 if (num_accounts > 1) {
633 if (!priv->accounts_popup)
634 priv->accounts_popup = gtk_menu_new ();
635 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
636 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
637 g_signal_connect (G_OBJECT (item),
639 G_CALLBACK (on_send_receive_csm_activated),
641 item = gtk_separator_menu_item_new ();
642 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
645 /* Create a new action group */
646 default_account = modest_account_mgr_get_default_account (mgr);
647 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
649 if (!active_account_name)
650 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
652 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
654 for (i = 0; i < num_accounts; i++) {
655 gchar *display_name = NULL;
656 const gchar *account_name;
657 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
660 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
663 account_name = modest_account_settings_get_account_name (settings);
665 if (default_account && account_name &&
666 !(strcmp (default_account, account_name) == 0)) {
667 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
668 modest_account_settings_get_display_name (settings));
670 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
671 modest_account_settings_get_display_name (settings));
676 /* Create action and add it to the action group. The
677 action name must be the account name, this way we
678 could know in the handlers the account to show */
679 if (settings && account_name) {
680 gchar* item_name, *refresh_action_name;
682 GtkAction *view_account_action, *refresh_account_action;
683 gchar *escaped_display_name;
685 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
687 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
688 escaped_display_name, NULL, NULL, 0));
689 g_free (escaped_display_name);
690 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
691 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
692 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
694 if (active_account_name) {
695 if (active_account_name && account_name &&
696 (strcmp (active_account_name, account_name) == 0)) {
697 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
701 /* Add ui from account data. We allow 2^9-1 account
702 changes in a single execution because we're
703 downcasting the guint to a guint8 in order to use a
704 GByteArray. It should be enough. */
705 item_name = g_strconcat (account_name, "Menu", NULL);
706 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
707 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
708 gtk_ui_manager_add_ui (parent_priv->ui_manager,
710 "/MenuBar/ViewMenu/ViewMenuAdditions",
713 GTK_UI_MANAGER_MENUITEM,
716 /* Connect the action signal "activate" */
717 g_signal_connect_after (G_OBJECT (view_account_action),
719 G_CALLBACK (on_show_account_action_toggled),
722 /* Create the items for the Tools->Send&Receive submenu */
723 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
724 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
725 display_name, NULL, NULL);
726 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
728 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
729 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
730 gtk_ui_manager_add_ui (parent_priv->ui_manager,
732 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
735 GTK_UI_MANAGER_MENUITEM,
737 g_free (refresh_action_name);
739 g_signal_connect_data (G_OBJECT (refresh_account_action),
741 G_CALLBACK (on_refresh_account_action_activated),
742 g_strdup (account_name),
743 (GClosureNotify) g_free,
746 /* Create item and add it to the send&receive
747 CSM. If there is only one account then
749 if (num_accounts > 1) {
750 GtkWidget *label = gtk_label_new(NULL);
751 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
752 if (default_account && (strcmp(account_name, default_account) == 0)) {
753 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
754 gtk_label_set_markup (GTK_LABEL (label), escaped);
757 gtk_label_set_text (GTK_LABEL (label), display_name);
760 item = gtk_menu_item_new ();
761 gtk_container_add (GTK_CONTAINER (item), label);
763 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
764 g_signal_connect_data (G_OBJECT (item),
766 G_CALLBACK (on_send_receive_csm_activated),
767 g_strdup (account_name),
768 (GClosureNotify) g_free,
775 g_free (display_name);
778 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
780 /* We cannot do this in the loop above because this relies on the action
781 * group being inserted. This makes the default account appear in bold.
782 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
783 for (i = 0; i < num_accounts; i++) {
784 gchar *item_name, *path;
786 ModestAccountSettings *settings;
787 const gchar *account_name;
790 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
791 account_name = modest_account_settings_get_account_name (settings);
792 is_default = (account_name && default_account && !strcmp (account_name, default_account));
794 /* Get the item of the view menu */
795 item_name = g_strconcat (account_name, "Menu", NULL);
796 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
797 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
801 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
802 if (GTK_IS_LABEL (child)) {
803 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
805 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
806 gtk_label_set_markup (GTK_LABEL (child), bold_name);
809 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
813 /* Get the item of the tools menu */
814 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
815 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
819 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
820 if (GTK_IS_LABEL (child)) {
821 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
823 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
824 gtk_label_set_markup (GTK_LABEL (child), bold_name);
827 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
832 g_object_unref (settings);
835 if (num_accounts > 1) {
836 /* Disconnect the tap-and-hold-query if it's connected */
837 if (modest_signal_mgr_is_connected (priv->sighandlers,
838 G_OBJECT (send_receive_button),
839 "tap-and-hold-query"))
840 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
841 G_OBJECT (send_receive_button),
842 "tap-and-hold-query");
844 /* Mandatory in order to view the menu contents */
845 gtk_widget_show_all (priv->accounts_popup);
847 /* Setup tap_and_hold just if was not done before*/
848 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
849 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
851 /* Connect the tap-and-hold-query in order not to show the CSM */
852 if (!modest_signal_mgr_is_connected (priv->sighandlers,
853 G_OBJECT (send_receive_button),
854 "tap-and-hold-query"))
855 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
856 G_OBJECT (send_receive_button),
857 "tap-and-hold-query",
858 G_CALLBACK (tap_and_hold_query_cb),
863 g_slist_free (accounts);
864 g_free (default_account);
867 /* Make sure that at least one account is viewed if there are any
868 * accounts, for instance when adding the first account: */
869 set_at_least_one_account_visible (self);
873 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
875 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
876 gtk_scrolled_window_add_with_viewport
877 (GTK_SCROLLED_WINDOW(win), widget);
879 gtk_container_add (GTK_CONTAINER(win),
890 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
892 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
894 GList *oerrsignals = priv->queue_err_signals;
895 while (oerrsignals) {
896 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
897 g_signal_handler_disconnect (esignal->queue, esignal->signal);
898 g_slice_free (QueueErrorSignal, esignal);
899 oerrsignals = g_list_next (oerrsignals);
901 g_list_free (priv->queue_err_signals);
902 priv->queue_err_signals = NULL;
907 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
909 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
912 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
916 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
918 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
920 /* Update visibility */
923 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
927 modest_main_window_disconnect_signals (ModestWindow *self)
929 ModestMainWindowPrivate *priv;
930 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
932 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
933 priv->sighandlers = NULL;
937 connect_signals (ModestMainWindow *self)
939 ModestWindowPrivate *parent_priv;
940 ModestMainWindowPrivate *priv;
943 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
944 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
949 modest_signal_mgr_connect (priv->sighandlers,
950 G_OBJECT(priv->folder_view), "key-press-event",
951 G_CALLBACK(on_inner_widgets_key_pressed), self);
953 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
954 "folder_selection_changed",
955 G_CALLBACK (on_folder_selection_changed),
958 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
959 "folder-display-name-changed",
960 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
963 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
965 G_CALLBACK (on_folder_view_focus_in),
968 /* Folder view CSM */
969 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
970 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
971 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
972 G_CALLBACK(_folder_view_csm_menu_activated),
976 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
977 G_CALLBACK(modest_ui_actions_on_header_selected), self);
979 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
980 G_CALLBACK(modest_ui_actions_on_header_activated), self);
982 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
983 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
985 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
986 G_CALLBACK(on_inner_widgets_key_pressed), self);
988 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
989 G_CALLBACK(on_msg_count_changed), self);
991 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
992 G_CALLBACK (on_header_view_focus_in), self);
994 modest_signal_mgr_connect (priv->sighandlers,
995 G_OBJECT (priv->header_view),
997 G_CALLBACK (on_updating_msg_list),
1000 /* Header view CSM */
1001 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1002 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1004 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1005 G_CALLBACK(_header_view_csm_menu_activated),
1010 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1011 G_CALLBACK (modest_main_window_window_state_event),
1013 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1014 * in destroy stage */
1015 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1017 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1019 /* Mail Operation Queue */
1021 modest_signal_mgr_connect (priv->sighandlers,
1022 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1024 G_CALLBACK (on_queue_changed), self);
1026 /* Track changes in the device name */
1028 modest_signal_mgr_connect (priv->sighandlers,
1029 G_OBJECT(modest_runtime_get_conf ()),
1031 G_CALLBACK (on_configuration_key_changed),
1034 /* Track account changes. We need to refresh the toolbar */
1036 modest_signal_mgr_connect (priv->sighandlers,
1037 G_OBJECT (modest_runtime_get_account_store ()),
1039 G_CALLBACK (on_account_inserted),
1042 modest_signal_mgr_connect (priv->sighandlers,
1043 G_OBJECT (modest_runtime_get_account_store ()),
1045 G_CALLBACK (on_account_removed),
1048 /* We need to refresh the send & receive menu to change the bold
1049 * account when the default account changes. */
1051 modest_signal_mgr_connect (priv->sighandlers,
1052 G_OBJECT (modest_runtime_get_account_mgr ()),
1053 "default_account_changed",
1054 G_CALLBACK (on_default_account_changed),
1059 modest_signal_mgr_connect (priv->sighandlers,
1060 G_OBJECT (modest_runtime_get_account_store ()),
1062 G_CALLBACK (on_account_changed),
1067 on_hildon_program_is_topmost_notify(GObject *self,
1068 GParamSpec *propert_param,
1071 HildonProgram *app = HILDON_PROGRAM (self);
1073 /* Note that use of hildon_program_set_can_hibernate()
1074 * is generally referred to as "setting the killable flag",
1075 * though hibernation does not seem equal to death.
1078 if (hildon_program_get_is_topmost (app)) {
1079 /* Prevent hibernation when the progam comes to the foreground,
1080 * because hibernation should only happen when the application
1081 * is in the background: */
1082 hildon_program_set_can_hibernate (app, FALSE);
1084 /* Remove new mail visual notifications */
1085 modest_platform_remove_new_mail_notifications (TRUE);
1087 /* Allow hibernation if the program has gone to the background: */
1089 /* However, prevent hibernation while the settings are being changed: */
1090 const gboolean hibernation_prevented =
1091 modest_window_mgr_get_hibernation_is_prevented (
1092 modest_runtime_get_window_mgr ());
1094 if (hibernation_prevented)
1095 hildon_program_set_can_hibernate (app, FALSE);
1097 /* Allow hibernation, after saving the state: */
1098 modest_osso_save_state();
1099 hildon_program_set_can_hibernate (app, TRUE);
1106 GtkWidget *folder_win;
1111 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1113 ShowHelper *helper = (ShowHelper *) user_data;
1114 GtkWidget *folder_win = helper->folder_win;
1115 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1117 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1118 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1120 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1122 /* Connect signals */
1123 connect_signals (MODEST_MAIN_WINDOW (self));
1125 /* Set account store */
1126 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1127 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1129 /* Load previous osso state, for instance if we are being restored from
1131 modest_osso_load_state ();
1133 /* Restore window & widget settings */
1134 priv->wait_for_settings = TRUE;
1135 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1136 priv->wait_for_settings = FALSE;
1138 /* Check if accounts exist and show the account wizard if not */
1139 gboolean accounts_exist =
1140 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1142 if (!accounts_exist) {
1143 /* This is necessary to have the main window shown behind the dialog
1144 It's an ugly hack... jschmid */
1145 gtk_widget_show_all(GTK_WIDGET(self));
1146 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1149 GtkAction *send_receive_all;
1150 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1151 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1152 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1153 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1154 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1155 modest_account_mgr_free_account_names (accounts);
1156 update_menus (MODEST_MAIN_WINDOW (self));
1159 /* Never call this function again (NOTE that it could happen
1160 as we hide the main window instead of closing it while
1161 there are operations ongoing) and free the helper */
1162 g_signal_handler_disconnect (self, helper->handler_id);
1163 g_slice_free (ShowHelper, helper);
1167 osso_display_event_cb (osso_display_state_t state,
1170 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1172 priv->display_state = state;
1174 /* Stop blinking if the screen becomes on */
1175 if (priv->display_state == OSSO_DISPLAY_ON)
1176 modest_platform_remove_new_mail_notifications (TRUE);
1180 modest_main_window_new (void)
1182 ModestMainWindow *self = NULL;
1183 ModestMainWindowPrivate *priv = NULL;
1184 ModestWindowPrivate *parent_priv = NULL;
1185 GtkWidget *folder_win = NULL;
1186 ModestDimmingRulesGroup *menu_rules_group = NULL;
1187 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1188 GtkActionGroup *action_group = NULL;
1189 GError *error = NULL;
1191 ModestConf *conf = NULL;
1192 GtkAction *action = NULL;
1193 GdkPixbuf *window_icon;
1196 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1197 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1198 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1200 parent_priv->ui_manager = gtk_ui_manager_new();
1201 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1203 action_group = gtk_action_group_new ("ModestMainWindowActions");
1204 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1206 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1207 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1209 /* Add common actions */
1210 gtk_action_group_add_actions (action_group,
1211 modest_action_entries,
1212 G_N_ELEMENTS (modest_action_entries),
1215 gtk_action_group_add_actions (action_group,
1216 modest_folder_view_action_entries,
1217 G_N_ELEMENTS (modest_folder_view_action_entries),
1220 gtk_action_group_add_actions (action_group,
1221 modest_header_view_action_entries,
1222 G_N_ELEMENTS (modest_header_view_action_entries),
1225 gtk_action_group_add_toggle_actions (action_group,
1226 modest_toggle_action_entries,
1227 G_N_ELEMENTS (modest_toggle_action_entries),
1230 gtk_action_group_add_toggle_actions (action_group,
1231 modest_main_window_toggle_action_entries,
1232 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1235 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1236 g_object_unref (action_group);
1238 /* Load the UI definition */
1239 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1240 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1241 if (error != NULL) {
1242 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1243 g_error_free (error);
1247 /* Add common dimming rules */
1248 modest_dimming_rules_group_add_rules (menu_rules_group,
1249 modest_main_window_menu_dimming_entries,
1250 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1251 MODEST_WINDOW (self));
1252 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1253 modest_main_window_toolbar_dimming_entries,
1254 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1255 MODEST_WINDOW (self));
1257 /* Insert dimming rules group for this window */
1258 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1259 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1260 g_object_unref (menu_rules_group);
1261 g_object_unref (toolbar_rules_group);
1263 /* Add accelerators */
1264 gtk_window_add_accel_group (GTK_WINDOW (self),
1265 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1267 /* Menubar. Update the state of some toggles */
1268 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1269 conf = modest_runtime_get_conf ();
1270 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1271 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1272 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1273 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1274 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1275 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1276 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1277 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1278 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1279 gtk_widget_show (parent_priv->menubar);
1281 /* Get device name */
1282 modest_maemo_utils_get_device_name ();
1286 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1287 g_object_ref (priv->header_view);
1288 if (!priv->header_view)
1289 g_printerr ("modest: cannot instantiate header view\n");
1290 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1291 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1292 MODEST_CONF_HEADER_VIEW_KEY);
1294 /* Other style properties of header view */
1295 g_object_set (G_OBJECT (priv->header_view),
1296 "rules-hint", FALSE,
1298 /* gtk_widget_show (priv->header_view); */
1301 priv->empty_view = create_empty_view ();
1302 gtk_widget_show (priv->empty_view);
1303 g_object_ref (priv->empty_view);
1305 /* Create scrolled windows */
1306 folder_win = gtk_scrolled_window_new (NULL, NULL);
1307 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1308 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1310 GTK_POLICY_AUTOMATIC);
1311 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1313 GTK_POLICY_AUTOMATIC);
1314 /* gtk_widget_show (priv->contents_widget); */
1317 priv->main_paned = gtk_hpaned_new ();
1318 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1319 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1320 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1322 /* putting it all together... */
1323 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1324 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1325 gtk_widget_show (priv->main_vbox);
1327 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1329 app = hildon_program_get_instance ();
1330 hildon_program_add_window (app, HILDON_WINDOW (self));
1332 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1333 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1335 /* Connect to "show" action. We delay the creation of some
1336 elements until that moment */
1337 helper = g_slice_new0 (ShowHelper);
1338 helper->folder_win = folder_win;
1339 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1340 G_CALLBACK (modest_main_window_on_show),
1343 /* Set window icon */
1344 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1346 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1347 g_object_unref (window_icon);
1350 /* Listen for changes in the screen, we don't want to show a
1351 led pattern when the display is on for example */
1352 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1353 osso_display_event_cb,
1356 /* Dont't restore settings here,
1357 * because it requires a gtk_widget_show(),
1358 * and we don't want to do that until later,
1359 * so that the UI is not visible for non-menu D-Bus activation.
1362 return MODEST_WINDOW(self);
1366 modest_main_window_set_style (ModestMainWindow *self,
1367 ModestMainWindowStyle style)
1369 ModestMainWindowPrivate *priv;
1370 ModestWindowPrivate *parent_priv;
1374 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1376 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1377 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1379 /* no change -> nothing to do */
1380 if (priv->style == style)
1383 /* Get toggle button and update the state if needed. This will
1384 happen only when the set_style is not invoked from the UI,
1385 for example when it's called from widget memory */
1386 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1387 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1388 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1389 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1390 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1391 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1392 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1395 priv->style = style;
1397 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1399 if (!priv->wait_for_settings)
1400 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1401 MODEST_CONF_MAIN_PANED_KEY);
1402 /* Remove main paned */
1403 g_object_ref (priv->main_paned);
1404 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1406 /* Reparent the contents widget to the main vbox */
1407 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1410 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1411 /* Remove header view */
1412 g_object_ref (priv->contents_widget);
1413 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1415 /* Reparent the main paned */
1416 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1417 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1419 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1423 g_return_if_reached ();
1426 /* Let header view grab the focus if it's being shown */
1427 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1428 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1430 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1433 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1436 ModestMainWindowStyle
1437 modest_main_window_get_style (ModestMainWindow *self)
1439 ModestMainWindowPrivate *priv;
1441 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1443 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1448 toolbar_resize (ModestMainWindow *self)
1450 ModestMainWindowPrivate *priv = NULL;
1451 ModestWindowPrivate *parent_priv = NULL;
1453 gint static_button_size;
1454 ModestWindowMgr *mgr;
1456 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1457 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1458 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1460 mgr = modest_runtime_get_window_mgr ();
1461 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1463 if (parent_priv->toolbar) {
1464 /* left size buttons */
1465 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1466 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1467 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1468 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1469 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1470 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1471 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1472 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1473 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1474 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1475 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1476 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1477 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1478 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1479 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1480 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1482 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1483 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1484 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1485 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1486 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1487 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1488 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1489 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1497 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1499 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1500 ModestWindowPrivate *parent_priv;
1501 ModestWindowMgr *mgr;
1502 gboolean is_fullscreen;
1503 GtkAction *fs_toggle_action;
1506 mgr = modest_runtime_get_window_mgr ();
1508 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1510 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1512 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1513 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1514 if (is_fullscreen != active) {
1515 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1518 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1526 modest_main_window_show_toolbar (ModestWindow *self,
1527 gboolean show_toolbar)
1529 ModestMainWindowPrivate *priv = NULL;
1530 ModestWindowPrivate *parent_priv = NULL;
1531 GtkWidget *reply_button = NULL, *menu = NULL;
1532 GtkWidget *placeholder = NULL;
1534 const gchar *action_name;
1537 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1538 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1539 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1541 /* Set optimized view status */
1542 priv->optimized_view = !show_toolbar;
1544 if (!parent_priv->toolbar) {
1545 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1547 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1549 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1550 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1551 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1552 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1553 toolbar_resize (MODEST_MAIN_WINDOW (self));
1555 /* Add ProgressBar (Transfer toolbar) */
1556 priv->progress_bar = modest_progress_bar_new ();
1557 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1558 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1559 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1560 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1561 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1563 /* Connect cancel 'clicked' signal to abort progress mode */
1564 g_signal_connect(priv->cancel_toolitem, "clicked",
1565 G_CALLBACK(cancel_progressbar),
1568 /* Add it to the observers list */
1569 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1572 hildon_window_add_toolbar (HILDON_WINDOW (self),
1573 GTK_TOOLBAR (parent_priv->toolbar));
1575 /* Set reply button tap and hold menu */
1576 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1577 "/ToolBar/ToolbarMessageReply");
1578 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1579 "/ToolbarReplyCSM");
1580 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1582 /* Set send & receive button tap and hold menu */
1583 update_menus (MODEST_MAIN_WINDOW (self));
1587 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1588 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1589 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1591 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1592 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1593 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1595 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1597 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1601 /* Update also the actions (to update the toggles in the
1602 menus), we have to do it manually because some other window
1603 of the same time could have changed it (remember that the
1604 toolbar fullscreen mode is shared by all the windows of the
1606 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1607 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1609 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1611 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1612 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1617 on_account_inserted (TnyAccountStore *accoust_store,
1618 TnyAccount *account,
1621 /* Transport accounts and local ones (MMC and the Local
1622 folders account do now cause menu changes */
1623 if (TNY_IS_STORE_ACCOUNT (account) &&
1624 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1626 update_menus (MODEST_MAIN_WINDOW (user_data));
1631 on_default_account_changed (ModestAccountMgr* mgr,
1634 update_menus (MODEST_MAIN_WINDOW (user_data));
1638 on_account_removed (TnyAccountStore *accoust_store,
1639 TnyAccount *account,
1642 /* Transport accounts and local ones (MMC and the Local
1643 folders account do now cause menu changes */
1644 if (TNY_IS_STORE_ACCOUNT (account) &&
1645 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1646 update_menus (MODEST_MAIN_WINDOW (user_data));
1650 on_account_changed (TnyAccountStore *account_store,
1651 TnyAccount *account,
1654 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1656 /* Transport accounts and local ones (MMC and the Local
1657 folders account do now cause menu changes */
1658 if (TNY_IS_STORE_ACCOUNT (account)) {
1659 /* We need to refresh the details widget because it could have changed */
1660 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1661 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1663 /* Update the menus as well, name could change */
1664 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1665 update_menus (MODEST_MAIN_WINDOW (user_data));
1670 * This function manages the key events used to navigate between
1671 * header and folder views (when the window is in split view)
1674 * -------------------------------------------------
1675 * HeaderView GDK_Left Move focus to folder view
1676 * FolderView GDK_Right Move focus to header view
1678 * There is no need to scroll to selected row, the widgets will be the
1679 * responsibles of doing that (probably managing the focus-in event
1682 on_inner_widgets_key_pressed (GtkWidget *widget,
1686 ModestMainWindowPrivate *priv;
1688 if (event->type == GDK_KEY_RELEASE)
1691 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1693 /* Do nothing if we're in SIMPLE style */
1694 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1697 if (MODEST_IS_HEADER_VIEW (widget)) {
1698 if (event->keyval == GDK_Left)
1699 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1700 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1701 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1702 if (selected_headers > 1) {
1703 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1706 GtkTreePath * cursor_path;
1707 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1708 if (cursor_path == NULL) {
1709 GtkTreeSelection *selection;
1711 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1712 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1715 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1716 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1721 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1722 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1728 set_alignment (GtkWidget *widget,
1731 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1732 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1736 create_empty_view (void)
1738 GtkLabel *label = NULL;
1739 GtkWidget *align = NULL;
1741 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1742 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1743 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1744 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1746 return GTK_WIDGET(align);
1750 * Free the returned string
1753 get_gray_color_markup (GtkWidget *styled_widget)
1755 gchar *gray_color_markup = NULL;
1756 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1757 /* Obtain the secondary text color. We need a realized widget, that's why
1758 we get styled_widget from outside */
1760 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1761 gray_color_markup = modest_text_utils_get_color_string (&color);
1762 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1764 if (!gray_color_markup)
1765 gray_color_markup = g_strdup ("#BBBBBB");
1767 return gray_color_markup;
1771 * Free the returned string
1774 create_device_name_visual_string (const gchar *device_name,
1775 const gchar *gray_color_markup)
1779 /* We have to use "" to fill the %s of the translation. We can
1780 not just use the device name because the device name is
1781 shown in a different color, so it could not be included
1782 into the <span> tag */
1783 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1784 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1795 GtkWidget *count_label;
1796 GtkWidget *msg_count_label;
1797 GtkWidget *size_label;
1798 gchar *color_markup;
1802 create_uint_label (const gchar *markup,
1806 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1810 create_gchar_label (const gchar *markup,
1814 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1818 update_folder_stats_status_cb (ModestFolderStats stats,
1821 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1824 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1825 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1828 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1829 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1832 if (widgets->size_label) {
1833 tmp = modest_text_utils_get_display_size (stats.local_size);
1834 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1835 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1842 update_folder_stats_cb (ModestFolderStats stats,
1845 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1848 update_folder_stats_status_cb (stats, user_data);
1850 /* frees. Note that the widgets could have been destroyed but
1851 we still keep a reference */
1852 g_free (widgets->color_markup);
1853 if (widgets->count_label)
1854 g_object_unref (widgets->count_label);
1855 if (widgets->msg_count_label)
1856 g_object_unref (widgets->msg_count_label);
1857 if (widgets->size_label)
1858 g_object_unref (widgets->size_label);
1859 g_slice_free (DetailsWidgets, widgets);
1863 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1865 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1870 gchar *gray_color_markup;
1871 DetailsWidgets *widgets;
1873 vbox = gtk_vbox_new (FALSE, 0);
1874 widgets = g_slice_new0 (DetailsWidgets);
1876 gray_color_markup = get_gray_color_markup (styled_widget);
1877 widgets->color_markup = g_strdup (gray_color_markup);
1879 /* Account description: */
1880 if (modest_tny_account_is_virtual_local_folders (account)
1881 || (modest_tny_account_is_memory_card_account (account))) {
1883 /* Get device name */
1884 gchar *device_name = NULL;
1885 if (modest_tny_account_is_virtual_local_folders (account))
1886 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1887 MODEST_CONF_DEVICE_NAME, NULL);
1889 device_name = g_strdup (tny_account_get_name (account));
1891 label = create_device_name_visual_string ((const gchar *) device_name,
1892 (const gchar *) gray_color_markup);
1893 label_w = gtk_label_new (NULL);
1894 gtk_label_set_markup (GTK_LABEL (label_w), label);
1895 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1896 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1897 g_free (device_name);
1900 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1901 gtk_box_pack_start (GTK_BOX (vbox),
1902 gtk_label_new (tny_account_get_name (account)),
1905 /* Other accounts, such as IMAP and POP: */
1910 /* Put proto in uppercase */
1911 proto = g_string_new (tny_account_get_proto (account));
1912 proto = g_string_ascii_up (proto);
1914 /* note: mcen_fi_localroot_description is something like "%s account"
1915 * however, we should display "%s account: %s"... therefore, ugly tmp */
1916 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1917 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1918 gray_color_markup, tmp, tny_account_get_name (account));
1921 label_w = gtk_label_new (NULL);
1922 gtk_label_set_markup (GTK_LABEL (label_w), label);
1923 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1924 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1925 g_string_free (proto, TRUE);
1931 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1932 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1933 label_w = gtk_label_new (NULL);
1934 gtk_label_set_markup (GTK_LABEL (label_w), label);
1935 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1936 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1939 widgets->msg_count_label = g_object_ref (label_w);
1942 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1943 label_w = gtk_label_new (NULL);
1944 gtk_label_set_markup (GTK_LABEL (label_w), label);
1945 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1946 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1949 widgets->count_label = g_object_ref (label_w);
1952 if (modest_tny_account_is_virtual_local_folders (account)
1953 || modest_tny_account_is_memory_card_account (account)) {
1955 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1957 label_w = gtk_label_new (NULL);
1958 gtk_label_set_markup (GTK_LABEL (label_w), label);
1959 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1960 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1963 widgets->size_label = g_object_ref (label_w);
1965 } else if (TNY_IS_ACCOUNT(folder_store)) {
1966 TnyAccount *account = TNY_ACCOUNT(folder_store);
1968 time_t last_updated;
1969 const gchar *last_updated_string;
1970 /* Get last updated from configuration */
1971 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1972 tny_account_get_id (account));
1974 if (last_updated > 0)
1975 last_updated_string = modest_text_utils_get_display_date(last_updated);
1977 last_updated_string = g_strdup (_("mcen_va_never"));
1979 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1980 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1981 label_w = gtk_label_new (NULL);
1982 gtk_label_set_markup (GTK_LABEL (label_w), label);
1983 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1984 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1988 g_free (gray_color_markup);
1990 /* Refresh folder stats asynchronously */
1991 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1992 update_folder_stats_cb,
1993 update_folder_stats_status_cb,
1997 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2003 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2005 ModestMainWindowPrivate *priv = NULL;
2007 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2009 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2011 return priv->send_receive_in_progress;
2015 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2017 GtkAction *action = NULL;
2018 GtkWidget *widget = NULL;
2019 ModestMainWindowPrivate *priv = NULL;
2021 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2022 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2024 priv->send_receive_in_progress = TRUE;
2026 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2027 gtk_action_set_sensitive (action, FALSE);
2028 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2029 /* gtk_action_set_sensitive (action, FALSE); */
2030 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2031 gtk_widget_set_sensitive (widget, FALSE);
2035 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2037 GtkAction *action = NULL;
2038 GtkWidget *widget = NULL;
2039 ModestMainWindowPrivate *priv = NULL;
2041 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2042 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2044 priv->send_receive_in_progress = FALSE;
2046 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2047 gtk_action_set_sensitive (action, TRUE);
2048 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2049 /* gtk_action_set_sensitive (action, TRUE); */
2050 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2051 gtk_widget_set_sensitive (widget, TRUE);
2056 on_msg_count_changed (ModestHeaderView *header_view,
2058 TnyFolderChange *change,
2059 ModestMainWindow *main_window)
2061 gboolean refilter = FALSE;
2062 gboolean folder_empty = FALSE;
2063 gboolean all_marked_as_deleted = FALSE;
2064 ModestMainWindowPrivate *priv;
2066 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2067 g_return_if_fail (TNY_IS_FOLDER(folder));
2068 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2070 if (change != NULL) {
2071 TnyFolderChangeChanged changed;
2073 changed = tny_folder_change_get_changed (change);
2074 /* If something changes */
2075 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2076 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2078 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2080 /* Play a sound (if configured) and make the LED blink */
2081 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2082 modest_platform_push_email_notification ();
2085 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2088 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2091 /* Check if all messages are marked to be deleted */
2092 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2093 folder_empty = folder_empty || all_marked_as_deleted;
2095 /* Set contents style of headers view */
2097 modest_main_window_set_contents_style (main_window,
2098 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2099 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2101 modest_main_window_set_contents_style (main_window,
2102 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2106 modest_header_view_refilter (header_view);
2111 modest_main_window_set_contents_style (ModestMainWindow *self,
2112 ModestMainWindowContentsStyle style)
2114 ModestMainWindowPrivate *priv;
2116 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2118 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2120 /* We allow to set the same content style than the previously
2121 set if there are details, because it could happen when we're
2122 selecting different accounts consecutively */
2123 if ((priv->contents_style == style) &&
2124 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2127 /* Remove previous child. Delete it if it was an account
2129 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2131 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2132 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2135 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2138 priv->contents_style = style;
2140 switch (priv->contents_style) {
2141 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2142 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2143 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2146 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2148 /* if we're started without main win, there may not be a folder
2149 * view. this fixes a GLib-Critical */
2150 if (priv->folder_view) {
2151 TnyFolderStore *selected_folderstore =
2152 modest_folder_view_get_selected (priv->folder_view);
2153 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2154 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2155 TNY_ACCOUNT (selected_folderstore));
2157 wrap_in_scrolled_window (priv->contents_widget,
2158 priv->details_widget);
2160 g_object_unref (selected_folderstore);
2161 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2166 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2167 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2168 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2172 g_return_if_reached ();
2176 gtk_widget_show_all (priv->contents_widget);
2179 ModestMainWindowContentsStyle
2180 modest_main_window_get_contents_style (ModestMainWindow *self)
2182 ModestMainWindowPrivate *priv;
2184 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2186 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2187 return priv->contents_style;
2192 on_configuration_key_changed (ModestConf* conf,
2194 ModestConfEvent event,
2195 ModestConfNotificationId id,
2196 ModestMainWindow *self)
2198 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2199 TnyAccount *account = NULL;
2201 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2204 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2207 if (priv->folder_view)
2208 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2210 if (account && TNY_IS_ACCOUNT (account) &&
2211 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2214 const gchar *device_name;
2215 gchar *new_text, *gray_color_markup;
2218 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2219 label = GTK_LABEL (children->data);
2221 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2222 MODEST_CONF_DEVICE_NAME, NULL);
2224 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2225 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2227 gtk_label_set_markup (label, new_text);
2228 gtk_widget_show (GTK_WIDGET (label));
2230 g_free (gray_color_markup);
2232 g_list_free (children);
2234 g_object_unref (account);
2238 set_toolbar_transfer_mode (ModestMainWindow *self)
2240 ModestMainWindowPrivate *priv = NULL;
2242 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2244 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2246 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2248 if (priv->progress_bar_timeout > 0) {
2249 g_source_remove (priv->progress_bar_timeout);
2250 priv->progress_bar_timeout = 0;
2257 set_toolbar_mode (ModestMainWindow *self,
2258 ModestToolBarModes mode)
2260 ModestWindowPrivate *parent_priv = NULL;
2261 ModestMainWindowPrivate *priv = NULL;
2262 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2264 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2266 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2267 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2269 /* In case this was called before the toolbar exists: */
2270 if (!(parent_priv->toolbar))
2273 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2275 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2276 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2277 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2279 /* Sets current toolbar mode */
2280 priv->current_toolbar_mode = mode;
2282 /* Checks the dimming rules */
2283 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2284 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2286 /* Show and hide toolbar items */
2288 case TOOLBAR_MODE_NORMAL:
2290 gtk_action_set_visible (sort_action, TRUE);
2292 gtk_action_set_visible (refresh_action, TRUE);
2293 if (priv->progress_toolitem) {
2294 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2295 gtk_widget_hide (priv->progress_toolitem);
2297 if (priv->progress_bar)
2298 gtk_widget_hide (priv->progress_bar);
2301 gtk_action_set_visible (cancel_action, FALSE);
2303 /* Hide toolbar if optimized view is enabled */
2304 if (priv->optimized_view)
2305 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2307 case TOOLBAR_MODE_TRANSFER:
2309 gtk_action_set_visible (sort_action, FALSE);
2311 gtk_action_set_visible (refresh_action, FALSE);
2313 gtk_action_set_visible (cancel_action, TRUE);
2314 if (priv->progress_bar)
2315 gtk_widget_show (priv->progress_bar);
2316 if (priv->progress_toolitem) {
2317 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2318 gtk_widget_show (priv->progress_toolitem);
2321 /* Show toolbar if it's hiden (optimized view ) */
2322 if (priv->optimized_view)
2323 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2326 g_return_if_reached ();
2331 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2333 ModestMainWindowPrivate *priv;
2335 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2336 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2338 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2342 cancel_progressbar (GtkToolButton *toolbutton,
2343 ModestMainWindow *self)
2346 ModestMainWindowPrivate *priv;
2348 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2350 /* Get operation observers and cancel all the operations */
2351 tmp = priv->progress_widgets;
2353 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2354 tmp=g_slist_next(tmp);
2359 observers_empty (ModestMainWindow *self)
2362 ModestMainWindowPrivate *priv;
2363 gboolean is_empty = TRUE;
2364 guint pending_ops = 0;
2366 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2367 tmp = priv->progress_widgets;
2369 /* Check all observers */
2370 while (tmp && is_empty) {
2371 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2372 is_empty = pending_ops == 0;
2374 tmp = g_slist_next(tmp);
2382 * Gets the toolbar mode needed for each mail operation. It stores in
2383 * @mode_changed if the toolbar mode has changed or not
2385 static ModestToolBarModes
2386 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2387 ModestMailOperation *mail_op,
2388 gboolean *mode_changed)
2390 ModestToolBarModes mode;
2391 ModestMainWindowPrivate *priv;
2393 *mode_changed = FALSE;
2394 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2396 /* Get toolbar mode from operation id*/
2397 switch (modest_mail_operation_get_type_operation (mail_op)) {
2398 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2399 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2400 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2401 mode = TOOLBAR_MODE_TRANSFER;
2402 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2403 *mode_changed = TRUE;
2406 mode = TOOLBAR_MODE_NORMAL;
2412 on_mail_operation_started (ModestMailOperation *mail_op,
2415 ModestMainWindow *self;
2416 ModestMailOperationTypeOperation op_type;
2417 ModestMainWindowPrivate *priv;
2418 ModestToolBarModes mode;
2420 gboolean mode_changed = FALSE;
2421 TnyAccount *account = NULL;
2423 self = MODEST_MAIN_WINDOW (user_data);
2424 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2426 /* Do not show progress for receiving operations if the
2427 account is the local account or the MMC one */
2428 op_type = modest_mail_operation_get_type_operation (mail_op);
2429 account = modest_mail_operation_get_account (mail_op);
2430 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2433 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2434 modest_tny_account_is_memory_card_account (account));
2436 g_object_unref (account);
2440 /* Show information banner. Remove old timeout */
2441 if (priv->retrieving_banner_timeout > 0) {
2442 g_source_remove (priv->retrieving_banner_timeout);
2443 priv->retrieving_banner_timeout = 0;
2445 /* Create a new timeout */
2446 priv->retrieving_banner_timeout =
2447 g_timeout_add (2000, show_retrieving_banner, self);
2450 /* Not every mail operation has account, noop does not */
2452 g_object_unref (account);
2454 /* Get toolbar mode from operation id*/
2455 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2457 /* Add operation observers and change toolbar if neccessary*/
2458 tmp = priv->progress_widgets;
2459 if (mode == TOOLBAR_MODE_TRANSFER) {
2461 GObject *source = modest_mail_operation_get_source(mail_op);
2462 if (G_OBJECT (self) == source) {
2463 set_toolbar_transfer_mode(self);
2465 g_object_unref (source);
2469 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2471 tmp = g_slist_next (tmp);
2475 /* Update the main menu as well, we need to explicitely do
2476 this in order to enable/disable accelerators */
2477 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2481 on_mail_operation_finished (ModestMailOperation *mail_op,
2484 ModestToolBarModes mode;
2485 ModestMailOperationTypeOperation op_type;
2487 ModestMainWindow *self;
2488 gboolean mode_changed;
2489 TnyAccount *account = NULL;
2490 ModestMainWindowPrivate *priv;
2492 self = MODEST_MAIN_WINDOW (user_data);
2493 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2495 /* The mail operation was not added to the progress objects if
2496 the account was the local account or the MMC one */
2497 op_type = modest_mail_operation_get_type_operation (mail_op);
2498 account = modest_mail_operation_get_account (mail_op);
2499 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2502 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2503 modest_tny_account_is_memory_card_account (account));
2505 g_object_unref (account);
2509 /* Remove old timeout */
2510 if (priv->retrieving_banner_timeout > 0) {
2511 g_source_remove (priv->retrieving_banner_timeout);
2512 priv->retrieving_banner_timeout = 0;
2515 /* Remove the banner if exists */
2516 if (priv->retrieving_banner) {
2517 gtk_widget_destroy (priv->retrieving_banner);
2518 priv->retrieving_banner = NULL;
2522 /* Not every mail operation has account, noop does not */
2524 g_object_unref (account);
2526 /* Get toolbar mode from operation id*/
2527 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2529 /* Change toolbar mode */
2530 tmp = priv->progress_widgets;
2531 if (mode == TOOLBAR_MODE_TRANSFER) {
2533 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2535 tmp = g_slist_next (tmp);
2538 /* If no more operations are being observed, NORMAL mode is enabled again */
2539 if (observers_empty (self)) {
2540 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2546 on_queue_changed (ModestMailOperationQueue *queue,
2547 ModestMailOperation *mail_op,
2548 ModestMailOperationQueueNotification type,
2549 ModestMainWindow *self)
2551 ModestMainWindowPrivate *priv;
2553 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2555 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2556 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2558 "operation-started",
2559 G_CALLBACK (on_mail_operation_started),
2561 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2563 "operation-finished",
2564 G_CALLBACK (on_mail_operation_finished),
2566 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2567 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2569 "operation-started");
2570 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2572 "operation-finished");
2577 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2579 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2581 ModestAccountMgr *mgr;
2582 ModestAccountSettings *settings;
2583 ModestServerAccountSettings *store_settings = NULL;
2585 /* Get account data */
2586 mgr = modest_runtime_get_account_mgr ();
2587 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2589 store_settings = modest_account_settings_get_store_settings (settings);
2591 /* Set the new visible & active account */
2592 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2593 const gchar *account_name;
2595 account_name = modest_account_settings_get_account_name (settings);
2597 modest_folder_view_set_account_id_of_visible_server_account
2599 modest_server_account_settings_get_account_name (store_settings));
2600 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2601 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2603 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2604 if (action != NULL) {
2605 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2606 modest_utils_toggle_action_set_active_block_notify (
2607 GTK_TOGGLE_ACTION (action),
2615 g_object_unref (store_settings);
2616 g_object_unref (settings);
2620 /* Make sure that at least one account is "viewed": */
2622 set_at_least_one_account_visible(ModestMainWindow *self)
2624 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2625 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2627 if (!(priv->folder_view)) {
2628 /* It is too early to do this. */
2632 const gchar *active_server_account_name =
2633 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2635 if (!active_server_account_name ||
2636 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2638 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2639 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2640 if (default_modest_name) {
2641 set_account_visible (self, default_modest_name);
2642 } else if (first_modest_name) {
2643 set_account_visible (self, first_modest_name);
2645 g_free (first_modest_name);
2646 g_free (default_modest_name);
2651 on_show_account_action_toggled (GtkToggleAction *action,
2654 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2656 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2657 if (gtk_toggle_action_get_active (action))
2658 set_account_visible (self, acc_name);
2662 refresh_account (const gchar *account_name)
2666 /* win must already exists here, obviously */
2667 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2670 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2674 /* If account_name == NULL, we must update all (option All) */
2676 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2678 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2683 on_refresh_account_action_activated (GtkAction *action,
2686 refresh_account ((const gchar*) user_data);
2690 on_send_receive_csm_activated (GtkMenuItem *item,
2693 refresh_account ((const gchar*) user_data);
2697 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2699 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2701 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2707 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2709 ModestMainWindow *main_window = NULL;
2711 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2712 main_window = MODEST_MAIN_WINDOW (userdata);
2714 /* Update toolbar dimming state */
2715 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2716 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2722 on_header_view_focus_in (GtkWidget *widget,
2723 GdkEventFocus *event,
2726 ModestMainWindow *main_window = NULL;
2728 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2730 main_window = MODEST_MAIN_WINDOW (userdata);
2732 /* Update toolbar dimming state */
2733 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2734 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2740 on_folder_selection_changed (ModestFolderView *folder_view,
2741 TnyFolderStore *folder_store,
2743 ModestMainWindow *main_window)
2745 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2746 GtkAction *action = NULL;
2747 gboolean show_reply = TRUE;
2748 gboolean show_forward = TRUE;
2749 gboolean show_cancel_send = FALSE;
2750 gboolean show_clipboard = TRUE;
2751 gboolean show_delete = TRUE;
2754 if (TNY_IS_ACCOUNT (folder_store)) {
2755 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2756 } else if (TNY_IS_FOLDER (folder_store)) {
2757 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2758 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2759 TNY_FOLDER (folder_store));
2760 switch (folder_type) {
2761 case TNY_FOLDER_TYPE_DRAFTS:
2762 show_clipboard = show_delete = TRUE;
2763 show_reply = show_forward = show_cancel_send = FALSE;
2765 case TNY_FOLDER_TYPE_SENT:
2766 show_forward = show_clipboard = show_delete = TRUE;
2767 show_reply = show_cancel_send = FALSE;
2769 case TNY_FOLDER_TYPE_OUTBOX:
2770 show_clipboard = show_delete = show_cancel_send = TRUE;
2771 show_reply = show_forward = FALSE;
2773 case TNY_FOLDER_TYPE_INVALID:
2774 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2777 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2778 show_cancel_send = FALSE;
2781 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2782 show_cancel_send = FALSE;
2787 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2788 gtk_action_set_visible (action, show_reply);
2789 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2790 gtk_action_set_visible (action, show_reply);
2791 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2792 gtk_action_set_visible (action, show_forward);
2793 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2794 gtk_action_set_visible (action, show_cancel_send);
2795 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2796 gtk_action_set_visible (action, show_delete);
2798 /* We finally call to the ui actions handler, after updating properly
2799 * the header view CSM */
2800 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2804 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2805 GtkTreeModel *model,
2806 GtkTreeRowReference *row_reference,
2807 ModestMainWindow *self)
2809 ModestMainWindowPrivate *priv = NULL;
2810 GtkTreeModel *header_model = NULL;
2811 GtkTreePath *path = NULL;
2813 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2814 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2815 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2817 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2818 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2820 /* Do nothing if we changed the folder in the main view */
2821 if (header_model != model)
2824 /* Select the message in the header view */
2825 path = gtk_tree_row_reference_get_path (row_reference);
2826 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2828 gtk_tree_path_free (path);
2834 show_updating_banner (gpointer user_data)
2836 ModestMainWindowPrivate *priv = NULL;
2838 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2840 if (priv->updating_banner == NULL) {
2842 /* We're outside the main lock */
2843 gdk_threads_enter ();
2844 priv->updating_banner =
2845 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2846 _CS ("ckdg_pb_updating"));
2847 gdk_threads_leave ();
2850 /* Remove timeout */
2851 priv->updating_banner_timeout = 0;
2856 * We use this function to show/hide a progress banner showing
2857 * "Updating" while the header view is being filled. We're not showing
2858 * it unless the update takes more than 2 seconds
2860 * If starting = TRUE then the refresh is starting, otherwise it means
2861 * that is has just finished
2864 on_updating_msg_list (ModestHeaderView *header_view,
2868 ModestMainWindowPrivate *priv = NULL;
2870 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2872 /* Remove old timeout */
2873 if (priv->updating_banner_timeout > 0) {
2874 g_source_remove (priv->updating_banner_timeout);
2875 priv->updating_banner_timeout = 0;
2878 /* Create a new timeout */
2880 priv->updating_banner_timeout =
2881 g_timeout_add (2000, show_updating_banner, user_data);
2883 /* Remove the banner if exists */
2884 if (priv->updating_banner) {
2885 gtk_widget_destroy (priv->updating_banner);
2886 priv->updating_banner = NULL;
2892 modest_main_window_screen_is_on (ModestMainWindow *self)
2894 ModestMainWindowPrivate *priv = NULL;
2896 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2898 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2900 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2904 remove_banners (ModestMainWindow *window)
2906 ModestMainWindowPrivate *priv;
2908 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2910 if (priv->retrieving_banner_timeout > 0) {
2911 g_source_remove (priv->retrieving_banner_timeout);
2912 priv->retrieving_banner_timeout = 0;
2915 if (priv->retrieving_banner != NULL) {
2916 gtk_widget_destroy (priv->retrieving_banner);
2917 priv->retrieving_banner = NULL;
2920 if (priv->updating_banner_timeout > 0) {
2921 g_source_remove (priv->updating_banner_timeout);
2922 priv->updating_banner_timeout = 0;
2925 if (priv->updating_banner != NULL) {
2926 gtk_widget_destroy (priv->updating_banner);
2927 priv->updating_banner = NULL;
2933 on_window_hide (GObject *gobject,
2937 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2939 if (!GTK_WIDGET_VISIBLE (gobject)) {
2940 TnyFolderStore *folder_store;
2941 ModestMainWindowPrivate *priv;
2943 /* Remove the currently shown banners */
2944 remove_banners (MODEST_MAIN_WINDOW (gobject));
2946 /* Force the folder view to sync the currently selected folder
2947 to save the read/unread status and to expunge messages */
2948 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2949 folder_store = modest_folder_view_get_selected (priv->folder_view);
2950 if (TNY_IS_FOLDER (folder_store)) {
2951 ModestMailOperation *mail_op;
2953 mail_op = modest_mail_operation_new (NULL);
2954 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2956 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2957 g_object_unref (mail_op);
2958 g_object_unref (folder_store);
2964 on_window_destroy (GtkObject *widget,
2967 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2969 remove_banners (MODEST_MAIN_WINDOW (widget));
2973 show_retrieving_banner (gpointer user_data)
2975 ModestMainWindowPrivate *priv = NULL;
2977 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2979 if (priv->retrieving_banner == NULL) {
2981 /* We're outside the main lock */
2982 gdk_threads_enter ();
2983 priv->retrieving_banner =
2984 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2985 _("mcen_ib_getting_items"));
2986 gdk_threads_leave ();
2989 /* Remove timeout */
2990 priv->retrieving_banner_timeout = 0;