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);
803 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
807 /* Get the item of the tools menu */
808 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
809 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
813 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
814 if (GTK_IS_LABEL (child)) {
815 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
817 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
818 gtk_label_set_markup (GTK_LABEL (child), bold_name);
821 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
826 g_object_unref (settings);
829 if (num_accounts > 1) {
830 /* Disconnect the tap-and-hold-query if it's connected */
831 if (modest_signal_mgr_is_connected (priv->sighandlers,
832 G_OBJECT (send_receive_button),
833 "tap-and-hold-query"))
834 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
835 G_OBJECT (send_receive_button),
836 "tap-and-hold-query");
838 /* Mandatory in order to view the menu contents */
839 gtk_widget_show_all (priv->accounts_popup);
841 /* Setup tap_and_hold just if was not done before*/
842 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
843 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
845 /* Connect the tap-and-hold-query in order not to show the CSM */
846 if (!modest_signal_mgr_is_connected (priv->sighandlers,
847 G_OBJECT (send_receive_button),
848 "tap-and-hold-query"))
849 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
850 G_OBJECT (send_receive_button),
851 "tap-and-hold-query",
852 G_CALLBACK (tap_and_hold_query_cb),
857 g_slist_free (accounts);
858 g_free (default_account);
861 /* Make sure that at least one account is viewed if there are any
862 * accounts, for instance when adding the first account: */
863 set_at_least_one_account_visible (self);
867 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
869 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
870 gtk_scrolled_window_add_with_viewport
871 (GTK_SCROLLED_WINDOW(win), widget);
873 gtk_container_add (GTK_CONTAINER(win),
884 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
886 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
888 GList *oerrsignals = priv->queue_err_signals;
889 while (oerrsignals) {
890 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
891 g_signal_handler_disconnect (esignal->queue, esignal->signal);
892 g_slice_free (QueueErrorSignal, esignal);
893 oerrsignals = g_list_next (oerrsignals);
895 g_list_free (priv->queue_err_signals);
896 priv->queue_err_signals = NULL;
901 modest_main_window_disconnect_signals (ModestWindow *self)
903 ModestMainWindowPrivate *priv;
904 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
906 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
907 priv->sighandlers = NULL;
911 connect_signals (ModestMainWindow *self)
913 ModestWindowPrivate *parent_priv;
914 ModestMainWindowPrivate *priv;
916 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
917 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
922 modest_signal_mgr_connect (priv->sighandlers,
923 G_OBJECT(priv->folder_view), "key-press-event",
924 G_CALLBACK(on_inner_widgets_key_pressed), self);
926 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
927 "folder_selection_changed",
928 G_CALLBACK (on_folder_selection_changed),
931 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
932 "folder-display-name-changed",
933 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
936 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
938 G_CALLBACK (on_folder_view_focus_in),
943 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
944 G_CALLBACK(modest_ui_actions_on_header_selected), self);
946 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
947 G_CALLBACK(modest_ui_actions_on_header_activated), self);
949 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
950 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
952 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
953 G_CALLBACK(on_inner_widgets_key_pressed), self);
955 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
956 G_CALLBACK(on_msg_count_changed), self);
958 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
959 G_CALLBACK (on_header_view_focus_in), self);
961 modest_signal_mgr_connect (priv->sighandlers,
962 G_OBJECT (priv->header_view),
964 G_CALLBACK (on_updating_msg_list),
968 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
969 * in destroy stage */
970 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
972 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
974 /* Mail Operation Queue */
976 modest_signal_mgr_connect (priv->sighandlers,
977 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
979 G_CALLBACK (on_queue_changed), self);
981 /* Track changes in the device name */
983 modest_signal_mgr_connect (priv->sighandlers,
984 G_OBJECT(modest_runtime_get_conf ()),
986 G_CALLBACK (on_configuration_key_changed),
989 /* Track account changes. We need to refresh the toolbar */
991 modest_signal_mgr_connect (priv->sighandlers,
992 G_OBJECT (modest_runtime_get_account_store ()),
994 G_CALLBACK (on_account_inserted),
997 modest_signal_mgr_connect (priv->sighandlers,
998 G_OBJECT (modest_runtime_get_account_store ()),
1000 G_CALLBACK (on_account_removed),
1003 /* We need to refresh the send & receive menu to change the bold
1004 * account when the default account changes. */
1006 modest_signal_mgr_connect (priv->sighandlers,
1007 G_OBJECT (modest_runtime_get_account_mgr ()),
1008 "default_account_changed",
1009 G_CALLBACK (on_default_account_changed),
1014 modest_signal_mgr_connect (priv->sighandlers,
1015 G_OBJECT (modest_runtime_get_account_store ()),
1017 G_CALLBACK (on_account_changed),
1022 on_hildon_program_is_topmost_notify(GObject *self,
1023 GParamSpec *propert_param,
1026 HildonProgram *app = HILDON_PROGRAM (self);
1028 /* Note that use of hildon_program_set_can_hibernate()
1029 * is generally referred to as "setting the killable flag",
1030 * though hibernation does not seem equal to death.
1033 if (hildon_program_get_is_topmost (app)) {
1034 /* Prevent hibernation when the progam comes to the foreground,
1035 * because hibernation should only happen when the application
1036 * is in the background: */
1037 hildon_program_set_can_hibernate (app, FALSE);
1039 /* Remove new mail visual notifications */
1040 modest_platform_remove_new_mail_notifications (TRUE);
1042 /* Allow hibernation if the program has gone to the background: */
1044 /* However, prevent hibernation while the settings are being changed: */
1045 const gboolean hibernation_prevented =
1046 modest_window_mgr_get_hibernation_is_prevented (
1047 modest_runtime_get_window_mgr ());
1049 if (hibernation_prevented)
1050 hildon_program_set_can_hibernate (app, FALSE);
1052 /* Allow hibernation, after saving the state: */
1053 modest_osso_save_state();
1054 hildon_program_set_can_hibernate (app, TRUE);
1061 GtkWidget *folder_win;
1066 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1068 ShowHelper *helper = (ShowHelper *) user_data;
1069 GtkWidget *folder_win = helper->folder_win;
1070 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1072 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1073 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1075 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1077 /* Connect signals */
1078 connect_signals (MODEST_MAIN_WINDOW (self));
1080 /* Set account store */
1081 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1082 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1084 /* Load previous osso state, for instance if we are being restored from
1086 modest_osso_load_state ();
1088 /* Restore window & widget settings */
1089 priv->wait_for_settings = TRUE;
1090 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1091 priv->wait_for_settings = FALSE;
1093 /* Check if accounts exist and show the account wizard if not */
1094 gboolean accounts_exist =
1095 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1097 if (!accounts_exist) {
1098 /* This is necessary to have the main window shown behind the dialog
1099 It's an ugly hack... jschmid */
1100 gtk_widget_show_all(GTK_WIDGET(self));
1101 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1103 update_menus (MODEST_MAIN_WINDOW (self));
1106 /* Never call this function again (NOTE that it could happen
1107 as we hide the main window instead of closing it while
1108 there are operations ongoing) and free the helper */
1109 g_signal_handler_disconnect (self, helper->handler_id);
1110 g_slice_free (ShowHelper, helper);
1114 osso_display_event_cb (osso_display_state_t state,
1117 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1119 priv->display_state = state;
1121 /* Stop blinking if the screen becomes on */
1122 if (priv->display_state == OSSO_DISPLAY_ON)
1123 modest_platform_remove_new_mail_notifications (TRUE);
1127 modest_main_window_new (void)
1129 ModestMainWindow *self = NULL;
1130 ModestMainWindowPrivate *priv = NULL;
1131 ModestWindowPrivate *parent_priv = NULL;
1132 GtkWidget *folder_win = NULL;
1133 ModestDimmingRulesGroup *menu_rules_group = NULL;
1134 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1135 GtkActionGroup *action_group = NULL;
1136 GError *error = NULL;
1138 GdkPixbuf *window_icon;
1141 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1142 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1143 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1145 parent_priv->ui_manager = gtk_ui_manager_new();
1146 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1148 action_group = gtk_action_group_new ("ModestMainWindowActions");
1149 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1151 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1152 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1154 /* Add common actions */
1155 gtk_action_group_add_actions (action_group,
1156 modest_action_entries,
1157 G_N_ELEMENTS (modest_action_entries),
1160 gtk_action_group_add_actions (action_group,
1161 modest_folder_view_action_entries,
1162 G_N_ELEMENTS (modest_folder_view_action_entries),
1165 gtk_action_group_add_actions (action_group,
1166 modest_header_view_action_entries,
1167 G_N_ELEMENTS (modest_header_view_action_entries),
1170 gtk_action_group_add_toggle_actions (action_group,
1171 modest_main_window_toggle_action_entries,
1172 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1175 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1176 g_object_unref (action_group);
1178 /* Load the UI definition */
1179 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1180 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1181 if (error != NULL) {
1182 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1183 g_error_free (error);
1187 /* Add common dimming rules */
1188 modest_dimming_rules_group_add_rules (menu_rules_group,
1189 modest_main_window_menu_dimming_entries,
1190 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1191 MODEST_WINDOW (self));
1192 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1193 modest_main_window_toolbar_dimming_entries,
1194 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1195 MODEST_WINDOW (self));
1197 /* Insert dimming rules group for this window */
1198 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1199 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1200 g_object_unref (menu_rules_group);
1201 g_object_unref (toolbar_rules_group);
1203 /* Add accelerators */
1204 gtk_window_add_accel_group (GTK_WINDOW (self),
1205 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1207 /* Menubar. Update the state of some toggles */
1208 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1209 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1210 gtk_widget_show (parent_priv->menubar);
1212 /* Get device name */
1213 modest_maemo_utils_get_device_name ();
1217 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1218 g_object_ref (priv->header_view);
1219 if (!priv->header_view)
1220 g_printerr ("modest: cannot instantiate header view\n");
1221 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1222 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1223 MODEST_CONF_HEADER_VIEW_KEY);
1225 /* Other style properties of header view */
1226 g_object_set (G_OBJECT (priv->header_view),
1227 "rules-hint", FALSE,
1229 /* gtk_widget_show (priv->header_view); */
1232 priv->empty_view = create_empty_view ();
1233 gtk_widget_show (priv->empty_view);
1234 g_object_ref (priv->empty_view);
1236 /* Create scrolled windows */
1237 folder_win = gtk_scrolled_window_new (NULL, NULL);
1238 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1239 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1241 GTK_POLICY_AUTOMATIC);
1242 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1244 GTK_POLICY_AUTOMATIC);
1245 /* gtk_widget_show (priv->contents_widget); */
1248 priv->main_paned = gtk_hpaned_new ();
1249 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1250 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1251 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1253 /* putting it all together... */
1254 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1255 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1256 gtk_widget_show (priv->main_vbox);
1258 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1260 app = hildon_program_get_instance ();
1261 hildon_program_add_window (app, HILDON_WINDOW (self));
1263 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1264 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1266 /* Connect to "show" action. We delay the creation of some
1267 elements until that moment */
1268 helper = g_slice_new0 (ShowHelper);
1269 helper->folder_win = folder_win;
1270 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1271 G_CALLBACK (modest_main_window_on_show),
1274 /* Set window icon */
1275 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1277 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1278 g_object_unref (window_icon);
1281 /* Listen for changes in the screen, we don't want to show a
1282 led pattern when the display is on for example */
1283 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1284 osso_display_event_cb,
1287 /* Dont't restore settings here,
1288 * because it requires a gtk_widget_show(),
1289 * and we don't want to do that until later,
1290 * so that the UI is not visible for non-menu D-Bus activation.
1293 return MODEST_WINDOW(self);
1297 modest_main_window_set_style (ModestMainWindow *self,
1298 ModestMainWindowStyle style)
1300 ModestMainWindowPrivate *priv;
1301 ModestWindowPrivate *parent_priv;
1304 GtkTreeSelection *sel;
1307 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1310 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1312 /* no change -> nothing to do */
1313 if (priv->style == style)
1316 /* Get toggle button and update the state if needed. This will
1317 happen only when the set_style is not invoked from the UI,
1318 for example when it's called from widget memory */
1319 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1320 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1321 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1322 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1323 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1324 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1325 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1328 /* We need to store the selection because it's lost when the
1329 widget is reparented */
1330 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1331 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1333 priv->style = style;
1335 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1337 if (!priv->wait_for_settings)
1338 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1339 MODEST_CONF_MAIN_PANED_KEY);
1340 /* Remove main paned */
1341 g_object_ref (priv->main_paned);
1342 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1344 /* Reparent the contents widget to the main vbox */
1345 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1348 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1349 /* Remove header view */
1350 g_object_ref (priv->contents_widget);
1351 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1353 /* Reparent the main paned */
1354 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1355 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1357 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1361 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1363 g_return_if_reached ();
1366 /* Reselect the previously selected folders. We disable the
1367 dimming rules execution during that time because there is
1368 no need to work out it again and it could take a lot of
1369 time if all the headers are selected */
1371 modest_window_disable_dimming (MODEST_WINDOW (self));
1373 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1374 list = g_list_next (list);
1376 modest_window_enable_dimming (MODEST_WINDOW (self));
1379 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1382 /* Let header view grab the focus if it's being shown */
1383 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1384 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1386 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1387 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1389 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1392 /* Check dimming rules */
1393 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1394 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1397 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1400 ModestMainWindowStyle
1401 modest_main_window_get_style (ModestMainWindow *self)
1403 ModestMainWindowPrivate *priv;
1405 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1407 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1412 toolbar_resize (ModestMainWindow *self)
1414 ModestMainWindowPrivate *priv = NULL;
1415 ModestWindowPrivate *parent_priv = NULL;
1417 gint static_button_size;
1418 ModestWindowMgr *mgr;
1420 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1421 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1422 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1424 mgr = modest_runtime_get_window_mgr ();
1425 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1427 if (parent_priv->toolbar) {
1428 /* left size buttons */
1429 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1430 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1431 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1432 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1433 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1434 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1435 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1436 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1437 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1438 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1439 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1440 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1441 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1444 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1447 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1448 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1449 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1450 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1459 modest_main_window_show_toolbar (ModestWindow *self,
1460 gboolean show_toolbar)
1462 ModestMainWindowPrivate *priv = NULL;
1463 ModestWindowPrivate *parent_priv = NULL;
1464 GtkWidget *reply_button = NULL, *menu = NULL;
1465 GtkWidget *placeholder = NULL;
1468 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1469 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1470 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1472 /* Set optimized view status */
1473 priv->optimized_view = !show_toolbar;
1475 if (!parent_priv->toolbar) {
1476 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1478 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1480 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1481 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1482 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1483 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1484 toolbar_resize (MODEST_MAIN_WINDOW (self));
1486 /* Add ProgressBar (Transfer toolbar) */
1487 priv->progress_bar = modest_progress_bar_new ();
1488 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1489 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1490 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1491 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1492 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1494 /* Connect cancel 'clicked' signal to abort progress mode */
1495 g_signal_connect(priv->cancel_toolitem, "clicked",
1496 G_CALLBACK(cancel_progressbar),
1499 /* Add it to the observers list */
1500 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1503 hildon_window_add_toolbar (HILDON_WINDOW (self),
1504 GTK_TOOLBAR (parent_priv->toolbar));
1506 /* Set reply button tap and hold menu */
1507 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1508 "/ToolBar/ToolbarMessageReply");
1509 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1510 "/ToolbarReplyCSM");
1511 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1513 /* Set send & receive button tap and hold menu */
1514 update_menus (MODEST_MAIN_WINDOW (self));
1518 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1519 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1520 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1522 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1523 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1524 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1526 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1528 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1534 on_account_inserted (TnyAccountStore *accoust_store,
1535 TnyAccount *account,
1538 /* Transport accounts and local ones (MMC and the Local
1539 folders account do now cause menu changes */
1540 if (TNY_IS_STORE_ACCOUNT (account) &&
1541 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1543 update_menus (MODEST_MAIN_WINDOW (user_data));
1548 on_default_account_changed (ModestAccountMgr* mgr,
1551 update_menus (MODEST_MAIN_WINDOW (user_data));
1555 on_account_removed (TnyAccountStore *accoust_store,
1556 TnyAccount *account,
1559 /* Transport accounts and local ones (MMC and the Local
1560 folders account do now cause menu changes */
1561 if (TNY_IS_STORE_ACCOUNT (account) &&
1562 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1563 update_menus (MODEST_MAIN_WINDOW (user_data));
1567 on_account_changed (TnyAccountStore *account_store,
1568 TnyAccount *account,
1571 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1573 /* Transport accounts and local ones (MMC and the Local
1574 folders account do now cause menu changes */
1575 if (TNY_IS_STORE_ACCOUNT (account)) {
1576 /* We need to refresh the details widget because it could have changed */
1577 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1578 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1580 /* Update the menus as well, name could change */
1581 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1582 update_menus (MODEST_MAIN_WINDOW (user_data));
1587 * This function manages the key events used to navigate between
1588 * header and folder views (when the window is in split view)
1591 * -------------------------------------------------
1592 * HeaderView GDK_Left Move focus to folder view
1593 * FolderView GDK_Right Move focus to header view
1595 * There is no need to scroll to selected row, the widgets will be the
1596 * responsibles of doing that (probably managing the focus-in event
1599 on_inner_widgets_key_pressed (GtkWidget *widget,
1603 ModestMainWindowPrivate *priv;
1605 if (event->type == GDK_KEY_RELEASE)
1608 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1610 /* Do nothing if we're in SIMPLE style */
1611 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1614 if (MODEST_IS_HEADER_VIEW (widget)) {
1615 if (event->keyval == GDK_Left)
1616 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1617 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1618 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1619 if (selected_headers > 1) {
1620 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1623 GtkTreePath * cursor_path;
1624 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1625 if (cursor_path == NULL) {
1626 GtkTreeSelection *selection;
1628 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1629 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1632 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1633 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1638 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1639 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1640 GtkTreePath *selected_path = NULL;
1641 GtkTreePath *start_path = NULL;
1642 GtkTreePath *end_path = NULL;
1644 GtkTreeSelection *selection;
1646 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1647 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1648 if (selected != NULL) {
1649 selected_path = (GtkTreePath *) selected->data;
1650 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1654 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1655 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1657 /* Scroll to first path */
1658 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1667 gtk_tree_path_free (start_path);
1669 gtk_tree_path_free (end_path);
1670 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1671 g_list_free (selected);
1673 #endif /* GTK_CHECK_VERSION */
1675 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1682 set_alignment (GtkWidget *widget,
1685 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1686 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1690 create_empty_view (void)
1692 GtkLabel *label = NULL;
1693 GtkWidget *align = NULL;
1695 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1696 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1697 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1698 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1700 return GTK_WIDGET(align);
1704 * Free the returned string
1707 get_gray_color_markup (GtkWidget *styled_widget)
1709 gchar *gray_color_markup = NULL;
1710 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1711 /* Obtain the secondary text color. We need a realized widget, that's why
1712 we get styled_widget from outside */
1714 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1715 gray_color_markup = modest_text_utils_get_color_string (&color);
1716 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1718 if (!gray_color_markup)
1719 gray_color_markup = g_strdup ("#BBBBBB");
1721 return gray_color_markup;
1725 * Free the returned string
1728 create_device_name_visual_string (const gchar *device_name,
1729 const gchar *gray_color_markup)
1733 /* We have to use "" to fill the %s of the translation. We can
1734 not just use the device name because the device name is
1735 shown in a different color, so it could not be included
1736 into the <span> tag */
1737 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1738 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1749 GtkWidget *count_label;
1750 GtkWidget *msg_count_label;
1751 GtkWidget *size_label;
1752 gchar *color_markup;
1756 create_uint_label (const gchar *markup,
1760 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1764 create_gchar_label (const gchar *markup,
1768 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1772 update_folder_stats_status_cb (ModestFolderStats stats,
1775 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1778 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1779 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1782 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1783 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1786 if (widgets->size_label) {
1787 tmp = modest_text_utils_get_display_size (stats.local_size);
1788 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1789 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1796 update_folder_stats_cb (ModestFolderStats stats,
1799 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1802 update_folder_stats_status_cb (stats, user_data);
1804 /* frees. Note that the widgets could have been destroyed but
1805 we still keep a reference */
1806 g_free (widgets->color_markup);
1807 if (widgets->count_label)
1808 g_object_unref (widgets->count_label);
1809 if (widgets->msg_count_label)
1810 g_object_unref (widgets->msg_count_label);
1811 if (widgets->size_label)
1812 g_object_unref (widgets->size_label);
1813 g_slice_free (DetailsWidgets, widgets);
1817 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1819 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1824 gchar *gray_color_markup;
1825 DetailsWidgets *widgets;
1827 vbox = gtk_vbox_new (FALSE, 0);
1828 widgets = g_slice_new0 (DetailsWidgets);
1830 gray_color_markup = get_gray_color_markup (styled_widget);
1831 widgets->color_markup = g_strdup (gray_color_markup);
1833 /* Account description: */
1834 if (modest_tny_account_is_virtual_local_folders (account)
1835 || (modest_tny_account_is_memory_card_account (account))) {
1837 /* Get device name */
1838 gchar *device_name = NULL;
1839 if (modest_tny_account_is_virtual_local_folders (account))
1840 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1841 MODEST_CONF_DEVICE_NAME, NULL);
1843 device_name = g_strdup (tny_account_get_name (account));
1845 label = create_device_name_visual_string ((const gchar *) device_name,
1846 (const gchar *) gray_color_markup);
1847 label_w = gtk_label_new (NULL);
1848 gtk_label_set_markup (GTK_LABEL (label_w), label);
1849 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1850 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1851 g_free (device_name);
1854 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1855 gtk_box_pack_start (GTK_BOX (vbox),
1856 gtk_label_new (tny_account_get_name (account)),
1859 /* Other accounts, such as IMAP and POP: */
1864 /* Put proto in uppercase */
1865 proto = g_string_new (tny_account_get_proto (account));
1866 proto = g_string_ascii_up (proto);
1868 /* note: mcen_fi_localroot_description is something like "%s account"
1869 * however, we should display "%s account: %s"... therefore, ugly tmp */
1870 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1871 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1872 gray_color_markup, tmp, tny_account_get_name (account));
1875 label_w = gtk_label_new (NULL);
1876 gtk_label_set_markup (GTK_LABEL (label_w), label);
1877 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1878 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1879 g_string_free (proto, TRUE);
1885 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1886 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1887 label_w = gtk_label_new (NULL);
1888 gtk_label_set_markup (GTK_LABEL (label_w), label);
1889 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1890 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1893 widgets->msg_count_label = g_object_ref (label_w);
1896 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1897 label_w = gtk_label_new (NULL);
1898 gtk_label_set_markup (GTK_LABEL (label_w), label);
1899 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1900 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1903 widgets->count_label = g_object_ref (label_w);
1906 if (modest_tny_account_is_virtual_local_folders (account)
1907 || modest_tny_account_is_memory_card_account (account)) {
1909 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1911 label_w = gtk_label_new (NULL);
1912 gtk_label_set_markup (GTK_LABEL (label_w), label);
1913 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1914 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1917 widgets->size_label = g_object_ref (label_w);
1919 } else if (TNY_IS_ACCOUNT(folder_store)) {
1920 TnyAccount *account = TNY_ACCOUNT(folder_store);
1922 time_t last_updated;
1923 const gchar *last_updated_string;
1924 /* Get last updated from configuration */
1925 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1926 tny_account_get_id (account));
1928 if (last_updated > 0)
1929 last_updated_string = modest_text_utils_get_display_date(last_updated);
1931 last_updated_string = g_strdup (_("mcen_va_never"));
1933 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1934 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1935 label_w = gtk_label_new (NULL);
1936 gtk_label_set_markup (GTK_LABEL (label_w), label);
1937 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1938 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1942 g_free (gray_color_markup);
1944 /* Refresh folder stats asynchronously */
1945 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1946 update_folder_stats_cb,
1947 update_folder_stats_status_cb,
1951 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1957 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1959 ModestMainWindowPrivate *priv = NULL;
1961 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1963 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1965 return priv->send_receive_in_progress;
1969 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1971 GtkAction *action = NULL;
1972 GtkWidget *widget = NULL;
1973 ModestMainWindowPrivate *priv = NULL;
1975 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1976 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1978 priv->send_receive_in_progress = TRUE;
1980 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1981 gtk_action_set_sensitive (action, FALSE);
1982 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1983 /* gtk_action_set_sensitive (action, FALSE); */
1984 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1985 gtk_widget_set_sensitive (widget, FALSE);
1989 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1991 GtkAction *action = NULL;
1992 GtkWidget *widget = NULL;
1993 ModestMainWindowPrivate *priv = NULL;
1995 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1996 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1998 priv->send_receive_in_progress = FALSE;
2000 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2001 gtk_action_set_sensitive (action, TRUE);
2002 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2003 /* gtk_action_set_sensitive (action, TRUE); */
2004 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2005 gtk_widget_set_sensitive (widget, TRUE);
2010 on_msg_count_changed (ModestHeaderView *header_view,
2012 TnyFolderChange *change,
2013 ModestMainWindow *main_window)
2015 gboolean refilter = FALSE;
2016 gboolean folder_empty = FALSE;
2017 gboolean all_marked_as_deleted = FALSE;
2018 ModestMainWindowPrivate *priv;
2020 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2021 g_return_if_fail (TNY_IS_FOLDER(folder));
2022 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2024 if (change != NULL) {
2025 TnyFolderChangeChanged changed;
2027 changed = tny_folder_change_get_changed (change);
2028 /* If something changes */
2029 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2030 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2032 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2034 /* Play a sound (if configured) and make the LED blink */
2035 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2036 modest_platform_push_email_notification ();
2039 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2042 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2045 /* Check if all messages are marked to be deleted */
2046 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2047 folder_empty = folder_empty || all_marked_as_deleted;
2049 /* Set contents style of headers view */
2051 modest_main_window_set_contents_style (main_window,
2052 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2053 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2055 modest_main_window_set_contents_style (main_window,
2056 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2060 modest_header_view_refilter (header_view);
2065 modest_main_window_set_contents_style (ModestMainWindow *self,
2066 ModestMainWindowContentsStyle style)
2068 ModestMainWindowPrivate *priv;
2070 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2072 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2074 /* We allow to set the same content style than the previously
2075 set if there are details, because it could happen when we're
2076 selecting different accounts consecutively */
2077 if ((priv->contents_style == style) &&
2078 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2081 /* Remove previous child. Delete it if it was an account
2083 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2085 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2086 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2089 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2092 priv->contents_style = style;
2094 switch (priv->contents_style) {
2095 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2096 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2097 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2099 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2100 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2102 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2104 /* if we're started without main win, there may not be a folder
2105 * view. this fixes a GLib-Critical */
2106 if (priv->folder_view) {
2107 TnyFolderStore *selected_folderstore =
2108 modest_folder_view_get_selected (priv->folder_view);
2109 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2110 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2111 TNY_ACCOUNT (selected_folderstore));
2113 wrap_in_scrolled_window (priv->contents_widget,
2114 priv->details_widget);
2116 if (selected_folderstore)
2117 g_object_unref (selected_folderstore);
2118 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2121 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2122 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2125 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2126 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2127 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2129 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2130 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2133 g_return_if_reached ();
2137 gtk_widget_show_all (priv->contents_widget);
2140 ModestMainWindowContentsStyle
2141 modest_main_window_get_contents_style (ModestMainWindow *self)
2143 ModestMainWindowPrivate *priv;
2145 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2147 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2148 return priv->contents_style;
2153 on_configuration_key_changed (ModestConf* conf,
2155 ModestConfEvent event,
2156 ModestConfNotificationId id,
2157 ModestMainWindow *self)
2159 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2160 TnyAccount *account = NULL;
2162 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2165 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2168 if (priv->folder_view)
2169 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2171 if (account && TNY_IS_ACCOUNT (account) &&
2172 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2175 const gchar *device_name;
2176 gchar *new_text, *gray_color_markup;
2179 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2180 label = GTK_LABEL (children->data);
2182 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2183 MODEST_CONF_DEVICE_NAME, NULL);
2185 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2186 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2188 gtk_label_set_markup (label, new_text);
2189 gtk_widget_show (GTK_WIDGET (label));
2191 g_free (gray_color_markup);
2193 g_list_free (children);
2195 g_object_unref (account);
2199 set_toolbar_transfer_mode (ModestMainWindow *self)
2201 ModestMainWindowPrivate *priv = NULL;
2203 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2205 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2207 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2209 if (priv->progress_bar_timeout > 0) {
2210 g_source_remove (priv->progress_bar_timeout);
2211 priv->progress_bar_timeout = 0;
2218 set_toolbar_mode (ModestMainWindow *self,
2219 ModestToolBarModes mode)
2221 ModestWindowPrivate *parent_priv = NULL;
2222 ModestMainWindowPrivate *priv = NULL;
2223 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2225 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2227 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2228 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2230 /* In case this was called before the toolbar exists: */
2231 if (!(parent_priv->toolbar))
2234 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2236 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2237 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2238 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2240 /* Sets current toolbar mode */
2241 priv->current_toolbar_mode = mode;
2243 /* Checks the dimming rules */
2244 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2245 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2247 /* Show and hide toolbar items */
2249 case TOOLBAR_MODE_NORMAL:
2251 gtk_action_set_visible (sort_action, TRUE);
2253 gtk_action_set_visible (refresh_action, TRUE);
2254 if (priv->progress_toolitem) {
2255 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2256 gtk_widget_hide (priv->progress_toolitem);
2258 if (priv->progress_bar)
2259 gtk_widget_hide (priv->progress_bar);
2262 gtk_action_set_visible (cancel_action, FALSE);
2264 /* Hide toolbar if optimized view is enabled */
2265 if (priv->optimized_view)
2266 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2268 case TOOLBAR_MODE_TRANSFER:
2270 gtk_action_set_visible (sort_action, FALSE);
2272 gtk_action_set_visible (refresh_action, FALSE);
2274 gtk_action_set_visible (cancel_action, TRUE);
2275 if (priv->progress_bar)
2276 gtk_widget_show (priv->progress_bar);
2277 if (priv->progress_toolitem) {
2278 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2279 gtk_widget_show (priv->progress_toolitem);
2282 /* Show toolbar if it's hiden (optimized view ) */
2283 if (priv->optimized_view)
2284 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2287 g_return_if_reached ();
2292 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2294 ModestMainWindowPrivate *priv;
2296 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2297 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2299 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2303 cancel_progressbar (GtkToolButton *toolbutton,
2304 ModestMainWindow *self)
2307 ModestMainWindowPrivate *priv;
2309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2311 /* Get operation observers and cancel all the operations */
2312 tmp = priv->progress_widgets;
2314 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2315 tmp=g_slist_next(tmp);
2320 observers_empty (ModestMainWindow *self)
2323 ModestMainWindowPrivate *priv;
2324 gboolean is_empty = TRUE;
2325 guint pending_ops = 0;
2327 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2328 tmp = priv->progress_widgets;
2330 /* Check all observers */
2331 while (tmp && is_empty) {
2332 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2333 is_empty = pending_ops == 0;
2335 tmp = g_slist_next(tmp);
2343 * Gets the toolbar mode needed for each mail operation. It stores in
2344 * @mode_changed if the toolbar mode has changed or not
2346 static ModestToolBarModes
2347 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2348 ModestMailOperation *mail_op,
2349 gboolean *mode_changed)
2351 ModestToolBarModes mode;
2352 ModestMainWindowPrivate *priv;
2354 *mode_changed = FALSE;
2355 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2357 /* Get toolbar mode from operation id*/
2358 switch (modest_mail_operation_get_type_operation (mail_op)) {
2359 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2360 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2361 mode = TOOLBAR_MODE_TRANSFER;
2362 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2363 *mode_changed = TRUE;
2366 mode = TOOLBAR_MODE_NORMAL;
2372 on_mail_operation_started (ModestMailOperation *mail_op,
2375 ModestMainWindow *self;
2376 ModestMailOperationTypeOperation op_type;
2377 ModestMainWindowPrivate *priv;
2378 ModestToolBarModes mode;
2380 gboolean mode_changed = FALSE;
2381 TnyAccount *account = NULL;
2383 self = MODEST_MAIN_WINDOW (user_data);
2384 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2386 /* Do not show progress for receiving operations if the
2387 account is the local account or the MMC one */
2388 op_type = modest_mail_operation_get_type_operation (mail_op);
2389 account = modest_mail_operation_get_account (mail_op);
2390 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2393 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2394 modest_tny_account_is_memory_card_account (account));
2396 g_object_unref (account);
2400 /* Show information banner. Remove old timeout */
2401 if (priv->opening_banner_timeout > 0) {
2402 g_source_remove (priv->opening_banner_timeout);
2403 priv->opening_banner_timeout = 0;
2405 /* Create a new timeout */
2406 priv->opening_banner_timeout =
2407 g_timeout_add (2000, show_opening_banner, self);
2410 /* Not every mail operation has account, noop does not */
2412 g_object_unref (account);
2414 /* Get toolbar mode from operation id*/
2415 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2417 /* Add operation observers and change toolbar if neccessary*/
2418 tmp = priv->progress_widgets;
2419 if (mode == TOOLBAR_MODE_TRANSFER) {
2421 GObject *source = modest_mail_operation_get_source(mail_op);
2422 if (G_OBJECT (self) == source) {
2423 set_toolbar_transfer_mode(self);
2425 g_object_unref (source);
2429 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2431 tmp = g_slist_next (tmp);
2435 /* Update the main menu as well, we need to explicitely do
2436 this in order to enable/disable accelerators */
2437 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2441 on_mail_operation_finished (ModestMailOperation *mail_op,
2444 ModestToolBarModes mode;
2445 ModestMailOperationTypeOperation op_type;
2447 ModestMainWindow *self;
2448 gboolean mode_changed;
2449 TnyAccount *account = NULL;
2450 ModestMainWindowPrivate *priv;
2452 self = MODEST_MAIN_WINDOW (user_data);
2453 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2455 /* The mail operation was not added to the progress objects if
2456 the account was the local account or the MMC one */
2457 op_type = modest_mail_operation_get_type_operation (mail_op);
2458 account = modest_mail_operation_get_account (mail_op);
2459 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2462 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2463 modest_tny_account_is_memory_card_account (account));
2465 g_object_unref (account);
2469 /* Remove old timeout */
2470 if (priv->opening_banner_timeout > 0) {
2471 g_source_remove (priv->opening_banner_timeout);
2472 priv->opening_banner_timeout = 0;
2475 /* Remove the banner if exists */
2476 if (priv->opening_banner) {
2477 gtk_widget_destroy (priv->opening_banner);
2478 priv->opening_banner = NULL;
2482 /* Not every mail operation has account, noop does not */
2484 g_object_unref (account);
2486 /* Get toolbar mode from operation id*/
2487 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2489 /* Change toolbar mode */
2490 tmp = priv->progress_widgets;
2491 if (mode == TOOLBAR_MODE_TRANSFER) {
2493 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2495 tmp = g_slist_next (tmp);
2498 /* If no more operations are being observed, NORMAL mode is enabled again */
2499 if (observers_empty (self)) {
2500 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2506 on_queue_changed (ModestMailOperationQueue *queue,
2507 ModestMailOperation *mail_op,
2508 ModestMailOperationQueueNotification type,
2509 ModestMainWindow *self)
2511 ModestMainWindowPrivate *priv;
2513 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2515 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2516 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2518 "operation-started",
2519 G_CALLBACK (on_mail_operation_started),
2521 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2523 "operation-finished",
2524 G_CALLBACK (on_mail_operation_finished),
2526 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2527 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2529 "operation-started");
2530 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2532 "operation-finished");
2537 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2539 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2541 ModestAccountMgr *mgr;
2542 ModestAccountSettings *settings;
2543 ModestServerAccountSettings *store_settings = NULL;
2545 /* Get account data */
2546 mgr = modest_runtime_get_account_mgr ();
2547 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2549 store_settings = modest_account_settings_get_store_settings (settings);
2551 /* Set the new visible & active account */
2552 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2553 const gchar *account_name;
2555 account_name = modest_account_settings_get_account_name (settings);
2557 modest_folder_view_set_account_id_of_visible_server_account
2559 modest_server_account_settings_get_account_name (store_settings));
2560 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2561 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2563 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2564 if (action != NULL) {
2565 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2566 modest_utils_toggle_action_set_active_block_notify (
2567 GTK_TOGGLE_ACTION (action),
2575 g_object_unref (store_settings);
2576 g_object_unref (settings);
2580 /* Make sure that at least one account is "viewed": */
2582 set_at_least_one_account_visible(ModestMainWindow *self)
2584 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2585 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2587 if (!(priv->folder_view)) {
2588 /* It is too early to do this. */
2592 const gchar *active_server_account_name =
2593 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2595 if (!active_server_account_name ||
2596 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2598 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2599 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2600 if (default_modest_name) {
2601 set_account_visible (self, default_modest_name);
2602 } else if (first_modest_name) {
2603 set_account_visible (self, first_modest_name);
2605 g_free (first_modest_name);
2606 g_free (default_modest_name);
2611 on_show_account_action_toggled (GtkToggleAction *action,
2614 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2616 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2617 if (gtk_toggle_action_get_active (action))
2618 set_account_visible (self, acc_name);
2622 refresh_account (const gchar *account_name)
2626 /* win must already exists here, obviously */
2627 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2630 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2634 /* If account_name == NULL, we must update all (option All) */
2636 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2638 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2643 on_refresh_account_action_activated (GtkAction *action,
2646 refresh_account ((const gchar*) user_data);
2650 on_send_receive_csm_activated (GtkMenuItem *item,
2653 refresh_account ((const gchar*) user_data);
2657 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2659 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2661 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2667 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2669 ModestMainWindow *main_window = NULL;
2671 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2672 main_window = MODEST_MAIN_WINDOW (userdata);
2674 /* Update toolbar dimming state */
2675 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2676 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2682 on_header_view_focus_in (GtkWidget *widget,
2683 GdkEventFocus *event,
2686 ModestMainWindow *main_window = NULL;
2688 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2690 main_window = MODEST_MAIN_WINDOW (userdata);
2692 /* Update toolbar dimming state */
2693 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2694 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2700 on_folder_selection_changed (ModestFolderView *folder_view,
2701 TnyFolderStore *folder_store,
2703 ModestMainWindow *main_window)
2705 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2706 GtkAction *action = NULL;
2707 gboolean show_reply = TRUE;
2708 gboolean show_forward = TRUE;
2709 gboolean show_cancel_send = FALSE;
2710 gboolean show_clipboard = TRUE;
2711 gboolean show_delete = TRUE;
2714 if (TNY_IS_ACCOUNT (folder_store)) {
2715 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2716 } else if (TNY_IS_FOLDER (folder_store)) {
2717 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2718 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2719 TNY_FOLDER (folder_store));
2720 switch (folder_type) {
2721 case TNY_FOLDER_TYPE_DRAFTS:
2722 show_clipboard = show_delete = TRUE;
2723 show_reply = show_forward = show_cancel_send = FALSE;
2725 case TNY_FOLDER_TYPE_SENT:
2726 show_forward = show_clipboard = show_delete = TRUE;
2727 show_reply = show_cancel_send = FALSE;
2729 case TNY_FOLDER_TYPE_OUTBOX:
2730 show_clipboard = show_delete = show_cancel_send = TRUE;
2731 show_reply = show_forward = FALSE;
2733 case TNY_FOLDER_TYPE_INVALID:
2734 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2737 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2738 show_cancel_send = FALSE;
2741 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2742 show_cancel_send = FALSE;
2747 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2748 gtk_action_set_visible (action, show_reply);
2749 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2750 gtk_action_set_visible (action, show_reply);
2751 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2752 gtk_action_set_visible (action, show_forward);
2753 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2754 gtk_action_set_visible (action, show_cancel_send);
2755 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2756 gtk_action_set_visible (action, show_delete);
2758 /* We finally call to the ui actions handler, after updating properly
2759 * the header view CSM */
2760 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2764 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2765 GtkTreeModel *model,
2766 GtkTreeRowReference *row_reference,
2767 ModestMainWindow *self)
2769 ModestMainWindowPrivate *priv = NULL;
2770 GtkTreeModel *header_model = NULL;
2771 GtkTreePath *path = NULL;
2773 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2774 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2775 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2777 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2778 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2780 /* Do nothing if we changed the folder in the main view */
2781 if (header_model != model)
2784 /* Select the message in the header view */
2785 path = gtk_tree_row_reference_get_path (row_reference);
2786 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2788 gtk_tree_path_free (path);
2794 updating_banner_destroyed (gpointer data,
2795 GObject *where_the_object_was)
2797 ModestMainWindowPrivate *priv = NULL;
2799 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2801 priv->updating_banner = NULL;
2805 show_updating_banner (gpointer user_data)
2807 ModestMainWindowPrivate *priv = NULL;
2809 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2811 if (priv->updating_banner == NULL) {
2813 /* We're outside the main lock */
2814 gdk_threads_enter ();
2815 priv->updating_banner =
2816 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2817 _CS ("ckdg_pb_updating"));
2819 /* We need this because banners in Maemo could be
2820 destroyed by dialogs so we need to properly update
2821 our reference to it */
2822 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2823 updating_banner_destroyed,
2825 gdk_threads_leave ();
2828 /* Remove timeout */
2829 priv->updating_banner_timeout = 0;
2834 * We use this function to show/hide a progress banner showing
2835 * "Updating" while the header view is being filled. We're not showing
2836 * it unless the update takes more than 2 seconds
2838 * If starting = TRUE then the refresh is starting, otherwise it means
2839 * that is has just finished
2842 on_updating_msg_list (ModestHeaderView *header_view,
2846 ModestMainWindowPrivate *priv = NULL;
2848 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2850 /* Remove old timeout */
2851 if (priv->updating_banner_timeout > 0) {
2852 g_source_remove (priv->updating_banner_timeout);
2853 priv->updating_banner_timeout = 0;
2856 /* Create a new timeout */
2858 priv->updating_banner_timeout =
2859 g_timeout_add (2000, show_updating_banner, user_data);
2861 /* Remove the banner if exists */
2862 if (priv->updating_banner) {
2863 gtk_widget_destroy (priv->updating_banner);
2864 priv->updating_banner = NULL;
2870 modest_main_window_screen_is_on (ModestMainWindow *self)
2872 ModestMainWindowPrivate *priv = NULL;
2874 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2876 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2878 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2882 remove_banners (ModestMainWindow *window)
2884 ModestMainWindowPrivate *priv;
2886 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2888 if (priv->opening_banner_timeout > 0) {
2889 g_source_remove (priv->opening_banner_timeout);
2890 priv->opening_banner_timeout = 0;
2893 if (priv->opening_banner != NULL) {
2894 gtk_widget_destroy (priv->opening_banner);
2895 priv->opening_banner = NULL;
2898 if (priv->updating_banner_timeout > 0) {
2899 g_source_remove (priv->updating_banner_timeout);
2900 priv->updating_banner_timeout = 0;
2903 if (priv->updating_banner != NULL) {
2904 gtk_widget_destroy (priv->updating_banner);
2905 priv->updating_banner = NULL;
2911 on_window_hide (GObject *gobject,
2915 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2917 if (!GTK_WIDGET_VISIBLE (gobject)) {
2918 TnyFolderStore *folder_store;
2919 ModestMainWindowPrivate *priv;
2921 /* Remove the currently shown banners */
2922 remove_banners (MODEST_MAIN_WINDOW (gobject));
2924 /* Force the folder view to sync the currently selected folder
2925 to save the read/unread status and to expunge messages */
2926 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2927 folder_store = modest_folder_view_get_selected (priv->folder_view);
2928 if (TNY_IS_FOLDER (folder_store)) {
2929 ModestMailOperation *mail_op;
2931 mail_op = modest_mail_operation_new (NULL);
2932 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2934 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2935 g_object_unref (mail_op);
2936 g_object_unref (folder_store);
2942 on_window_destroy (GtkObject *widget,
2945 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2947 remove_banners (MODEST_MAIN_WINDOW (widget));
2951 opening_banner_destroyed (gpointer data,
2952 GObject *where_the_object_was)
2954 ModestMainWindowPrivate *priv = NULL;
2956 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2958 priv->opening_banner = NULL;
2962 show_opening_banner (gpointer user_data)
2964 ModestMainWindowPrivate *priv = NULL;
2966 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2968 if (priv->opening_banner == NULL) {
2970 /* We're outside the main lock */
2971 gdk_threads_enter ();
2972 priv->opening_banner =
2973 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2974 _("mail_me_opening"));
2976 /* We need this because banners in Maemo could be
2977 destroyed by dialogs so we need to properly update
2978 our reference to it */
2979 g_object_weak_ref (G_OBJECT (priv->opening_banner),
2980 opening_banner_destroyed,
2983 /* We need this because banners in Maemo could be
2984 destroyed by dialogs so we need to properly update
2985 our reference to it */
2986 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2987 updating_banner_destroyed,
2989 gdk_threads_leave ();
2992 /* Remove timeout */
2993 priv->opening_banner_timeout = 0;