1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-utils.h>
57 #include <modest-maemo-utils.h>
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-mail-operation.h"
61 #include "modest-icon-names.h"
62 #include "modest-progress-bar.h"
63 #include "modest-text-utils.h"
64 #include "modest-ui-dimming-manager.h"
65 #include "maemo/modest-osso-state-saving.h"
66 #include "modest-text-utils.h"
67 #include "modest-signal-mgr.h"
69 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
76 /* 'private'/'protected' functions */
77 static void modest_main_window_class_init (ModestMainWindowClass *klass);
78 static void modest_main_window_init (ModestMainWindow *obj);
79 static void modest_main_window_finalize (GObject *obj);
81 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
82 GdkEventWindowState *event,
85 static void connect_signals (ModestMainWindow *self);
87 static void modest_main_window_disconnect_signals (ModestWindow *self);
89 static void restore_settings (ModestMainWindow *self,
90 gboolean do_folder_view_too);
92 static void save_state (ModestWindow *self);
94 static void update_menus (ModestMainWindow* self);
96 static void modest_main_window_show_toolbar (ModestWindow *window,
97 gboolean show_toolbar);
99 static void cancel_progressbar (GtkToolButton *toolbutton,
100 ModestMainWindow *self);
102 static void on_queue_changed (ModestMailOperationQueue *queue,
103 ModestMailOperation *mail_op,
104 ModestMailOperationQueueNotification type,
105 ModestMainWindow *self);
107 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
109 static void on_account_inserted (TnyAccountStore *accoust_store,
113 static void on_account_removed (TnyAccountStore *accoust_store,
117 static void on_account_changed (TnyAccountStore *account_store,
121 static void on_default_account_changed (ModestAccountMgr* mgr,
124 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
128 static void on_configuration_key_changed (ModestConf* conf,
130 ModestConfEvent event,
131 ModestConfNotificationId id,
132 ModestMainWindow *self);
134 static void set_toolbar_mode (ModestMainWindow *self,
135 ModestToolBarModes mode);
137 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
139 static void on_show_account_action_toggled (GtkToggleAction *action,
142 static void on_refresh_account_action_activated (GtkAction *action,
145 static void on_send_receive_csm_activated (GtkMenuItem *item,
148 static void on_msg_count_changed (ModestHeaderView *header_view,
150 TnyFolderChange *change,
151 ModestMainWindow *main_window);
153 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
156 static GtkWidget * create_empty_view (void);
158 static gboolean on_folder_view_focus_in (GtkWidget *widget,
159 GdkEventFocus *event,
162 static gboolean on_header_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static void on_folder_selection_changed (ModestFolderView *folder_view,
167 TnyFolderStore *folder_store,
169 ModestMainWindow *main_window);
171 static void set_at_least_one_account_visible(ModestMainWindow *self);
173 static void on_updating_msg_list (ModestHeaderView *header_view,
177 static gboolean restore_paned_timeout_handler (gpointer *data);
179 static gboolean show_retrieving_banner (gpointer user_data);
181 static void on_window_destroy (GtkObject *widget,
184 static void on_window_hide (GObject *gobject,
188 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
189 struct _ModestMainWindowPrivate {
190 GtkWidget *msg_paned;
191 GtkWidget *main_paned;
192 GtkWidget *main_vbox;
193 GtkWidget *contents_widget;
194 GtkWidget *empty_view;
196 /* Progress observers */
197 GtkWidget *progress_bar;
198 GSList *progress_widgets;
201 GtkWidget *progress_toolitem;
202 GtkWidget *cancel_toolitem;
203 GtkWidget *sort_toolitem;
204 GtkWidget *refresh_toolitem;
205 ModestToolBarModes current_toolbar_mode;
207 /* Merge ids used to add/remove accounts to the ViewMenu*/
208 GByteArray *merge_ids;
209 GtkActionGroup *view_additions_group;
211 /* On-demand widgets */
212 GtkWidget *accounts_popup;
213 GtkWidget *details_widget;
215 /* Optimized view enabled */
216 gboolean optimized_view;
218 /* Optimized view enabled */
219 gboolean send_receive_in_progress;
221 ModestHeaderView *header_view;
222 ModestFolderView *folder_view;
224 ModestMainWindowStyle style;
225 ModestMainWindowContentsStyle contents_style;
226 gboolean wait_for_settings;
228 guint progress_bar_timeout;
229 guint restore_paned_timeout;
231 /* Signal handler UIDs */
232 GList *queue_err_signals;
235 /* "Updating" banner for header view */
236 GtkWidget *updating_banner;
237 guint updating_banner_timeout;
239 /* "Retrieving" banner for header view */
240 GtkWidget *retrieving_banner;
241 guint retrieving_banner_timeout;
244 osso_display_state_t display_state;
246 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
247 MODEST_TYPE_MAIN_WINDOW, \
248 ModestMainWindowPrivate))
250 typedef struct _GetMsgAsyncHelper {
251 ModestMainWindowPrivate *main_window_private;
253 ModestTnyMsgReplyType reply_type;
254 ModestTnyMsgForwardType forward_type;
261 static GtkWindowClass *parent_class = NULL;
264 /* Private actions */
265 /* This is the context sensitive menu: */
266 static const GtkActionEntry modest_folder_view_action_entries [] = {
268 /* Folder View CSM actions */
269 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
270 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
271 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
272 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
273 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
274 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
277 static const GtkActionEntry modest_header_view_action_entries [] = {
279 /* Header View CSM actions */
280 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
281 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
282 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
283 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
284 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
285 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
286 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
287 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
288 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
289 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
292 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
293 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
296 /************************************************************************/
299 modest_main_window_get_type (void)
301 static GType my_type = 0;
303 static const GTypeInfo my_info = {
304 sizeof(ModestMainWindowClass),
305 NULL, /* base init */
306 NULL, /* base finalize */
307 (GClassInitFunc) modest_main_window_class_init,
308 NULL, /* class finalize */
309 NULL, /* class data */
310 sizeof(ModestMainWindow),
312 (GInstanceInitFunc) modest_main_window_init,
315 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
323 modest_main_window_class_init (ModestMainWindowClass *klass)
325 GObjectClass *gobject_class;
326 gobject_class = (GObjectClass*) klass;
327 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
329 parent_class = g_type_class_peek_parent (klass);
330 gobject_class->finalize = modest_main_window_finalize;
332 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
334 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
335 modest_window_class->save_state_func = save_state;
336 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
337 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
338 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
342 modest_main_window_init (ModestMainWindow *obj)
344 ModestMainWindowPrivate *priv;
346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
348 priv->queue_err_signals = NULL;
349 priv->msg_paned = NULL;
350 priv->main_paned = NULL;
351 priv->main_vbox = NULL;
352 priv->header_view = NULL;
353 priv->folder_view = NULL;
354 priv->contents_widget = NULL;
355 priv->accounts_popup = NULL;
356 priv->details_widget = NULL;
357 priv->empty_view = NULL;
358 priv->progress_widgets = NULL;
359 priv->progress_bar = NULL;
360 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
361 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
362 priv->wait_for_settings = TRUE;
363 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
364 priv->merge_ids = NULL;
365 priv->optimized_view = FALSE;
366 priv->send_receive_in_progress = FALSE;
367 priv->progress_bar_timeout = 0;
368 priv->restore_paned_timeout = 0;
369 priv->sighandlers = NULL;
370 priv->updating_banner = NULL;
371 priv->updating_banner_timeout = 0;
372 priv->retrieving_banner = NULL;
373 priv->retrieving_banner_timeout = 0;
374 priv->display_state = OSSO_DISPLAY_ON;
376 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
378 "applications_email_mainview");
382 modest_main_window_finalize (GObject *obj)
384 ModestMainWindowPrivate *priv;
386 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
388 /* Sanity check: shouldn't be needed, the window mgr should
389 call this function before */
390 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
391 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
393 if (priv->empty_view) {
394 g_object_unref (priv->empty_view);
395 priv->empty_view = NULL;
398 if (priv->header_view) {
399 g_object_unref (priv->header_view);
400 priv->header_view = NULL;
403 g_slist_free (priv->progress_widgets);
405 g_byte_array_free (priv->merge_ids, TRUE);
407 if (priv->progress_bar_timeout > 0) {
408 g_source_remove (priv->progress_bar_timeout);
409 priv->progress_bar_timeout = 0;
412 if (priv->updating_banner_timeout > 0) {
413 g_source_remove (priv->updating_banner_timeout);
414 priv->updating_banner_timeout = 0;
417 if (priv->updating_banner) {
418 gtk_widget_destroy (priv->updating_banner);
419 priv->updating_banner = NULL;
422 if (priv->retrieving_banner_timeout > 0) {
423 g_source_remove (priv->retrieving_banner_timeout);
424 priv->retrieving_banner_timeout = 0;
427 if (priv->retrieving_banner) {
428 gtk_widget_destroy (priv->retrieving_banner);
429 priv->retrieving_banner = NULL;
432 if (priv->restore_paned_timeout > 0) {
433 g_source_remove (priv->restore_paned_timeout);
434 priv->restore_paned_timeout = 0;
437 G_OBJECT_CLASS(parent_class)->finalize (obj);
441 modest_main_window_get_child_widget (ModestMainWindow *self,
442 ModestMainWindowWidgetType widget_type)
444 ModestMainWindowPrivate *priv;
447 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
448 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
451 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
453 switch (widget_type) {
454 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
455 widget = (GtkWidget*)priv->header_view; break;
456 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
457 widget = (GtkWidget*)priv->folder_view; break;
462 /* Note that the window could have been destroyed, and so
463 their children, but still have some references */
464 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
468 restore_paned_timeout_handler (gpointer *data)
470 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
471 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
474 /* Timeouts are outside the main lock */
475 gdk_threads_enter ();
476 if (GTK_WIDGET_VISIBLE (main_window)) {
477 conf = modest_runtime_get_conf ();
478 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
479 MODEST_CONF_MAIN_PANED_KEY);
481 gdk_threads_leave ();
488 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
491 ModestMainWindowPrivate *priv;
493 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
495 conf = modest_runtime_get_conf ();
497 modest_widget_memory_restore (conf, G_OBJECT(self),
498 MODEST_CONF_MAIN_WINDOW_KEY);
500 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
501 MODEST_CONF_HEADER_VIEW_KEY);
503 if (do_folder_view_too)
504 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
505 MODEST_CONF_FOLDER_VIEW_KEY);
507 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
508 /* MODEST_CONF_MAIN_PANED_KEY); */
510 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
512 /* We need to force a redraw here in order to get the right
513 position of the horizontal paned separator */
514 gtk_widget_show (GTK_WIDGET (self));
519 save_state (ModestWindow *window)
522 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
523 ModestMainWindowPrivate *priv;
525 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
526 conf = modest_runtime_get_conf ();
528 modest_widget_memory_save (conf,G_OBJECT(self),
529 MODEST_CONF_MAIN_WINDOW_KEY);
530 /* Only save main paned position if we're in split mode */
531 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
532 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
533 MODEST_CONF_MAIN_PANED_KEY);
534 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
535 MODEST_CONF_FOLDER_VIEW_KEY);
539 compare_display_names (ModestAccountSettings *a,
540 ModestAccountSettings *b)
542 return g_utf8_collate (modest_account_settings_get_display_name (a),
543 modest_account_settings_get_display_name (b));
547 /* We use this function to prevent the send&receive CSM to be shown
548 when there are less than two account */
550 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
556 update_menus (ModestMainWindow* self)
558 GSList *account_names, *iter, *accounts;
559 ModestMainWindowPrivate *priv;
560 ModestWindowPrivate *parent_priv;
561 ModestAccountMgr *mgr;
562 gint i, num_accounts;
564 gchar *default_account;
565 const gchar *active_account_name;
566 GtkWidget *send_receive_button, *item;
567 GtkAction *send_receive_all = NULL;
570 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
571 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
573 /* Get enabled account IDs */
574 mgr = modest_runtime_get_account_mgr ();
575 account_names = modest_account_mgr_account_names (mgr, TRUE);
576 iter = account_names;
580 ModestAccountSettings *settings =
581 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
582 accounts = g_slist_prepend (accounts, settings);
586 modest_account_mgr_free_account_names (account_names);
587 account_names = NULL;
589 /* Order the list of accounts by its display name */
590 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
591 num_accounts = g_slist_length (accounts);
593 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
594 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
595 gtk_action_set_visible (send_receive_all, num_accounts > 0);
597 /* Delete old send&receive popup items. We can not just do a
598 menu_detach because it does not work well with
600 if (priv->accounts_popup)
601 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
602 (GtkCallback) gtk_widget_destroy, NULL);
604 /* Delete old entries in the View menu. Do not free groups, it
606 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
608 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
609 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
610 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
611 GTK_ACTION_GROUP (groups->data));
614 if (priv->merge_ids) {
615 for (i = 0; i < priv->merge_ids->len; i++)
616 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
617 g_byte_array_free (priv->merge_ids, TRUE);
619 /* We need to call this in order to ensure
620 that the new actions are added in the right
621 order (alphabetical) */
622 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
624 groups = g_list_next (groups);
626 priv->merge_ids = g_byte_array_sized_new (num_accounts);
628 /* Get send receive button */
629 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
630 "/ToolBar/ToolbarSendReceive");
632 /* Create the menu */
633 if (num_accounts > 1) {
634 if (!priv->accounts_popup)
635 priv->accounts_popup = gtk_menu_new ();
636 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
637 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
638 g_signal_connect (G_OBJECT (item),
640 G_CALLBACK (on_send_receive_csm_activated),
642 item = gtk_separator_menu_item_new ();
643 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
646 /* Create a new action group */
647 default_account = modest_account_mgr_get_default_account (mgr);
648 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
650 if (!active_account_name)
651 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
653 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
655 for (i = 0; i < num_accounts; i++) {
656 gchar *display_name = NULL;
657 const gchar *account_name;
658 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
661 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
664 account_name = modest_account_settings_get_account_name (settings);
666 if (default_account && account_name &&
667 !(strcmp (default_account, account_name) == 0)) {
668 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
669 modest_account_settings_get_display_name (settings));
671 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
672 modest_account_settings_get_display_name (settings));
677 /* Create action and add it to the action group. The
678 action name must be the account name, this way we
679 could know in the handlers the account to show */
680 if (settings && account_name) {
681 gchar* item_name, *refresh_action_name;
683 GtkAction *view_account_action, *refresh_account_action;
684 gchar *escaped_display_name;
686 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
688 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
689 escaped_display_name, NULL, NULL, 0));
690 g_free (escaped_display_name);
691 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
692 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
693 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
695 if (active_account_name) {
696 if (active_account_name && account_name &&
697 (strcmp (active_account_name, account_name) == 0)) {
698 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
702 /* Add ui from account data. We allow 2^9-1 account
703 changes in a single execution because we're
704 downcasting the guint to a guint8 in order to use a
705 GByteArray. It should be enough :-) */
706 item_name = g_strconcat (account_name, "Menu", NULL);
707 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
708 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
709 gtk_ui_manager_add_ui (parent_priv->ui_manager,
711 "/MenuBar/ViewMenu/ViewMenuAdditions",
714 GTK_UI_MANAGER_MENUITEM,
717 /* Connect the action signal "activate" */
718 g_signal_connect_after (G_OBJECT (view_account_action),
720 G_CALLBACK (on_show_account_action_toggled),
723 /* Create the items for the Tools->Send&Receive submenu */
724 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
725 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
726 display_name, NULL, NULL);
727 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
729 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
730 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
731 gtk_ui_manager_add_ui (parent_priv->ui_manager,
733 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
736 GTK_UI_MANAGER_MENUITEM,
738 g_free (refresh_action_name);
740 g_signal_connect_data (G_OBJECT (refresh_account_action),
742 G_CALLBACK (on_refresh_account_action_activated),
743 g_strdup (account_name),
744 (GClosureNotify) g_free,
747 /* Create item and add it to the send&receive
748 CSM. If there is only one account then
750 if (num_accounts > 1) {
751 GtkWidget *label = gtk_label_new(NULL);
752 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
753 if (default_account && (strcmp(account_name, default_account) == 0)) {
754 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
755 gtk_label_set_markup (GTK_LABEL (label), escaped);
758 gtk_label_set_text (GTK_LABEL (label), display_name);
761 item = gtk_menu_item_new ();
762 gtk_container_add (GTK_CONTAINER (item), label);
764 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
766 g_signal_connect_data (G_OBJECT (item),
768 G_CALLBACK (on_send_receive_csm_activated),
769 g_strdup (account_name),
770 (GClosureNotify) g_free,
777 g_free (display_name);
780 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
782 /* We cannot do this in the loop above because this relies on the action
783 * group being inserted. This makes the default account appear in bold.
784 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
785 for (i = 0; i < num_accounts; i++) {
786 gchar *item_name, *path;
788 ModestAccountSettings *settings;
789 const gchar *account_name;
792 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
793 account_name = modest_account_settings_get_account_name (settings);
794 is_default = (account_name && default_account && !strcmp (account_name, default_account));
796 /* Get the item of the view menu */
797 item_name = g_strconcat (account_name, "Menu", NULL);
798 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
799 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
803 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
804 if (GTK_IS_LABEL (child)) {
805 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
807 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
808 gtk_label_set_markup (GTK_LABEL (child), bold_name);
811 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
815 /* Get the item of the tools menu */
816 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
817 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
821 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
822 if (GTK_IS_LABEL (child)) {
823 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
825 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
826 gtk_label_set_markup (GTK_LABEL (child), bold_name);
829 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
834 g_object_unref (settings);
837 if (num_accounts > 1) {
838 /* Disconnect the tap-and-hold-query if it's connected */
839 if (modest_signal_mgr_is_connected (priv->sighandlers,
840 G_OBJECT (send_receive_button),
841 "tap-and-hold-query"))
842 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
843 G_OBJECT (send_receive_button),
844 "tap-and-hold-query");
846 /* Mandatory in order to view the menu contents */
847 gtk_widget_show_all (priv->accounts_popup);
849 /* Setup tap_and_hold just if was not done before*/
850 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
851 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
853 /* Connect the tap-and-hold-query in order not to show the CSM */
854 if (!modest_signal_mgr_is_connected (priv->sighandlers,
855 G_OBJECT (send_receive_button),
856 "tap-and-hold-query"))
857 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
858 G_OBJECT (send_receive_button),
859 "tap-and-hold-query",
860 G_CALLBACK (tap_and_hold_query_cb),
865 g_slist_free (accounts);
866 g_free (default_account);
869 /* Make sure that at least one account is viewed if there are any
870 * accounts, for instance when adding the first account: */
871 set_at_least_one_account_visible (self);
875 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
877 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
878 gtk_scrolled_window_add_with_viewport
879 (GTK_SCROLLED_WINDOW(win), widget);
881 gtk_container_add (GTK_CONTAINER(win),
892 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
894 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
896 GList *oerrsignals = priv->queue_err_signals;
897 while (oerrsignals) {
898 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
899 g_signal_handler_disconnect (esignal->queue, esignal->signal);
900 g_slice_free (QueueErrorSignal, esignal);
901 oerrsignals = g_list_next (oerrsignals);
903 g_list_free (priv->queue_err_signals);
904 priv->queue_err_signals = NULL;
909 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
911 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
914 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
918 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
920 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
922 /* Update visibility */
925 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
929 modest_main_window_disconnect_signals (ModestWindow *self)
931 ModestMainWindowPrivate *priv;
932 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
934 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
935 priv->sighandlers = NULL;
939 connect_signals (ModestMainWindow *self)
941 ModestWindowPrivate *parent_priv;
942 ModestMainWindowPrivate *priv;
945 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
946 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
951 modest_signal_mgr_connect (priv->sighandlers,
952 G_OBJECT(priv->folder_view), "key-press-event",
953 G_CALLBACK(on_inner_widgets_key_pressed), self);
955 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
956 "folder_selection_changed",
957 G_CALLBACK (on_folder_selection_changed),
960 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
961 "folder-display-name-changed",
962 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
965 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
967 G_CALLBACK (on_folder_view_focus_in),
970 /* Folder view CSM */
971 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
972 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
973 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
974 G_CALLBACK(_folder_view_csm_menu_activated),
978 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
979 G_CALLBACK(modest_ui_actions_on_header_selected), self);
981 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
982 G_CALLBACK(modest_ui_actions_on_header_activated), self);
984 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
985 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
987 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
988 G_CALLBACK(on_inner_widgets_key_pressed), self);
990 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
991 G_CALLBACK(on_msg_count_changed), self);
993 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
994 G_CALLBACK (on_header_view_focus_in), self);
996 modest_signal_mgr_connect (priv->sighandlers,
997 G_OBJECT (priv->header_view),
999 G_CALLBACK (on_updating_msg_list),
1002 /* Header view CSM */
1003 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1004 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1006 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1007 G_CALLBACK(_header_view_csm_menu_activated),
1012 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1013 G_CALLBACK (modest_main_window_window_state_event),
1015 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1016 * in destroy stage */
1017 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1019 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1021 /* Mail Operation Queue */
1023 modest_signal_mgr_connect (priv->sighandlers,
1024 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1026 G_CALLBACK (on_queue_changed), self);
1028 /* Track changes in the device name */
1030 modest_signal_mgr_connect (priv->sighandlers,
1031 G_OBJECT(modest_runtime_get_conf ()),
1033 G_CALLBACK (on_configuration_key_changed),
1036 /* Track account changes. We need to refresh the toolbar */
1038 modest_signal_mgr_connect (priv->sighandlers,
1039 G_OBJECT (modest_runtime_get_account_store ()),
1041 G_CALLBACK (on_account_inserted),
1044 modest_signal_mgr_connect (priv->sighandlers,
1045 G_OBJECT (modest_runtime_get_account_store ()),
1047 G_CALLBACK (on_account_removed),
1050 /* We need to refresh the send & receive menu to change the bold
1051 * account when the default account changes. */
1053 modest_signal_mgr_connect (priv->sighandlers,
1054 G_OBJECT (modest_runtime_get_account_mgr ()),
1055 "default_account_changed",
1056 G_CALLBACK (on_default_account_changed),
1061 modest_signal_mgr_connect (priv->sighandlers,
1062 G_OBJECT (modest_runtime_get_account_store ()),
1064 G_CALLBACK (on_account_changed),
1069 on_hildon_program_is_topmost_notify(GObject *self,
1070 GParamSpec *propert_param,
1073 HildonProgram *app = HILDON_PROGRAM (self);
1075 /* Note that use of hildon_program_set_can_hibernate()
1076 * is generally referred to as "setting the killable flag",
1077 * though hibernation does not seem equal to death.
1080 if (hildon_program_get_is_topmost (app)) {
1081 /* Prevent hibernation when the progam comes to the foreground,
1082 * because hibernation should only happen when the application
1083 * is in the background: */
1084 hildon_program_set_can_hibernate (app, FALSE);
1086 /* Remove new mail visual notifications */
1087 modest_platform_remove_new_mail_notifications (TRUE);
1089 /* Allow hibernation if the program has gone to the background: */
1091 /* However, prevent hibernation while the settings are being changed: */
1092 const gboolean hibernation_prevented =
1093 modest_window_mgr_get_hibernation_is_prevented (
1094 modest_runtime_get_window_mgr ());
1096 if (hibernation_prevented)
1097 hildon_program_set_can_hibernate (app, FALSE);
1099 /* Allow hibernation, after saving the state: */
1100 modest_osso_save_state();
1101 hildon_program_set_can_hibernate (app, TRUE);
1108 GtkWidget *folder_win;
1113 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1115 ShowHelper *helper = (ShowHelper *) user_data;
1116 GtkWidget *folder_win = helper->folder_win;
1117 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1119 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1120 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1122 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1124 /* Connect signals */
1125 connect_signals (MODEST_MAIN_WINDOW (self));
1127 /* Set account store */
1128 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1129 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1131 /* Load previous osso state, for instance if we are being restored from
1133 modest_osso_load_state ();
1135 /* Restore window & widget settings */
1136 priv->wait_for_settings = TRUE;
1137 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1138 priv->wait_for_settings = FALSE;
1140 /* Check if accounts exist and show the account wizard if not */
1141 gboolean accounts_exist =
1142 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1144 if (!accounts_exist) {
1145 /* This is necessary to have the main window shown behind the dialog
1146 It's an ugly hack... jschmid */
1147 gtk_widget_show_all(GTK_WIDGET(self));
1148 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1151 GtkAction *send_receive_all;
1152 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1153 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1154 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1155 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1156 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1157 modest_account_mgr_free_account_names (accounts);
1158 update_menus (MODEST_MAIN_WINDOW (self));
1161 /* Never call this function again (NOTE that it could happen
1162 as we hide the main window instead of closing it while
1163 there are operations ongoing) and free the helper */
1164 g_signal_handler_disconnect (self, helper->handler_id);
1165 g_slice_free (ShowHelper, helper);
1169 osso_display_event_cb (osso_display_state_t state,
1172 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1174 priv->display_state = state;
1176 /* Stop blinking if the screen becomes on */
1177 if (priv->display_state == OSSO_DISPLAY_ON)
1178 modest_platform_remove_new_mail_notifications (TRUE);
1182 modest_main_window_new (void)
1184 ModestMainWindow *self = NULL;
1185 ModestMainWindowPrivate *priv = NULL;
1186 ModestWindowPrivate *parent_priv = NULL;
1187 GtkWidget *folder_win = NULL;
1188 ModestDimmingRulesGroup *menu_rules_group = NULL;
1189 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1190 GtkActionGroup *action_group = NULL;
1191 GError *error = NULL;
1193 ModestConf *conf = NULL;
1194 GtkAction *action = NULL;
1195 GdkPixbuf *window_icon;
1198 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1199 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1200 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1202 parent_priv->ui_manager = gtk_ui_manager_new();
1203 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1205 action_group = gtk_action_group_new ("ModestMainWindowActions");
1206 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1208 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1209 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1211 /* Add common actions */
1212 gtk_action_group_add_actions (action_group,
1213 modest_action_entries,
1214 G_N_ELEMENTS (modest_action_entries),
1217 gtk_action_group_add_actions (action_group,
1218 modest_folder_view_action_entries,
1219 G_N_ELEMENTS (modest_folder_view_action_entries),
1222 gtk_action_group_add_actions (action_group,
1223 modest_header_view_action_entries,
1224 G_N_ELEMENTS (modest_header_view_action_entries),
1227 gtk_action_group_add_toggle_actions (action_group,
1228 modest_toggle_action_entries,
1229 G_N_ELEMENTS (modest_toggle_action_entries),
1232 gtk_action_group_add_toggle_actions (action_group,
1233 modest_main_window_toggle_action_entries,
1234 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1237 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1238 g_object_unref (action_group);
1240 /* Load the UI definition */
1241 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1242 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1243 if (error != NULL) {
1244 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1245 g_error_free (error);
1249 /* Add common dimming rules */
1250 modest_dimming_rules_group_add_rules (menu_rules_group,
1251 modest_main_window_menu_dimming_entries,
1252 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1253 MODEST_WINDOW (self));
1254 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1255 modest_main_window_toolbar_dimming_entries,
1256 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1257 MODEST_WINDOW (self));
1259 /* Insert dimming rules group for this window */
1260 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1261 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1262 g_object_unref (menu_rules_group);
1263 g_object_unref (toolbar_rules_group);
1265 /* Add accelerators */
1266 gtk_window_add_accel_group (GTK_WINDOW (self),
1267 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1269 /* Menubar. Update the state of some toggles */
1270 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1271 conf = modest_runtime_get_conf ();
1272 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1273 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1274 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1275 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1276 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1277 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1278 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1279 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1280 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1281 gtk_widget_show (parent_priv->menubar);
1283 /* Get device name */
1284 modest_maemo_utils_get_device_name ();
1288 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1289 g_object_ref (priv->header_view);
1290 if (!priv->header_view)
1291 g_printerr ("modest: cannot instantiate header view\n");
1292 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1293 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1294 MODEST_CONF_HEADER_VIEW_KEY);
1296 /* Other style properties of header view */
1297 g_object_set (G_OBJECT (priv->header_view),
1298 "rules-hint", FALSE,
1300 /* gtk_widget_show (priv->header_view); */
1303 priv->empty_view = create_empty_view ();
1304 gtk_widget_show (priv->empty_view);
1305 g_object_ref (priv->empty_view);
1307 /* Create scrolled windows */
1308 folder_win = gtk_scrolled_window_new (NULL, NULL);
1309 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1310 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1312 GTK_POLICY_AUTOMATIC);
1313 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1315 GTK_POLICY_AUTOMATIC);
1316 /* gtk_widget_show (priv->contents_widget); */
1319 priv->main_paned = gtk_hpaned_new ();
1320 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1321 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1322 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1324 /* putting it all together... */
1325 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1326 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1327 gtk_widget_show (priv->main_vbox);
1329 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1331 app = hildon_program_get_instance ();
1332 hildon_program_add_window (app, HILDON_WINDOW (self));
1334 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1335 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1337 /* Connect to "show" action. We delay the creation of some
1338 elements until that moment */
1339 helper = g_slice_new0 (ShowHelper);
1340 helper->folder_win = folder_win;
1341 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1342 G_CALLBACK (modest_main_window_on_show),
1345 /* Set window icon */
1346 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1348 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1349 g_object_unref (window_icon);
1352 /* Listen for changes in the screen, we don't want to show a
1353 led pattern when the display is on for example */
1354 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1355 osso_display_event_cb,
1358 /* Dont't restore settings here,
1359 * because it requires a gtk_widget_show(),
1360 * and we don't want to do that until later,
1361 * so that the UI is not visible for non-menu D-Bus activation.
1364 return MODEST_WINDOW(self);
1368 modest_main_window_set_style (ModestMainWindow *self,
1369 ModestMainWindowStyle style)
1371 ModestMainWindowPrivate *priv;
1372 ModestWindowPrivate *parent_priv;
1376 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1378 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1379 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1381 /* no change -> nothing to do */
1382 if (priv->style == style)
1385 /* Get toggle button and update the state if needed. This will
1386 happen only when the set_style is not invoked from the UI,
1387 for example when it's called from widget memory */
1388 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1389 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1390 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1391 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1392 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1393 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1394 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1397 priv->style = style;
1399 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1401 if (!priv->wait_for_settings)
1402 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1403 MODEST_CONF_MAIN_PANED_KEY);
1404 /* Remove main paned */
1405 g_object_ref (priv->main_paned);
1406 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1408 /* Reparent the contents widget to the main vbox */
1409 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1412 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1413 /* Remove header view */
1414 g_object_ref (priv->contents_widget);
1415 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1417 /* Reparent the main paned */
1418 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1419 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1421 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1425 g_return_if_reached ();
1428 /* Let header view grab the focus if it's being shown */
1429 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1430 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1432 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1435 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1438 ModestMainWindowStyle
1439 modest_main_window_get_style (ModestMainWindow *self)
1441 ModestMainWindowPrivate *priv;
1443 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1445 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1450 toolbar_resize (ModestMainWindow *self)
1452 ModestMainWindowPrivate *priv = NULL;
1453 ModestWindowPrivate *parent_priv = NULL;
1455 gint static_button_size;
1456 ModestWindowMgr *mgr;
1458 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1459 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1460 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1462 mgr = modest_runtime_get_window_mgr ();
1463 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1465 if (parent_priv->toolbar) {
1466 /* left size buttons */
1467 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1468 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1469 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1470 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1471 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1472 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1473 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1474 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1475 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1478 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1479 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1480 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1482 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1484 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1485 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1486 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1487 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1488 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1489 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1490 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1491 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1499 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1501 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1502 ModestWindowPrivate *parent_priv;
1503 ModestWindowMgr *mgr;
1504 gboolean is_fullscreen;
1505 GtkAction *fs_toggle_action;
1508 mgr = modest_runtime_get_window_mgr ();
1510 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1512 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1514 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1515 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1516 if (is_fullscreen != active) {
1517 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1520 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1528 modest_main_window_show_toolbar (ModestWindow *self,
1529 gboolean show_toolbar)
1531 ModestMainWindowPrivate *priv = NULL;
1532 ModestWindowPrivate *parent_priv = NULL;
1533 GtkWidget *reply_button = NULL, *menu = NULL;
1534 GtkWidget *placeholder = NULL;
1536 const gchar *action_name;
1539 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1540 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1541 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1543 /* Set optimized view status */
1544 priv->optimized_view = !show_toolbar;
1546 if (!parent_priv->toolbar) {
1547 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1549 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1551 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1552 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1553 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1554 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1555 toolbar_resize (MODEST_MAIN_WINDOW (self));
1557 /* Add ProgressBar (Transfer toolbar) */
1558 priv->progress_bar = modest_progress_bar_new ();
1559 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1560 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1561 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1562 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1563 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1565 /* Connect cancel 'clicked' signal to abort progress mode */
1566 g_signal_connect(priv->cancel_toolitem, "clicked",
1567 G_CALLBACK(cancel_progressbar),
1570 /* Add it to the observers list */
1571 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1574 hildon_window_add_toolbar (HILDON_WINDOW (self),
1575 GTK_TOOLBAR (parent_priv->toolbar));
1577 /* Set reply button tap and hold menu */
1578 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1579 "/ToolBar/ToolbarMessageReply");
1580 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1581 "/ToolbarReplyCSM");
1582 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1584 /* Set send & receive button tap and hold menu */
1585 update_menus (MODEST_MAIN_WINDOW (self));
1589 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1590 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1591 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1593 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1594 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1595 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1597 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1599 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1603 /* Update also the actions (to update the toggles in the
1604 menus), we have to do it manually because some other window
1605 of the same time could have changed it (remember that the
1606 toolbar fullscreen mode is shared by all the windows of the
1608 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1609 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1611 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1613 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1614 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1619 on_account_inserted (TnyAccountStore *accoust_store,
1620 TnyAccount *account,
1623 /* Transport accounts and local ones (MMC and the Local
1624 folders account do now cause menu changes */
1625 if (TNY_IS_STORE_ACCOUNT (account) &&
1626 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1628 update_menus (MODEST_MAIN_WINDOW (user_data));
1633 on_default_account_changed (ModestAccountMgr* mgr,
1636 update_menus (MODEST_MAIN_WINDOW (user_data));
1640 on_account_removed (TnyAccountStore *accoust_store,
1641 TnyAccount *account,
1644 /* Transport accounts and local ones (MMC and the Local
1645 folders account do now cause menu changes */
1646 if (TNY_IS_STORE_ACCOUNT (account) &&
1647 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1648 update_menus (MODEST_MAIN_WINDOW (user_data));
1652 on_account_changed (TnyAccountStore *account_store,
1653 TnyAccount *account,
1656 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1658 /* Transport accounts and local ones (MMC and the Local
1659 folders account do now cause menu changes */
1660 if (TNY_IS_STORE_ACCOUNT (account)) {
1661 /* We need to refresh the details widget because it could have changed */
1662 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1663 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1665 /* Update the menus as well, name could change */
1666 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1667 update_menus (MODEST_MAIN_WINDOW (user_data));
1672 * This function manages the key events used to navigate between
1673 * header and folder views (when the window is in split view)
1676 * -------------------------------------------------
1677 * HeaderView GDK_Left Move focus to folder view
1678 * FolderView GDK_Right Move focus to header view
1680 * There is no need to scroll to selected row, the widgets will be the
1681 * responsibles of doing that (probably managing the focus-in event
1684 on_inner_widgets_key_pressed (GtkWidget *widget,
1688 ModestMainWindowPrivate *priv;
1690 if (event->type == GDK_KEY_RELEASE)
1693 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1695 /* Do nothing if we're in SIMPLE style */
1696 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1699 if (MODEST_IS_HEADER_VIEW (widget)) {
1700 if (event->keyval == GDK_Left)
1701 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1702 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1703 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1704 if (selected_headers > 1) {
1705 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1708 GtkTreePath * cursor_path;
1709 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1710 if (cursor_path == NULL) {
1711 GtkTreeSelection *selection;
1713 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1714 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1717 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1718 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1723 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1724 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1730 set_alignment (GtkWidget *widget,
1733 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1734 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1738 create_empty_view (void)
1740 GtkLabel *label = NULL;
1741 GtkWidget *align = NULL;
1743 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1744 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1745 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1746 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1748 return GTK_WIDGET(align);
1752 * Free the returned string
1755 get_gray_color_markup (GtkWidget *styled_widget)
1757 gchar *gray_color_markup = NULL;
1758 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1759 /* Obtain the secondary text color. We need a realized widget, that's why
1760 we get styled_widget from outside */
1762 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1763 gray_color_markup = modest_text_utils_get_color_string (&color);
1764 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1766 if (!gray_color_markup)
1767 gray_color_markup = g_strdup ("#BBBBBB");
1769 return gray_color_markup;
1773 * Free the returned string
1776 create_device_name_visual_string (const gchar *device_name,
1777 const gchar *gray_color_markup)
1781 /* We have to use "" to fill the %s of the translation. We can
1782 not just use the device name because the device name is
1783 shown in a different color, so it could not be included
1784 into the <span> tag */
1785 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1786 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1797 GtkWidget *count_label;
1798 GtkWidget *msg_count_label;
1799 GtkWidget *size_label;
1800 gchar *color_markup;
1804 create_uint_label (const gchar *markup,
1808 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1812 create_gchar_label (const gchar *markup,
1816 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1820 update_folder_stats_status_cb (ModestFolderStats stats,
1823 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1826 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1827 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1830 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1831 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1834 if (widgets->size_label) {
1835 tmp = modest_text_utils_get_display_size (stats.local_size);
1836 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1837 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1844 update_folder_stats_cb (ModestFolderStats stats,
1847 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1850 update_folder_stats_status_cb (stats, user_data);
1852 /* frees. Note that the widgets could have been destroyed but
1853 we still keep a reference */
1854 g_free (widgets->color_markup);
1855 if (widgets->count_label)
1856 g_object_unref (widgets->count_label);
1857 if (widgets->msg_count_label)
1858 g_object_unref (widgets->msg_count_label);
1859 if (widgets->size_label)
1860 g_object_unref (widgets->size_label);
1861 g_slice_free (DetailsWidgets, widgets);
1865 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1867 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1872 gchar *gray_color_markup;
1873 DetailsWidgets *widgets;
1875 vbox = gtk_vbox_new (FALSE, 0);
1876 widgets = g_slice_new0 (DetailsWidgets);
1878 gray_color_markup = get_gray_color_markup (styled_widget);
1879 widgets->color_markup = g_strdup (gray_color_markup);
1881 /* Account description: */
1882 if (modest_tny_account_is_virtual_local_folders (account)
1883 || (modest_tny_account_is_memory_card_account (account))) {
1885 /* Get device name */
1886 gchar *device_name = NULL;
1887 if (modest_tny_account_is_virtual_local_folders (account))
1888 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1889 MODEST_CONF_DEVICE_NAME, NULL);
1891 device_name = g_strdup (tny_account_get_name (account));
1893 label = create_device_name_visual_string ((const gchar *) device_name,
1894 (const gchar *) gray_color_markup);
1895 label_w = gtk_label_new (NULL);
1896 gtk_label_set_markup (GTK_LABEL (label_w), label);
1897 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1898 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1899 g_free (device_name);
1902 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1903 gtk_box_pack_start (GTK_BOX (vbox),
1904 gtk_label_new (tny_account_get_name (account)),
1907 /* Other accounts, such as IMAP and POP: */
1912 /* Put proto in uppercase */
1913 proto = g_string_new (tny_account_get_proto (account));
1914 proto = g_string_ascii_up (proto);
1916 /* note: mcen_fi_localroot_description is something like "%s account"
1917 * however, we should display "%s account: %s"... therefore, ugly tmp */
1918 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1919 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1920 gray_color_markup, tmp, tny_account_get_name (account));
1923 label_w = gtk_label_new (NULL);
1924 gtk_label_set_markup (GTK_LABEL (label_w), label);
1925 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1926 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1927 g_string_free (proto, TRUE);
1933 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1934 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1935 label_w = gtk_label_new (NULL);
1936 gtk_label_set_markup (GTK_LABEL (label_w), label);
1937 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1938 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1941 widgets->msg_count_label = g_object_ref (label_w);
1944 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1945 label_w = gtk_label_new (NULL);
1946 gtk_label_set_markup (GTK_LABEL (label_w), label);
1947 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1948 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1951 widgets->count_label = g_object_ref (label_w);
1954 if (modest_tny_account_is_virtual_local_folders (account)
1955 || modest_tny_account_is_memory_card_account (account)) {
1957 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1959 label_w = gtk_label_new (NULL);
1960 gtk_label_set_markup (GTK_LABEL (label_w), label);
1961 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1962 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1965 widgets->size_label = g_object_ref (label_w);
1967 } else if (TNY_IS_ACCOUNT(folder_store)) {
1968 TnyAccount *account = TNY_ACCOUNT(folder_store);
1970 time_t last_updated;
1971 const gchar *last_updated_string;
1972 /* Get last updated from configuration */
1973 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1974 tny_account_get_id (account));
1976 if (last_updated > 0)
1977 last_updated_string = modest_text_utils_get_display_date(last_updated);
1979 last_updated_string = g_strdup (_("mcen_va_never"));
1981 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1982 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1983 label_w = gtk_label_new (NULL);
1984 gtk_label_set_markup (GTK_LABEL (label_w), label);
1985 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1986 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1990 g_free (gray_color_markup);
1992 /* Refresh folder stats asynchronously */
1993 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1994 update_folder_stats_cb,
1995 update_folder_stats_status_cb,
1999 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2005 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2007 ModestMainWindowPrivate *priv = NULL;
2009 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2011 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2013 return priv->send_receive_in_progress;
2017 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2019 GtkAction *action = NULL;
2020 GtkWidget *widget = NULL;
2021 ModestMainWindowPrivate *priv = NULL;
2023 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2024 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2026 priv->send_receive_in_progress = TRUE;
2028 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2029 gtk_action_set_sensitive (action, FALSE);
2030 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2031 /* gtk_action_set_sensitive (action, FALSE); */
2032 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2033 gtk_widget_set_sensitive (widget, FALSE);
2037 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2039 GtkAction *action = NULL;
2040 GtkWidget *widget = NULL;
2041 ModestMainWindowPrivate *priv = NULL;
2043 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2044 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2046 priv->send_receive_in_progress = FALSE;
2048 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2049 gtk_action_set_sensitive (action, TRUE);
2050 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2051 /* gtk_action_set_sensitive (action, TRUE); */
2052 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2053 gtk_widget_set_sensitive (widget, TRUE);
2058 on_msg_count_changed (ModestHeaderView *header_view,
2060 TnyFolderChange *change,
2061 ModestMainWindow *main_window)
2063 gboolean refilter = FALSE;
2064 gboolean folder_empty = FALSE;
2065 gboolean all_marked_as_deleted = FALSE;
2066 ModestMainWindowPrivate *priv;
2068 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2069 g_return_if_fail (TNY_IS_FOLDER(folder));
2070 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2072 if (change != NULL) {
2073 TnyFolderChangeChanged changed;
2075 changed = tny_folder_change_get_changed (change);
2076 /* If something changes */
2077 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2078 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2080 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2082 /* Play a sound (if configured) and make the LED blink */
2083 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2084 modest_platform_push_email_notification ();
2087 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2090 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2093 /* Check if all messages are marked to be deleted */
2094 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2095 folder_empty = folder_empty || all_marked_as_deleted;
2097 /* Set contents style of headers view */
2099 modest_main_window_set_contents_style (main_window,
2100 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2101 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2103 modest_main_window_set_contents_style (main_window,
2104 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2108 modest_header_view_refilter (header_view);
2113 modest_main_window_set_contents_style (ModestMainWindow *self,
2114 ModestMainWindowContentsStyle style)
2116 ModestMainWindowPrivate *priv;
2118 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2120 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2122 /* We allow to set the same content style than the previously
2123 set if there are details, because it could happen when we're
2124 selecting different accounts consecutively */
2125 if ((priv->contents_style == style) &&
2126 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2129 /* Remove previous child. Delete it if it was an account
2131 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2133 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2134 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2137 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2140 priv->contents_style = style;
2142 switch (priv->contents_style) {
2143 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2144 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2145 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2148 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2150 /* if we're started without main win, there may not be a folder
2151 * view. this fixes a GLib-Critical */
2152 if (priv->folder_view) {
2153 TnyFolderStore *selected_folderstore =
2154 modest_folder_view_get_selected (priv->folder_view);
2155 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2156 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2157 TNY_ACCOUNT (selected_folderstore));
2159 wrap_in_scrolled_window (priv->contents_widget,
2160 priv->details_widget);
2162 g_object_unref (selected_folderstore);
2163 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2168 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2169 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2170 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2174 g_return_if_reached ();
2178 gtk_widget_show_all (priv->contents_widget);
2181 ModestMainWindowContentsStyle
2182 modest_main_window_get_contents_style (ModestMainWindow *self)
2184 ModestMainWindowPrivate *priv;
2186 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2188 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2189 return priv->contents_style;
2194 on_configuration_key_changed (ModestConf* conf,
2196 ModestConfEvent event,
2197 ModestConfNotificationId id,
2198 ModestMainWindow *self)
2200 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2201 TnyAccount *account = NULL;
2203 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2206 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2209 if (priv->folder_view)
2210 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2212 if (account && TNY_IS_ACCOUNT (account) &&
2213 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2216 const gchar *device_name;
2217 gchar *new_text, *gray_color_markup;
2220 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2221 label = GTK_LABEL (children->data);
2223 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2224 MODEST_CONF_DEVICE_NAME, NULL);
2226 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2227 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2229 gtk_label_set_markup (label, new_text);
2230 gtk_widget_show (GTK_WIDGET (label));
2232 g_free (gray_color_markup);
2234 g_list_free (children);
2236 g_object_unref (account);
2240 set_toolbar_transfer_mode (ModestMainWindow *self)
2242 ModestMainWindowPrivate *priv = NULL;
2244 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2246 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2248 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2250 if (priv->progress_bar_timeout > 0) {
2251 g_source_remove (priv->progress_bar_timeout);
2252 priv->progress_bar_timeout = 0;
2259 set_toolbar_mode (ModestMainWindow *self,
2260 ModestToolBarModes mode)
2262 ModestWindowPrivate *parent_priv = NULL;
2263 ModestMainWindowPrivate *priv = NULL;
2264 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2266 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2268 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2269 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2271 /* In case this was called before the toolbar exists: */
2272 if (!(parent_priv->toolbar))
2275 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2277 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2278 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2279 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2281 /* Sets current toolbar mode */
2282 priv->current_toolbar_mode = mode;
2284 /* Checks the dimming rules */
2285 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2286 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2288 /* Show and hide toolbar items */
2290 case TOOLBAR_MODE_NORMAL:
2292 gtk_action_set_visible (sort_action, TRUE);
2294 gtk_action_set_visible (refresh_action, TRUE);
2295 if (priv->progress_toolitem) {
2296 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2297 gtk_widget_hide (priv->progress_toolitem);
2299 if (priv->progress_bar)
2300 gtk_widget_hide (priv->progress_bar);
2303 gtk_action_set_visible (cancel_action, FALSE);
2305 /* Hide toolbar if optimized view is enabled */
2306 if (priv->optimized_view)
2307 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2309 case TOOLBAR_MODE_TRANSFER:
2311 gtk_action_set_visible (sort_action, FALSE);
2313 gtk_action_set_visible (refresh_action, FALSE);
2315 gtk_action_set_visible (cancel_action, TRUE);
2316 if (priv->progress_bar)
2317 gtk_widget_show (priv->progress_bar);
2318 if (priv->progress_toolitem) {
2319 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2320 gtk_widget_show (priv->progress_toolitem);
2323 /* Show toolbar if it's hiden (optimized view ) */
2324 if (priv->optimized_view)
2325 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2328 g_return_if_reached ();
2333 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2335 ModestMainWindowPrivate *priv;
2337 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2340 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2344 cancel_progressbar (GtkToolButton *toolbutton,
2345 ModestMainWindow *self)
2348 ModestMainWindowPrivate *priv;
2350 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2352 /* Get operation observers and cancel all the operations */
2353 tmp = priv->progress_widgets;
2355 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2356 tmp=g_slist_next(tmp);
2361 observers_empty (ModestMainWindow *self)
2364 ModestMainWindowPrivate *priv;
2365 gboolean is_empty = TRUE;
2366 guint pending_ops = 0;
2368 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2369 tmp = priv->progress_widgets;
2371 /* Check all observers */
2372 while (tmp && is_empty) {
2373 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2374 is_empty = pending_ops == 0;
2376 tmp = g_slist_next(tmp);
2384 * Gets the toolbar mode needed for each mail operation. It stores in
2385 * @mode_changed if the toolbar mode has changed or not
2387 static ModestToolBarModes
2388 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2389 ModestMailOperation *mail_op,
2390 gboolean *mode_changed)
2392 ModestToolBarModes mode;
2393 ModestMainWindowPrivate *priv;
2395 *mode_changed = FALSE;
2396 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2398 /* Get toolbar mode from operation id*/
2399 switch (modest_mail_operation_get_type_operation (mail_op)) {
2400 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2401 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2402 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2403 mode = TOOLBAR_MODE_TRANSFER;
2404 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2405 *mode_changed = TRUE;
2408 mode = TOOLBAR_MODE_NORMAL;
2414 on_mail_operation_started (ModestMailOperation *mail_op,
2417 ModestMainWindow *self;
2418 ModestMailOperationTypeOperation op_type;
2419 ModestMainWindowPrivate *priv;
2420 ModestToolBarModes mode;
2422 gboolean mode_changed = FALSE;
2423 TnyAccount *account = NULL;
2425 self = MODEST_MAIN_WINDOW (user_data);
2426 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2428 /* Do not show progress for receiving operations if the
2429 account is the local account or the MMC one */
2430 op_type = modest_mail_operation_get_type_operation (mail_op);
2431 account = modest_mail_operation_get_account (mail_op);
2432 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2435 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2436 modest_tny_account_is_memory_card_account (account));
2438 g_object_unref (account);
2442 /* Show information banner. Remove old timeout */
2443 if (priv->retrieving_banner_timeout > 0) {
2444 g_source_remove (priv->retrieving_banner_timeout);
2445 priv->retrieving_banner_timeout = 0;
2447 /* Create a new timeout */
2448 priv->retrieving_banner_timeout =
2449 g_timeout_add (2000, show_retrieving_banner, self);
2452 /* Not every mail operation has account, noop does not */
2454 g_object_unref (account);
2456 /* Get toolbar mode from operation id*/
2457 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2459 /* Add operation observers and change toolbar if neccessary*/
2460 tmp = priv->progress_widgets;
2461 if (mode == TOOLBAR_MODE_TRANSFER) {
2463 GObject *source = modest_mail_operation_get_source(mail_op);
2464 if (G_OBJECT (self) == source) {
2465 set_toolbar_transfer_mode(self);
2467 g_object_unref (source);
2471 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2473 tmp = g_slist_next (tmp);
2477 /* Update the main menu as well, we need to explicitely do
2478 this in order to enable/disable accelerators */
2479 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2483 on_mail_operation_finished (ModestMailOperation *mail_op,
2486 ModestToolBarModes mode;
2487 ModestMailOperationTypeOperation op_type;
2489 ModestMainWindow *self;
2490 gboolean mode_changed;
2491 TnyAccount *account = NULL;
2492 ModestMainWindowPrivate *priv;
2494 self = MODEST_MAIN_WINDOW (user_data);
2495 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2497 /* The mail operation was not added to the progress objects if
2498 the account was the local account or the MMC one */
2499 op_type = modest_mail_operation_get_type_operation (mail_op);
2500 account = modest_mail_operation_get_account (mail_op);
2501 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2504 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2505 modest_tny_account_is_memory_card_account (account));
2507 g_object_unref (account);
2511 /* Remove old timeout */
2512 if (priv->retrieving_banner_timeout > 0) {
2513 g_source_remove (priv->retrieving_banner_timeout);
2514 priv->retrieving_banner_timeout = 0;
2517 /* Remove the banner if exists */
2518 if (priv->retrieving_banner) {
2519 gtk_widget_destroy (priv->retrieving_banner);
2520 priv->retrieving_banner = NULL;
2524 /* Not every mail operation has account, noop does not */
2526 g_object_unref (account);
2528 /* Get toolbar mode from operation id*/
2529 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2531 /* Change toolbar mode */
2532 tmp = priv->progress_widgets;
2533 if (mode == TOOLBAR_MODE_TRANSFER) {
2535 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2537 tmp = g_slist_next (tmp);
2540 /* If no more operations are being observed, NORMAL mode is enabled again */
2541 if (observers_empty (self)) {
2542 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2548 on_queue_changed (ModestMailOperationQueue *queue,
2549 ModestMailOperation *mail_op,
2550 ModestMailOperationQueueNotification type,
2551 ModestMainWindow *self)
2553 ModestMainWindowPrivate *priv;
2555 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2557 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2558 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2560 "operation-started",
2561 G_CALLBACK (on_mail_operation_started),
2563 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2565 "operation-finished",
2566 G_CALLBACK (on_mail_operation_finished),
2568 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2569 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2571 "operation-started");
2572 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2574 "operation-finished");
2579 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2581 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2583 ModestAccountMgr *mgr;
2584 ModestAccountSettings *settings;
2585 ModestServerAccountSettings *store_settings = NULL;
2587 /* Get account data */
2588 mgr = modest_runtime_get_account_mgr ();
2589 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2591 store_settings = modest_account_settings_get_store_settings (settings);
2593 /* Set the new visible & active account */
2594 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2595 const gchar *account_name;
2597 account_name = modest_account_settings_get_account_name (settings);
2599 modest_folder_view_set_account_id_of_visible_server_account
2601 modest_server_account_settings_get_account_name (store_settings));
2602 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2603 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2605 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2606 if (action != NULL) {
2607 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2608 modest_utils_toggle_action_set_active_block_notify (
2609 GTK_TOGGLE_ACTION (action),
2617 g_object_unref (store_settings);
2618 g_object_unref (settings);
2622 /* Make sure that at least one account is "viewed": */
2624 set_at_least_one_account_visible(ModestMainWindow *self)
2626 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2627 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2629 if (!(priv->folder_view)) {
2630 /* It is too early to do this. */
2634 const gchar *active_server_account_name =
2635 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2637 if (!active_server_account_name ||
2638 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2640 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2641 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2642 if (default_modest_name) {
2643 set_account_visible (self, default_modest_name);
2644 } else if (first_modest_name) {
2645 set_account_visible (self, first_modest_name);
2647 g_free (first_modest_name);
2648 g_free (default_modest_name);
2653 on_show_account_action_toggled (GtkToggleAction *action,
2656 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2658 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2659 if (gtk_toggle_action_get_active (action))
2660 set_account_visible (self, acc_name);
2664 refresh_account (const gchar *account_name)
2668 /* win must already exists here, obviously */
2669 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2672 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2676 /* If account_name == NULL, we must update all (option All) */
2678 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2680 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2685 on_refresh_account_action_activated (GtkAction *action,
2688 refresh_account ((const gchar*) user_data);
2692 on_send_receive_csm_activated (GtkMenuItem *item,
2695 refresh_account ((const gchar*) user_data);
2699 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2701 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2703 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2709 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2711 ModestMainWindow *main_window = NULL;
2713 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2714 main_window = MODEST_MAIN_WINDOW (userdata);
2716 /* Update toolbar dimming state */
2717 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2718 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2724 on_header_view_focus_in (GtkWidget *widget,
2725 GdkEventFocus *event,
2728 ModestMainWindow *main_window = NULL;
2730 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2732 main_window = MODEST_MAIN_WINDOW (userdata);
2734 /* Update toolbar dimming state */
2735 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2736 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2742 on_folder_selection_changed (ModestFolderView *folder_view,
2743 TnyFolderStore *folder_store,
2745 ModestMainWindow *main_window)
2747 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2748 GtkAction *action = NULL;
2749 gboolean show_reply = TRUE;
2750 gboolean show_forward = TRUE;
2751 gboolean show_cancel_send = FALSE;
2752 gboolean show_clipboard = TRUE;
2753 gboolean show_delete = TRUE;
2756 if (TNY_IS_ACCOUNT (folder_store)) {
2757 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2758 } else if (TNY_IS_FOLDER (folder_store)) {
2759 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2760 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2761 TNY_FOLDER (folder_store));
2762 switch (folder_type) {
2763 case TNY_FOLDER_TYPE_DRAFTS:
2764 show_clipboard = show_delete = TRUE;
2765 show_reply = show_forward = show_cancel_send = FALSE;
2767 case TNY_FOLDER_TYPE_SENT:
2768 show_forward = show_clipboard = show_delete = TRUE;
2769 show_reply = show_cancel_send = FALSE;
2771 case TNY_FOLDER_TYPE_OUTBOX:
2772 show_clipboard = show_delete = show_cancel_send = TRUE;
2773 show_reply = show_forward = FALSE;
2775 case TNY_FOLDER_TYPE_INVALID:
2776 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2779 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2780 show_cancel_send = FALSE;
2783 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2784 show_cancel_send = FALSE;
2789 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2790 gtk_action_set_visible (action, show_reply);
2791 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2792 gtk_action_set_visible (action, show_reply);
2793 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2794 gtk_action_set_visible (action, show_forward);
2795 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2796 gtk_action_set_visible (action, show_cancel_send);
2797 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2798 gtk_action_set_visible (action, show_delete);
2800 /* We finally call to the ui actions handler, after updating properly
2801 * the header view CSM */
2802 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2806 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2807 GtkTreeModel *model,
2808 GtkTreeRowReference *row_reference,
2809 ModestMainWindow *self)
2811 ModestMainWindowPrivate *priv = NULL;
2812 GtkTreeModel *header_model = NULL;
2813 GtkTreePath *path = NULL;
2815 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2816 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2817 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2819 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2820 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2822 /* Do nothing if we changed the folder in the main view */
2823 if (header_model != model)
2826 /* Select the message in the header view */
2827 path = gtk_tree_row_reference_get_path (row_reference);
2828 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2830 gtk_tree_path_free (path);
2836 show_updating_banner (gpointer user_data)
2838 ModestMainWindowPrivate *priv = NULL;
2840 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2842 if (priv->updating_banner == NULL) {
2844 /* We're outside the main lock */
2845 gdk_threads_enter ();
2846 priv->updating_banner =
2847 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2848 _CS ("ckdg_pb_updating"));
2849 gdk_threads_leave ();
2852 /* Remove timeout */
2853 priv->updating_banner_timeout = 0;
2858 * We use this function to show/hide a progress banner showing
2859 * "Updating" while the header view is being filled. We're not showing
2860 * it unless the update takes more than 2 seconds
2862 * If starting = TRUE then the refresh is starting, otherwise it means
2863 * that is has just finished
2866 on_updating_msg_list (ModestHeaderView *header_view,
2870 ModestMainWindowPrivate *priv = NULL;
2872 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2874 /* Remove old timeout */
2875 if (priv->updating_banner_timeout > 0) {
2876 g_source_remove (priv->updating_banner_timeout);
2877 priv->updating_banner_timeout = 0;
2880 /* Create a new timeout */
2882 priv->updating_banner_timeout =
2883 g_timeout_add (2000, show_updating_banner, user_data);
2885 /* Remove the banner if exists */
2886 if (priv->updating_banner) {
2887 gtk_widget_destroy (priv->updating_banner);
2888 priv->updating_banner = NULL;
2894 modest_main_window_screen_is_on (ModestMainWindow *self)
2896 ModestMainWindowPrivate *priv = NULL;
2898 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2900 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2902 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2906 remove_banners (ModestMainWindow *window)
2908 ModestMainWindowPrivate *priv;
2910 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2912 if (priv->retrieving_banner_timeout > 0) {
2913 g_source_remove (priv->retrieving_banner_timeout);
2914 priv->retrieving_banner_timeout = 0;
2917 if (priv->retrieving_banner != NULL) {
2918 gtk_widget_destroy (priv->retrieving_banner);
2919 priv->retrieving_banner = NULL;
2922 if (priv->updating_banner_timeout > 0) {
2923 g_source_remove (priv->updating_banner_timeout);
2924 priv->updating_banner_timeout = 0;
2927 if (priv->updating_banner != NULL) {
2928 gtk_widget_destroy (priv->updating_banner);
2929 priv->updating_banner = NULL;
2935 on_window_hide (GObject *gobject,
2939 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2941 if (!GTK_WIDGET_VISIBLE (gobject)) {
2942 TnyFolderStore *folder_store;
2943 ModestMainWindowPrivate *priv;
2945 /* Remove the currently shown banners */
2946 remove_banners (MODEST_MAIN_WINDOW (gobject));
2948 /* Force the folder view to sync the currently selected folder
2949 to save the read/unread status and to expunge messages */
2950 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2951 folder_store = modest_folder_view_get_selected (priv->folder_view);
2952 if (TNY_IS_FOLDER (folder_store)) {
2953 ModestMailOperation *mail_op;
2955 mail_op = modest_mail_operation_new (NULL);
2956 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2958 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2959 g_object_unref (mail_op);
2960 g_object_unref (folder_store);
2966 on_window_destroy (GtkObject *widget,
2969 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2971 remove_banners (MODEST_MAIN_WINDOW (widget));
2975 show_retrieving_banner (gpointer user_data)
2977 ModestMainWindowPrivate *priv = NULL;
2979 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2981 if (priv->retrieving_banner == NULL) {
2983 /* We're outside the main lock */
2984 gdk_threads_enter ();
2985 priv->retrieving_banner =
2986 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2987 _("mcen_ib_getting_items"));
2988 gdk_threads_leave ();
2991 /* Remove timeout */
2992 priv->retrieving_banner_timeout = 0;