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 switch (strcmp (modest_account_settings_get_display_name (a),
543 modest_account_settings_get_display_name (b))) {
551 g_return_val_if_reached (0);
555 /* We use this function to prevent the send&receive CSM to be shown
556 when there are less than two account */
558 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
564 update_menus (ModestMainWindow* self)
566 GSList *account_names, *iter, *accounts;
567 ModestMainWindowPrivate *priv;
568 ModestWindowPrivate *parent_priv;
569 ModestAccountMgr *mgr;
570 gint i, num_accounts;
572 gchar *default_account;
573 const gchar *active_account_name;
574 GtkWidget *send_receive_button, *item;
575 GtkAction *send_receive_all = NULL;
578 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
579 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
581 /* Get enabled account IDs */
582 mgr = modest_runtime_get_account_mgr ();
583 account_names = modest_account_mgr_account_names (mgr, TRUE);
584 iter = account_names;
588 ModestAccountSettings *settings =
589 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
590 accounts = g_slist_prepend (accounts, settings);
594 modest_account_mgr_free_account_names (account_names);
595 account_names = NULL;
597 /* Order the list of accounts by its display name */
598 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
599 num_accounts = g_slist_length (accounts);
601 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
602 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
603 gtk_action_set_visible (send_receive_all, num_accounts > 0);
605 /* Delete old send&receive popup items. We can not just do a
606 menu_detach because it does not work well with
608 if (priv->accounts_popup)
609 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
610 (GtkCallback) gtk_widget_destroy, NULL);
612 /* Delete old entries in the View menu. Do not free groups, it
614 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
616 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
617 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
618 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
619 GTK_ACTION_GROUP (groups->data));
622 if (priv->merge_ids) {
623 for (i = 0; i < priv->merge_ids->len; i++)
624 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
625 g_byte_array_free (priv->merge_ids, TRUE);
627 /* We need to call this in order to ensure
628 that the new actions are added in the right
629 order (alphabetical) */
630 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
632 groups = g_list_next (groups);
634 priv->merge_ids = g_byte_array_sized_new (num_accounts);
636 /* Get send receive button */
637 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
638 "/ToolBar/ToolbarSendReceive");
640 /* Create the menu */
641 if (num_accounts > 1) {
642 if (!priv->accounts_popup)
643 priv->accounts_popup = gtk_menu_new ();
644 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
645 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
646 g_signal_connect (G_OBJECT (item),
648 G_CALLBACK (on_send_receive_csm_activated),
650 item = gtk_separator_menu_item_new ();
651 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
654 /* Create a new action group */
655 default_account = modest_account_mgr_get_default_account (mgr);
656 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
658 if (!active_account_name)
659 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
661 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
663 for (i = 0; i < num_accounts; i++) {
664 gchar *display_name = NULL;
665 const gchar *account_name;
666 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
669 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
672 account_name = modest_account_settings_get_account_name (settings);
674 if (default_account && account_name &&
675 !(strcmp (default_account, account_name) == 0)) {
676 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
677 modest_account_settings_get_display_name (settings));
679 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
680 modest_account_settings_get_display_name (settings));
685 /* Create action and add it to the action group. The
686 action name must be the account name, this way we
687 could know in the handlers the account to show */
688 if (settings && account_name) {
689 gchar* item_name, *refresh_action_name;
691 GtkAction *view_account_action, *refresh_account_action;
692 gchar *escaped_display_name;
694 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
696 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
697 escaped_display_name, NULL, NULL, 0));
698 g_free (escaped_display_name);
699 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
700 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
701 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
703 if (active_account_name) {
704 if (active_account_name && account_name &&
705 (strcmp (active_account_name, account_name) == 0)) {
706 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
710 /* Add ui from account data. We allow 2^9-1 account
711 changes in a single execution because we're
712 downcasting the guint to a guint8 in order to use a
713 GByteArray. It should be enough :-) */
714 item_name = g_strconcat (account_name, "Menu", NULL);
715 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
716 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
717 gtk_ui_manager_add_ui (parent_priv->ui_manager,
719 "/MenuBar/ViewMenu/ViewMenuAdditions",
722 GTK_UI_MANAGER_MENUITEM,
725 /* Connect the action signal "activate" */
726 g_signal_connect_after (G_OBJECT (view_account_action),
728 G_CALLBACK (on_show_account_action_toggled),
731 /* Create the items for the Tools->Send&Receive submenu */
732 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
733 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
734 display_name, NULL, NULL);
735 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
737 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
738 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
739 gtk_ui_manager_add_ui (parent_priv->ui_manager,
741 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
744 GTK_UI_MANAGER_MENUITEM,
746 g_free (refresh_action_name);
748 g_signal_connect_data (G_OBJECT (refresh_account_action),
750 G_CALLBACK (on_refresh_account_action_activated),
751 g_strdup (account_name),
752 (GClosureNotify) g_free,
755 /* Create item and add it to the send&receive
756 CSM. If there is only one account then
758 if (num_accounts > 1) {
759 GtkWidget *label = gtk_label_new(NULL);
760 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
761 if (default_account && (strcmp(account_name, default_account) == 0)) {
762 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
763 gtk_label_set_markup (GTK_LABEL (label), escaped);
766 gtk_label_set_text (GTK_LABEL (label), display_name);
769 item = gtk_menu_item_new ();
770 gtk_container_add (GTK_CONTAINER (item), label);
772 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
774 g_signal_connect_data (G_OBJECT (item),
776 G_CALLBACK (on_send_receive_csm_activated),
777 g_strdup (account_name),
778 (GClosureNotify) g_free,
785 g_free (display_name);
788 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
790 /* We cannot do this in the loop above because this relies on the action
791 * group being inserted. This makes the default account appear in bold.
792 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
793 for (i = 0; i < num_accounts; i++) {
794 gchar *item_name, *path;
796 ModestAccountSettings *settings;
797 const gchar *account_name;
800 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
801 account_name = modest_account_settings_get_account_name (settings);
802 is_default = (account_name && default_account && !strcmp (account_name, default_account));
804 /* Get the item of the view menu */
805 item_name = g_strconcat (account_name, "Menu", NULL);
806 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
807 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
811 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
812 if (GTK_IS_LABEL (child)) {
813 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
815 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
816 gtk_label_set_markup (GTK_LABEL (child), bold_name);
819 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
823 /* Get the item of the tools menu */
824 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
825 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
829 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
830 if (GTK_IS_LABEL (child)) {
831 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
833 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
834 gtk_label_set_markup (GTK_LABEL (child), bold_name);
837 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
842 g_object_unref (settings);
845 if (num_accounts > 1) {
846 /* Disconnect the tap-and-hold-query if it's connected */
847 if (modest_signal_mgr_is_connected (priv->sighandlers,
848 G_OBJECT (send_receive_button),
849 "tap-and-hold-query"))
850 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
851 G_OBJECT (send_receive_button),
852 "tap-and-hold-query");
854 /* Mandatory in order to view the menu contents */
855 gtk_widget_show_all (priv->accounts_popup);
857 /* Setup tap_and_hold just if was not done before*/
858 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
859 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
861 /* Connect the tap-and-hold-query in order not to show the CSM */
862 if (!modest_signal_mgr_is_connected (priv->sighandlers,
863 G_OBJECT (send_receive_button),
864 "tap-and-hold-query"))
865 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
866 G_OBJECT (send_receive_button),
867 "tap-and-hold-query",
868 G_CALLBACK (tap_and_hold_query_cb),
873 g_slist_free (accounts);
874 g_free (default_account);
877 /* Make sure that at least one account is viewed if there are any
878 * accounts, for instance when adding the first account: */
879 set_at_least_one_account_visible (self);
883 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
885 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
886 gtk_scrolled_window_add_with_viewport
887 (GTK_SCROLLED_WINDOW(win), widget);
889 gtk_container_add (GTK_CONTAINER(win),
900 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
902 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
904 GList *oerrsignals = priv->queue_err_signals;
905 while (oerrsignals) {
906 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
907 g_signal_handler_disconnect (esignal->queue, esignal->signal);
908 g_slice_free (QueueErrorSignal, esignal);
909 oerrsignals = g_list_next (oerrsignals);
911 g_list_free (priv->queue_err_signals);
912 priv->queue_err_signals = NULL;
917 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
919 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
922 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
926 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
928 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
930 /* Update visibility */
933 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
937 modest_main_window_disconnect_signals (ModestWindow *self)
939 ModestMainWindowPrivate *priv;
940 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
942 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
943 priv->sighandlers = NULL;
947 connect_signals (ModestMainWindow *self)
949 ModestWindowPrivate *parent_priv;
950 ModestMainWindowPrivate *priv;
953 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
954 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
959 modest_signal_mgr_connect (priv->sighandlers,
960 G_OBJECT(priv->folder_view), "key-press-event",
961 G_CALLBACK(on_inner_widgets_key_pressed), self);
963 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
964 "folder_selection_changed",
965 G_CALLBACK (on_folder_selection_changed),
968 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
969 "folder-display-name-changed",
970 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
973 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
975 G_CALLBACK (on_folder_view_focus_in),
978 /* Folder view CSM */
979 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
980 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
981 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
982 G_CALLBACK(_folder_view_csm_menu_activated),
986 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
987 G_CALLBACK(modest_ui_actions_on_header_selected), self);
989 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
990 G_CALLBACK(modest_ui_actions_on_header_activated), self);
992 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
993 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
995 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
996 G_CALLBACK(on_inner_widgets_key_pressed), self);
998 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
999 G_CALLBACK(on_msg_count_changed), self);
1001 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
1002 G_CALLBACK (on_header_view_focus_in), self);
1004 modest_signal_mgr_connect (priv->sighandlers,
1005 G_OBJECT (priv->header_view),
1006 "updating-msg-list",
1007 G_CALLBACK (on_updating_msg_list),
1010 /* Header view CSM */
1011 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1012 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1014 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1015 G_CALLBACK(_header_view_csm_menu_activated),
1020 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1021 G_CALLBACK (modest_main_window_window_state_event),
1023 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1024 * in destroy stage */
1025 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1027 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1029 /* Mail Operation Queue */
1031 modest_signal_mgr_connect (priv->sighandlers,
1032 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1034 G_CALLBACK (on_queue_changed), self);
1036 /* Track changes in the device name */
1038 modest_signal_mgr_connect (priv->sighandlers,
1039 G_OBJECT(modest_runtime_get_conf ()),
1041 G_CALLBACK (on_configuration_key_changed),
1044 /* Track account changes. We need to refresh the toolbar */
1046 modest_signal_mgr_connect (priv->sighandlers,
1047 G_OBJECT (modest_runtime_get_account_store ()),
1049 G_CALLBACK (on_account_inserted),
1052 modest_signal_mgr_connect (priv->sighandlers,
1053 G_OBJECT (modest_runtime_get_account_store ()),
1055 G_CALLBACK (on_account_removed),
1058 /* We need to refresh the send & receive menu to change the bold
1059 * account when the default account changes. */
1061 modest_signal_mgr_connect (priv->sighandlers,
1062 G_OBJECT (modest_runtime_get_account_mgr ()),
1063 "default_account_changed",
1064 G_CALLBACK (on_default_account_changed),
1069 modest_signal_mgr_connect (priv->sighandlers,
1070 G_OBJECT (modest_runtime_get_account_store ()),
1072 G_CALLBACK (on_account_changed),
1077 on_hildon_program_is_topmost_notify(GObject *self,
1078 GParamSpec *propert_param,
1081 HildonProgram *app = HILDON_PROGRAM (self);
1083 /* Note that use of hildon_program_set_can_hibernate()
1084 * is generally referred to as "setting the killable flag",
1085 * though hibernation does not seem equal to death.
1088 if (hildon_program_get_is_topmost (app)) {
1089 /* Prevent hibernation when the progam comes to the foreground,
1090 * because hibernation should only happen when the application
1091 * is in the background: */
1092 hildon_program_set_can_hibernate (app, FALSE);
1094 /* Remove new mail visual notifications */
1095 modest_platform_remove_new_mail_notifications (TRUE);
1097 /* Allow hibernation if the program has gone to the background: */
1099 /* However, prevent hibernation while the settings are being changed: */
1100 const gboolean hibernation_prevented =
1101 modest_window_mgr_get_hibernation_is_prevented (
1102 modest_runtime_get_window_mgr ());
1104 if (hibernation_prevented)
1105 hildon_program_set_can_hibernate (app, FALSE);
1107 /* Allow hibernation, after saving the state: */
1108 modest_osso_save_state();
1109 hildon_program_set_can_hibernate (app, TRUE);
1116 GtkWidget *folder_win;
1121 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1123 ShowHelper *helper = (ShowHelper *) user_data;
1124 GtkWidget *folder_win = helper->folder_win;
1125 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1127 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1128 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1130 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1132 /* Connect signals */
1133 connect_signals (MODEST_MAIN_WINDOW (self));
1135 /* Set account store */
1136 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1137 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1139 /* Load previous osso state, for instance if we are being restored from
1141 modest_osso_load_state ();
1143 /* Restore window & widget settings */
1144 priv->wait_for_settings = TRUE;
1145 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1146 priv->wait_for_settings = FALSE;
1148 /* Check if accounts exist and show the account wizard if not */
1149 gboolean accounts_exist =
1150 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1152 if (!accounts_exist) {
1153 /* This is necessary to have the main window shown behind the dialog
1154 It's an ugly hack... jschmid */
1155 gtk_widget_show_all(GTK_WIDGET(self));
1156 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1159 GtkAction *send_receive_all;
1160 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1161 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1162 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1163 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1164 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1165 modest_account_mgr_free_account_names (accounts);
1166 update_menus (MODEST_MAIN_WINDOW (self));
1169 /* Never call this function again (NOTE that it could happen
1170 as we hide the main window instead of closing it while
1171 there are operations ongoing) and free the helper */
1172 g_signal_handler_disconnect (self, helper->handler_id);
1173 g_slice_free (ShowHelper, helper);
1177 osso_display_event_cb (osso_display_state_t state,
1180 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1182 priv->display_state = state;
1184 /* Stop blinking if the screen becomes on */
1185 if (priv->display_state == OSSO_DISPLAY_ON)
1186 modest_platform_remove_new_mail_notifications (TRUE);
1190 modest_main_window_new (void)
1192 ModestMainWindow *self = NULL;
1193 ModestMainWindowPrivate *priv = NULL;
1194 ModestWindowPrivate *parent_priv = NULL;
1195 GtkWidget *folder_win = NULL;
1196 ModestDimmingRulesGroup *menu_rules_group = NULL;
1197 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1198 GtkActionGroup *action_group = NULL;
1199 GError *error = NULL;
1201 ModestConf *conf = NULL;
1202 GtkAction *action = NULL;
1203 GdkPixbuf *window_icon;
1206 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1207 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1208 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1210 parent_priv->ui_manager = gtk_ui_manager_new();
1211 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1213 action_group = gtk_action_group_new ("ModestMainWindowActions");
1214 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1216 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1217 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1219 /* Add common actions */
1220 gtk_action_group_add_actions (action_group,
1221 modest_action_entries,
1222 G_N_ELEMENTS (modest_action_entries),
1225 gtk_action_group_add_actions (action_group,
1226 modest_folder_view_action_entries,
1227 G_N_ELEMENTS (modest_folder_view_action_entries),
1230 gtk_action_group_add_actions (action_group,
1231 modest_header_view_action_entries,
1232 G_N_ELEMENTS (modest_header_view_action_entries),
1235 gtk_action_group_add_toggle_actions (action_group,
1236 modest_toggle_action_entries,
1237 G_N_ELEMENTS (modest_toggle_action_entries),
1240 gtk_action_group_add_toggle_actions (action_group,
1241 modest_main_window_toggle_action_entries,
1242 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1245 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1246 g_object_unref (action_group);
1248 /* Load the UI definition */
1249 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1250 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1251 if (error != NULL) {
1252 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1253 g_error_free (error);
1257 /* Add common dimming rules */
1258 modest_dimming_rules_group_add_rules (menu_rules_group,
1259 modest_main_window_menu_dimming_entries,
1260 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1261 MODEST_WINDOW (self));
1262 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1263 modest_main_window_toolbar_dimming_entries,
1264 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1265 MODEST_WINDOW (self));
1267 /* Insert dimming rules group for this window */
1268 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1269 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1270 g_object_unref (menu_rules_group);
1271 g_object_unref (toolbar_rules_group);
1273 /* Add accelerators */
1274 gtk_window_add_accel_group (GTK_WINDOW (self),
1275 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1277 /* Menubar. Update the state of some toggles */
1278 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1279 conf = modest_runtime_get_conf ();
1280 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1281 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1282 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1283 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1284 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1285 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1286 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1287 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1288 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1289 gtk_widget_show (parent_priv->menubar);
1291 /* Get device name */
1292 modest_maemo_utils_get_device_name ();
1296 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1297 g_object_ref (priv->header_view);
1298 if (!priv->header_view)
1299 g_printerr ("modest: cannot instantiate header view\n");
1300 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1301 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1302 MODEST_CONF_HEADER_VIEW_KEY);
1304 /* Other style properties of header view */
1305 g_object_set (G_OBJECT (priv->header_view),
1306 "rules-hint", FALSE,
1308 /* gtk_widget_show (priv->header_view); */
1311 priv->empty_view = create_empty_view ();
1312 gtk_widget_show (priv->empty_view);
1313 g_object_ref (priv->empty_view);
1315 /* Create scrolled windows */
1316 folder_win = gtk_scrolled_window_new (NULL, NULL);
1317 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1318 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1320 GTK_POLICY_AUTOMATIC);
1321 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1323 GTK_POLICY_AUTOMATIC);
1324 /* gtk_widget_show (priv->contents_widget); */
1327 priv->main_paned = gtk_hpaned_new ();
1328 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1329 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1330 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1332 /* putting it all together... */
1333 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1334 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1335 gtk_widget_show (priv->main_vbox);
1337 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1339 app = hildon_program_get_instance ();
1340 hildon_program_add_window (app, HILDON_WINDOW (self));
1342 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1343 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1345 /* Connect to "show" action. We delay the creation of some
1346 elements until that moment */
1347 helper = g_slice_new0 (ShowHelper);
1348 helper->folder_win = folder_win;
1349 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1350 G_CALLBACK (modest_main_window_on_show),
1353 /* Set window icon */
1354 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1356 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1357 g_object_unref (window_icon);
1360 /* Listen for changes in the screen, we don't want to show a
1361 led pattern when the display is on for example */
1362 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1363 osso_display_event_cb,
1366 /* Dont't restore settings here,
1367 * because it requires a gtk_widget_show(),
1368 * and we don't want to do that until later,
1369 * so that the UI is not visible for non-menu D-Bus activation.
1372 return MODEST_WINDOW(self);
1376 modest_main_window_set_style (ModestMainWindow *self,
1377 ModestMainWindowStyle style)
1379 ModestMainWindowPrivate *priv;
1380 ModestWindowPrivate *parent_priv;
1384 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1386 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1387 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1389 /* no change -> nothing to do */
1390 if (priv->style == style)
1393 /* Get toggle button and update the state if needed. This will
1394 happen only when the set_style is not invoked from the UI,
1395 for example when it's called from widget memory */
1396 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1397 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1398 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1399 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1400 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1401 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1402 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1405 priv->style = style;
1407 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1409 if (!priv->wait_for_settings)
1410 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1411 MODEST_CONF_MAIN_PANED_KEY);
1412 /* Remove main paned */
1413 g_object_ref (priv->main_paned);
1414 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1416 /* Reparent the contents widget to the main vbox */
1417 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1420 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1421 /* Remove header view */
1422 g_object_ref (priv->contents_widget);
1423 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1425 /* Reparent the main paned */
1426 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1427 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1429 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1433 g_return_if_reached ();
1436 /* Let header view grab the focus if it's being shown */
1437 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1438 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1440 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1443 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1446 ModestMainWindowStyle
1447 modest_main_window_get_style (ModestMainWindow *self)
1449 ModestMainWindowPrivate *priv;
1451 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1453 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1458 toolbar_resize (ModestMainWindow *self)
1460 ModestMainWindowPrivate *priv = NULL;
1461 ModestWindowPrivate *parent_priv = NULL;
1463 gint static_button_size;
1464 ModestWindowMgr *mgr;
1466 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1467 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1468 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1470 mgr = modest_runtime_get_window_mgr ();
1471 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1473 if (parent_priv->toolbar) {
1474 /* left size buttons */
1475 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1478 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1479 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1480 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1482 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1483 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1484 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1485 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1486 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1487 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1488 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1489 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1490 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1492 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1493 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1494 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1495 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1496 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1497 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1498 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1499 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1507 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1509 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1510 ModestWindowPrivate *parent_priv;
1511 ModestWindowMgr *mgr;
1512 gboolean is_fullscreen;
1513 GtkAction *fs_toggle_action;
1516 mgr = modest_runtime_get_window_mgr ();
1518 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1520 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1522 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1523 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1524 if (is_fullscreen != active) {
1525 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1528 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1536 modest_main_window_show_toolbar (ModestWindow *self,
1537 gboolean show_toolbar)
1539 ModestMainWindowPrivate *priv = NULL;
1540 ModestWindowPrivate *parent_priv = NULL;
1541 GtkWidget *reply_button = NULL, *menu = NULL;
1542 GtkWidget *placeholder = NULL;
1544 const gchar *action_name;
1547 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1548 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1549 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1551 /* Set optimized view status */
1552 priv->optimized_view = !show_toolbar;
1554 if (!parent_priv->toolbar) {
1555 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1557 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1559 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1560 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1561 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1562 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1563 toolbar_resize (MODEST_MAIN_WINDOW (self));
1565 /* Add ProgressBar (Transfer toolbar) */
1566 priv->progress_bar = modest_progress_bar_new ();
1567 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1568 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1569 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1570 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1571 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1573 /* Connect cancel 'clicked' signal to abort progress mode */
1574 g_signal_connect(priv->cancel_toolitem, "clicked",
1575 G_CALLBACK(cancel_progressbar),
1578 /* Add it to the observers list */
1579 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1582 hildon_window_add_toolbar (HILDON_WINDOW (self),
1583 GTK_TOOLBAR (parent_priv->toolbar));
1585 /* Set reply button tap and hold menu */
1586 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1587 "/ToolBar/ToolbarMessageReply");
1588 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1589 "/ToolbarReplyCSM");
1590 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1592 /* Set send & receive button tap and hold menu */
1593 update_menus (MODEST_MAIN_WINDOW (self));
1597 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1598 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1599 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1601 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1602 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1603 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1605 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1607 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1611 /* Update also the actions (to update the toggles in the
1612 menus), we have to do it manually because some other window
1613 of the same time could have changed it (remember that the
1614 toolbar fullscreen mode is shared by all the windows of the
1616 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1617 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1619 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1621 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1622 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1627 on_account_inserted (TnyAccountStore *accoust_store,
1628 TnyAccount *account,
1631 /* Transport accounts and local ones (MMC and the Local
1632 folders account do now cause menu changes */
1633 if (TNY_IS_STORE_ACCOUNT (account) &&
1634 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1636 update_menus (MODEST_MAIN_WINDOW (user_data));
1641 on_default_account_changed (ModestAccountMgr* mgr,
1644 update_menus (MODEST_MAIN_WINDOW (user_data));
1648 on_account_removed (TnyAccountStore *accoust_store,
1649 TnyAccount *account,
1652 /* Transport accounts and local ones (MMC and the Local
1653 folders account do now cause menu changes */
1654 if (TNY_IS_STORE_ACCOUNT (account) &&
1655 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1656 update_menus (MODEST_MAIN_WINDOW (user_data));
1660 on_account_changed (TnyAccountStore *account_store,
1661 TnyAccount *account,
1664 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1666 /* Transport accounts and local ones (MMC and the Local
1667 folders account do now cause menu changes */
1668 if (TNY_IS_STORE_ACCOUNT (account)) {
1669 /* We need to refresh the details widget because it could have changed */
1670 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1671 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1673 /* Update the menus as well, name could change */
1674 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1675 update_menus (MODEST_MAIN_WINDOW (user_data));
1680 * This function manages the key events used to navigate between
1681 * header and folder views (when the window is in split view)
1684 * -------------------------------------------------
1685 * HeaderView GDK_Left Move focus to folder view
1686 * FolderView GDK_Right Move focus to header view
1688 * There is no need to scroll to selected row, the widgets will be the
1689 * responsibles of doing that (probably managing the focus-in event
1692 on_inner_widgets_key_pressed (GtkWidget *widget,
1696 ModestMainWindowPrivate *priv;
1698 if (event->type == GDK_KEY_RELEASE)
1701 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1703 /* Do nothing if we're in SIMPLE style */
1704 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1707 if (MODEST_IS_HEADER_VIEW (widget)) {
1708 if (event->keyval == GDK_Left)
1709 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1710 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1711 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1712 if (selected_headers > 1) {
1713 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1716 GtkTreePath * cursor_path;
1717 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1718 if (cursor_path == NULL) {
1719 GtkTreeSelection *selection;
1721 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1722 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1725 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1726 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1731 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1732 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1738 set_alignment (GtkWidget *widget,
1741 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1742 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1746 create_empty_view (void)
1748 GtkLabel *label = NULL;
1749 GtkWidget *align = NULL;
1751 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1752 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1753 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1754 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1756 return GTK_WIDGET(align);
1760 * Free the returned string
1763 get_gray_color_markup (GtkWidget *styled_widget)
1765 gchar *gray_color_markup = NULL;
1766 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1767 /* Obtain the secondary text color. We need a realized widget, that's why
1768 we get styled_widget from outside */
1770 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1771 gray_color_markup = modest_text_utils_get_color_string (&color);
1772 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1774 if (!gray_color_markup)
1775 gray_color_markup = g_strdup ("#BBBBBB");
1777 return gray_color_markup;
1781 * Free the returned string
1784 create_device_name_visual_string (const gchar *device_name,
1785 const gchar *gray_color_markup)
1789 /* We have to use "" to fill the %s of the translation. We can
1790 not just use the device name because the device name is
1791 shown in a different color, so it could not be included
1792 into the <span> tag */
1793 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1794 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1805 GtkWidget *count_label;
1806 GtkWidget *msg_count_label;
1807 GtkWidget *size_label;
1808 gchar *color_markup;
1812 create_uint_label (const gchar *markup,
1816 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1820 create_gchar_label (const gchar *markup,
1824 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1828 update_folder_stats_status_cb (ModestFolderStats stats,
1831 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1834 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1835 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1838 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1839 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1842 if (widgets->size_label) {
1843 tmp = modest_text_utils_get_display_size (stats.local_size);
1844 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1845 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1852 update_folder_stats_cb (ModestFolderStats stats,
1855 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1858 update_folder_stats_status_cb (stats, user_data);
1860 /* frees. Note that the widgets could have been destroyed but
1861 we still keep a reference */
1862 g_free (widgets->color_markup);
1863 if (widgets->count_label)
1864 g_object_unref (widgets->count_label);
1865 if (widgets->msg_count_label)
1866 g_object_unref (widgets->msg_count_label);
1867 if (widgets->size_label)
1868 g_object_unref (widgets->size_label);
1869 g_slice_free (DetailsWidgets, widgets);
1873 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1875 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1880 gchar *gray_color_markup;
1881 DetailsWidgets *widgets;
1883 vbox = gtk_vbox_new (FALSE, 0);
1884 widgets = g_slice_new0 (DetailsWidgets);
1886 gray_color_markup = get_gray_color_markup (styled_widget);
1887 widgets->color_markup = g_strdup (gray_color_markup);
1889 /* Account description: */
1890 if (modest_tny_account_is_virtual_local_folders (account)
1891 || (modest_tny_account_is_memory_card_account (account))) {
1893 /* Get device name */
1894 gchar *device_name = NULL;
1895 if (modest_tny_account_is_virtual_local_folders (account))
1896 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1897 MODEST_CONF_DEVICE_NAME, NULL);
1899 device_name = g_strdup (tny_account_get_name (account));
1901 label = create_device_name_visual_string ((const gchar *) device_name,
1902 (const gchar *) gray_color_markup);
1903 label_w = gtk_label_new (NULL);
1904 gtk_label_set_markup (GTK_LABEL (label_w), label);
1905 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1906 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1907 g_free (device_name);
1910 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1911 gtk_box_pack_start (GTK_BOX (vbox),
1912 gtk_label_new (tny_account_get_name (account)),
1915 /* Other accounts, such as IMAP and POP: */
1920 /* Put proto in uppercase */
1921 proto = g_string_new (tny_account_get_proto (account));
1922 proto = g_string_ascii_up (proto);
1924 /* note: mcen_fi_localroot_description is something like "%s account"
1925 * however, we should display "%s account: %s"... therefore, ugly tmp */
1926 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1927 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1928 gray_color_markup, tmp, tny_account_get_name (account));
1931 label_w = gtk_label_new (NULL);
1932 gtk_label_set_markup (GTK_LABEL (label_w), label);
1933 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1934 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1935 g_string_free (proto, TRUE);
1941 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1942 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 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->msg_count_label = g_object_ref (label_w);
1952 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1953 label_w = gtk_label_new (NULL);
1954 gtk_label_set_markup (GTK_LABEL (label_w), label);
1955 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1956 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1959 widgets->count_label = g_object_ref (label_w);
1962 if (modest_tny_account_is_virtual_local_folders (account)
1963 || modest_tny_account_is_memory_card_account (account)) {
1965 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1967 label_w = gtk_label_new (NULL);
1968 gtk_label_set_markup (GTK_LABEL (label_w), label);
1969 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1970 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1973 widgets->size_label = g_object_ref (label_w);
1975 } else if (TNY_IS_ACCOUNT(folder_store)) {
1976 TnyAccount *account = TNY_ACCOUNT(folder_store);
1978 time_t last_updated;
1979 const gchar *last_updated_string;
1980 /* Get last updated from configuration */
1981 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1982 tny_account_get_id (account));
1984 if (last_updated > 0)
1985 last_updated_string = modest_text_utils_get_display_date(last_updated);
1987 last_updated_string = g_strdup (_("mcen_va_never"));
1989 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1990 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1991 label_w = gtk_label_new (NULL);
1992 gtk_label_set_markup (GTK_LABEL (label_w), label);
1993 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1994 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1998 g_free (gray_color_markup);
2000 /* Refresh folder stats asynchronously */
2001 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
2002 update_folder_stats_cb,
2003 update_folder_stats_status_cb,
2007 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2013 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2015 ModestMainWindowPrivate *priv = NULL;
2017 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2019 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2021 return priv->send_receive_in_progress;
2025 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2027 GtkAction *action = NULL;
2028 GtkWidget *widget = NULL;
2029 ModestMainWindowPrivate *priv = NULL;
2031 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2032 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2034 priv->send_receive_in_progress = TRUE;
2036 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2037 gtk_action_set_sensitive (action, FALSE);
2038 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2039 /* gtk_action_set_sensitive (action, FALSE); */
2040 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2041 gtk_widget_set_sensitive (widget, FALSE);
2045 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2047 GtkAction *action = NULL;
2048 GtkWidget *widget = NULL;
2049 ModestMainWindowPrivate *priv = NULL;
2051 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2052 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2054 priv->send_receive_in_progress = FALSE;
2056 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2057 gtk_action_set_sensitive (action, TRUE);
2058 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2059 /* gtk_action_set_sensitive (action, TRUE); */
2060 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2061 gtk_widget_set_sensitive (widget, TRUE);
2066 on_msg_count_changed (ModestHeaderView *header_view,
2068 TnyFolderChange *change,
2069 ModestMainWindow *main_window)
2071 gboolean refilter = FALSE;
2072 gboolean folder_empty = FALSE;
2073 gboolean all_marked_as_deleted = FALSE;
2074 ModestMainWindowPrivate *priv;
2076 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2077 g_return_if_fail (TNY_IS_FOLDER(folder));
2078 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2080 if (change != NULL) {
2081 TnyFolderChangeChanged changed;
2083 changed = tny_folder_change_get_changed (change);
2084 /* If something changes */
2085 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2086 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2088 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2090 /* Play a sound (if configured) and make the LED blink */
2091 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2092 modest_platform_push_email_notification ();
2095 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2098 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2101 /* Check if all messages are marked to be deleted */
2102 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2103 folder_empty = folder_empty || all_marked_as_deleted;
2105 /* Set contents style of headers view */
2107 modest_main_window_set_contents_style (main_window,
2108 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2109 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2111 modest_main_window_set_contents_style (main_window,
2112 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2116 modest_header_view_refilter (header_view);
2121 modest_main_window_set_contents_style (ModestMainWindow *self,
2122 ModestMainWindowContentsStyle style)
2124 ModestMainWindowPrivate *priv;
2126 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2128 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2130 /* We allow to set the same content style than the previously
2131 set if there are details, because it could happen when we're
2132 selecting different accounts consecutively */
2133 if ((priv->contents_style == style) &&
2134 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2137 /* Remove previous child. Delete it if it was an account
2139 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2141 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2142 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2145 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2148 priv->contents_style = style;
2150 switch (priv->contents_style) {
2151 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2152 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2153 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2156 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2158 /* if we're started without main win, there may not be a folder
2159 * view. this fixes a GLib-Critical */
2160 if (priv->folder_view) {
2161 TnyFolderStore *selected_folderstore =
2162 modest_folder_view_get_selected (priv->folder_view);
2163 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2164 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2165 TNY_ACCOUNT (selected_folderstore));
2167 wrap_in_scrolled_window (priv->contents_widget,
2168 priv->details_widget);
2170 g_object_unref (selected_folderstore);
2171 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2176 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2177 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2178 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2182 g_return_if_reached ();
2186 gtk_widget_show_all (priv->contents_widget);
2189 ModestMainWindowContentsStyle
2190 modest_main_window_get_contents_style (ModestMainWindow *self)
2192 ModestMainWindowPrivate *priv;
2194 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2196 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2197 return priv->contents_style;
2202 on_configuration_key_changed (ModestConf* conf,
2204 ModestConfEvent event,
2205 ModestConfNotificationId id,
2206 ModestMainWindow *self)
2208 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2209 TnyAccount *account = NULL;
2211 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2214 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2217 if (priv->folder_view)
2218 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2220 if (account && TNY_IS_ACCOUNT (account) &&
2221 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2224 const gchar *device_name;
2225 gchar *new_text, *gray_color_markup;
2228 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2229 label = GTK_LABEL (children->data);
2231 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2232 MODEST_CONF_DEVICE_NAME, NULL);
2234 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2235 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2237 gtk_label_set_markup (label, new_text);
2238 gtk_widget_show (GTK_WIDGET (label));
2240 g_free (gray_color_markup);
2242 g_list_free (children);
2244 g_object_unref (account);
2248 set_toolbar_transfer_mode (ModestMainWindow *self)
2250 ModestMainWindowPrivate *priv = NULL;
2252 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2254 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2256 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2258 if (priv->progress_bar_timeout > 0) {
2259 g_source_remove (priv->progress_bar_timeout);
2260 priv->progress_bar_timeout = 0;
2267 set_toolbar_mode (ModestMainWindow *self,
2268 ModestToolBarModes mode)
2270 ModestWindowPrivate *parent_priv = NULL;
2271 ModestMainWindowPrivate *priv = NULL;
2272 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2274 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2276 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2277 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2279 /* In case this was called before the toolbar exists: */
2280 if (!(parent_priv->toolbar))
2283 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2285 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2286 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2287 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2289 /* Sets current toolbar mode */
2290 priv->current_toolbar_mode = mode;
2292 /* Checks the dimming rules */
2293 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2294 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2296 /* Show and hide toolbar items */
2298 case TOOLBAR_MODE_NORMAL:
2300 gtk_action_set_visible (sort_action, TRUE);
2302 gtk_action_set_visible (refresh_action, TRUE);
2303 if (priv->progress_toolitem) {
2304 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2305 gtk_widget_hide (priv->progress_toolitem);
2307 if (priv->progress_bar)
2308 gtk_widget_hide (priv->progress_bar);
2311 gtk_action_set_visible (cancel_action, FALSE);
2313 /* Hide toolbar if optimized view is enabled */
2314 if (priv->optimized_view)
2315 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2317 case TOOLBAR_MODE_TRANSFER:
2319 gtk_action_set_visible (sort_action, FALSE);
2321 gtk_action_set_visible (refresh_action, FALSE);
2323 gtk_action_set_visible (cancel_action, TRUE);
2324 if (priv->progress_bar)
2325 gtk_widget_show (priv->progress_bar);
2326 if (priv->progress_toolitem) {
2327 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2328 gtk_widget_show (priv->progress_toolitem);
2331 /* Show toolbar if it's hiden (optimized view ) */
2332 if (priv->optimized_view)
2333 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2336 g_return_if_reached ();
2341 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2343 ModestMainWindowPrivate *priv;
2345 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2348 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2352 cancel_progressbar (GtkToolButton *toolbutton,
2353 ModestMainWindow *self)
2356 ModestMainWindowPrivate *priv;
2358 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2360 /* Get operation observers and cancel all the operations */
2361 tmp = priv->progress_widgets;
2363 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2364 tmp=g_slist_next(tmp);
2369 observers_empty (ModestMainWindow *self)
2372 ModestMainWindowPrivate *priv;
2373 gboolean is_empty = TRUE;
2374 guint pending_ops = 0;
2376 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2377 tmp = priv->progress_widgets;
2379 /* Check all observers */
2380 while (tmp && is_empty) {
2381 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2382 is_empty = pending_ops == 0;
2384 tmp = g_slist_next(tmp);
2392 * Gets the toolbar mode needed for each mail operation. It stores in
2393 * @mode_changed if the toolbar mode has changed or not
2395 static ModestToolBarModes
2396 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2397 ModestMailOperation *mail_op,
2398 gboolean *mode_changed)
2400 ModestToolBarModes mode;
2401 ModestMainWindowPrivate *priv;
2403 *mode_changed = FALSE;
2404 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2406 /* Get toolbar mode from operation id*/
2407 switch (modest_mail_operation_get_type_operation (mail_op)) {
2408 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2409 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2410 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2411 mode = TOOLBAR_MODE_TRANSFER;
2412 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2413 *mode_changed = TRUE;
2416 mode = TOOLBAR_MODE_NORMAL;
2422 on_mail_operation_started (ModestMailOperation *mail_op,
2425 ModestMainWindow *self;
2426 ModestMailOperationTypeOperation op_type;
2427 ModestMainWindowPrivate *priv;
2428 ModestToolBarModes mode;
2430 gboolean mode_changed = FALSE;
2431 TnyAccount *account = NULL;
2433 self = MODEST_MAIN_WINDOW (user_data);
2434 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2436 /* Do not show progress for receiving operations if the
2437 account is the local account or the MMC one */
2438 op_type = modest_mail_operation_get_type_operation (mail_op);
2439 account = modest_mail_operation_get_account (mail_op);
2440 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2443 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2444 modest_tny_account_is_memory_card_account (account));
2446 g_object_unref (account);
2450 /* Show information banner. Remove old timeout */
2451 if (priv->retrieving_banner_timeout > 0) {
2452 g_source_remove (priv->retrieving_banner_timeout);
2453 priv->retrieving_banner_timeout = 0;
2455 /* Create a new timeout */
2456 priv->retrieving_banner_timeout =
2457 g_timeout_add (2000, show_retrieving_banner, self);
2460 /* Not every mail operation has account, noop does not */
2462 g_object_unref (account);
2464 /* Get toolbar mode from operation id*/
2465 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2467 /* Add operation observers and change toolbar if neccessary*/
2468 tmp = priv->progress_widgets;
2469 if (mode == TOOLBAR_MODE_TRANSFER) {
2471 GObject *source = modest_mail_operation_get_source(mail_op);
2472 if (G_OBJECT (self) == source) {
2473 set_toolbar_transfer_mode(self);
2475 g_object_unref (source);
2479 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2481 tmp = g_slist_next (tmp);
2485 /* Update the main menu as well, we need to explicitely do
2486 this in order to enable/disable accelerators */
2487 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2491 on_mail_operation_finished (ModestMailOperation *mail_op,
2494 ModestToolBarModes mode;
2495 ModestMailOperationTypeOperation op_type;
2497 ModestMainWindow *self;
2498 gboolean mode_changed;
2499 TnyAccount *account = NULL;
2500 ModestMainWindowPrivate *priv;
2502 self = MODEST_MAIN_WINDOW (user_data);
2503 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2505 /* The mail operation was not added to the progress objects if
2506 the account was the local account or the MMC one */
2507 op_type = modest_mail_operation_get_type_operation (mail_op);
2508 account = modest_mail_operation_get_account (mail_op);
2509 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2512 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2513 modest_tny_account_is_memory_card_account (account));
2515 g_object_unref (account);
2519 /* Remove old timeout */
2520 if (priv->retrieving_banner_timeout > 0) {
2521 g_source_remove (priv->retrieving_banner_timeout);
2522 priv->retrieving_banner_timeout = 0;
2525 /* Remove the banner if exists */
2526 if (priv->retrieving_banner) {
2527 gtk_widget_destroy (priv->retrieving_banner);
2528 priv->retrieving_banner = NULL;
2532 /* Not every mail operation has account, noop does not */
2534 g_object_unref (account);
2536 /* Get toolbar mode from operation id*/
2537 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2539 /* Change toolbar mode */
2540 tmp = priv->progress_widgets;
2541 if (mode == TOOLBAR_MODE_TRANSFER) {
2543 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2545 tmp = g_slist_next (tmp);
2548 /* If no more operations are being observed, NORMAL mode is enabled again */
2549 if (observers_empty (self)) {
2550 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2556 on_queue_changed (ModestMailOperationQueue *queue,
2557 ModestMailOperation *mail_op,
2558 ModestMailOperationQueueNotification type,
2559 ModestMainWindow *self)
2561 ModestMainWindowPrivate *priv;
2563 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2565 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2566 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2568 "operation-started",
2569 G_CALLBACK (on_mail_operation_started),
2571 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2573 "operation-finished",
2574 G_CALLBACK (on_mail_operation_finished),
2576 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2577 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2579 "operation-started");
2580 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2582 "operation-finished");
2587 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2589 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2591 ModestAccountMgr *mgr;
2592 ModestAccountSettings *settings;
2593 ModestServerAccountSettings *store_settings = NULL;
2595 /* Get account data */
2596 mgr = modest_runtime_get_account_mgr ();
2597 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2599 store_settings = modest_account_settings_get_store_settings (settings);
2601 /* Set the new visible & active account */
2602 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2603 const gchar *account_name;
2605 account_name = modest_account_settings_get_account_name (settings);
2607 modest_folder_view_set_account_id_of_visible_server_account
2609 modest_server_account_settings_get_account_name (store_settings));
2610 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2611 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2613 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2614 if (action != NULL) {
2615 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2616 modest_utils_toggle_action_set_active_block_notify (
2617 GTK_TOGGLE_ACTION (action),
2625 g_object_unref (store_settings);
2626 g_object_unref (settings);
2630 /* Make sure that at least one account is "viewed": */
2632 set_at_least_one_account_visible(ModestMainWindow *self)
2634 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2635 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2637 if (!(priv->folder_view)) {
2638 /* It is too early to do this. */
2642 const gchar *active_server_account_name =
2643 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2645 if (!active_server_account_name ||
2646 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2648 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2649 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2650 if (default_modest_name) {
2651 set_account_visible (self, default_modest_name);
2652 } else if (first_modest_name) {
2653 set_account_visible (self, first_modest_name);
2655 g_free (first_modest_name);
2656 g_free (default_modest_name);
2661 on_show_account_action_toggled (GtkToggleAction *action,
2664 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2666 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2667 if (gtk_toggle_action_get_active (action))
2668 set_account_visible (self, acc_name);
2672 refresh_account (const gchar *account_name)
2676 /* win must already exists here, obviously */
2677 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2680 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2684 /* If account_name == NULL, we must update all (option All) */
2686 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2688 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2693 on_refresh_account_action_activated (GtkAction *action,
2696 refresh_account ((const gchar*) user_data);
2700 on_send_receive_csm_activated (GtkMenuItem *item,
2703 refresh_account ((const gchar*) user_data);
2707 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2709 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2711 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2717 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2719 ModestMainWindow *main_window = NULL;
2721 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2722 main_window = MODEST_MAIN_WINDOW (userdata);
2724 /* Update toolbar dimming state */
2725 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2726 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2732 on_header_view_focus_in (GtkWidget *widget,
2733 GdkEventFocus *event,
2736 ModestMainWindow *main_window = NULL;
2738 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2740 main_window = MODEST_MAIN_WINDOW (userdata);
2742 /* Update toolbar dimming state */
2743 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2744 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2750 on_folder_selection_changed (ModestFolderView *folder_view,
2751 TnyFolderStore *folder_store,
2753 ModestMainWindow *main_window)
2755 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2756 GtkAction *action = NULL;
2757 gboolean show_reply = TRUE;
2758 gboolean show_forward = TRUE;
2759 gboolean show_cancel_send = FALSE;
2760 gboolean show_clipboard = TRUE;
2761 gboolean show_delete = TRUE;
2764 if (TNY_IS_ACCOUNT (folder_store)) {
2765 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2766 } else if (TNY_IS_FOLDER (folder_store)) {
2767 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2768 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2769 TNY_FOLDER (folder_store));
2770 switch (folder_type) {
2771 case TNY_FOLDER_TYPE_DRAFTS:
2772 show_clipboard = show_delete = TRUE;
2773 show_reply = show_forward = show_cancel_send = FALSE;
2775 case TNY_FOLDER_TYPE_SENT:
2776 show_forward = show_clipboard = show_delete = TRUE;
2777 show_reply = show_cancel_send = FALSE;
2779 case TNY_FOLDER_TYPE_OUTBOX:
2780 show_clipboard = show_delete = show_cancel_send = TRUE;
2781 show_reply = show_forward = FALSE;
2783 case TNY_FOLDER_TYPE_INVALID:
2784 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2787 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2788 show_cancel_send = FALSE;
2791 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2792 show_cancel_send = FALSE;
2797 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2798 gtk_action_set_visible (action, show_reply);
2799 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2800 gtk_action_set_visible (action, show_reply);
2801 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2802 gtk_action_set_visible (action, show_forward);
2803 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2804 gtk_action_set_visible (action, show_cancel_send);
2805 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2806 gtk_action_set_visible (action, show_delete);
2808 /* We finally call to the ui actions handler, after updating properly
2809 * the header view CSM */
2810 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2814 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2815 GtkTreeModel *model,
2816 GtkTreeRowReference *row_reference,
2817 ModestMainWindow *self)
2819 ModestMainWindowPrivate *priv = NULL;
2820 GtkTreeModel *header_model = NULL;
2821 GtkTreePath *path = NULL;
2823 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2824 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2825 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2827 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2828 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2830 /* Do nothing if we changed the folder in the main view */
2831 if (header_model != model)
2834 /* Select the message in the header view */
2835 path = gtk_tree_row_reference_get_path (row_reference);
2836 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2838 gtk_tree_path_free (path);
2844 show_updating_banner (gpointer user_data)
2846 ModestMainWindowPrivate *priv = NULL;
2848 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2850 if (priv->updating_banner == NULL) {
2852 /* We're outside the main lock */
2853 gdk_threads_enter ();
2854 priv->updating_banner =
2855 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2856 _CS ("ckdg_pb_updating"));
2857 gdk_threads_leave ();
2860 /* Remove timeout */
2861 priv->updating_banner_timeout = 0;
2866 * We use this function to show/hide a progress banner showing
2867 * "Updating" while the header view is being filled. We're not showing
2868 * it unless the update takes more than 2 seconds
2870 * If starting = TRUE then the refresh is starting, otherwise it means
2871 * that is has just finished
2874 on_updating_msg_list (ModestHeaderView *header_view,
2878 ModestMainWindowPrivate *priv = NULL;
2880 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2882 /* Remove old timeout */
2883 if (priv->updating_banner_timeout > 0) {
2884 g_source_remove (priv->updating_banner_timeout);
2885 priv->updating_banner_timeout = 0;
2888 /* Create a new timeout */
2890 priv->updating_banner_timeout =
2891 g_timeout_add (2000, show_updating_banner, user_data);
2893 /* Remove the banner if exists */
2894 if (priv->updating_banner) {
2895 gtk_widget_destroy (priv->updating_banner);
2896 priv->updating_banner = NULL;
2902 modest_main_window_screen_is_on (ModestMainWindow *self)
2904 ModestMainWindowPrivate *priv = NULL;
2906 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2908 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2910 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2914 remove_banners (ModestMainWindow *window)
2916 ModestMainWindowPrivate *priv;
2918 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2920 if (priv->retrieving_banner_timeout > 0) {
2921 g_source_remove (priv->retrieving_banner_timeout);
2922 priv->retrieving_banner_timeout = 0;
2925 if (priv->retrieving_banner != NULL) {
2926 gtk_widget_destroy (priv->retrieving_banner);
2927 priv->retrieving_banner = NULL;
2930 if (priv->updating_banner_timeout > 0) {
2931 g_source_remove (priv->updating_banner_timeout);
2932 priv->updating_banner_timeout = 0;
2935 if (priv->updating_banner != NULL) {
2936 gtk_widget_destroy (priv->updating_banner);
2937 priv->updating_banner = NULL;
2943 on_window_hide (GObject *gobject,
2947 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2949 if (!GTK_WIDGET_VISIBLE (gobject)) {
2950 TnyFolderStore *folder_store;
2951 ModestMainWindowPrivate *priv;
2953 /* Remove the currently shown banners */
2954 remove_banners (MODEST_MAIN_WINDOW (gobject));
2956 /* Force the folder view to sync the currently selected folder
2957 to save the read/unread status and to expunge messages */
2958 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2959 folder_store = modest_folder_view_get_selected (priv->folder_view);
2960 if (TNY_IS_FOLDER (folder_store)) {
2961 ModestMailOperation *mail_op;
2963 mail_op = modest_mail_operation_new (NULL);
2964 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2966 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2967 g_object_unref (mail_op);
2968 g_object_unref (folder_store);
2974 on_window_destroy (GtkObject *widget,
2977 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2979 remove_banners (MODEST_MAIN_WINDOW (widget));
2983 show_retrieving_banner (gpointer user_data)
2985 ModestMainWindowPrivate *priv = NULL;
2987 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2989 if (priv->retrieving_banner == NULL) {
2991 /* We're outside the main lock */
2992 gdk_threads_enter ();
2993 priv->retrieving_banner =
2994 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2995 _("mcen_ib_getting_items"));
2996 gdk_threads_leave ();
2999 /* Remove timeout */
3000 priv->retrieving_banner_timeout = 0;