1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-error.h>
37 #include "modest-hildon-includes.h"
38 #include "modest-defs.h"
40 #include "widgets/modest-header-view-priv.h"
41 #include "widgets/modest-main-window.h"
42 #include "widgets/modest-msg-edit-window.h"
43 #include "widgets/modest-account-view-window.h"
44 #include "modest-runtime.h"
45 #include "modest-account-mgr-helpers.h"
46 #include "modest-platform.h"
47 #include "modest-widget-memory.h"
48 #include "modest-window-priv.h"
49 #include "modest-main-window-ui.h"
50 #include "modest-main-window-ui-dimming.h"
51 #include "modest-account-mgr.h"
52 #include "modest-tny-account.h"
53 #include "modest-tny-folder.h"
54 #include "modest-conf.h"
55 #include <modest-utils.h>
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
66 #include "modest-signal-mgr.h"
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
75 /* 'private'/'protected' functions */
76 static void modest_main_window_class_init (ModestMainWindowClass *klass);
77 static void modest_main_window_init (ModestMainWindow *obj);
78 static void modest_main_window_finalize (GObject *obj);
80 static void connect_signals (ModestMainWindow *self);
82 static void modest_main_window_disconnect_signals (ModestWindow *self);
84 static void restore_settings (ModestMainWindow *self,
85 gboolean do_folder_view_too);
87 static void save_state (ModestWindow *self);
89 static void update_menus (ModestMainWindow* self);
91 static void modest_main_window_show_toolbar (ModestWindow *window,
92 gboolean show_toolbar);
94 static void cancel_progressbar (GtkToolButton *toolbutton,
95 ModestMainWindow *self);
97 static void on_queue_changed (ModestMailOperationQueue *queue,
98 ModestMailOperation *mail_op,
99 ModestMailOperationQueueNotification type,
100 ModestMainWindow *self);
102 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
104 static void on_account_inserted (TnyAccountStore *accoust_store,
108 static void on_account_removed (TnyAccountStore *accoust_store,
112 static void on_account_changed (TnyAccountStore *account_store,
116 static void on_default_account_changed (ModestAccountMgr* mgr,
119 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
123 static void on_configuration_key_changed (ModestConf* conf,
125 ModestConfEvent event,
126 ModestConfNotificationId id,
127 ModestMainWindow *self);
129 static void set_toolbar_mode (ModestMainWindow *self,
130 ModestToolBarModes mode);
132 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
134 static void on_show_account_action_toggled (GtkToggleAction *action,
137 static void on_refresh_account_action_activated (GtkAction *action,
140 static void on_send_receive_csm_activated (GtkMenuItem *item,
143 static void on_msg_count_changed (ModestHeaderView *header_view,
145 TnyFolderChange *change,
146 ModestMainWindow *main_window);
148 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
151 static GtkWidget * create_empty_view (void);
153 static gboolean on_folder_view_focus_in (GtkWidget *widget,
154 GdkEventFocus *event,
157 static gboolean on_header_view_focus_in (GtkWidget *widget,
158 GdkEventFocus *event,
161 static void on_folder_selection_changed (ModestFolderView *folder_view,
162 TnyFolderStore *folder_store,
164 ModestMainWindow *main_window);
166 static void set_at_least_one_account_visible(ModestMainWindow *self);
168 static void on_updating_msg_list (ModestHeaderView *header_view,
172 static gboolean restore_paned_timeout_handler (gpointer *data);
174 static gboolean show_opening_banner (gpointer user_data);
176 static void on_window_destroy (GtkObject *widget,
179 static void on_window_hide (GObject *gobject,
183 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
184 struct _ModestMainWindowPrivate {
185 GtkWidget *msg_paned;
186 GtkWidget *main_paned;
187 GtkWidget *main_vbox;
188 GtkWidget *contents_widget;
189 GtkWidget *empty_view;
191 /* Progress observers */
192 GtkWidget *progress_bar;
193 GSList *progress_widgets;
196 GtkWidget *progress_toolitem;
197 GtkWidget *cancel_toolitem;
198 GtkWidget *sort_toolitem;
199 GtkWidget *refresh_toolitem;
200 ModestToolBarModes current_toolbar_mode;
202 /* Merge ids used to add/remove accounts to the Accounts Menu*/
203 GByteArray *merge_ids;
204 GtkActionGroup *view_additions_group;
206 /* On-demand widgets */
207 GtkWidget *accounts_popup;
208 GtkWidget *details_widget;
210 /* Optimized view enabled */
211 gboolean optimized_view;
213 /* Optimized view enabled */
214 gboolean send_receive_in_progress;
216 ModestHeaderView *header_view;
217 ModestFolderView *folder_view;
219 ModestMainWindowStyle style;
220 ModestMainWindowContentsStyle contents_style;
221 gboolean wait_for_settings;
223 guint progress_bar_timeout;
224 guint restore_paned_timeout;
226 /* Signal handler UIDs */
227 GList *queue_err_signals;
230 /* "Updating" banner for header view */
231 GtkWidget *updating_banner;
232 guint updating_banner_timeout;
234 /* "Opening" banner for header view */
235 GtkWidget *opening_banner;
236 guint opening_banner_timeout;
239 osso_display_state_t display_state;
241 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
242 MODEST_TYPE_MAIN_WINDOW, \
243 ModestMainWindowPrivate))
245 typedef struct _GetMsgAsyncHelper {
246 ModestMainWindowPrivate *main_window_private;
248 ModestTnyMsgReplyType reply_type;
249 ModestTnyMsgForwardType forward_type;
256 static GtkWindowClass *parent_class = NULL;
259 /* Private actions */
260 /* This is the context sensitive menu: */
261 static const GtkActionEntry modest_folder_view_action_entries [] = {
263 /* Folder View CSM actions */
264 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
265 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
266 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
267 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
270 static const GtkActionEntry modest_header_view_action_entries [] = {
272 /* Header View CSM actions */
273 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
274 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
275 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
276 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
277 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
278 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
279 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
280 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
281 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
284 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
285 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
288 /************************************************************************/
291 modest_main_window_get_type (void)
293 static GType my_type = 0;
295 static const GTypeInfo my_info = {
296 sizeof(ModestMainWindowClass),
297 NULL, /* base init */
298 NULL, /* base finalize */
299 (GClassInitFunc) modest_main_window_class_init,
300 NULL, /* class finalize */
301 NULL, /* class data */
302 sizeof(ModestMainWindow),
304 (GInstanceInitFunc) modest_main_window_init,
307 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
315 modest_main_window_class_init (ModestMainWindowClass *klass)
317 GObjectClass *gobject_class;
318 gobject_class = (GObjectClass*) klass;
319 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
321 parent_class = g_type_class_peek_parent (klass);
322 gobject_class->finalize = modest_main_window_finalize;
324 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
326 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
327 modest_window_class->save_state_func = save_state;
328 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
329 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
330 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
334 modest_main_window_init (ModestMainWindow *obj)
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
340 priv->queue_err_signals = NULL;
341 priv->msg_paned = NULL;
342 priv->main_paned = NULL;
343 priv->main_vbox = NULL;
344 priv->header_view = NULL;
345 priv->folder_view = NULL;
346 priv->contents_widget = NULL;
347 priv->accounts_popup = NULL;
348 priv->details_widget = NULL;
349 priv->empty_view = NULL;
350 priv->progress_widgets = NULL;
351 priv->progress_bar = NULL;
352 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
353 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
354 priv->wait_for_settings = TRUE;
355 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
356 priv->merge_ids = NULL;
357 priv->optimized_view = FALSE;
358 priv->send_receive_in_progress = FALSE;
359 priv->progress_bar_timeout = 0;
360 priv->restore_paned_timeout = 0;
361 priv->sighandlers = NULL;
362 priv->updating_banner = NULL;
363 priv->updating_banner_timeout = 0;
364 priv->opening_banner = NULL;
365 priv->opening_banner_timeout = 0;
366 priv->display_state = OSSO_DISPLAY_ON;
368 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
370 "applications_email_mainview");
374 modest_main_window_finalize (GObject *obj)
376 ModestMainWindowPrivate *priv;
378 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
380 /* Sanity check: shouldn't be needed, the window mgr should
381 call this function before */
382 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
383 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
385 if (priv->empty_view) {
386 g_object_unref (priv->empty_view);
387 priv->empty_view = NULL;
390 if (priv->header_view) {
391 g_object_unref (priv->header_view);
392 priv->header_view = NULL;
395 g_slist_free (priv->progress_widgets);
397 g_byte_array_free (priv->merge_ids, TRUE);
399 if (priv->progress_bar_timeout > 0) {
400 g_source_remove (priv->progress_bar_timeout);
401 priv->progress_bar_timeout = 0;
404 if (priv->updating_banner_timeout > 0) {
405 g_source_remove (priv->updating_banner_timeout);
406 priv->updating_banner_timeout = 0;
409 if (priv->updating_banner) {
410 gtk_widget_destroy (priv->updating_banner);
411 priv->updating_banner = NULL;
414 if (priv->opening_banner_timeout > 0) {
415 g_source_remove (priv->opening_banner_timeout);
416 priv->opening_banner_timeout = 0;
419 if (priv->opening_banner) {
420 gtk_widget_destroy (priv->opening_banner);
421 priv->opening_banner = NULL;
424 if (priv->restore_paned_timeout > 0) {
425 g_source_remove (priv->restore_paned_timeout);
426 priv->restore_paned_timeout = 0;
429 G_OBJECT_CLASS(parent_class)->finalize (obj);
433 modest_main_window_get_child_widget (ModestMainWindow *self,
434 ModestMainWindowWidgetType widget_type)
436 ModestMainWindowPrivate *priv;
439 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
440 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
443 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
445 switch (widget_type) {
446 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
447 widget = (GtkWidget*)priv->header_view; break;
448 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
449 widget = (GtkWidget*)priv->folder_view; break;
454 /* Note that the window could have been destroyed, and so
455 their children, but still have some references */
456 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
460 restore_paned_timeout_handler (gpointer *data)
462 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
463 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
466 /* Timeouts are outside the main lock */
467 gdk_threads_enter ();
468 if (GTK_WIDGET_VISIBLE (main_window)) {
469 conf = modest_runtime_get_conf ();
470 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
471 MODEST_CONF_MAIN_PANED_KEY);
473 gdk_threads_leave ();
480 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
483 ModestMainWindowPrivate *priv;
485 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
487 conf = modest_runtime_get_conf ();
489 modest_widget_memory_restore (conf, G_OBJECT(self),
490 MODEST_CONF_MAIN_WINDOW_KEY);
492 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
493 MODEST_CONF_HEADER_VIEW_KEY);
495 if (do_folder_view_too)
496 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
497 MODEST_CONF_FOLDER_VIEW_KEY);
499 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
500 /* MODEST_CONF_MAIN_PANED_KEY); */
502 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
504 /* We need to force a redraw here in order to get the right
505 position of the horizontal paned separator */
506 gtk_widget_show (GTK_WIDGET (self));
511 save_state (ModestWindow *window)
514 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
515 ModestMainWindowPrivate *priv;
517 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
518 conf = modest_runtime_get_conf ();
520 modest_widget_memory_save (conf,G_OBJECT(self),
521 MODEST_CONF_MAIN_WINDOW_KEY);
522 /* Only save main paned position if we're in split mode */
523 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
524 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
525 MODEST_CONF_MAIN_PANED_KEY);
526 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
527 MODEST_CONF_FOLDER_VIEW_KEY);
531 compare_display_names (ModestAccountSettings *a,
532 ModestAccountSettings *b)
534 return g_utf8_collate (modest_account_settings_get_display_name (a),
535 modest_account_settings_get_display_name (b));
539 /* We use this function to prevent the send&receive CSM to be shown
540 when there are less than two account */
542 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
548 update_menus (ModestMainWindow* self)
550 GSList *account_names, *iter, *accounts;
551 ModestMainWindowPrivate *priv;
552 ModestWindowPrivate *parent_priv;
553 ModestAccountMgr *mgr;
554 gint i, num_accounts;
556 gchar *default_account;
557 const gchar *active_account_name;
558 GtkWidget *send_receive_button, *item;
559 GtkAction *send_receive_all = NULL;
562 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
563 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
565 /* Get enabled account IDs */
566 mgr = modest_runtime_get_account_mgr ();
567 account_names = modest_account_mgr_account_names (mgr, TRUE);
568 iter = account_names;
572 ModestAccountSettings *settings =
573 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
574 accounts = g_slist_prepend (accounts, settings);
578 modest_account_mgr_free_account_names (account_names);
579 account_names = NULL;
581 /* Order the list of accounts by its display name */
582 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
583 num_accounts = g_slist_length (accounts);
585 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
586 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
587 gtk_action_set_visible (send_receive_all, num_accounts > 0);
589 /* Delete old send&receive popup items. We can not just do a
590 menu_detach because it does not work well with
592 if (priv->accounts_popup)
593 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
594 (GtkCallback) gtk_widget_destroy, NULL);
596 /* Delete old entries in the View menu. Do not free groups, it
598 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
600 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
601 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
602 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
603 GTK_ACTION_GROUP (groups->data));
606 if (priv->merge_ids) {
607 for (i = 0; i < priv->merge_ids->len; i++)
608 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
609 g_byte_array_free (priv->merge_ids, TRUE);
611 /* We need to call this in order to ensure
612 that the new actions are added in the right
613 order (alphabetical) */
614 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
616 groups = g_list_next (groups);
618 priv->merge_ids = g_byte_array_sized_new (num_accounts);
620 /* Get send receive button */
621 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
622 "/ToolBar/ToolbarSendReceive");
624 /* Create the menu */
625 if (num_accounts > 1) {
626 if (!priv->accounts_popup)
627 priv->accounts_popup = gtk_menu_new ();
628 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
629 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
630 g_signal_connect (G_OBJECT (item),
632 G_CALLBACK (on_send_receive_csm_activated),
634 item = gtk_separator_menu_item_new ();
635 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
638 /* Create a new action group */
639 default_account = modest_account_mgr_get_default_account (mgr);
640 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
642 if (!active_account_name)
643 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
645 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
647 for (i = 0; i < num_accounts; i++) {
648 gchar *display_name = NULL;
649 const gchar *account_name;
650 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
653 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
656 account_name = modest_account_settings_get_account_name (settings);
658 if (default_account && account_name &&
659 !(strcmp (default_account, account_name) == 0)) {
660 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
661 modest_account_settings_get_display_name (settings));
663 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
664 modest_account_settings_get_display_name (settings));
669 /* Create action and add it to the action group. The
670 action name must be the account name, this way we
671 could know in the handlers the account to show */
672 if (settings && account_name) {
673 gchar* item_name, *refresh_action_name;
675 GtkAction *view_account_action, *refresh_account_action;
676 gchar *escaped_display_name;
678 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
680 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
681 escaped_display_name, NULL, NULL, 0));
682 g_free (escaped_display_name);
683 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
684 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
685 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
687 if (active_account_name) {
688 if (active_account_name && account_name &&
689 (strcmp (active_account_name, account_name) == 0)) {
690 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
694 /* Add ui from account data. We allow 2^9-1 account
695 changes in a single execution because we're
696 downcasting the guint to a guint8 in order to use a
697 GByteArray. It should be enough :-) */
698 item_name = g_strconcat (account_name, "Menu", NULL);
699 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
700 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
701 gtk_ui_manager_add_ui (parent_priv->ui_manager,
703 "/MenuBar/AccountsMenu/AccountsMenuAdditions",
706 GTK_UI_MANAGER_MENUITEM,
709 /* Connect the action signal "activate" */
710 g_signal_connect_after (G_OBJECT (view_account_action),
712 G_CALLBACK (on_show_account_action_toggled),
715 /* Create the items for the Tools->Send&Receive submenu */
716 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
717 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
718 display_name, NULL, NULL);
719 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
721 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
722 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
723 gtk_ui_manager_add_ui (parent_priv->ui_manager,
725 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
728 GTK_UI_MANAGER_MENUITEM,
730 g_free (refresh_action_name);
732 g_signal_connect_data (G_OBJECT (refresh_account_action),
734 G_CALLBACK (on_refresh_account_action_activated),
735 g_strdup (account_name),
736 (GClosureNotify) g_free,
739 /* Create item and add it to the send&receive
740 CSM. If there is only one account then
742 if (num_accounts > 1) {
743 GtkWidget *label = gtk_label_new(NULL);
744 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
745 if (default_account && (strcmp(account_name, default_account) == 0)) {
746 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
747 gtk_label_set_markup (GTK_LABEL (label), escaped);
750 gtk_label_set_text (GTK_LABEL (label), display_name);
753 item = gtk_menu_item_new ();
754 gtk_container_add (GTK_CONTAINER (item), label);
756 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
758 g_signal_connect_data (G_OBJECT (item),
760 G_CALLBACK (on_send_receive_csm_activated),
761 g_strdup (account_name),
762 (GClosureNotify) g_free,
769 g_free (display_name);
772 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
774 /* We cannot do this in the loop above because this relies on the action
775 * group being inserted. This makes the default account appear in bold.
776 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
777 for (i = 0; i < num_accounts; i++) {
778 gchar *item_name, *path;
780 ModestAccountSettings *settings;
781 const gchar *account_name;
784 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
785 account_name = modest_account_settings_get_account_name (settings);
786 is_default = (account_name && default_account && !strcmp (account_name, default_account));
788 /* Get the item of the view menu */
789 item_name = g_strconcat (account_name, "Menu", NULL);
790 path = g_strconcat ("/MenuBar/AccountsMenu/AccountsMenuAdditions/", item_name, NULL);
791 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
795 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
796 if (GTK_IS_LABEL (child)) {
797 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
799 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
800 gtk_label_set_markup (GTK_LABEL (child), bold_name);
806 /* Get the item of the tools menu */
807 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
808 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
812 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
813 if (GTK_IS_LABEL (child)) {
814 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
816 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
817 gtk_label_set_markup (GTK_LABEL (child), bold_name);
820 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
825 g_object_unref (settings);
828 if (num_accounts > 1) {
829 /* Disconnect the tap-and-hold-query if it's connected */
830 if (modest_signal_mgr_is_connected (priv->sighandlers,
831 G_OBJECT (send_receive_button),
832 "tap-and-hold-query"))
833 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
834 G_OBJECT (send_receive_button),
835 "tap-and-hold-query");
837 /* Mandatory in order to view the menu contents */
838 gtk_widget_show_all (priv->accounts_popup);
840 /* Setup tap_and_hold just if was not done before*/
841 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
842 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
844 /* Connect the tap-and-hold-query in order not to show the CSM */
845 if (!modest_signal_mgr_is_connected (priv->sighandlers,
846 G_OBJECT (send_receive_button),
847 "tap-and-hold-query"))
848 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
849 G_OBJECT (send_receive_button),
850 "tap-and-hold-query",
851 G_CALLBACK (tap_and_hold_query_cb),
856 g_slist_free (accounts);
857 g_free (default_account);
860 /* Make sure that at least one account is viewed if there are any
861 * accounts, for instance when adding the first account: */
862 set_at_least_one_account_visible (self);
866 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
868 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
869 gtk_scrolled_window_add_with_viewport
870 (GTK_SCROLLED_WINDOW(win), widget);
872 gtk_container_add (GTK_CONTAINER(win),
883 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
885 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
887 GList *oerrsignals = priv->queue_err_signals;
888 while (oerrsignals) {
889 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
890 g_signal_handler_disconnect (esignal->queue, esignal->signal);
891 g_slice_free (QueueErrorSignal, esignal);
892 oerrsignals = g_list_next (oerrsignals);
894 g_list_free (priv->queue_err_signals);
895 priv->queue_err_signals = NULL;
900 modest_main_window_disconnect_signals (ModestWindow *self)
902 ModestMainWindowPrivate *priv;
903 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
905 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
906 priv->sighandlers = NULL;
910 connect_signals (ModestMainWindow *self)
912 ModestWindowPrivate *parent_priv;
913 ModestMainWindowPrivate *priv;
915 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
916 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
921 modest_signal_mgr_connect (priv->sighandlers,
922 G_OBJECT(priv->folder_view), "key-press-event",
923 G_CALLBACK(on_inner_widgets_key_pressed), self);
925 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
926 "folder_selection_changed",
927 G_CALLBACK (on_folder_selection_changed),
930 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
931 "folder-display-name-changed",
932 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
935 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
937 G_CALLBACK (on_folder_view_focus_in),
942 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
943 G_CALLBACK(modest_ui_actions_on_header_selected), self);
945 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
946 G_CALLBACK(modest_ui_actions_on_header_activated), self);
948 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
949 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
951 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
952 G_CALLBACK(on_inner_widgets_key_pressed), self);
954 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
955 G_CALLBACK(on_msg_count_changed), self);
957 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
958 G_CALLBACK (on_header_view_focus_in), self);
960 modest_signal_mgr_connect (priv->sighandlers,
961 G_OBJECT (priv->header_view),
963 G_CALLBACK (on_updating_msg_list),
967 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
968 * in destroy stage */
969 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
971 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
973 /* Mail Operation Queue */
975 modest_signal_mgr_connect (priv->sighandlers,
976 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
978 G_CALLBACK (on_queue_changed), self);
980 /* Track changes in the device name */
982 modest_signal_mgr_connect (priv->sighandlers,
983 G_OBJECT(modest_runtime_get_conf ()),
985 G_CALLBACK (on_configuration_key_changed),
988 /* Track account changes. We need to refresh the toolbar */
990 modest_signal_mgr_connect (priv->sighandlers,
991 G_OBJECT (modest_runtime_get_account_store ()),
993 G_CALLBACK (on_account_inserted),
996 modest_signal_mgr_connect (priv->sighandlers,
997 G_OBJECT (modest_runtime_get_account_store ()),
999 G_CALLBACK (on_account_removed),
1002 /* We need to refresh the send & receive menu to change the bold
1003 * account when the default account changes. */
1005 modest_signal_mgr_connect (priv->sighandlers,
1006 G_OBJECT (modest_runtime_get_account_mgr ()),
1007 "default_account_changed",
1008 G_CALLBACK (on_default_account_changed),
1013 modest_signal_mgr_connect (priv->sighandlers,
1014 G_OBJECT (modest_runtime_get_account_store ()),
1016 G_CALLBACK (on_account_changed),
1021 on_hildon_program_is_topmost_notify(GObject *self,
1022 GParamSpec *propert_param,
1025 HildonProgram *app = HILDON_PROGRAM (self);
1027 /* Note that use of hildon_program_set_can_hibernate()
1028 * is generally referred to as "setting the killable flag",
1029 * though hibernation does not seem equal to death.
1032 if (hildon_program_get_is_topmost (app)) {
1033 /* Prevent hibernation when the progam comes to the foreground,
1034 * because hibernation should only happen when the application
1035 * is in the background: */
1036 hildon_program_set_can_hibernate (app, FALSE);
1038 /* Remove new mail visual notifications */
1039 modest_platform_remove_new_mail_notifications (TRUE);
1041 /* Allow hibernation if the program has gone to the background: */
1043 /* However, prevent hibernation while the settings are being changed: */
1044 const gboolean hibernation_prevented =
1045 modest_window_mgr_get_hibernation_is_prevented (
1046 modest_runtime_get_window_mgr ());
1048 if (hibernation_prevented)
1049 hildon_program_set_can_hibernate (app, FALSE);
1051 /* Allow hibernation, after saving the state: */
1052 modest_osso_save_state();
1053 hildon_program_set_can_hibernate (app, TRUE);
1060 GtkWidget *folder_win;
1065 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1067 ShowHelper *helper = (ShowHelper *) user_data;
1068 GtkWidget *folder_win = helper->folder_win;
1069 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1071 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1072 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1074 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1076 /* Connect signals */
1077 connect_signals (MODEST_MAIN_WINDOW (self));
1079 /* Set account store */
1080 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1081 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1083 /* Load previous osso state, for instance if we are being restored from
1085 modest_osso_load_state ();
1087 /* Restore window & widget settings */
1088 priv->wait_for_settings = TRUE;
1089 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1090 priv->wait_for_settings = FALSE;
1092 /* Check if accounts exist and show the account wizard if not */
1093 gboolean accounts_exist =
1094 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1096 if (!accounts_exist) {
1097 /* This is necessary to have the main window shown behind the dialog
1098 It's an ugly hack... jschmid */
1099 gtk_widget_show_all(GTK_WIDGET(self));
1100 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1102 update_menus (MODEST_MAIN_WINDOW (self));
1105 /* Never call this function again (NOTE that it could happen
1106 as we hide the main window instead of closing it while
1107 there are operations ongoing) and free the helper */
1108 g_signal_handler_disconnect (self, helper->handler_id);
1109 g_slice_free (ShowHelper, helper);
1113 osso_display_event_cb (osso_display_state_t state,
1116 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1118 priv->display_state = state;
1120 /* Stop blinking if the screen becomes on */
1121 if (priv->display_state == OSSO_DISPLAY_ON)
1122 modest_platform_remove_new_mail_notifications (TRUE);
1126 modest_main_window_new (void)
1128 ModestMainWindow *self = NULL;
1129 ModestMainWindowPrivate *priv = NULL;
1130 ModestWindowPrivate *parent_priv = NULL;
1131 GtkWidget *folder_win = NULL;
1132 ModestDimmingRulesGroup *menu_rules_group = NULL;
1133 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1134 GtkActionGroup *action_group = NULL;
1135 GError *error = NULL;
1137 GdkPixbuf *window_icon;
1140 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1141 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1142 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1144 parent_priv->ui_manager = gtk_ui_manager_new();
1145 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1147 action_group = gtk_action_group_new ("ModestMainWindowActions");
1148 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1150 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1151 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1153 /* Add common actions */
1154 gtk_action_group_add_actions (action_group,
1155 modest_action_entries,
1156 G_N_ELEMENTS (modest_action_entries),
1159 gtk_action_group_add_actions (action_group,
1160 modest_folder_view_action_entries,
1161 G_N_ELEMENTS (modest_folder_view_action_entries),
1164 gtk_action_group_add_actions (action_group,
1165 modest_header_view_action_entries,
1166 G_N_ELEMENTS (modest_header_view_action_entries),
1169 gtk_action_group_add_toggle_actions (action_group,
1170 modest_main_window_toggle_action_entries,
1171 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1174 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1175 g_object_unref (action_group);
1177 /* Load the UI definition */
1178 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1179 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1180 if (error != NULL) {
1181 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1182 g_error_free (error);
1186 /* Add common dimming rules */
1187 modest_dimming_rules_group_add_rules (menu_rules_group,
1188 modest_main_window_menu_dimming_entries,
1189 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1190 MODEST_WINDOW (self));
1191 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1192 modest_main_window_toolbar_dimming_entries,
1193 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1194 MODEST_WINDOW (self));
1196 /* Insert dimming rules group for this window */
1197 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1198 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1199 g_object_unref (menu_rules_group);
1200 g_object_unref (toolbar_rules_group);
1202 /* Add accelerators */
1203 gtk_window_add_accel_group (GTK_WINDOW (self),
1204 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1206 /* Menubar. Update the state of some toggles */
1207 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1208 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1209 gtk_widget_show (parent_priv->menubar);
1211 /* Get device name */
1212 modest_maemo_utils_get_device_name ();
1216 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1217 g_object_ref (priv->header_view);
1218 if (!priv->header_view)
1219 g_printerr ("modest: cannot instantiate header view\n");
1220 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1221 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1222 MODEST_CONF_HEADER_VIEW_KEY);
1224 /* Other style properties of header view */
1225 g_object_set (G_OBJECT (priv->header_view),
1226 "rules-hint", FALSE,
1228 /* gtk_widget_show (priv->header_view); */
1231 priv->empty_view = create_empty_view ();
1232 gtk_widget_show (priv->empty_view);
1233 g_object_ref (priv->empty_view);
1235 /* Create scrolled windows */
1236 folder_win = gtk_scrolled_window_new (NULL, NULL);
1237 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1238 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1240 GTK_POLICY_AUTOMATIC);
1241 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1243 GTK_POLICY_AUTOMATIC);
1244 /* gtk_widget_show (priv->contents_widget); */
1247 priv->main_paned = gtk_hpaned_new ();
1248 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1249 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1250 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1252 /* putting it all together... */
1253 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1254 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1255 gtk_widget_show (priv->main_vbox);
1257 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1259 app = hildon_program_get_instance ();
1260 hildon_program_add_window (app, HILDON_WINDOW (self));
1262 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1263 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1265 /* Connect to "show" action. We delay the creation of some
1266 elements until that moment */
1267 helper = g_slice_new0 (ShowHelper);
1268 helper->folder_win = folder_win;
1269 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1270 G_CALLBACK (modest_main_window_on_show),
1273 /* Set window icon */
1274 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1276 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1277 g_object_unref (window_icon);
1280 /* Listen for changes in the screen, we don't want to show a
1281 led pattern when the display is on for example */
1282 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1283 osso_display_event_cb,
1286 /* Dont't restore settings here,
1287 * because it requires a gtk_widget_show(),
1288 * and we don't want to do that until later,
1289 * so that the UI is not visible for non-menu D-Bus activation.
1292 return MODEST_WINDOW(self);
1296 modest_main_window_set_style (ModestMainWindow *self,
1297 ModestMainWindowStyle style)
1299 ModestMainWindowPrivate *priv;
1300 ModestWindowPrivate *parent_priv;
1303 GtkTreeSelection *sel;
1306 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1308 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1309 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1311 /* no change -> nothing to do */
1312 if (priv->style == style)
1315 /* Get toggle button and update the state if needed. This will
1316 happen only when the set_style is not invoked from the UI,
1317 for example when it's called from widget memory */
1318 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1319 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1320 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1321 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1322 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1323 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1324 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1327 /* We need to store the selection because it's lost when the
1328 widget is reparented */
1329 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1330 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1332 priv->style = style;
1334 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1336 if (!priv->wait_for_settings)
1337 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1338 MODEST_CONF_MAIN_PANED_KEY);
1339 /* Remove main paned */
1340 g_object_ref (priv->main_paned);
1341 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1343 /* Reparent the contents widget to the main vbox */
1344 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1347 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1348 /* Remove header view */
1349 g_object_ref (priv->contents_widget);
1350 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1352 /* Reparent the main paned */
1353 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1354 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1356 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1360 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1362 g_return_if_reached ();
1365 /* Reselect the previously selected folders. We disable the
1366 dimming rules execution during that time because there is
1367 no need to work out it again and it could take a lot of
1368 time if all the headers are selected */
1370 modest_window_disable_dimming (MODEST_WINDOW (self));
1372 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1373 list = g_list_next (list);
1375 modest_window_enable_dimming (MODEST_WINDOW (self));
1378 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1381 /* Let header view grab the focus if it's being shown */
1382 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1383 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1385 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1386 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1388 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1391 /* Check dimming rules */
1392 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1393 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1396 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1399 ModestMainWindowStyle
1400 modest_main_window_get_style (ModestMainWindow *self)
1402 ModestMainWindowPrivate *priv;
1404 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1406 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1411 toolbar_resize (ModestMainWindow *self)
1413 ModestMainWindowPrivate *priv = NULL;
1414 ModestWindowPrivate *parent_priv = NULL;
1416 gint static_button_size;
1417 ModestWindowMgr *mgr;
1419 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1420 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1421 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1423 mgr = modest_runtime_get_window_mgr ();
1424 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1426 if (parent_priv->toolbar) {
1427 /* left size buttons */
1428 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1429 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1430 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1431 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1432 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1433 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1434 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1435 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1436 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1437 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1438 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1439 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1440 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1441 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1442 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1443 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1445 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1446 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1447 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1448 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1449 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1450 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1451 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1452 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1458 modest_main_window_show_toolbar (ModestWindow *self,
1459 gboolean show_toolbar)
1461 ModestMainWindowPrivate *priv = NULL;
1462 ModestWindowPrivate *parent_priv = NULL;
1463 GtkWidget *reply_button = NULL, *menu = NULL;
1464 GtkWidget *placeholder = NULL;
1467 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1468 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1469 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1471 /* Set optimized view status */
1472 priv->optimized_view = !show_toolbar;
1474 if (!parent_priv->toolbar) {
1475 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1477 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1479 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1480 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1481 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1482 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1483 toolbar_resize (MODEST_MAIN_WINDOW (self));
1485 /* Add ProgressBar (Transfer toolbar) */
1486 priv->progress_bar = modest_progress_bar_new ();
1487 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1488 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1489 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1490 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1491 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1493 /* Connect cancel 'clicked' signal to abort progress mode */
1494 g_signal_connect(priv->cancel_toolitem, "clicked",
1495 G_CALLBACK(cancel_progressbar),
1498 /* Add it to the observers list */
1499 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1502 hildon_window_add_toolbar (HILDON_WINDOW (self),
1503 GTK_TOOLBAR (parent_priv->toolbar));
1505 /* Set reply button tap and hold menu */
1506 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1507 "/ToolBar/ToolbarMessageReply");
1508 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1509 "/ToolbarReplyCSM");
1510 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1512 /* Set send & receive button tap and hold menu */
1513 update_menus (MODEST_MAIN_WINDOW (self));
1517 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1518 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1519 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1521 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1522 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1523 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1525 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1527 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1533 on_account_inserted (TnyAccountStore *accoust_store,
1534 TnyAccount *account,
1537 /* Transport accounts and local ones (MMC and the Local
1538 folders account do now cause menu changes */
1539 if (TNY_IS_STORE_ACCOUNT (account) &&
1540 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1542 update_menus (MODEST_MAIN_WINDOW (user_data));
1547 on_default_account_changed (ModestAccountMgr* mgr,
1550 update_menus (MODEST_MAIN_WINDOW (user_data));
1554 on_account_removed (TnyAccountStore *accoust_store,
1555 TnyAccount *account,
1558 /* Transport accounts and local ones (MMC and the Local
1559 folders account do now cause menu changes */
1560 if (TNY_IS_STORE_ACCOUNT (account) &&
1561 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1562 update_menus (MODEST_MAIN_WINDOW (user_data));
1566 on_account_changed (TnyAccountStore *account_store,
1567 TnyAccount *account,
1570 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1572 /* Transport accounts and local ones (MMC and the Local
1573 folders account do now cause menu changes */
1574 if (TNY_IS_STORE_ACCOUNT (account)) {
1575 /* We need to refresh the details widget because it could have changed */
1576 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1577 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1579 /* Update the menus as well, name could change */
1580 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1581 update_menus (MODEST_MAIN_WINDOW (user_data));
1586 * This function manages the key events used to navigate between
1587 * header and folder views (when the window is in split view)
1590 * -------------------------------------------------
1591 * HeaderView GDK_Left Move focus to folder view
1592 * FolderView GDK_Right Move focus to header view
1594 * There is no need to scroll to selected row, the widgets will be the
1595 * responsibles of doing that (probably managing the focus-in event
1598 on_inner_widgets_key_pressed (GtkWidget *widget,
1602 ModestMainWindowPrivate *priv;
1604 if (event->type == GDK_KEY_RELEASE)
1607 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1609 /* Do nothing if we're in SIMPLE style */
1610 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1613 if (MODEST_IS_HEADER_VIEW (widget)) {
1614 if (event->keyval == GDK_Left)
1615 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1616 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1617 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1618 if (selected_headers > 1) {
1619 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1622 GtkTreePath * cursor_path;
1623 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1624 if (cursor_path == NULL) {
1625 GtkTreeSelection *selection;
1627 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1628 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1631 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1632 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1637 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1638 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1639 GtkTreePath *selected_path = NULL;
1640 GtkTreePath *start_path = NULL;
1641 GtkTreePath *end_path = NULL;
1643 GtkTreeSelection *selection;
1645 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1646 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1647 if (selected != NULL) {
1648 selected_path = (GtkTreePath *) selected->data;
1649 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1653 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1654 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1656 /* Scroll to first path */
1657 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1666 gtk_tree_path_free (start_path);
1668 gtk_tree_path_free (end_path);
1669 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1670 g_list_free (selected);
1672 #endif /* GTK_CHECK_VERSION */
1674 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1681 set_alignment (GtkWidget *widget,
1684 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1685 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1689 create_empty_view (void)
1691 GtkLabel *label = NULL;
1692 GtkWidget *align = NULL;
1694 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1695 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1696 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1697 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1699 return GTK_WIDGET(align);
1703 * Free the returned string
1706 get_gray_color_markup (GtkWidget *styled_widget)
1708 gchar *gray_color_markup = NULL;
1709 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1710 /* Obtain the secondary text color. We need a realized widget, that's why
1711 we get styled_widget from outside */
1713 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1714 gray_color_markup = modest_text_utils_get_color_string (&color);
1715 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1717 if (!gray_color_markup)
1718 gray_color_markup = g_strdup ("#BBBBBB");
1720 return gray_color_markup;
1724 * Free the returned string
1727 create_device_name_visual_string (const gchar *device_name,
1728 const gchar *gray_color_markup)
1732 /* We have to use "" to fill the %s of the translation. We can
1733 not just use the device name because the device name is
1734 shown in a different color, so it could not be included
1735 into the <span> tag */
1736 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1737 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1748 GtkWidget *count_label;
1749 GtkWidget *msg_count_label;
1750 GtkWidget *size_label;
1751 gchar *color_markup;
1755 create_uint_label (const gchar *markup,
1759 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1763 create_gchar_label (const gchar *markup,
1767 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1771 update_folder_stats_status_cb (ModestFolderStats stats,
1774 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1777 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1778 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1781 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1782 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1785 if (widgets->size_label) {
1786 tmp = modest_text_utils_get_display_size (stats.local_size);
1787 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1788 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1795 update_folder_stats_cb (ModestFolderStats stats,
1798 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1801 update_folder_stats_status_cb (stats, user_data);
1803 /* frees. Note that the widgets could have been destroyed but
1804 we still keep a reference */
1805 g_free (widgets->color_markup);
1806 if (widgets->count_label)
1807 g_object_unref (widgets->count_label);
1808 if (widgets->msg_count_label)
1809 g_object_unref (widgets->msg_count_label);
1810 if (widgets->size_label)
1811 g_object_unref (widgets->size_label);
1812 g_slice_free (DetailsWidgets, widgets);
1816 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1818 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1823 gchar *gray_color_markup;
1824 DetailsWidgets *widgets;
1826 vbox = gtk_vbox_new (FALSE, 0);
1827 widgets = g_slice_new0 (DetailsWidgets);
1829 gray_color_markup = get_gray_color_markup (styled_widget);
1830 widgets->color_markup = g_strdup (gray_color_markup);
1832 /* Account description: */
1833 if (modest_tny_account_is_virtual_local_folders (account)
1834 || (modest_tny_account_is_memory_card_account (account))) {
1836 /* Get device name */
1837 gchar *device_name = NULL;
1838 if (modest_tny_account_is_virtual_local_folders (account))
1839 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1840 MODEST_CONF_DEVICE_NAME, NULL);
1842 device_name = g_strdup (tny_account_get_name (account));
1844 label = create_device_name_visual_string ((const gchar *) device_name,
1845 (const gchar *) gray_color_markup);
1846 label_w = gtk_label_new (NULL);
1847 gtk_label_set_markup (GTK_LABEL (label_w), label);
1848 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1849 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1850 g_free (device_name);
1853 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1854 gtk_box_pack_start (GTK_BOX (vbox),
1855 gtk_label_new (tny_account_get_name (account)),
1858 /* Other accounts, such as IMAP and POP: */
1863 /* Put proto in uppercase */
1864 proto = g_string_new (tny_account_get_proto (account));
1865 proto = g_string_ascii_up (proto);
1867 /* note: mcen_fi_localroot_description is something like "%s account"
1868 * however, we should display "%s account: %s"... therefore, ugly tmp */
1869 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1870 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1871 gray_color_markup, tmp, tny_account_get_name (account));
1874 label_w = gtk_label_new (NULL);
1875 gtk_label_set_markup (GTK_LABEL (label_w), label);
1876 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1877 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1878 g_string_free (proto, TRUE);
1884 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1885 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1886 label_w = gtk_label_new (NULL);
1887 gtk_label_set_markup (GTK_LABEL (label_w), label);
1888 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1889 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1892 widgets->msg_count_label = g_object_ref (label_w);
1895 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1896 label_w = gtk_label_new (NULL);
1897 gtk_label_set_markup (GTK_LABEL (label_w), label);
1898 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1899 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1902 widgets->count_label = g_object_ref (label_w);
1905 if (modest_tny_account_is_virtual_local_folders (account)
1906 || modest_tny_account_is_memory_card_account (account)) {
1908 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1910 label_w = gtk_label_new (NULL);
1911 gtk_label_set_markup (GTK_LABEL (label_w), label);
1912 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1913 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1916 widgets->size_label = g_object_ref (label_w);
1918 } else if (TNY_IS_ACCOUNT(folder_store)) {
1919 TnyAccount *account = TNY_ACCOUNT(folder_store);
1921 time_t last_updated;
1922 const gchar *last_updated_string;
1923 /* Get last updated from configuration */
1924 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1925 tny_account_get_id (account));
1927 if (last_updated > 0)
1928 last_updated_string = modest_text_utils_get_display_date(last_updated);
1930 last_updated_string = g_strdup (_("mcen_va_never"));
1932 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1933 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1934 label_w = gtk_label_new (NULL);
1935 gtk_label_set_markup (GTK_LABEL (label_w), label);
1936 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1937 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1941 g_free (gray_color_markup);
1943 /* Refresh folder stats asynchronously */
1944 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1945 update_folder_stats_cb,
1946 update_folder_stats_status_cb,
1950 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1956 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1958 ModestMainWindowPrivate *priv = NULL;
1960 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1962 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1964 return priv->send_receive_in_progress;
1968 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1970 GtkAction *action = NULL;
1971 GtkWidget *widget = NULL;
1972 ModestMainWindowPrivate *priv = NULL;
1974 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1975 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1977 priv->send_receive_in_progress = TRUE;
1979 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1980 gtk_action_set_sensitive (action, FALSE);
1981 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1982 /* gtk_action_set_sensitive (action, FALSE); */
1983 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1984 gtk_widget_set_sensitive (widget, FALSE);
1988 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1990 GtkAction *action = NULL;
1991 GtkWidget *widget = NULL;
1992 ModestMainWindowPrivate *priv = NULL;
1994 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1995 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1997 priv->send_receive_in_progress = FALSE;
1999 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2000 gtk_action_set_sensitive (action, TRUE);
2001 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2002 /* gtk_action_set_sensitive (action, TRUE); */
2003 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2004 gtk_widget_set_sensitive (widget, TRUE);
2009 on_msg_count_changed (ModestHeaderView *header_view,
2011 TnyFolderChange *change,
2012 ModestMainWindow *main_window)
2014 gboolean refilter = FALSE;
2015 gboolean folder_empty = FALSE;
2016 gboolean all_marked_as_deleted = FALSE;
2017 ModestMainWindowPrivate *priv;
2019 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2020 g_return_if_fail (TNY_IS_FOLDER(folder));
2021 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2023 if (change != NULL) {
2024 TnyFolderChangeChanged changed;
2026 changed = tny_folder_change_get_changed (change);
2027 /* If something changes */
2028 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2029 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2031 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2033 /* Play a sound (if configured) and make the LED blink */
2034 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2035 modest_platform_push_email_notification ();
2038 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2041 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2044 /* Check if all messages are marked to be deleted */
2045 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2046 folder_empty = folder_empty || all_marked_as_deleted;
2048 /* Set contents style of headers view */
2050 modest_main_window_set_contents_style (main_window,
2051 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2052 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2054 modest_main_window_set_contents_style (main_window,
2055 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2059 modest_header_view_refilter (header_view);
2064 modest_main_window_set_contents_style (ModestMainWindow *self,
2065 ModestMainWindowContentsStyle style)
2067 ModestMainWindowPrivate *priv;
2069 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2071 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2073 /* We allow to set the same content style than the previously
2074 set if there are details, because it could happen when we're
2075 selecting different accounts consecutively */
2076 if ((priv->contents_style == style) &&
2077 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2080 /* Remove previous child. Delete it if it was an account
2082 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2084 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2085 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2088 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2091 priv->contents_style = style;
2093 switch (priv->contents_style) {
2094 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2095 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2096 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2098 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2099 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2101 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2103 /* if we're started without main win, there may not be a folder
2104 * view. this fixes a GLib-Critical */
2105 if (priv->folder_view) {
2106 TnyFolderStore *selected_folderstore =
2107 modest_folder_view_get_selected (priv->folder_view);
2108 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2109 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2110 TNY_ACCOUNT (selected_folderstore));
2112 wrap_in_scrolled_window (priv->contents_widget,
2113 priv->details_widget);
2115 if (selected_folderstore)
2116 g_object_unref (selected_folderstore);
2117 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2120 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2121 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2124 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2125 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2126 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2128 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2129 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2132 g_return_if_reached ();
2136 gtk_widget_show_all (priv->contents_widget);
2139 ModestMainWindowContentsStyle
2140 modest_main_window_get_contents_style (ModestMainWindow *self)
2142 ModestMainWindowPrivate *priv;
2144 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2146 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2147 return priv->contents_style;
2152 on_configuration_key_changed (ModestConf* conf,
2154 ModestConfEvent event,
2155 ModestConfNotificationId id,
2156 ModestMainWindow *self)
2158 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2159 TnyAccount *account = NULL;
2161 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2164 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2167 if (priv->folder_view)
2168 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2170 if (account && TNY_IS_ACCOUNT (account) &&
2171 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2174 const gchar *device_name;
2175 gchar *new_text, *gray_color_markup;
2178 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2179 label = GTK_LABEL (children->data);
2181 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2182 MODEST_CONF_DEVICE_NAME, NULL);
2184 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2185 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2187 gtk_label_set_markup (label, new_text);
2188 gtk_widget_show (GTK_WIDGET (label));
2190 g_free (gray_color_markup);
2192 g_list_free (children);
2194 g_object_unref (account);
2198 set_toolbar_transfer_mode (ModestMainWindow *self)
2200 ModestMainWindowPrivate *priv = NULL;
2202 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2204 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2206 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2208 if (priv->progress_bar_timeout > 0) {
2209 g_source_remove (priv->progress_bar_timeout);
2210 priv->progress_bar_timeout = 0;
2217 set_toolbar_mode (ModestMainWindow *self,
2218 ModestToolBarModes mode)
2220 ModestWindowPrivate *parent_priv = NULL;
2221 ModestMainWindowPrivate *priv = NULL;
2222 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2224 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2226 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2227 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2229 /* In case this was called before the toolbar exists: */
2230 if (!(parent_priv->toolbar))
2233 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2235 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2236 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2237 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2239 /* Sets current toolbar mode */
2240 priv->current_toolbar_mode = mode;
2242 /* Checks the dimming rules */
2243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2244 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2246 /* Show and hide toolbar items */
2248 case TOOLBAR_MODE_NORMAL:
2250 gtk_action_set_visible (sort_action, TRUE);
2252 gtk_action_set_visible (refresh_action, TRUE);
2253 if (priv->progress_toolitem) {
2254 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2255 gtk_widget_hide (priv->progress_toolitem);
2257 if (priv->progress_bar)
2258 gtk_widget_hide (priv->progress_bar);
2261 gtk_action_set_visible (cancel_action, FALSE);
2263 /* Hide toolbar if optimized view is enabled */
2264 if (priv->optimized_view)
2265 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2267 case TOOLBAR_MODE_TRANSFER:
2269 gtk_action_set_visible (sort_action, FALSE);
2271 gtk_action_set_visible (refresh_action, FALSE);
2273 gtk_action_set_visible (cancel_action, TRUE);
2274 if (priv->progress_bar)
2275 gtk_widget_show (priv->progress_bar);
2276 if (priv->progress_toolitem) {
2277 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2278 gtk_widget_show (priv->progress_toolitem);
2281 /* Show toolbar if it's hiden (optimized view ) */
2282 if (priv->optimized_view)
2283 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2286 g_return_if_reached ();
2291 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2293 ModestMainWindowPrivate *priv;
2295 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2296 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2298 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2302 cancel_progressbar (GtkToolButton *toolbutton,
2303 ModestMainWindow *self)
2306 ModestMainWindowPrivate *priv;
2308 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2310 /* Get operation observers and cancel all the operations */
2311 tmp = priv->progress_widgets;
2313 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2314 tmp=g_slist_next(tmp);
2319 observers_empty (ModestMainWindow *self)
2322 ModestMainWindowPrivate *priv;
2323 gboolean is_empty = TRUE;
2324 guint pending_ops = 0;
2326 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2327 tmp = priv->progress_widgets;
2329 /* Check all observers */
2330 while (tmp && is_empty) {
2331 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2332 is_empty = pending_ops == 0;
2334 tmp = g_slist_next(tmp);
2342 * Gets the toolbar mode needed for each mail operation. It stores in
2343 * @mode_changed if the toolbar mode has changed or not
2345 static ModestToolBarModes
2346 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2347 ModestMailOperation *mail_op,
2348 gboolean *mode_changed)
2350 ModestToolBarModes mode;
2351 ModestMainWindowPrivate *priv;
2353 *mode_changed = FALSE;
2354 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2356 /* Get toolbar mode from operation id*/
2357 switch (modest_mail_operation_get_type_operation (mail_op)) {
2358 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2359 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2360 mode = TOOLBAR_MODE_TRANSFER;
2361 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2362 *mode_changed = TRUE;
2365 mode = TOOLBAR_MODE_NORMAL;
2371 on_mail_operation_started (ModestMailOperation *mail_op,
2374 ModestMainWindow *self;
2375 ModestMailOperationTypeOperation op_type;
2376 ModestMainWindowPrivate *priv;
2377 ModestToolBarModes mode;
2379 gboolean mode_changed = FALSE;
2380 TnyAccount *account = NULL;
2382 self = MODEST_MAIN_WINDOW (user_data);
2383 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2385 /* Do not show progress for receiving operations if the
2386 account is the local account or the MMC one */
2387 op_type = modest_mail_operation_get_type_operation (mail_op);
2388 account = modest_mail_operation_get_account (mail_op);
2389 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2392 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2393 modest_tny_account_is_memory_card_account (account));
2395 g_object_unref (account);
2399 /* Show information banner. Remove old timeout */
2400 if (priv->opening_banner_timeout > 0) {
2401 g_source_remove (priv->opening_banner_timeout);
2402 priv->opening_banner_timeout = 0;
2404 /* Create a new timeout */
2405 priv->opening_banner_timeout =
2406 g_timeout_add (2000, show_opening_banner, self);
2409 /* Not every mail operation has account, noop does not */
2411 g_object_unref (account);
2413 /* Get toolbar mode from operation id*/
2414 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2416 /* Add operation observers and change toolbar if neccessary*/
2417 tmp = priv->progress_widgets;
2418 if (mode == TOOLBAR_MODE_TRANSFER) {
2420 GObject *source = modest_mail_operation_get_source(mail_op);
2421 if (G_OBJECT (self) == source) {
2422 set_toolbar_transfer_mode(self);
2424 g_object_unref (source);
2428 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2430 tmp = g_slist_next (tmp);
2434 /* Update the main menu as well, we need to explicitely do
2435 this in order to enable/disable accelerators */
2436 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2440 on_mail_operation_finished (ModestMailOperation *mail_op,
2443 ModestToolBarModes mode;
2444 ModestMailOperationTypeOperation op_type;
2446 ModestMainWindow *self;
2447 gboolean mode_changed;
2448 TnyAccount *account = NULL;
2449 ModestMainWindowPrivate *priv;
2451 self = MODEST_MAIN_WINDOW (user_data);
2452 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2454 /* The mail operation was not added to the progress objects if
2455 the account was the local account or the MMC one */
2456 op_type = modest_mail_operation_get_type_operation (mail_op);
2457 account = modest_mail_operation_get_account (mail_op);
2458 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2461 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2462 modest_tny_account_is_memory_card_account (account));
2464 g_object_unref (account);
2468 /* Remove old timeout */
2469 if (priv->opening_banner_timeout > 0) {
2470 g_source_remove (priv->opening_banner_timeout);
2471 priv->opening_banner_timeout = 0;
2474 /* Remove the banner if exists */
2475 if (priv->opening_banner) {
2476 gtk_widget_destroy (priv->opening_banner);
2477 priv->opening_banner = NULL;
2481 /* Not every mail operation has account, noop does not */
2483 g_object_unref (account);
2485 /* Get toolbar mode from operation id*/
2486 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2488 /* Change toolbar mode */
2489 tmp = priv->progress_widgets;
2490 if (mode == TOOLBAR_MODE_TRANSFER) {
2492 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2494 tmp = g_slist_next (tmp);
2497 /* If no more operations are being observed, NORMAL mode is enabled again */
2498 if (observers_empty (self)) {
2499 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2505 on_queue_changed (ModestMailOperationQueue *queue,
2506 ModestMailOperation *mail_op,
2507 ModestMailOperationQueueNotification type,
2508 ModestMainWindow *self)
2510 ModestMainWindowPrivate *priv;
2512 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2514 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2515 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2517 "operation-started",
2518 G_CALLBACK (on_mail_operation_started),
2520 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2522 "operation-finished",
2523 G_CALLBACK (on_mail_operation_finished),
2525 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2526 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2528 "operation-started");
2529 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2531 "operation-finished");
2536 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2538 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2540 ModestAccountMgr *mgr;
2541 ModestAccountSettings *settings;
2542 ModestServerAccountSettings *store_settings = NULL;
2544 /* Get account data */
2545 mgr = modest_runtime_get_account_mgr ();
2546 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2548 store_settings = modest_account_settings_get_store_settings (settings);
2550 /* Set the new visible & active account */
2551 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2552 const gchar *account_name;
2554 account_name = modest_account_settings_get_account_name (settings);
2556 modest_folder_view_set_account_id_of_visible_server_account
2558 modest_server_account_settings_get_account_name (store_settings));
2559 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2560 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2562 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2563 if (action != NULL) {
2564 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2565 modest_utils_toggle_action_set_active_block_notify (
2566 GTK_TOGGLE_ACTION (action),
2574 g_object_unref (store_settings);
2575 g_object_unref (settings);
2579 /* Make sure that at least one account is "viewed": */
2581 set_at_least_one_account_visible(ModestMainWindow *self)
2583 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2584 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2586 if (!(priv->folder_view)) {
2587 /* It is too early to do this. */
2591 const gchar *active_server_account_name =
2592 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2594 if (!active_server_account_name ||
2595 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2597 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2598 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2599 if (default_modest_name) {
2600 set_account_visible (self, default_modest_name);
2601 } else if (first_modest_name) {
2602 set_account_visible (self, first_modest_name);
2604 g_free (first_modest_name);
2605 g_free (default_modest_name);
2610 on_show_account_action_toggled (GtkToggleAction *action,
2613 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2615 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2616 if (gtk_toggle_action_get_active (action))
2617 set_account_visible (self, acc_name);
2621 refresh_account (const gchar *account_name)
2625 /* win must already exists here, obviously */
2626 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2629 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2633 /* If account_name == NULL, we must update all (option All) */
2635 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2637 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2642 on_refresh_account_action_activated (GtkAction *action,
2645 refresh_account ((const gchar*) user_data);
2649 on_send_receive_csm_activated (GtkMenuItem *item,
2652 refresh_account ((const gchar*) user_data);
2656 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2658 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2660 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2666 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2668 ModestMainWindow *main_window = NULL;
2670 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2671 main_window = MODEST_MAIN_WINDOW (userdata);
2673 /* Update toolbar dimming state */
2674 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2675 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2681 on_header_view_focus_in (GtkWidget *widget,
2682 GdkEventFocus *event,
2685 ModestMainWindow *main_window = NULL;
2687 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2689 main_window = MODEST_MAIN_WINDOW (userdata);
2691 /* Update toolbar dimming state */
2692 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2693 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2699 on_folder_selection_changed (ModestFolderView *folder_view,
2700 TnyFolderStore *folder_store,
2702 ModestMainWindow *main_window)
2704 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2705 GtkAction *action = NULL;
2706 gboolean show_reply = TRUE;
2707 gboolean show_forward = TRUE;
2708 gboolean show_cancel_send = FALSE;
2709 gboolean show_clipboard = TRUE;
2710 gboolean show_delete = TRUE;
2713 if (TNY_IS_ACCOUNT (folder_store)) {
2714 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2715 } else if (TNY_IS_FOLDER (folder_store)) {
2716 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2717 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2718 TNY_FOLDER (folder_store));
2719 switch (folder_type) {
2720 case TNY_FOLDER_TYPE_DRAFTS:
2721 show_clipboard = show_delete = TRUE;
2722 show_reply = show_forward = show_cancel_send = FALSE;
2724 case TNY_FOLDER_TYPE_SENT:
2725 show_forward = show_clipboard = show_delete = TRUE;
2726 show_reply = show_cancel_send = FALSE;
2728 case TNY_FOLDER_TYPE_OUTBOX:
2729 show_clipboard = show_delete = show_cancel_send = TRUE;
2730 show_reply = show_forward = FALSE;
2732 case TNY_FOLDER_TYPE_INVALID:
2733 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2736 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2737 show_cancel_send = FALSE;
2740 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2741 show_cancel_send = FALSE;
2746 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2747 gtk_action_set_visible (action, show_reply);
2748 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2749 gtk_action_set_visible (action, show_reply);
2750 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2751 gtk_action_set_visible (action, show_forward);
2752 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2753 gtk_action_set_visible (action, show_cancel_send);
2754 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2755 gtk_action_set_visible (action, show_delete);
2757 /* We finally call to the ui actions handler, after updating properly
2758 * the header view CSM */
2759 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2763 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2764 GtkTreeModel *model,
2765 GtkTreeRowReference *row_reference,
2766 ModestMainWindow *self)
2768 ModestMainWindowPrivate *priv = NULL;
2769 GtkTreeModel *header_model = NULL;
2770 GtkTreePath *path = NULL;
2772 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2773 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2774 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2776 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2777 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2779 /* Do nothing if we changed the folder in the main view */
2780 if (header_model != model)
2783 /* Select the message in the header view */
2784 path = gtk_tree_row_reference_get_path (row_reference);
2785 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2787 gtk_tree_path_free (path);
2793 updating_banner_destroyed (gpointer data,
2794 GObject *where_the_object_was)
2796 ModestMainWindowPrivate *priv = NULL;
2798 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2800 priv->updating_banner = NULL;
2804 show_updating_banner (gpointer user_data)
2806 ModestMainWindowPrivate *priv = NULL;
2808 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2810 if (priv->updating_banner == NULL) {
2812 /* We're outside the main lock */
2813 gdk_threads_enter ();
2814 priv->updating_banner =
2815 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2816 _CS ("ckdg_pb_updating"));
2818 /* We need this because banners in Maemo could be
2819 destroyed by dialogs so we need to properly update
2820 our reference to it */
2821 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2822 updating_banner_destroyed,
2824 gdk_threads_leave ();
2827 /* Remove timeout */
2828 priv->updating_banner_timeout = 0;
2833 * We use this function to show/hide a progress banner showing
2834 * "Updating" while the header view is being filled. We're not showing
2835 * it unless the update takes more than 2 seconds
2837 * If starting = TRUE then the refresh is starting, otherwise it means
2838 * that is has just finished
2841 on_updating_msg_list (ModestHeaderView *header_view,
2845 ModestMainWindowPrivate *priv = NULL;
2847 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2849 /* Remove old timeout */
2850 if (priv->updating_banner_timeout > 0) {
2851 g_source_remove (priv->updating_banner_timeout);
2852 priv->updating_banner_timeout = 0;
2855 /* Create a new timeout */
2857 priv->updating_banner_timeout =
2858 g_timeout_add (2000, show_updating_banner, user_data);
2860 /* Remove the banner if exists */
2861 if (priv->updating_banner) {
2862 gtk_widget_destroy (priv->updating_banner);
2863 priv->updating_banner = NULL;
2869 modest_main_window_screen_is_on (ModestMainWindow *self)
2871 ModestMainWindowPrivate *priv = NULL;
2873 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2875 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2877 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2881 remove_banners (ModestMainWindow *window)
2883 ModestMainWindowPrivate *priv;
2885 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2887 if (priv->opening_banner_timeout > 0) {
2888 g_source_remove (priv->opening_banner_timeout);
2889 priv->opening_banner_timeout = 0;
2892 if (priv->opening_banner != NULL) {
2893 gtk_widget_destroy (priv->opening_banner);
2894 priv->opening_banner = NULL;
2897 if (priv->updating_banner_timeout > 0) {
2898 g_source_remove (priv->updating_banner_timeout);
2899 priv->updating_banner_timeout = 0;
2902 if (priv->updating_banner != NULL) {
2903 gtk_widget_destroy (priv->updating_banner);
2904 priv->updating_banner = NULL;
2910 on_window_hide (GObject *gobject,
2914 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2916 if (!GTK_WIDGET_VISIBLE (gobject)) {
2917 TnyFolderStore *folder_store;
2918 ModestMainWindowPrivate *priv;
2920 /* Remove the currently shown banners */
2921 remove_banners (MODEST_MAIN_WINDOW (gobject));
2923 /* Force the folder view to sync the currently selected folder
2924 to save the read/unread status and to expunge messages */
2925 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2926 folder_store = modest_folder_view_get_selected (priv->folder_view);
2927 if (TNY_IS_FOLDER (folder_store)) {
2928 ModestMailOperation *mail_op;
2930 mail_op = modest_mail_operation_new (NULL);
2931 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2933 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2934 g_object_unref (mail_op);
2935 g_object_unref (folder_store);
2941 on_window_destroy (GtkObject *widget,
2944 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2946 remove_banners (MODEST_MAIN_WINDOW (widget));
2950 opening_banner_destroyed (gpointer data,
2951 GObject *where_the_object_was)
2953 ModestMainWindowPrivate *priv = NULL;
2955 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2957 priv->opening_banner = NULL;
2961 show_opening_banner (gpointer user_data)
2963 ModestMainWindowPrivate *priv = NULL;
2965 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2967 if (priv->opening_banner == NULL) {
2969 /* We're outside the main lock */
2970 gdk_threads_enter ();
2971 priv->opening_banner =
2972 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2973 _("mail_me_opening"));
2975 /* We need this because banners in Maemo could be
2976 destroyed by dialogs so we need to properly update
2977 our reference to it */
2978 g_object_weak_ref (G_OBJECT (priv->opening_banner),
2979 opening_banner_destroyed,
2982 /* We need this because banners in Maemo could be
2983 destroyed by dialogs so we need to properly update
2984 our reference to it */
2985 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2986 updating_banner_destroyed,
2988 gdk_threads_leave ();
2991 /* Remove timeout */
2992 priv->opening_banner_timeout = 0;