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-error.h>
37 #include "modest-hildon-includes.h"
38 #include "modest-defs.h"
40 #include "widgets/modest-header-view-priv.h"
41 #include "widgets/modest-main-window.h"
42 #include "widgets/modest-msg-edit-window.h"
43 #include "widgets/modest-account-view-window.h"
44 #include "modest-runtime.h"
45 #include "modest-account-mgr-helpers.h"
46 #include "modest-platform.h"
47 #include "modest-widget-memory.h"
48 #include "modest-window-priv.h"
49 #include "modest-main-window-ui.h"
50 #include "modest-main-window-ui-dimming.h"
51 #include "modest-account-mgr.h"
52 #include "modest-tny-account.h"
53 #include "modest-tny-folder.h"
54 #include "modest-conf.h"
55 #include <modest-utils.h>
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
66 #include "modest-signal-mgr.h"
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
75 /* 'private'/'protected' functions */
76 static void modest_main_window_class_init (ModestMainWindowClass *klass);
77 static void modest_main_window_init (ModestMainWindow *obj);
78 static void modest_main_window_finalize (GObject *obj);
80 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
81 GdkEventWindowState *event,
84 static void connect_signals (ModestMainWindow *self);
86 static void modest_main_window_disconnect_signals (ModestWindow *self);
88 static void restore_settings (ModestMainWindow *self,
89 gboolean do_folder_view_too);
91 static void save_state (ModestWindow *self);
93 static void update_menus (ModestMainWindow* self);
95 static void modest_main_window_show_toolbar (ModestWindow *window,
96 gboolean show_toolbar);
98 static void cancel_progressbar (GtkToolButton *toolbutton,
99 ModestMainWindow *self);
101 static void on_queue_changed (ModestMailOperationQueue *queue,
102 ModestMailOperation *mail_op,
103 ModestMailOperationQueueNotification type,
104 ModestMainWindow *self);
106 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
108 static void on_account_inserted (TnyAccountStore *accoust_store,
112 static void on_account_removed (TnyAccountStore *accoust_store,
116 static void on_account_changed (TnyAccountStore *account_store,
120 static void on_default_account_changed (ModestAccountMgr* mgr,
123 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
127 static void on_configuration_key_changed (ModestConf* conf,
129 ModestConfEvent event,
130 ModestConfNotificationId id,
131 ModestMainWindow *self);
133 static void set_toolbar_mode (ModestMainWindow *self,
134 ModestToolBarModes mode);
136 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
138 static void on_show_account_action_toggled (GtkToggleAction *action,
141 static void on_refresh_account_action_activated (GtkAction *action,
144 static void on_send_receive_csm_activated (GtkMenuItem *item,
147 static void on_msg_count_changed (ModestHeaderView *header_view,
149 TnyFolderChange *change,
150 ModestMainWindow *main_window);
152 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
155 static GtkWidget * create_empty_view (void);
157 static gboolean on_folder_view_focus_in (GtkWidget *widget,
158 GdkEventFocus *event,
161 static gboolean on_header_view_focus_in (GtkWidget *widget,
162 GdkEventFocus *event,
165 static void on_folder_selection_changed (ModestFolderView *folder_view,
166 TnyFolderStore *folder_store,
168 ModestMainWindow *main_window);
170 static void set_at_least_one_account_visible(ModestMainWindow *self);
172 static void on_updating_msg_list (ModestHeaderView *header_view,
176 static gboolean restore_paned_timeout_handler (gpointer *data);
178 static gboolean show_opening_banner (gpointer user_data);
180 static void on_window_destroy (GtkObject *widget,
183 static void on_window_hide (GObject *gobject,
187 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
188 struct _ModestMainWindowPrivate {
189 GtkWidget *msg_paned;
190 GtkWidget *main_paned;
191 GtkWidget *main_vbox;
192 GtkWidget *contents_widget;
193 GtkWidget *empty_view;
195 /* Progress observers */
196 GtkWidget *progress_bar;
197 GSList *progress_widgets;
200 GtkWidget *progress_toolitem;
201 GtkWidget *cancel_toolitem;
202 GtkWidget *sort_toolitem;
203 GtkWidget *refresh_toolitem;
204 ModestToolBarModes current_toolbar_mode;
206 /* Merge ids used to add/remove accounts to the ViewMenu*/
207 GByteArray *merge_ids;
208 GtkActionGroup *view_additions_group;
210 /* On-demand widgets */
211 GtkWidget *accounts_popup;
212 GtkWidget *details_widget;
214 /* Optimized view enabled */
215 gboolean optimized_view;
217 /* Optimized view enabled */
218 gboolean send_receive_in_progress;
220 ModestHeaderView *header_view;
221 ModestFolderView *folder_view;
223 ModestMainWindowStyle style;
224 ModestMainWindowContentsStyle contents_style;
225 gboolean wait_for_settings;
227 guint progress_bar_timeout;
228 guint restore_paned_timeout;
230 /* Signal handler UIDs */
231 GList *queue_err_signals;
234 /* "Updating" banner for header view */
235 GtkWidget *updating_banner;
236 guint updating_banner_timeout;
238 /* "Opening" banner for header view */
239 GtkWidget *opening_banner;
240 guint opening_banner_timeout;
243 osso_display_state_t display_state;
245 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
246 MODEST_TYPE_MAIN_WINDOW, \
247 ModestMainWindowPrivate))
249 typedef struct _GetMsgAsyncHelper {
250 ModestMainWindowPrivate *main_window_private;
252 ModestTnyMsgReplyType reply_type;
253 ModestTnyMsgForwardType forward_type;
260 static GtkWindowClass *parent_class = NULL;
263 /* Private actions */
264 /* This is the context sensitive menu: */
265 static const GtkActionEntry modest_folder_view_action_entries [] = {
267 /* Folder View CSM actions */
268 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
269 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
270 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
271 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
272 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
273 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
276 static const GtkActionEntry modest_header_view_action_entries [] = {
278 /* Header View CSM actions */
279 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
280 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
281 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
282 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
283 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
284 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
285 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
286 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
287 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
288 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
291 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
292 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
295 /************************************************************************/
298 modest_main_window_get_type (void)
300 static GType my_type = 0;
302 static const GTypeInfo my_info = {
303 sizeof(ModestMainWindowClass),
304 NULL, /* base init */
305 NULL, /* base finalize */
306 (GClassInitFunc) modest_main_window_class_init,
307 NULL, /* class finalize */
308 NULL, /* class data */
309 sizeof(ModestMainWindow),
311 (GInstanceInitFunc) modest_main_window_init,
314 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 modest_main_window_class_init (ModestMainWindowClass *klass)
324 GObjectClass *gobject_class;
325 gobject_class = (GObjectClass*) klass;
326 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
328 parent_class = g_type_class_peek_parent (klass);
329 gobject_class->finalize = modest_main_window_finalize;
331 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
333 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
334 modest_window_class->save_state_func = save_state;
335 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
336 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
337 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
341 modest_main_window_init (ModestMainWindow *obj)
343 ModestMainWindowPrivate *priv;
345 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
347 priv->queue_err_signals = NULL;
348 priv->msg_paned = NULL;
349 priv->main_paned = NULL;
350 priv->main_vbox = NULL;
351 priv->header_view = NULL;
352 priv->folder_view = NULL;
353 priv->contents_widget = NULL;
354 priv->accounts_popup = NULL;
355 priv->details_widget = NULL;
356 priv->empty_view = NULL;
357 priv->progress_widgets = NULL;
358 priv->progress_bar = NULL;
359 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
360 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
361 priv->wait_for_settings = TRUE;
362 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
363 priv->merge_ids = NULL;
364 priv->optimized_view = FALSE;
365 priv->send_receive_in_progress = FALSE;
366 priv->progress_bar_timeout = 0;
367 priv->restore_paned_timeout = 0;
368 priv->sighandlers = NULL;
369 priv->updating_banner = NULL;
370 priv->updating_banner_timeout = 0;
371 priv->opening_banner = NULL;
372 priv->opening_banner_timeout = 0;
373 priv->display_state = OSSO_DISPLAY_ON;
375 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
377 "applications_email_mainview");
381 modest_main_window_finalize (GObject *obj)
383 ModestMainWindowPrivate *priv;
385 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
387 /* Sanity check: shouldn't be needed, the window mgr should
388 call this function before */
389 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
390 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
392 if (priv->empty_view) {
393 g_object_unref (priv->empty_view);
394 priv->empty_view = NULL;
397 if (priv->header_view) {
398 g_object_unref (priv->header_view);
399 priv->header_view = NULL;
402 g_slist_free (priv->progress_widgets);
404 g_byte_array_free (priv->merge_ids, TRUE);
406 if (priv->progress_bar_timeout > 0) {
407 g_source_remove (priv->progress_bar_timeout);
408 priv->progress_bar_timeout = 0;
411 if (priv->updating_banner_timeout > 0) {
412 g_source_remove (priv->updating_banner_timeout);
413 priv->updating_banner_timeout = 0;
416 if (priv->updating_banner) {
417 gtk_widget_destroy (priv->updating_banner);
418 priv->updating_banner = NULL;
421 if (priv->opening_banner_timeout > 0) {
422 g_source_remove (priv->opening_banner_timeout);
423 priv->opening_banner_timeout = 0;
426 if (priv->opening_banner) {
427 gtk_widget_destroy (priv->opening_banner);
428 priv->opening_banner = NULL;
431 if (priv->restore_paned_timeout > 0) {
432 g_source_remove (priv->restore_paned_timeout);
433 priv->restore_paned_timeout = 0;
436 G_OBJECT_CLASS(parent_class)->finalize (obj);
440 modest_main_window_get_child_widget (ModestMainWindow *self,
441 ModestMainWindowWidgetType widget_type)
443 ModestMainWindowPrivate *priv;
446 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
447 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
450 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
452 switch (widget_type) {
453 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
454 widget = (GtkWidget*)priv->header_view; break;
455 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
456 widget = (GtkWidget*)priv->folder_view; break;
461 /* Note that the window could have been destroyed, and so
462 their children, but still have some references */
463 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
467 restore_paned_timeout_handler (gpointer *data)
469 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
470 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
473 /* Timeouts are outside the main lock */
474 gdk_threads_enter ();
475 if (GTK_WIDGET_VISIBLE (main_window)) {
476 conf = modest_runtime_get_conf ();
477 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
478 MODEST_CONF_MAIN_PANED_KEY);
480 gdk_threads_leave ();
487 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
490 ModestMainWindowPrivate *priv;
492 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
494 conf = modest_runtime_get_conf ();
496 modest_widget_memory_restore (conf, G_OBJECT(self),
497 MODEST_CONF_MAIN_WINDOW_KEY);
499 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
500 MODEST_CONF_HEADER_VIEW_KEY);
502 if (do_folder_view_too)
503 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
504 MODEST_CONF_FOLDER_VIEW_KEY);
506 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
507 /* MODEST_CONF_MAIN_PANED_KEY); */
509 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
511 /* We need to force a redraw here in order to get the right
512 position of the horizontal paned separator */
513 gtk_widget_show (GTK_WIDGET (self));
518 save_state (ModestWindow *window)
521 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
522 ModestMainWindowPrivate *priv;
524 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
525 conf = modest_runtime_get_conf ();
527 modest_widget_memory_save (conf,G_OBJECT(self),
528 MODEST_CONF_MAIN_WINDOW_KEY);
529 /* Only save main paned position if we're in split mode */
530 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
531 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
532 MODEST_CONF_MAIN_PANED_KEY);
533 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
534 MODEST_CONF_FOLDER_VIEW_KEY);
538 compare_display_names (ModestAccountSettings *a,
539 ModestAccountSettings *b)
541 return g_utf8_collate (modest_account_settings_get_display_name (a),
542 modest_account_settings_get_display_name (b));
546 /* We use this function to prevent the send&receive CSM to be shown
547 when there are less than two account */
549 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
555 update_menus (ModestMainWindow* self)
557 GSList *account_names, *iter, *accounts;
558 ModestMainWindowPrivate *priv;
559 ModestWindowPrivate *parent_priv;
560 ModestAccountMgr *mgr;
561 gint i, num_accounts;
563 gchar *default_account;
564 const gchar *active_account_name;
565 GtkWidget *send_receive_button, *item;
566 GtkAction *send_receive_all = NULL;
569 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
570 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
572 /* Get enabled account IDs */
573 mgr = modest_runtime_get_account_mgr ();
574 account_names = modest_account_mgr_account_names (mgr, TRUE);
575 iter = account_names;
579 ModestAccountSettings *settings =
580 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
581 accounts = g_slist_prepend (accounts, settings);
585 modest_account_mgr_free_account_names (account_names);
586 account_names = NULL;
588 /* Order the list of accounts by its display name */
589 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
590 num_accounts = g_slist_length (accounts);
592 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
593 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
594 gtk_action_set_visible (send_receive_all, num_accounts > 0);
596 /* Delete old send&receive popup items. We can not just do a
597 menu_detach because it does not work well with
599 if (priv->accounts_popup)
600 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
601 (GtkCallback) gtk_widget_destroy, NULL);
603 /* Delete old entries in the View menu. Do not free groups, it
605 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
607 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
608 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
609 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
610 GTK_ACTION_GROUP (groups->data));
613 if (priv->merge_ids) {
614 for (i = 0; i < priv->merge_ids->len; i++)
615 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
616 g_byte_array_free (priv->merge_ids, TRUE);
618 /* We need to call this in order to ensure
619 that the new actions are added in the right
620 order (alphabetical) */
621 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
623 groups = g_list_next (groups);
625 priv->merge_ids = g_byte_array_sized_new (num_accounts);
627 /* Get send receive button */
628 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
629 "/ToolBar/ToolbarSendReceive");
631 /* Create the menu */
632 if (num_accounts > 1) {
633 if (!priv->accounts_popup)
634 priv->accounts_popup = gtk_menu_new ();
635 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
636 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
637 g_signal_connect (G_OBJECT (item),
639 G_CALLBACK (on_send_receive_csm_activated),
641 item = gtk_separator_menu_item_new ();
642 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
645 /* Create a new action group */
646 default_account = modest_account_mgr_get_default_account (mgr);
647 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
649 if (!active_account_name)
650 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
652 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
654 for (i = 0; i < num_accounts; i++) {
655 gchar *display_name = NULL;
656 const gchar *account_name;
657 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
660 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
663 account_name = modest_account_settings_get_account_name (settings);
665 if (default_account && account_name &&
666 !(strcmp (default_account, account_name) == 0)) {
667 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
668 modest_account_settings_get_display_name (settings));
670 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
671 modest_account_settings_get_display_name (settings));
676 /* Create action and add it to the action group. The
677 action name must be the account name, this way we
678 could know in the handlers the account to show */
679 if (settings && account_name) {
680 gchar* item_name, *refresh_action_name;
682 GtkAction *view_account_action, *refresh_account_action;
683 gchar *escaped_display_name;
685 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
687 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
688 escaped_display_name, NULL, NULL, 0));
689 g_free (escaped_display_name);
690 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
691 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
692 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
694 if (active_account_name) {
695 if (active_account_name && account_name &&
696 (strcmp (active_account_name, account_name) == 0)) {
697 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
701 /* Add ui from account data. We allow 2^9-1 account
702 changes in a single execution because we're
703 downcasting the guint to a guint8 in order to use a
704 GByteArray. It should be enough :-) */
705 item_name = g_strconcat (account_name, "Menu", NULL);
706 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
707 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
708 gtk_ui_manager_add_ui (parent_priv->ui_manager,
710 "/MenuBar/ViewMenu/ViewMenuAdditions",
713 GTK_UI_MANAGER_MENUITEM,
716 /* Connect the action signal "activate" */
717 g_signal_connect_after (G_OBJECT (view_account_action),
719 G_CALLBACK (on_show_account_action_toggled),
722 /* Create the items for the Tools->Send&Receive submenu */
723 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
724 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
725 display_name, NULL, NULL);
726 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
728 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
729 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
730 gtk_ui_manager_add_ui (parent_priv->ui_manager,
732 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
735 GTK_UI_MANAGER_MENUITEM,
737 g_free (refresh_action_name);
739 g_signal_connect_data (G_OBJECT (refresh_account_action),
741 G_CALLBACK (on_refresh_account_action_activated),
742 g_strdup (account_name),
743 (GClosureNotify) g_free,
746 /* Create item and add it to the send&receive
747 CSM. If there is only one account then
749 if (num_accounts > 1) {
750 GtkWidget *label = gtk_label_new(NULL);
751 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
752 if (default_account && (strcmp(account_name, default_account) == 0)) {
753 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
754 gtk_label_set_markup (GTK_LABEL (label), escaped);
757 gtk_label_set_text (GTK_LABEL (label), display_name);
760 item = gtk_menu_item_new ();
761 gtk_container_add (GTK_CONTAINER (item), label);
763 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
765 g_signal_connect_data (G_OBJECT (item),
767 G_CALLBACK (on_send_receive_csm_activated),
768 g_strdup (account_name),
769 (GClosureNotify) g_free,
776 g_free (display_name);
779 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
781 /* We cannot do this in the loop above because this relies on the action
782 * group being inserted. This makes the default account appear in bold.
783 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
784 for (i = 0; i < num_accounts; i++) {
785 gchar *item_name, *path;
787 ModestAccountSettings *settings;
788 const gchar *account_name;
791 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
792 account_name = modest_account_settings_get_account_name (settings);
793 is_default = (account_name && default_account && !strcmp (account_name, default_account));
795 /* Get the item of the view menu */
796 item_name = g_strconcat (account_name, "Menu", NULL);
797 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
798 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
802 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
803 if (GTK_IS_LABEL (child)) {
804 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
806 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
807 gtk_label_set_markup (GTK_LABEL (child), bold_name);
810 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
814 /* Get the item of the tools menu */
815 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
816 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
820 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
821 if (GTK_IS_LABEL (child)) {
822 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
824 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
825 gtk_label_set_markup (GTK_LABEL (child), bold_name);
828 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
833 g_object_unref (settings);
836 if (num_accounts > 1) {
837 /* Disconnect the tap-and-hold-query if it's connected */
838 if (modest_signal_mgr_is_connected (priv->sighandlers,
839 G_OBJECT (send_receive_button),
840 "tap-and-hold-query"))
841 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
842 G_OBJECT (send_receive_button),
843 "tap-and-hold-query");
845 /* Mandatory in order to view the menu contents */
846 gtk_widget_show_all (priv->accounts_popup);
848 /* Setup tap_and_hold just if was not done before*/
849 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
850 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
852 /* Connect the tap-and-hold-query in order not to show the CSM */
853 if (!modest_signal_mgr_is_connected (priv->sighandlers,
854 G_OBJECT (send_receive_button),
855 "tap-and-hold-query"))
856 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
857 G_OBJECT (send_receive_button),
858 "tap-and-hold-query",
859 G_CALLBACK (tap_and_hold_query_cb),
864 g_slist_free (accounts);
865 g_free (default_account);
868 /* Make sure that at least one account is viewed if there are any
869 * accounts, for instance when adding the first account: */
870 set_at_least_one_account_visible (self);
874 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
876 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
877 gtk_scrolled_window_add_with_viewport
878 (GTK_SCROLLED_WINDOW(win), widget);
880 gtk_container_add (GTK_CONTAINER(win),
891 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
893 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
895 GList *oerrsignals = priv->queue_err_signals;
896 while (oerrsignals) {
897 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
898 g_signal_handler_disconnect (esignal->queue, esignal->signal);
899 g_slice_free (QueueErrorSignal, esignal);
900 oerrsignals = g_list_next (oerrsignals);
902 g_list_free (priv->queue_err_signals);
903 priv->queue_err_signals = NULL;
908 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
910 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
913 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
917 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
919 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
921 /* Update visibility */
924 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
928 modest_main_window_disconnect_signals (ModestWindow *self)
930 ModestMainWindowPrivate *priv;
931 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
933 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
934 priv->sighandlers = NULL;
938 connect_signals (ModestMainWindow *self)
940 ModestWindowPrivate *parent_priv;
941 ModestMainWindowPrivate *priv;
944 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
945 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
950 modest_signal_mgr_connect (priv->sighandlers,
951 G_OBJECT(priv->folder_view), "key-press-event",
952 G_CALLBACK(on_inner_widgets_key_pressed), self);
954 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
955 "folder_selection_changed",
956 G_CALLBACK (on_folder_selection_changed),
959 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
960 "folder-display-name-changed",
961 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
964 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
966 G_CALLBACK (on_folder_view_focus_in),
969 /* Folder view CSM */
970 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
971 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
972 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
973 G_CALLBACK(_folder_view_csm_menu_activated),
977 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
978 G_CALLBACK(modest_ui_actions_on_header_selected), self);
980 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
981 G_CALLBACK(modest_ui_actions_on_header_activated), self);
983 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
984 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
986 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
987 G_CALLBACK(on_inner_widgets_key_pressed), self);
989 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
990 G_CALLBACK(on_msg_count_changed), self);
992 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
993 G_CALLBACK (on_header_view_focus_in), self);
995 modest_signal_mgr_connect (priv->sighandlers,
996 G_OBJECT (priv->header_view),
998 G_CALLBACK (on_updating_msg_list),
1001 /* Header view CSM */
1002 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1003 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1005 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1006 G_CALLBACK(_header_view_csm_menu_activated),
1011 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1012 G_CALLBACK (modest_main_window_window_state_event),
1014 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1015 * in destroy stage */
1016 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1018 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1020 /* Mail Operation Queue */
1022 modest_signal_mgr_connect (priv->sighandlers,
1023 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1025 G_CALLBACK (on_queue_changed), self);
1027 /* Track changes in the device name */
1029 modest_signal_mgr_connect (priv->sighandlers,
1030 G_OBJECT(modest_runtime_get_conf ()),
1032 G_CALLBACK (on_configuration_key_changed),
1035 /* Track account changes. We need to refresh the toolbar */
1037 modest_signal_mgr_connect (priv->sighandlers,
1038 G_OBJECT (modest_runtime_get_account_store ()),
1040 G_CALLBACK (on_account_inserted),
1043 modest_signal_mgr_connect (priv->sighandlers,
1044 G_OBJECT (modest_runtime_get_account_store ()),
1046 G_CALLBACK (on_account_removed),
1049 /* We need to refresh the send & receive menu to change the bold
1050 * account when the default account changes. */
1052 modest_signal_mgr_connect (priv->sighandlers,
1053 G_OBJECT (modest_runtime_get_account_mgr ()),
1054 "default_account_changed",
1055 G_CALLBACK (on_default_account_changed),
1060 modest_signal_mgr_connect (priv->sighandlers,
1061 G_OBJECT (modest_runtime_get_account_store ()),
1063 G_CALLBACK (on_account_changed),
1068 on_hildon_program_is_topmost_notify(GObject *self,
1069 GParamSpec *propert_param,
1072 HildonProgram *app = HILDON_PROGRAM (self);
1074 /* Note that use of hildon_program_set_can_hibernate()
1075 * is generally referred to as "setting the killable flag",
1076 * though hibernation does not seem equal to death.
1079 if (hildon_program_get_is_topmost (app)) {
1080 /* Prevent hibernation when the progam comes to the foreground,
1081 * because hibernation should only happen when the application
1082 * is in the background: */
1083 hildon_program_set_can_hibernate (app, FALSE);
1085 /* Remove new mail visual notifications */
1086 modest_platform_remove_new_mail_notifications (TRUE);
1088 /* Allow hibernation if the program has gone to the background: */
1090 /* However, prevent hibernation while the settings are being changed: */
1091 const gboolean hibernation_prevented =
1092 modest_window_mgr_get_hibernation_is_prevented (
1093 modest_runtime_get_window_mgr ());
1095 if (hibernation_prevented)
1096 hildon_program_set_can_hibernate (app, FALSE);
1098 /* Allow hibernation, after saving the state: */
1099 modest_osso_save_state();
1100 hildon_program_set_can_hibernate (app, TRUE);
1107 GtkWidget *folder_win;
1112 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1114 ShowHelper *helper = (ShowHelper *) user_data;
1115 GtkWidget *folder_win = helper->folder_win;
1116 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1118 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1119 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1121 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1123 /* Connect signals */
1124 connect_signals (MODEST_MAIN_WINDOW (self));
1126 /* Set account store */
1127 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1128 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1130 /* Load previous osso state, for instance if we are being restored from
1132 modest_osso_load_state ();
1134 /* Restore window & widget settings */
1135 priv->wait_for_settings = TRUE;
1136 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1137 priv->wait_for_settings = FALSE;
1139 /* Check if accounts exist and show the account wizard if not */
1140 gboolean accounts_exist =
1141 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1143 if (!accounts_exist) {
1144 /* This is necessary to have the main window shown behind the dialog
1145 It's an ugly hack... jschmid */
1146 gtk_widget_show_all(GTK_WIDGET(self));
1147 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1149 update_menus (MODEST_MAIN_WINDOW (self));
1152 /* Never call this function again (NOTE that it could happen
1153 as we hide the main window instead of closing it while
1154 there are operations ongoing) and free the helper */
1155 g_signal_handler_disconnect (self, helper->handler_id);
1156 g_slice_free (ShowHelper, helper);
1160 osso_display_event_cb (osso_display_state_t state,
1163 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1165 priv->display_state = state;
1167 /* Stop blinking if the screen becomes on */
1168 if (priv->display_state == OSSO_DISPLAY_ON)
1169 modest_platform_remove_new_mail_notifications (TRUE);
1173 modest_main_window_new (void)
1175 ModestMainWindow *self = NULL;
1176 ModestMainWindowPrivate *priv = NULL;
1177 ModestWindowPrivate *parent_priv = NULL;
1178 GtkWidget *folder_win = NULL;
1179 ModestDimmingRulesGroup *menu_rules_group = NULL;
1180 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1181 GtkActionGroup *action_group = NULL;
1182 GError *error = NULL;
1184 GdkPixbuf *window_icon;
1187 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1188 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1189 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1191 parent_priv->ui_manager = gtk_ui_manager_new();
1192 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1194 action_group = gtk_action_group_new ("ModestMainWindowActions");
1195 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1197 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1198 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1200 /* Add common actions */
1201 gtk_action_group_add_actions (action_group,
1202 modest_action_entries,
1203 G_N_ELEMENTS (modest_action_entries),
1206 gtk_action_group_add_actions (action_group,
1207 modest_folder_view_action_entries,
1208 G_N_ELEMENTS (modest_folder_view_action_entries),
1211 gtk_action_group_add_actions (action_group,
1212 modest_header_view_action_entries,
1213 G_N_ELEMENTS (modest_header_view_action_entries),
1216 gtk_action_group_add_toggle_actions (action_group,
1217 modest_toggle_action_entries,
1218 G_N_ELEMENTS (modest_toggle_action_entries),
1221 gtk_action_group_add_toggle_actions (action_group,
1222 modest_main_window_toggle_action_entries,
1223 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1226 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1227 g_object_unref (action_group);
1229 /* Load the UI definition */
1230 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1231 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1232 if (error != NULL) {
1233 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1234 g_error_free (error);
1238 /* Add common dimming rules */
1239 modest_dimming_rules_group_add_rules (menu_rules_group,
1240 modest_main_window_menu_dimming_entries,
1241 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1242 MODEST_WINDOW (self));
1243 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1244 modest_main_window_toolbar_dimming_entries,
1245 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1246 MODEST_WINDOW (self));
1248 /* Insert dimming rules group for this window */
1249 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1250 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1251 g_object_unref (menu_rules_group);
1252 g_object_unref (toolbar_rules_group);
1254 /* Add accelerators */
1255 gtk_window_add_accel_group (GTK_WINDOW (self),
1256 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1258 /* Menubar. Update the state of some toggles */
1259 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1260 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1261 gtk_widget_show (parent_priv->menubar);
1263 /* Get device name */
1264 modest_maemo_utils_get_device_name ();
1268 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1269 g_object_ref (priv->header_view);
1270 if (!priv->header_view)
1271 g_printerr ("modest: cannot instantiate header view\n");
1272 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1273 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1274 MODEST_CONF_HEADER_VIEW_KEY);
1276 /* Other style properties of header view */
1277 g_object_set (G_OBJECT (priv->header_view),
1278 "rules-hint", FALSE,
1280 /* gtk_widget_show (priv->header_view); */
1283 priv->empty_view = create_empty_view ();
1284 gtk_widget_show (priv->empty_view);
1285 g_object_ref (priv->empty_view);
1287 /* Create scrolled windows */
1288 folder_win = gtk_scrolled_window_new (NULL, NULL);
1289 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1290 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1292 GTK_POLICY_AUTOMATIC);
1293 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1295 GTK_POLICY_AUTOMATIC);
1296 /* gtk_widget_show (priv->contents_widget); */
1299 priv->main_paned = gtk_hpaned_new ();
1300 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1301 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1302 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1304 /* putting it all together... */
1305 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1306 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1307 gtk_widget_show (priv->main_vbox);
1309 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1311 app = hildon_program_get_instance ();
1312 hildon_program_add_window (app, HILDON_WINDOW (self));
1314 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1315 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1317 /* Connect to "show" action. We delay the creation of some
1318 elements until that moment */
1319 helper = g_slice_new0 (ShowHelper);
1320 helper->folder_win = folder_win;
1321 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1322 G_CALLBACK (modest_main_window_on_show),
1325 /* Set window icon */
1326 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1328 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1329 g_object_unref (window_icon);
1332 /* Listen for changes in the screen, we don't want to show a
1333 led pattern when the display is on for example */
1334 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1335 osso_display_event_cb,
1338 /* Dont't restore settings here,
1339 * because it requires a gtk_widget_show(),
1340 * and we don't want to do that until later,
1341 * so that the UI is not visible for non-menu D-Bus activation.
1344 return MODEST_WINDOW(self);
1348 modest_main_window_set_style (ModestMainWindow *self,
1349 ModestMainWindowStyle style)
1351 ModestMainWindowPrivate *priv;
1352 ModestWindowPrivate *parent_priv;
1355 GtkTreeSelection *sel;
1358 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1360 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1361 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1363 /* no change -> nothing to do */
1364 if (priv->style == style)
1367 /* Get toggle button and update the state if needed. This will
1368 happen only when the set_style is not invoked from the UI,
1369 for example when it's called from widget memory */
1370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1371 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1372 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1373 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1374 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1375 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1376 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1379 /* We need to store the selection because it's lost when the
1380 widget is reparented */
1381 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1382 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1384 priv->style = style;
1386 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1388 if (!priv->wait_for_settings)
1389 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1390 MODEST_CONF_MAIN_PANED_KEY);
1391 /* Remove main paned */
1392 g_object_ref (priv->main_paned);
1393 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1395 /* Reparent the contents widget to the main vbox */
1396 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1399 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1400 /* Remove header view */
1401 g_object_ref (priv->contents_widget);
1402 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1404 /* Reparent the main paned */
1405 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1406 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1408 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1412 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1414 g_return_if_reached ();
1417 /* Reselect the previously selected folders. We disable the
1418 dimming rules execution during that time because there is
1419 no need to work out it again and it could take a lot of
1420 time if all the headers are selected */
1422 modest_window_disable_dimming (MODEST_WINDOW (self));
1424 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1425 list = g_list_next (list);
1427 modest_window_enable_dimming (MODEST_WINDOW (self));
1430 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1433 /* Let header view grab the focus if it's being shown */
1434 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1435 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1437 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1438 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1440 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1443 /* Check dimming rules */
1444 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1445 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1448 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1451 ModestMainWindowStyle
1452 modest_main_window_get_style (ModestMainWindow *self)
1454 ModestMainWindowPrivate *priv;
1456 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1458 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1463 toolbar_resize (ModestMainWindow *self)
1465 ModestMainWindowPrivate *priv = NULL;
1466 ModestWindowPrivate *parent_priv = NULL;
1468 gint static_button_size;
1469 ModestWindowMgr *mgr;
1471 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1472 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1473 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1475 mgr = modest_runtime_get_window_mgr ();
1476 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1478 if (parent_priv->toolbar) {
1479 /* left size buttons */
1480 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1481 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1482 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1483 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1484 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1485 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1486 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1487 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1488 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1489 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1490 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1491 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1492 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1493 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1494 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1495 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1497 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1498 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1499 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1500 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1501 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1502 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1503 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1504 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1512 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1514 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1515 ModestWindowPrivate *parent_priv;
1516 ModestWindowMgr *mgr;
1517 gboolean is_fullscreen;
1518 GtkAction *fs_toggle_action;
1521 mgr = modest_runtime_get_window_mgr ();
1523 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1525 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1527 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1528 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1529 if (is_fullscreen != active) {
1530 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1533 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1541 modest_main_window_show_toolbar (ModestWindow *self,
1542 gboolean show_toolbar)
1544 ModestMainWindowPrivate *priv = NULL;
1545 ModestWindowPrivate *parent_priv = NULL;
1546 GtkWidget *reply_button = NULL, *menu = NULL;
1547 GtkWidget *placeholder = NULL;
1550 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1551 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1552 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1554 /* Set optimized view status */
1555 priv->optimized_view = !show_toolbar;
1557 if (!parent_priv->toolbar) {
1558 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1560 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1562 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1563 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1564 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1565 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1566 toolbar_resize (MODEST_MAIN_WINDOW (self));
1568 /* Add ProgressBar (Transfer toolbar) */
1569 priv->progress_bar = modest_progress_bar_new ();
1570 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1571 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1572 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1573 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1574 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1576 /* Connect cancel 'clicked' signal to abort progress mode */
1577 g_signal_connect(priv->cancel_toolitem, "clicked",
1578 G_CALLBACK(cancel_progressbar),
1581 /* Add it to the observers list */
1582 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1585 hildon_window_add_toolbar (HILDON_WINDOW (self),
1586 GTK_TOOLBAR (parent_priv->toolbar));
1588 /* Set reply button tap and hold menu */
1589 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1590 "/ToolBar/ToolbarMessageReply");
1591 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1592 "/ToolbarReplyCSM");
1593 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1595 /* Set send & receive button tap and hold menu */
1596 update_menus (MODEST_MAIN_WINDOW (self));
1600 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1601 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1602 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1604 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1605 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1606 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1608 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1610 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1616 on_account_inserted (TnyAccountStore *accoust_store,
1617 TnyAccount *account,
1620 /* Transport accounts and local ones (MMC and the Local
1621 folders account do now cause menu changes */
1622 if (TNY_IS_STORE_ACCOUNT (account) &&
1623 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1625 update_menus (MODEST_MAIN_WINDOW (user_data));
1630 on_default_account_changed (ModestAccountMgr* mgr,
1633 update_menus (MODEST_MAIN_WINDOW (user_data));
1637 on_account_removed (TnyAccountStore *accoust_store,
1638 TnyAccount *account,
1641 /* Transport accounts and local ones (MMC and the Local
1642 folders account do now cause menu changes */
1643 if (TNY_IS_STORE_ACCOUNT (account) &&
1644 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1645 update_menus (MODEST_MAIN_WINDOW (user_data));
1649 on_account_changed (TnyAccountStore *account_store,
1650 TnyAccount *account,
1653 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1655 /* Transport accounts and local ones (MMC and the Local
1656 folders account do now cause menu changes */
1657 if (TNY_IS_STORE_ACCOUNT (account)) {
1658 /* We need to refresh the details widget because it could have changed */
1659 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1660 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1662 /* Update the menus as well, name could change */
1663 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1664 update_menus (MODEST_MAIN_WINDOW (user_data));
1669 * This function manages the key events used to navigate between
1670 * header and folder views (when the window is in split view)
1673 * -------------------------------------------------
1674 * HeaderView GDK_Left Move focus to folder view
1675 * FolderView GDK_Right Move focus to header view
1677 * There is no need to scroll to selected row, the widgets will be the
1678 * responsibles of doing that (probably managing the focus-in event
1681 on_inner_widgets_key_pressed (GtkWidget *widget,
1685 ModestMainWindowPrivate *priv;
1687 if (event->type == GDK_KEY_RELEASE)
1690 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1692 /* Do nothing if we're in SIMPLE style */
1693 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1696 if (MODEST_IS_HEADER_VIEW (widget)) {
1697 if (event->keyval == GDK_Left)
1698 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1699 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1700 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1701 if (selected_headers > 1) {
1702 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1705 GtkTreePath * cursor_path;
1706 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1707 if (cursor_path == NULL) {
1708 GtkTreeSelection *selection;
1710 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1711 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1714 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1715 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1720 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1721 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1722 GtkTreePath *selected_path = NULL;
1723 GtkTreePath *start_path = NULL;
1724 GtkTreePath *end_path = NULL;
1726 GtkTreeSelection *selection;
1728 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1729 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1730 if (selected != NULL) {
1731 selected_path = (GtkTreePath *) selected->data;
1732 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1736 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1737 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1739 /* Scroll to first path */
1740 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1749 gtk_tree_path_free (start_path);
1751 gtk_tree_path_free (end_path);
1752 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1753 g_list_free (selected);
1755 #endif /* GTK_CHECK_VERSION */
1757 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1764 set_alignment (GtkWidget *widget,
1767 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1768 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1772 create_empty_view (void)
1774 GtkLabel *label = NULL;
1775 GtkWidget *align = NULL;
1777 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1778 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1779 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1780 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1782 return GTK_WIDGET(align);
1786 * Free the returned string
1789 get_gray_color_markup (GtkWidget *styled_widget)
1791 gchar *gray_color_markup = NULL;
1792 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1793 /* Obtain the secondary text color. We need a realized widget, that's why
1794 we get styled_widget from outside */
1796 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1797 gray_color_markup = modest_text_utils_get_color_string (&color);
1798 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1800 if (!gray_color_markup)
1801 gray_color_markup = g_strdup ("#BBBBBB");
1803 return gray_color_markup;
1807 * Free the returned string
1810 create_device_name_visual_string (const gchar *device_name,
1811 const gchar *gray_color_markup)
1815 /* We have to use "" to fill the %s of the translation. We can
1816 not just use the device name because the device name is
1817 shown in a different color, so it could not be included
1818 into the <span> tag */
1819 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1820 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1831 GtkWidget *count_label;
1832 GtkWidget *msg_count_label;
1833 GtkWidget *size_label;
1834 gchar *color_markup;
1838 create_uint_label (const gchar *markup,
1842 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1846 create_gchar_label (const gchar *markup,
1850 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1854 update_folder_stats_status_cb (ModestFolderStats stats,
1857 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1860 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1861 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1864 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1865 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1868 if (widgets->size_label) {
1869 tmp = modest_text_utils_get_display_size (stats.local_size);
1870 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1871 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1878 update_folder_stats_cb (ModestFolderStats stats,
1881 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1884 update_folder_stats_status_cb (stats, user_data);
1886 /* frees. Note that the widgets could have been destroyed but
1887 we still keep a reference */
1888 g_free (widgets->color_markup);
1889 if (widgets->count_label)
1890 g_object_unref (widgets->count_label);
1891 if (widgets->msg_count_label)
1892 g_object_unref (widgets->msg_count_label);
1893 if (widgets->size_label)
1894 g_object_unref (widgets->size_label);
1895 g_slice_free (DetailsWidgets, widgets);
1899 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1901 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1906 gchar *gray_color_markup;
1907 DetailsWidgets *widgets;
1909 vbox = gtk_vbox_new (FALSE, 0);
1910 widgets = g_slice_new0 (DetailsWidgets);
1912 gray_color_markup = get_gray_color_markup (styled_widget);
1913 widgets->color_markup = g_strdup (gray_color_markup);
1915 /* Account description: */
1916 if (modest_tny_account_is_virtual_local_folders (account)
1917 || (modest_tny_account_is_memory_card_account (account))) {
1919 /* Get device name */
1920 gchar *device_name = NULL;
1921 if (modest_tny_account_is_virtual_local_folders (account))
1922 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1923 MODEST_CONF_DEVICE_NAME, NULL);
1925 device_name = g_strdup (tny_account_get_name (account));
1927 label = create_device_name_visual_string ((const gchar *) device_name,
1928 (const gchar *) gray_color_markup);
1929 label_w = gtk_label_new (NULL);
1930 gtk_label_set_markup (GTK_LABEL (label_w), label);
1931 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1932 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1933 g_free (device_name);
1936 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1937 gtk_box_pack_start (GTK_BOX (vbox),
1938 gtk_label_new (tny_account_get_name (account)),
1941 /* Other accounts, such as IMAP and POP: */
1946 /* Put proto in uppercase */
1947 proto = g_string_new (tny_account_get_proto (account));
1948 proto = g_string_ascii_up (proto);
1950 /* note: mcen_fi_localroot_description is something like "%s account"
1951 * however, we should display "%s account: %s"... therefore, ugly tmp */
1952 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1953 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1954 gray_color_markup, tmp, tny_account_get_name (account));
1957 label_w = gtk_label_new (NULL);
1958 gtk_label_set_markup (GTK_LABEL (label_w), label);
1959 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1960 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1961 g_string_free (proto, TRUE);
1967 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1968 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1969 label_w = gtk_label_new (NULL);
1970 gtk_label_set_markup (GTK_LABEL (label_w), label);
1971 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1972 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1975 widgets->msg_count_label = g_object_ref (label_w);
1978 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1979 label_w = gtk_label_new (NULL);
1980 gtk_label_set_markup (GTK_LABEL (label_w), label);
1981 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1982 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1985 widgets->count_label = g_object_ref (label_w);
1988 if (modest_tny_account_is_virtual_local_folders (account)
1989 || modest_tny_account_is_memory_card_account (account)) {
1991 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1993 label_w = gtk_label_new (NULL);
1994 gtk_label_set_markup (GTK_LABEL (label_w), label);
1995 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1996 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1999 widgets->size_label = g_object_ref (label_w);
2001 } else if (TNY_IS_ACCOUNT(folder_store)) {
2002 TnyAccount *account = TNY_ACCOUNT(folder_store);
2004 time_t last_updated;
2005 const gchar *last_updated_string;
2006 /* Get last updated from configuration */
2007 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
2008 tny_account_get_id (account));
2010 if (last_updated > 0)
2011 last_updated_string = modest_text_utils_get_display_date(last_updated);
2013 last_updated_string = g_strdup (_("mcen_va_never"));
2015 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
2016 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
2017 label_w = gtk_label_new (NULL);
2018 gtk_label_set_markup (GTK_LABEL (label_w), label);
2019 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
2020 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2024 g_free (gray_color_markup);
2026 /* Refresh folder stats asynchronously */
2027 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
2028 update_folder_stats_cb,
2029 update_folder_stats_status_cb,
2033 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2039 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2041 ModestMainWindowPrivate *priv = NULL;
2043 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2045 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2047 return priv->send_receive_in_progress;
2051 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2053 GtkAction *action = NULL;
2054 GtkWidget *widget = NULL;
2055 ModestMainWindowPrivate *priv = NULL;
2057 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2058 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2060 priv->send_receive_in_progress = TRUE;
2062 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2063 gtk_action_set_sensitive (action, FALSE);
2064 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2065 /* gtk_action_set_sensitive (action, FALSE); */
2066 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2067 gtk_widget_set_sensitive (widget, FALSE);
2071 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2073 GtkAction *action = NULL;
2074 GtkWidget *widget = NULL;
2075 ModestMainWindowPrivate *priv = NULL;
2077 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2078 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2080 priv->send_receive_in_progress = FALSE;
2082 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2083 gtk_action_set_sensitive (action, TRUE);
2084 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2085 /* gtk_action_set_sensitive (action, TRUE); */
2086 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2087 gtk_widget_set_sensitive (widget, TRUE);
2092 on_msg_count_changed (ModestHeaderView *header_view,
2094 TnyFolderChange *change,
2095 ModestMainWindow *main_window)
2097 gboolean refilter = FALSE;
2098 gboolean folder_empty = FALSE;
2099 gboolean all_marked_as_deleted = FALSE;
2100 ModestMainWindowPrivate *priv;
2102 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2103 g_return_if_fail (TNY_IS_FOLDER(folder));
2104 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2106 if (change != NULL) {
2107 TnyFolderChangeChanged changed;
2109 changed = tny_folder_change_get_changed (change);
2110 /* If something changes */
2111 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2112 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2114 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2116 /* Play a sound (if configured) and make the LED blink */
2117 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2118 modest_platform_push_email_notification ();
2121 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2124 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2127 /* Check if all messages are marked to be deleted */
2128 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2129 folder_empty = folder_empty || all_marked_as_deleted;
2131 /* Set contents style of headers view */
2133 modest_main_window_set_contents_style (main_window,
2134 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2135 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2137 modest_main_window_set_contents_style (main_window,
2138 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2142 modest_header_view_refilter (header_view);
2147 modest_main_window_set_contents_style (ModestMainWindow *self,
2148 ModestMainWindowContentsStyle style)
2150 ModestMainWindowPrivate *priv;
2152 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2154 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2156 /* We allow to set the same content style than the previously
2157 set if there are details, because it could happen when we're
2158 selecting different accounts consecutively */
2159 if ((priv->contents_style == style) &&
2160 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2163 /* Remove previous child. Delete it if it was an account
2165 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2167 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2168 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2171 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2174 priv->contents_style = style;
2176 switch (priv->contents_style) {
2177 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2178 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2179 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2181 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2182 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2184 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2186 /* if we're started without main win, there may not be a folder
2187 * view. this fixes a GLib-Critical */
2188 if (priv->folder_view) {
2189 TnyFolderStore *selected_folderstore =
2190 modest_folder_view_get_selected (priv->folder_view);
2191 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2192 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2193 TNY_ACCOUNT (selected_folderstore));
2195 wrap_in_scrolled_window (priv->contents_widget,
2196 priv->details_widget);
2198 if (selected_folderstore)
2199 g_object_unref (selected_folderstore);
2200 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2203 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2204 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2207 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2208 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2209 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2211 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2212 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2215 g_return_if_reached ();
2219 gtk_widget_show_all (priv->contents_widget);
2222 ModestMainWindowContentsStyle
2223 modest_main_window_get_contents_style (ModestMainWindow *self)
2225 ModestMainWindowPrivate *priv;
2227 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2229 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2230 return priv->contents_style;
2235 on_configuration_key_changed (ModestConf* conf,
2237 ModestConfEvent event,
2238 ModestConfNotificationId id,
2239 ModestMainWindow *self)
2241 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2242 TnyAccount *account = NULL;
2244 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2247 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2250 if (priv->folder_view)
2251 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2253 if (account && TNY_IS_ACCOUNT (account) &&
2254 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2257 const gchar *device_name;
2258 gchar *new_text, *gray_color_markup;
2261 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2262 label = GTK_LABEL (children->data);
2264 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2265 MODEST_CONF_DEVICE_NAME, NULL);
2267 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2268 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2270 gtk_label_set_markup (label, new_text);
2271 gtk_widget_show (GTK_WIDGET (label));
2273 g_free (gray_color_markup);
2275 g_list_free (children);
2277 g_object_unref (account);
2281 set_toolbar_transfer_mode (ModestMainWindow *self)
2283 ModestMainWindowPrivate *priv = NULL;
2285 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2287 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2289 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2291 if (priv->progress_bar_timeout > 0) {
2292 g_source_remove (priv->progress_bar_timeout);
2293 priv->progress_bar_timeout = 0;
2300 set_toolbar_mode (ModestMainWindow *self,
2301 ModestToolBarModes mode)
2303 ModestWindowPrivate *parent_priv = NULL;
2304 ModestMainWindowPrivate *priv = NULL;
2305 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2307 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2309 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2310 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2312 /* In case this was called before the toolbar exists: */
2313 if (!(parent_priv->toolbar))
2316 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2318 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2319 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2320 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2322 /* Sets current toolbar mode */
2323 priv->current_toolbar_mode = mode;
2325 /* Checks the dimming rules */
2326 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2327 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2329 /* Show and hide toolbar items */
2331 case TOOLBAR_MODE_NORMAL:
2333 gtk_action_set_visible (sort_action, TRUE);
2335 gtk_action_set_visible (refresh_action, TRUE);
2336 if (priv->progress_toolitem) {
2337 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2338 gtk_widget_hide (priv->progress_toolitem);
2340 if (priv->progress_bar)
2341 gtk_widget_hide (priv->progress_bar);
2344 gtk_action_set_visible (cancel_action, FALSE);
2346 /* Hide toolbar if optimized view is enabled */
2347 if (priv->optimized_view)
2348 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2350 case TOOLBAR_MODE_TRANSFER:
2352 gtk_action_set_visible (sort_action, FALSE);
2354 gtk_action_set_visible (refresh_action, FALSE);
2356 gtk_action_set_visible (cancel_action, TRUE);
2357 if (priv->progress_bar)
2358 gtk_widget_show (priv->progress_bar);
2359 if (priv->progress_toolitem) {
2360 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2361 gtk_widget_show (priv->progress_toolitem);
2364 /* Show toolbar if it's hiden (optimized view ) */
2365 if (priv->optimized_view)
2366 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2369 g_return_if_reached ();
2374 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2376 ModestMainWindowPrivate *priv;
2378 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2379 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2381 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2385 cancel_progressbar (GtkToolButton *toolbutton,
2386 ModestMainWindow *self)
2389 ModestMainWindowPrivate *priv;
2391 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2393 /* Get operation observers and cancel all the operations */
2394 tmp = priv->progress_widgets;
2396 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2397 tmp=g_slist_next(tmp);
2402 observers_empty (ModestMainWindow *self)
2405 ModestMainWindowPrivate *priv;
2406 gboolean is_empty = TRUE;
2407 guint pending_ops = 0;
2409 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2410 tmp = priv->progress_widgets;
2412 /* Check all observers */
2413 while (tmp && is_empty) {
2414 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2415 is_empty = pending_ops == 0;
2417 tmp = g_slist_next(tmp);
2425 * Gets the toolbar mode needed for each mail operation. It stores in
2426 * @mode_changed if the toolbar mode has changed or not
2428 static ModestToolBarModes
2429 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2430 ModestMailOperation *mail_op,
2431 gboolean *mode_changed)
2433 ModestToolBarModes mode;
2434 ModestMainWindowPrivate *priv;
2436 *mode_changed = FALSE;
2437 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2439 /* Get toolbar mode from operation id*/
2440 switch (modest_mail_operation_get_type_operation (mail_op)) {
2441 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2442 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2443 mode = TOOLBAR_MODE_TRANSFER;
2444 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2445 *mode_changed = TRUE;
2448 mode = TOOLBAR_MODE_NORMAL;
2454 on_mail_operation_started (ModestMailOperation *mail_op,
2457 ModestMainWindow *self;
2458 ModestMailOperationTypeOperation op_type;
2459 ModestMainWindowPrivate *priv;
2460 ModestToolBarModes mode;
2462 gboolean mode_changed = FALSE;
2463 TnyAccount *account = NULL;
2465 self = MODEST_MAIN_WINDOW (user_data);
2466 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2468 /* Do not show progress for receiving operations if the
2469 account is the local account or the MMC one */
2470 op_type = modest_mail_operation_get_type_operation (mail_op);
2471 account = modest_mail_operation_get_account (mail_op);
2472 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2475 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2476 modest_tny_account_is_memory_card_account (account));
2478 g_object_unref (account);
2482 /* Show information banner. Remove old timeout */
2483 if (priv->opening_banner_timeout > 0) {
2484 g_source_remove (priv->opening_banner_timeout);
2485 priv->opening_banner_timeout = 0;
2487 /* Create a new timeout */
2488 priv->opening_banner_timeout =
2489 g_timeout_add (2000, show_opening_banner, self);
2492 /* Not every mail operation has account, noop does not */
2494 g_object_unref (account);
2496 /* Get toolbar mode from operation id*/
2497 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2499 /* Add operation observers and change toolbar if neccessary*/
2500 tmp = priv->progress_widgets;
2501 if (mode == TOOLBAR_MODE_TRANSFER) {
2503 GObject *source = modest_mail_operation_get_source(mail_op);
2504 if (G_OBJECT (self) == source) {
2505 set_toolbar_transfer_mode(self);
2507 g_object_unref (source);
2511 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2513 tmp = g_slist_next (tmp);
2517 /* Update the main menu as well, we need to explicitely do
2518 this in order to enable/disable accelerators */
2519 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2523 on_mail_operation_finished (ModestMailOperation *mail_op,
2526 ModestToolBarModes mode;
2527 ModestMailOperationTypeOperation op_type;
2529 ModestMainWindow *self;
2530 gboolean mode_changed;
2531 TnyAccount *account = NULL;
2532 ModestMainWindowPrivate *priv;
2534 self = MODEST_MAIN_WINDOW (user_data);
2535 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2537 /* The mail operation was not added to the progress objects if
2538 the account was the local account or the MMC one */
2539 op_type = modest_mail_operation_get_type_operation (mail_op);
2540 account = modest_mail_operation_get_account (mail_op);
2541 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2544 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2545 modest_tny_account_is_memory_card_account (account));
2547 g_object_unref (account);
2551 /* Remove old timeout */
2552 if (priv->opening_banner_timeout > 0) {
2553 g_source_remove (priv->opening_banner_timeout);
2554 priv->opening_banner_timeout = 0;
2557 /* Remove the banner if exists */
2558 if (priv->opening_banner) {
2559 gtk_widget_destroy (priv->opening_banner);
2560 priv->opening_banner = NULL;
2564 /* Not every mail operation has account, noop does not */
2566 g_object_unref (account);
2568 /* Get toolbar mode from operation id*/
2569 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2571 /* Change toolbar mode */
2572 tmp = priv->progress_widgets;
2573 if (mode == TOOLBAR_MODE_TRANSFER) {
2575 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2577 tmp = g_slist_next (tmp);
2580 /* If no more operations are being observed, NORMAL mode is enabled again */
2581 if (observers_empty (self)) {
2582 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2588 on_queue_changed (ModestMailOperationQueue *queue,
2589 ModestMailOperation *mail_op,
2590 ModestMailOperationQueueNotification type,
2591 ModestMainWindow *self)
2593 ModestMainWindowPrivate *priv;
2595 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2597 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2598 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2600 "operation-started",
2601 G_CALLBACK (on_mail_operation_started),
2603 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2605 "operation-finished",
2606 G_CALLBACK (on_mail_operation_finished),
2608 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2609 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2611 "operation-started");
2612 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2614 "operation-finished");
2619 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2621 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2623 ModestAccountMgr *mgr;
2624 ModestAccountSettings *settings;
2625 ModestServerAccountSettings *store_settings = NULL;
2627 /* Get account data */
2628 mgr = modest_runtime_get_account_mgr ();
2629 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2631 store_settings = modest_account_settings_get_store_settings (settings);
2633 /* Set the new visible & active account */
2634 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2635 const gchar *account_name;
2637 account_name = modest_account_settings_get_account_name (settings);
2639 modest_folder_view_set_account_id_of_visible_server_account
2641 modest_server_account_settings_get_account_name (store_settings));
2642 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2643 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2645 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2646 if (action != NULL) {
2647 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2648 modest_utils_toggle_action_set_active_block_notify (
2649 GTK_TOGGLE_ACTION (action),
2657 g_object_unref (store_settings);
2658 g_object_unref (settings);
2662 /* Make sure that at least one account is "viewed": */
2664 set_at_least_one_account_visible(ModestMainWindow *self)
2666 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2667 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2669 if (!(priv->folder_view)) {
2670 /* It is too early to do this. */
2674 const gchar *active_server_account_name =
2675 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2677 if (!active_server_account_name ||
2678 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2680 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2681 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2682 if (default_modest_name) {
2683 set_account_visible (self, default_modest_name);
2684 } else if (first_modest_name) {
2685 set_account_visible (self, first_modest_name);
2687 g_free (first_modest_name);
2688 g_free (default_modest_name);
2693 on_show_account_action_toggled (GtkToggleAction *action,
2696 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2698 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2699 if (gtk_toggle_action_get_active (action))
2700 set_account_visible (self, acc_name);
2704 refresh_account (const gchar *account_name)
2708 /* win must already exists here, obviously */
2709 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2712 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2716 /* If account_name == NULL, we must update all (option All) */
2718 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2720 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2725 on_refresh_account_action_activated (GtkAction *action,
2728 refresh_account ((const gchar*) user_data);
2732 on_send_receive_csm_activated (GtkMenuItem *item,
2735 refresh_account ((const gchar*) user_data);
2739 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2741 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2743 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2749 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2751 ModestMainWindow *main_window = NULL;
2753 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2754 main_window = MODEST_MAIN_WINDOW (userdata);
2756 /* Update toolbar dimming state */
2757 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2758 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2764 on_header_view_focus_in (GtkWidget *widget,
2765 GdkEventFocus *event,
2768 ModestMainWindow *main_window = NULL;
2770 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2772 main_window = MODEST_MAIN_WINDOW (userdata);
2774 /* Update toolbar dimming state */
2775 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2776 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2782 on_folder_selection_changed (ModestFolderView *folder_view,
2783 TnyFolderStore *folder_store,
2785 ModestMainWindow *main_window)
2787 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2788 GtkAction *action = NULL;
2789 gboolean show_reply = TRUE;
2790 gboolean show_forward = TRUE;
2791 gboolean show_cancel_send = FALSE;
2792 gboolean show_clipboard = TRUE;
2793 gboolean show_delete = TRUE;
2796 if (TNY_IS_ACCOUNT (folder_store)) {
2797 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2798 } else if (TNY_IS_FOLDER (folder_store)) {
2799 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2800 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2801 TNY_FOLDER (folder_store));
2802 switch (folder_type) {
2803 case TNY_FOLDER_TYPE_DRAFTS:
2804 show_clipboard = show_delete = TRUE;
2805 show_reply = show_forward = show_cancel_send = FALSE;
2807 case TNY_FOLDER_TYPE_SENT:
2808 show_forward = show_clipboard = show_delete = TRUE;
2809 show_reply = show_cancel_send = FALSE;
2811 case TNY_FOLDER_TYPE_OUTBOX:
2812 show_clipboard = show_delete = show_cancel_send = TRUE;
2813 show_reply = show_forward = FALSE;
2815 case TNY_FOLDER_TYPE_INVALID:
2816 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2819 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2820 show_cancel_send = FALSE;
2823 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2824 show_cancel_send = FALSE;
2829 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2830 gtk_action_set_visible (action, show_reply);
2831 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2832 gtk_action_set_visible (action, show_reply);
2833 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2834 gtk_action_set_visible (action, show_forward);
2835 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2836 gtk_action_set_visible (action, show_cancel_send);
2837 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2838 gtk_action_set_visible (action, show_delete);
2840 /* We finally call to the ui actions handler, after updating properly
2841 * the header view CSM */
2842 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2846 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2847 GtkTreeModel *model,
2848 GtkTreeRowReference *row_reference,
2849 ModestMainWindow *self)
2851 ModestMainWindowPrivate *priv = NULL;
2852 GtkTreeModel *header_model = NULL;
2853 GtkTreePath *path = NULL;
2855 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2856 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2857 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2859 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2860 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2862 /* Do nothing if we changed the folder in the main view */
2863 if (header_model != model)
2866 /* Select the message in the header view */
2867 path = gtk_tree_row_reference_get_path (row_reference);
2868 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2870 gtk_tree_path_free (path);
2876 updating_banner_destroyed (gpointer data,
2877 GObject *where_the_object_was)
2879 ModestMainWindowPrivate *priv = NULL;
2881 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2883 priv->updating_banner = NULL;
2887 show_updating_banner (gpointer user_data)
2889 ModestMainWindowPrivate *priv = NULL;
2891 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2893 if (priv->updating_banner == NULL) {
2895 /* We're outside the main lock */
2896 gdk_threads_enter ();
2897 priv->updating_banner =
2898 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2899 _CS ("ckdg_pb_updating"));
2901 /* We need this because banners in Maemo could be
2902 destroyed by dialogs so we need to properly update
2903 our reference to it */
2904 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2905 updating_banner_destroyed,
2907 gdk_threads_leave ();
2910 /* Remove timeout */
2911 priv->updating_banner_timeout = 0;
2916 * We use this function to show/hide a progress banner showing
2917 * "Updating" while the header view is being filled. We're not showing
2918 * it unless the update takes more than 2 seconds
2920 * If starting = TRUE then the refresh is starting, otherwise it means
2921 * that is has just finished
2924 on_updating_msg_list (ModestHeaderView *header_view,
2928 ModestMainWindowPrivate *priv = NULL;
2930 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2932 /* Remove old timeout */
2933 if (priv->updating_banner_timeout > 0) {
2934 g_source_remove (priv->updating_banner_timeout);
2935 priv->updating_banner_timeout = 0;
2938 /* Create a new timeout */
2940 priv->updating_banner_timeout =
2941 g_timeout_add (2000, show_updating_banner, user_data);
2943 /* Remove the banner if exists */
2944 if (priv->updating_banner) {
2945 gtk_widget_destroy (priv->updating_banner);
2946 priv->updating_banner = NULL;
2952 modest_main_window_screen_is_on (ModestMainWindow *self)
2954 ModestMainWindowPrivate *priv = NULL;
2956 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2958 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2960 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2964 remove_banners (ModestMainWindow *window)
2966 ModestMainWindowPrivate *priv;
2968 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2970 if (priv->opening_banner_timeout > 0) {
2971 g_source_remove (priv->opening_banner_timeout);
2972 priv->opening_banner_timeout = 0;
2975 if (priv->opening_banner != NULL) {
2976 gtk_widget_destroy (priv->opening_banner);
2977 priv->opening_banner = NULL;
2980 if (priv->updating_banner_timeout > 0) {
2981 g_source_remove (priv->updating_banner_timeout);
2982 priv->updating_banner_timeout = 0;
2985 if (priv->updating_banner != NULL) {
2986 gtk_widget_destroy (priv->updating_banner);
2987 priv->updating_banner = NULL;
2993 on_window_hide (GObject *gobject,
2997 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2999 if (!GTK_WIDGET_VISIBLE (gobject)) {
3000 TnyFolderStore *folder_store;
3001 ModestMainWindowPrivate *priv;
3003 /* Remove the currently shown banners */
3004 remove_banners (MODEST_MAIN_WINDOW (gobject));
3006 /* Force the folder view to sync the currently selected folder
3007 to save the read/unread status and to expunge messages */
3008 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
3009 folder_store = modest_folder_view_get_selected (priv->folder_view);
3010 if (TNY_IS_FOLDER (folder_store)) {
3011 ModestMailOperation *mail_op;
3013 mail_op = modest_mail_operation_new (NULL);
3014 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3016 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
3017 g_object_unref (mail_op);
3018 g_object_unref (folder_store);
3024 on_window_destroy (GtkObject *widget,
3027 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
3029 remove_banners (MODEST_MAIN_WINDOW (widget));
3033 opening_banner_destroyed (gpointer data,
3034 GObject *where_the_object_was)
3036 ModestMainWindowPrivate *priv = NULL;
3038 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
3040 priv->opening_banner = NULL;
3044 show_opening_banner (gpointer user_data)
3046 ModestMainWindowPrivate *priv = NULL;
3048 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
3050 if (priv->opening_banner == NULL) {
3052 /* We're outside the main lock */
3053 gdk_threads_enter ();
3054 priv->opening_banner =
3055 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
3056 _("mail_me_opening"));
3058 /* We need this because banners in Maemo could be
3059 destroyed by dialogs so we need to properly update
3060 our reference to it */
3061 g_object_weak_ref (G_OBJECT (priv->opening_banner),
3062 opening_banner_destroyed,
3065 /* We need this because banners in Maemo could be
3066 destroyed by dialogs so we need to properly update
3067 our reference to it */
3068 g_object_weak_ref (G_OBJECT (priv->updating_banner),
3069 updating_banner_destroyed,
3071 gdk_threads_leave ();
3074 /* Remove timeout */
3075 priv->opening_banner_timeout = 0;