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 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
903 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
906 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
910 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
912 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
914 /* Update visibility */
917 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
921 modest_main_window_disconnect_signals (ModestWindow *self)
923 ModestMainWindowPrivate *priv;
924 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
926 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
927 priv->sighandlers = NULL;
931 connect_signals (ModestMainWindow *self)
933 ModestWindowPrivate *parent_priv;
934 ModestMainWindowPrivate *priv;
937 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
938 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
943 modest_signal_mgr_connect (priv->sighandlers,
944 G_OBJECT(priv->folder_view), "key-press-event",
945 G_CALLBACK(on_inner_widgets_key_pressed), self);
947 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
948 "folder_selection_changed",
949 G_CALLBACK (on_folder_selection_changed),
952 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
953 "folder-display-name-changed",
954 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
957 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
959 G_CALLBACK (on_folder_view_focus_in),
962 /* Folder view CSM */
963 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
964 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
965 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
966 G_CALLBACK(_folder_view_csm_menu_activated),
970 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
971 G_CALLBACK(modest_ui_actions_on_header_selected), self);
973 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
974 G_CALLBACK(modest_ui_actions_on_header_activated), self);
976 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
977 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
979 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
980 G_CALLBACK(on_inner_widgets_key_pressed), self);
982 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
983 G_CALLBACK(on_msg_count_changed), self);
985 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
986 G_CALLBACK (on_header_view_focus_in), self);
988 modest_signal_mgr_connect (priv->sighandlers,
989 G_OBJECT (priv->header_view),
991 G_CALLBACK (on_updating_msg_list),
994 /* Header view CSM */
995 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
996 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
998 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
999 G_CALLBACK(_header_view_csm_menu_activated),
1003 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1004 * in destroy stage */
1005 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1007 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1009 /* Mail Operation Queue */
1011 modest_signal_mgr_connect (priv->sighandlers,
1012 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1014 G_CALLBACK (on_queue_changed), self);
1016 /* Track changes in the device name */
1018 modest_signal_mgr_connect (priv->sighandlers,
1019 G_OBJECT(modest_runtime_get_conf ()),
1021 G_CALLBACK (on_configuration_key_changed),
1024 /* Track account changes. We need to refresh the toolbar */
1026 modest_signal_mgr_connect (priv->sighandlers,
1027 G_OBJECT (modest_runtime_get_account_store ()),
1029 G_CALLBACK (on_account_inserted),
1032 modest_signal_mgr_connect (priv->sighandlers,
1033 G_OBJECT (modest_runtime_get_account_store ()),
1035 G_CALLBACK (on_account_removed),
1038 /* We need to refresh the send & receive menu to change the bold
1039 * account when the default account changes. */
1041 modest_signal_mgr_connect (priv->sighandlers,
1042 G_OBJECT (modest_runtime_get_account_mgr ()),
1043 "default_account_changed",
1044 G_CALLBACK (on_default_account_changed),
1049 modest_signal_mgr_connect (priv->sighandlers,
1050 G_OBJECT (modest_runtime_get_account_store ()),
1052 G_CALLBACK (on_account_changed),
1057 on_hildon_program_is_topmost_notify(GObject *self,
1058 GParamSpec *propert_param,
1061 HildonProgram *app = HILDON_PROGRAM (self);
1063 /* Note that use of hildon_program_set_can_hibernate()
1064 * is generally referred to as "setting the killable flag",
1065 * though hibernation does not seem equal to death.
1068 if (hildon_program_get_is_topmost (app)) {
1069 /* Prevent hibernation when the progam comes to the foreground,
1070 * because hibernation should only happen when the application
1071 * is in the background: */
1072 hildon_program_set_can_hibernate (app, FALSE);
1074 /* Remove new mail visual notifications */
1075 modest_platform_remove_new_mail_notifications (TRUE);
1077 /* Allow hibernation if the program has gone to the background: */
1079 /* However, prevent hibernation while the settings are being changed: */
1080 const gboolean hibernation_prevented =
1081 modest_window_mgr_get_hibernation_is_prevented (
1082 modest_runtime_get_window_mgr ());
1084 if (hibernation_prevented)
1085 hildon_program_set_can_hibernate (app, FALSE);
1087 /* Allow hibernation, after saving the state: */
1088 modest_osso_save_state();
1089 hildon_program_set_can_hibernate (app, TRUE);
1096 GtkWidget *folder_win;
1101 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1103 ShowHelper *helper = (ShowHelper *) user_data;
1104 GtkWidget *folder_win = helper->folder_win;
1105 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1107 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1108 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1110 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1112 /* Connect signals */
1113 connect_signals (MODEST_MAIN_WINDOW (self));
1115 /* Set account store */
1116 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1117 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1119 /* Load previous osso state, for instance if we are being restored from
1121 modest_osso_load_state ();
1123 /* Restore window & widget settings */
1124 priv->wait_for_settings = TRUE;
1125 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1126 priv->wait_for_settings = FALSE;
1128 /* Check if accounts exist and show the account wizard if not */
1129 gboolean accounts_exist =
1130 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1132 if (!accounts_exist) {
1133 /* This is necessary to have the main window shown behind the dialog
1134 It's an ugly hack... jschmid */
1135 gtk_widget_show_all(GTK_WIDGET(self));
1136 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1138 update_menus (MODEST_MAIN_WINDOW (self));
1141 /* Never call this function again (NOTE that it could happen
1142 as we hide the main window instead of closing it while
1143 there are operations ongoing) and free the helper */
1144 g_signal_handler_disconnect (self, helper->handler_id);
1145 g_slice_free (ShowHelper, helper);
1149 osso_display_event_cb (osso_display_state_t state,
1152 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1154 priv->display_state = state;
1156 /* Stop blinking if the screen becomes on */
1157 if (priv->display_state == OSSO_DISPLAY_ON)
1158 modest_platform_remove_new_mail_notifications (TRUE);
1162 modest_main_window_new (void)
1164 ModestMainWindow *self = NULL;
1165 ModestMainWindowPrivate *priv = NULL;
1166 ModestWindowPrivate *parent_priv = NULL;
1167 GtkWidget *folder_win = NULL;
1168 ModestDimmingRulesGroup *menu_rules_group = NULL;
1169 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1170 GtkActionGroup *action_group = NULL;
1171 GError *error = NULL;
1173 GdkPixbuf *window_icon;
1176 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1177 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1178 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1180 parent_priv->ui_manager = gtk_ui_manager_new();
1181 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1183 action_group = gtk_action_group_new ("ModestMainWindowActions");
1184 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1186 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1187 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1189 /* Add common actions */
1190 gtk_action_group_add_actions (action_group,
1191 modest_action_entries,
1192 G_N_ELEMENTS (modest_action_entries),
1195 gtk_action_group_add_actions (action_group,
1196 modest_folder_view_action_entries,
1197 G_N_ELEMENTS (modest_folder_view_action_entries),
1200 gtk_action_group_add_actions (action_group,
1201 modest_header_view_action_entries,
1202 G_N_ELEMENTS (modest_header_view_action_entries),
1205 gtk_action_group_add_toggle_actions (action_group,
1206 modest_main_window_toggle_action_entries,
1207 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1210 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1211 g_object_unref (action_group);
1213 /* Load the UI definition */
1214 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1215 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1216 if (error != NULL) {
1217 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1218 g_error_free (error);
1222 /* Add common dimming rules */
1223 modest_dimming_rules_group_add_rules (menu_rules_group,
1224 modest_main_window_menu_dimming_entries,
1225 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1226 MODEST_WINDOW (self));
1227 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1228 modest_main_window_toolbar_dimming_entries,
1229 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1230 MODEST_WINDOW (self));
1232 /* Insert dimming rules group for this window */
1233 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1234 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1235 g_object_unref (menu_rules_group);
1236 g_object_unref (toolbar_rules_group);
1238 /* Add accelerators */
1239 gtk_window_add_accel_group (GTK_WINDOW (self),
1240 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1242 /* Menubar. Update the state of some toggles */
1243 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1244 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1245 gtk_widget_show (parent_priv->menubar);
1247 /* Get device name */
1248 modest_maemo_utils_get_device_name ();
1252 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1253 g_object_ref (priv->header_view);
1254 if (!priv->header_view)
1255 g_printerr ("modest: cannot instantiate header view\n");
1256 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1257 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1258 MODEST_CONF_HEADER_VIEW_KEY);
1260 /* Other style properties of header view */
1261 g_object_set (G_OBJECT (priv->header_view),
1262 "rules-hint", FALSE,
1264 /* gtk_widget_show (priv->header_view); */
1267 priv->empty_view = create_empty_view ();
1268 gtk_widget_show (priv->empty_view);
1269 g_object_ref (priv->empty_view);
1271 /* Create scrolled windows */
1272 folder_win = gtk_scrolled_window_new (NULL, NULL);
1273 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1274 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1276 GTK_POLICY_AUTOMATIC);
1277 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1279 GTK_POLICY_AUTOMATIC);
1280 /* gtk_widget_show (priv->contents_widget); */
1283 priv->main_paned = gtk_hpaned_new ();
1284 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1285 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1286 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1288 /* putting it all together... */
1289 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1290 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1291 gtk_widget_show (priv->main_vbox);
1293 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1295 app = hildon_program_get_instance ();
1296 hildon_program_add_window (app, HILDON_WINDOW (self));
1298 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1299 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1301 /* Connect to "show" action. We delay the creation of some
1302 elements until that moment */
1303 helper = g_slice_new0 (ShowHelper);
1304 helper->folder_win = folder_win;
1305 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1306 G_CALLBACK (modest_main_window_on_show),
1309 /* Set window icon */
1310 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1312 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1313 g_object_unref (window_icon);
1316 /* Listen for changes in the screen, we don't want to show a
1317 led pattern when the display is on for example */
1318 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1319 osso_display_event_cb,
1322 /* Dont't restore settings here,
1323 * because it requires a gtk_widget_show(),
1324 * and we don't want to do that until later,
1325 * so that the UI is not visible for non-menu D-Bus activation.
1328 return MODEST_WINDOW(self);
1332 modest_main_window_set_style (ModestMainWindow *self,
1333 ModestMainWindowStyle style)
1335 ModestMainWindowPrivate *priv;
1336 ModestWindowPrivate *parent_priv;
1339 GtkTreeSelection *sel;
1342 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1344 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1345 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1347 /* no change -> nothing to do */
1348 if (priv->style == style)
1351 /* Get toggle button and update the state if needed. This will
1352 happen only when the set_style is not invoked from the UI,
1353 for example when it's called from widget memory */
1354 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1355 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1356 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1357 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1358 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1359 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1360 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1363 /* We need to store the selection because it's lost when the
1364 widget is reparented */
1365 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1366 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1368 priv->style = style;
1370 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1372 if (!priv->wait_for_settings)
1373 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1374 MODEST_CONF_MAIN_PANED_KEY);
1375 /* Remove main paned */
1376 g_object_ref (priv->main_paned);
1377 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1379 /* Reparent the contents widget to the main vbox */
1380 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1383 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1384 /* Remove header view */
1385 g_object_ref (priv->contents_widget);
1386 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1388 /* Reparent the main paned */
1389 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1390 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1392 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1396 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1398 g_return_if_reached ();
1401 /* Reselect the previously selected folders. We disable the
1402 dimming rules execution during that time because there is
1403 no need to work out it again and it could take a lot of
1404 time if all the headers are selected */
1406 modest_window_disable_dimming (MODEST_WINDOW (self));
1408 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1409 list = g_list_next (list);
1411 modest_window_enable_dimming (MODEST_WINDOW (self));
1414 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1417 /* Let header view grab the focus if it's being shown */
1418 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1419 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1421 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1422 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1424 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1427 /* Check dimming rules */
1428 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1429 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1432 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1435 ModestMainWindowStyle
1436 modest_main_window_get_style (ModestMainWindow *self)
1438 ModestMainWindowPrivate *priv;
1440 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1442 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1447 toolbar_resize (ModestMainWindow *self)
1449 ModestMainWindowPrivate *priv = NULL;
1450 ModestWindowPrivate *parent_priv = NULL;
1452 gint static_button_size;
1453 ModestWindowMgr *mgr;
1455 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1456 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1457 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1459 mgr = modest_runtime_get_window_mgr ();
1460 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1462 if (parent_priv->toolbar) {
1463 /* left size buttons */
1464 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1467 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1468 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1469 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1470 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1471 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1472 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1475 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1476 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1477 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1478 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1479 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1482 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1483 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1484 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1485 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1486 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1487 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1488 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1494 modest_main_window_show_toolbar (ModestWindow *self,
1495 gboolean show_toolbar)
1497 ModestMainWindowPrivate *priv = NULL;
1498 ModestWindowPrivate *parent_priv = NULL;
1499 GtkWidget *reply_button = NULL, *menu = NULL;
1500 GtkWidget *placeholder = NULL;
1503 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1504 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1505 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1507 /* Set optimized view status */
1508 priv->optimized_view = !show_toolbar;
1510 if (!parent_priv->toolbar) {
1511 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1513 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1515 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1516 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1517 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1518 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1519 toolbar_resize (MODEST_MAIN_WINDOW (self));
1521 /* Add ProgressBar (Transfer toolbar) */
1522 priv->progress_bar = modest_progress_bar_new ();
1523 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1524 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1525 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1526 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1527 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1529 /* Connect cancel 'clicked' signal to abort progress mode */
1530 g_signal_connect(priv->cancel_toolitem, "clicked",
1531 G_CALLBACK(cancel_progressbar),
1534 /* Add it to the observers list */
1535 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1538 hildon_window_add_toolbar (HILDON_WINDOW (self),
1539 GTK_TOOLBAR (parent_priv->toolbar));
1541 /* Set reply button tap and hold menu */
1542 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1543 "/ToolBar/ToolbarMessageReply");
1544 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1545 "/ToolbarReplyCSM");
1546 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1548 /* Set send & receive button tap and hold menu */
1549 update_menus (MODEST_MAIN_WINDOW (self));
1553 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1554 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1555 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1557 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1558 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1559 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1561 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1563 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1569 on_account_inserted (TnyAccountStore *accoust_store,
1570 TnyAccount *account,
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 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1578 update_menus (MODEST_MAIN_WINDOW (user_data));
1583 on_default_account_changed (ModestAccountMgr* mgr,
1586 update_menus (MODEST_MAIN_WINDOW (user_data));
1590 on_account_removed (TnyAccountStore *accoust_store,
1591 TnyAccount *account,
1594 /* Transport accounts and local ones (MMC and the Local
1595 folders account do now cause menu changes */
1596 if (TNY_IS_STORE_ACCOUNT (account) &&
1597 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1598 update_menus (MODEST_MAIN_WINDOW (user_data));
1602 on_account_changed (TnyAccountStore *account_store,
1603 TnyAccount *account,
1606 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1608 /* Transport accounts and local ones (MMC and the Local
1609 folders account do now cause menu changes */
1610 if (TNY_IS_STORE_ACCOUNT (account)) {
1611 /* We need to refresh the details widget because it could have changed */
1612 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1613 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1615 /* Update the menus as well, name could change */
1616 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1617 update_menus (MODEST_MAIN_WINDOW (user_data));
1622 * This function manages the key events used to navigate between
1623 * header and folder views (when the window is in split view)
1626 * -------------------------------------------------
1627 * HeaderView GDK_Left Move focus to folder view
1628 * FolderView GDK_Right Move focus to header view
1630 * There is no need to scroll to selected row, the widgets will be the
1631 * responsibles of doing that (probably managing the focus-in event
1634 on_inner_widgets_key_pressed (GtkWidget *widget,
1638 ModestMainWindowPrivate *priv;
1640 if (event->type == GDK_KEY_RELEASE)
1643 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1645 /* Do nothing if we're in SIMPLE style */
1646 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1649 if (MODEST_IS_HEADER_VIEW (widget)) {
1650 if (event->keyval == GDK_Left)
1651 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1652 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1653 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1654 if (selected_headers > 1) {
1655 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1658 GtkTreePath * cursor_path;
1659 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1660 if (cursor_path == NULL) {
1661 GtkTreeSelection *selection;
1663 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1664 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1667 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1668 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1673 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1674 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1675 GtkTreePath *selected_path = NULL;
1676 GtkTreePath *start_path = NULL;
1677 GtkTreePath *end_path = NULL;
1679 GtkTreeSelection *selection;
1681 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1682 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1683 if (selected != NULL) {
1684 selected_path = (GtkTreePath *) selected->data;
1685 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1689 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1690 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1692 /* Scroll to first path */
1693 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1702 gtk_tree_path_free (start_path);
1704 gtk_tree_path_free (end_path);
1705 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1706 g_list_free (selected);
1708 #endif /* GTK_CHECK_VERSION */
1710 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1717 set_alignment (GtkWidget *widget,
1720 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1721 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1725 create_empty_view (void)
1727 GtkLabel *label = NULL;
1728 GtkWidget *align = NULL;
1730 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1731 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1732 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1733 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1735 return GTK_WIDGET(align);
1739 * Free the returned string
1742 get_gray_color_markup (GtkWidget *styled_widget)
1744 gchar *gray_color_markup = NULL;
1745 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1746 /* Obtain the secondary text color. We need a realized widget, that's why
1747 we get styled_widget from outside */
1749 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1750 gray_color_markup = modest_text_utils_get_color_string (&color);
1751 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1753 if (!gray_color_markup)
1754 gray_color_markup = g_strdup ("#BBBBBB");
1756 return gray_color_markup;
1760 * Free the returned string
1763 create_device_name_visual_string (const gchar *device_name,
1764 const gchar *gray_color_markup)
1768 /* We have to use "" to fill the %s of the translation. We can
1769 not just use the device name because the device name is
1770 shown in a different color, so it could not be included
1771 into the <span> tag */
1772 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1773 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1784 GtkWidget *count_label;
1785 GtkWidget *msg_count_label;
1786 GtkWidget *size_label;
1787 gchar *color_markup;
1791 create_uint_label (const gchar *markup,
1795 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1799 create_gchar_label (const gchar *markup,
1803 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1807 update_folder_stats_status_cb (ModestFolderStats stats,
1810 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1813 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1814 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1817 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1818 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1821 if (widgets->size_label) {
1822 tmp = modest_text_utils_get_display_size (stats.local_size);
1823 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1824 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1831 update_folder_stats_cb (ModestFolderStats stats,
1834 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1837 update_folder_stats_status_cb (stats, user_data);
1839 /* frees. Note that the widgets could have been destroyed but
1840 we still keep a reference */
1841 g_free (widgets->color_markup);
1842 if (widgets->count_label)
1843 g_object_unref (widgets->count_label);
1844 if (widgets->msg_count_label)
1845 g_object_unref (widgets->msg_count_label);
1846 if (widgets->size_label)
1847 g_object_unref (widgets->size_label);
1848 g_slice_free (DetailsWidgets, widgets);
1852 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1854 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1859 gchar *gray_color_markup;
1860 DetailsWidgets *widgets;
1862 vbox = gtk_vbox_new (FALSE, 0);
1863 widgets = g_slice_new0 (DetailsWidgets);
1865 gray_color_markup = get_gray_color_markup (styled_widget);
1866 widgets->color_markup = g_strdup (gray_color_markup);
1868 /* Account description: */
1869 if (modest_tny_account_is_virtual_local_folders (account)
1870 || (modest_tny_account_is_memory_card_account (account))) {
1872 /* Get device name */
1873 gchar *device_name = NULL;
1874 if (modest_tny_account_is_virtual_local_folders (account))
1875 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1876 MODEST_CONF_DEVICE_NAME, NULL);
1878 device_name = g_strdup (tny_account_get_name (account));
1880 label = create_device_name_visual_string ((const gchar *) device_name,
1881 (const gchar *) gray_color_markup);
1882 label_w = gtk_label_new (NULL);
1883 gtk_label_set_markup (GTK_LABEL (label_w), label);
1884 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1885 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1886 g_free (device_name);
1889 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1890 gtk_box_pack_start (GTK_BOX (vbox),
1891 gtk_label_new (tny_account_get_name (account)),
1894 /* Other accounts, such as IMAP and POP: */
1899 /* Put proto in uppercase */
1900 proto = g_string_new (tny_account_get_proto (account));
1901 proto = g_string_ascii_up (proto);
1903 /* note: mcen_fi_localroot_description is something like "%s account"
1904 * however, we should display "%s account: %s"... therefore, ugly tmp */
1905 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1906 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1907 gray_color_markup, tmp, tny_account_get_name (account));
1910 label_w = gtk_label_new (NULL);
1911 gtk_label_set_markup (GTK_LABEL (label_w), label);
1912 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1913 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1914 g_string_free (proto, TRUE);
1920 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1921 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1922 label_w = gtk_label_new (NULL);
1923 gtk_label_set_markup (GTK_LABEL (label_w), label);
1924 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1925 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1928 widgets->msg_count_label = g_object_ref (label_w);
1931 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1932 label_w = gtk_label_new (NULL);
1933 gtk_label_set_markup (GTK_LABEL (label_w), label);
1934 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1935 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1938 widgets->count_label = g_object_ref (label_w);
1941 if (modest_tny_account_is_virtual_local_folders (account)
1942 || modest_tny_account_is_memory_card_account (account)) {
1944 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1946 label_w = gtk_label_new (NULL);
1947 gtk_label_set_markup (GTK_LABEL (label_w), label);
1948 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1949 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1952 widgets->size_label = g_object_ref (label_w);
1954 } else if (TNY_IS_ACCOUNT(folder_store)) {
1955 TnyAccount *account = TNY_ACCOUNT(folder_store);
1957 time_t last_updated;
1958 const gchar *last_updated_string;
1959 /* Get last updated from configuration */
1960 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1961 tny_account_get_id (account));
1963 if (last_updated > 0)
1964 last_updated_string = modest_text_utils_get_display_date(last_updated);
1966 last_updated_string = g_strdup (_("mcen_va_never"));
1968 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1969 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1970 label_w = gtk_label_new (NULL);
1971 gtk_label_set_markup (GTK_LABEL (label_w), label);
1972 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1973 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1977 g_free (gray_color_markup);
1979 /* Refresh folder stats asynchronously */
1980 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1981 update_folder_stats_cb,
1982 update_folder_stats_status_cb,
1986 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1992 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1994 ModestMainWindowPrivate *priv = NULL;
1996 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1998 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2000 return priv->send_receive_in_progress;
2004 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2006 GtkAction *action = NULL;
2007 GtkWidget *widget = NULL;
2008 ModestMainWindowPrivate *priv = NULL;
2010 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2011 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2013 priv->send_receive_in_progress = TRUE;
2015 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2016 gtk_action_set_sensitive (action, FALSE);
2017 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2018 /* gtk_action_set_sensitive (action, FALSE); */
2019 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2020 gtk_widget_set_sensitive (widget, FALSE);
2024 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2026 GtkAction *action = NULL;
2027 GtkWidget *widget = NULL;
2028 ModestMainWindowPrivate *priv = NULL;
2030 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2031 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2033 priv->send_receive_in_progress = FALSE;
2035 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2036 gtk_action_set_sensitive (action, TRUE);
2037 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2038 /* gtk_action_set_sensitive (action, TRUE); */
2039 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2040 gtk_widget_set_sensitive (widget, TRUE);
2045 on_msg_count_changed (ModestHeaderView *header_view,
2047 TnyFolderChange *change,
2048 ModestMainWindow *main_window)
2050 gboolean refilter = FALSE;
2051 gboolean folder_empty = FALSE;
2052 gboolean all_marked_as_deleted = FALSE;
2053 ModestMainWindowPrivate *priv;
2055 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2056 g_return_if_fail (TNY_IS_FOLDER(folder));
2057 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2059 if (change != NULL) {
2060 TnyFolderChangeChanged changed;
2062 changed = tny_folder_change_get_changed (change);
2063 /* If something changes */
2064 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2065 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2067 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2069 /* Play a sound (if configured) and make the LED blink */
2070 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2071 modest_platform_push_email_notification ();
2074 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2077 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2080 /* Check if all messages are marked to be deleted */
2081 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2082 folder_empty = folder_empty || all_marked_as_deleted;
2084 /* Set contents style of headers view */
2086 modest_main_window_set_contents_style (main_window,
2087 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2088 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2090 modest_main_window_set_contents_style (main_window,
2091 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2095 modest_header_view_refilter (header_view);
2100 modest_main_window_set_contents_style (ModestMainWindow *self,
2101 ModestMainWindowContentsStyle style)
2103 ModestMainWindowPrivate *priv;
2105 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2107 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2109 /* We allow to set the same content style than the previously
2110 set if there are details, because it could happen when we're
2111 selecting different accounts consecutively */
2112 if ((priv->contents_style == style) &&
2113 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2116 /* Remove previous child. Delete it if it was an account
2118 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2120 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2121 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2124 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2127 priv->contents_style = style;
2129 switch (priv->contents_style) {
2130 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2131 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2132 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2134 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2135 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2137 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2139 /* if we're started without main win, there may not be a folder
2140 * view. this fixes a GLib-Critical */
2141 if (priv->folder_view) {
2142 TnyFolderStore *selected_folderstore =
2143 modest_folder_view_get_selected (priv->folder_view);
2144 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2145 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2146 TNY_ACCOUNT (selected_folderstore));
2148 wrap_in_scrolled_window (priv->contents_widget,
2149 priv->details_widget);
2151 if (selected_folderstore)
2152 g_object_unref (selected_folderstore);
2153 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2156 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2157 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2160 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2161 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2162 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2164 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2165 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2168 g_return_if_reached ();
2172 gtk_widget_show_all (priv->contents_widget);
2175 ModestMainWindowContentsStyle
2176 modest_main_window_get_contents_style (ModestMainWindow *self)
2178 ModestMainWindowPrivate *priv;
2180 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2182 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2183 return priv->contents_style;
2188 on_configuration_key_changed (ModestConf* conf,
2190 ModestConfEvent event,
2191 ModestConfNotificationId id,
2192 ModestMainWindow *self)
2194 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2195 TnyAccount *account = NULL;
2197 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2200 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2203 if (priv->folder_view)
2204 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2206 if (account && TNY_IS_ACCOUNT (account) &&
2207 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2210 const gchar *device_name;
2211 gchar *new_text, *gray_color_markup;
2214 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2215 label = GTK_LABEL (children->data);
2217 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2218 MODEST_CONF_DEVICE_NAME, NULL);
2220 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2221 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2223 gtk_label_set_markup (label, new_text);
2224 gtk_widget_show (GTK_WIDGET (label));
2226 g_free (gray_color_markup);
2228 g_list_free (children);
2230 g_object_unref (account);
2234 set_toolbar_transfer_mode (ModestMainWindow *self)
2236 ModestMainWindowPrivate *priv = NULL;
2238 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2240 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2242 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2244 if (priv->progress_bar_timeout > 0) {
2245 g_source_remove (priv->progress_bar_timeout);
2246 priv->progress_bar_timeout = 0;
2253 set_toolbar_mode (ModestMainWindow *self,
2254 ModestToolBarModes mode)
2256 ModestWindowPrivate *parent_priv = NULL;
2257 ModestMainWindowPrivate *priv = NULL;
2258 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2260 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2262 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2263 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2265 /* In case this was called before the toolbar exists: */
2266 if (!(parent_priv->toolbar))
2269 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2271 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2272 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2273 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2275 /* Sets current toolbar mode */
2276 priv->current_toolbar_mode = mode;
2278 /* Checks the dimming rules */
2279 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2280 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2282 /* Show and hide toolbar items */
2284 case TOOLBAR_MODE_NORMAL:
2286 gtk_action_set_visible (sort_action, TRUE);
2288 gtk_action_set_visible (refresh_action, TRUE);
2289 if (priv->progress_toolitem) {
2290 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2291 gtk_widget_hide (priv->progress_toolitem);
2293 if (priv->progress_bar)
2294 gtk_widget_hide (priv->progress_bar);
2297 gtk_action_set_visible (cancel_action, FALSE);
2299 /* Hide toolbar if optimized view is enabled */
2300 if (priv->optimized_view)
2301 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2303 case TOOLBAR_MODE_TRANSFER:
2305 gtk_action_set_visible (sort_action, FALSE);
2307 gtk_action_set_visible (refresh_action, FALSE);
2309 gtk_action_set_visible (cancel_action, TRUE);
2310 if (priv->progress_bar)
2311 gtk_widget_show (priv->progress_bar);
2312 if (priv->progress_toolitem) {
2313 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2314 gtk_widget_show (priv->progress_toolitem);
2317 /* Show toolbar if it's hiden (optimized view ) */
2318 if (priv->optimized_view)
2319 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2322 g_return_if_reached ();
2327 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2329 ModestMainWindowPrivate *priv;
2331 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2332 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2334 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2338 cancel_progressbar (GtkToolButton *toolbutton,
2339 ModestMainWindow *self)
2342 ModestMainWindowPrivate *priv;
2344 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2346 /* Get operation observers and cancel all the operations */
2347 tmp = priv->progress_widgets;
2349 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2350 tmp=g_slist_next(tmp);
2355 observers_empty (ModestMainWindow *self)
2358 ModestMainWindowPrivate *priv;
2359 gboolean is_empty = TRUE;
2360 guint pending_ops = 0;
2362 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2363 tmp = priv->progress_widgets;
2365 /* Check all observers */
2366 while (tmp && is_empty) {
2367 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2368 is_empty = pending_ops == 0;
2370 tmp = g_slist_next(tmp);
2378 * Gets the toolbar mode needed for each mail operation. It stores in
2379 * @mode_changed if the toolbar mode has changed or not
2381 static ModestToolBarModes
2382 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2383 ModestMailOperation *mail_op,
2384 gboolean *mode_changed)
2386 ModestToolBarModes mode;
2387 ModestMainWindowPrivate *priv;
2389 *mode_changed = FALSE;
2390 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2392 /* Get toolbar mode from operation id*/
2393 switch (modest_mail_operation_get_type_operation (mail_op)) {
2394 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2395 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2396 mode = TOOLBAR_MODE_TRANSFER;
2397 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2398 *mode_changed = TRUE;
2401 mode = TOOLBAR_MODE_NORMAL;
2407 on_mail_operation_started (ModestMailOperation *mail_op,
2410 ModestMainWindow *self;
2411 ModestMailOperationTypeOperation op_type;
2412 ModestMainWindowPrivate *priv;
2413 ModestToolBarModes mode;
2415 gboolean mode_changed = FALSE;
2416 TnyAccount *account = NULL;
2418 self = MODEST_MAIN_WINDOW (user_data);
2419 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2421 /* Do not show progress for receiving operations if the
2422 account is the local account or the MMC one */
2423 op_type = modest_mail_operation_get_type_operation (mail_op);
2424 account = modest_mail_operation_get_account (mail_op);
2425 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2428 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2429 modest_tny_account_is_memory_card_account (account));
2431 g_object_unref (account);
2435 /* Show information banner. Remove old timeout */
2436 if (priv->opening_banner_timeout > 0) {
2437 g_source_remove (priv->opening_banner_timeout);
2438 priv->opening_banner_timeout = 0;
2440 /* Create a new timeout */
2441 priv->opening_banner_timeout =
2442 g_timeout_add (2000, show_opening_banner, self);
2445 /* Not every mail operation has account, noop does not */
2447 g_object_unref (account);
2449 /* Get toolbar mode from operation id*/
2450 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2452 /* Add operation observers and change toolbar if neccessary*/
2453 tmp = priv->progress_widgets;
2454 if (mode == TOOLBAR_MODE_TRANSFER) {
2456 GObject *source = modest_mail_operation_get_source(mail_op);
2457 if (G_OBJECT (self) == source) {
2458 set_toolbar_transfer_mode(self);
2460 g_object_unref (source);
2464 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2466 tmp = g_slist_next (tmp);
2470 /* Update the main menu as well, we need to explicitely do
2471 this in order to enable/disable accelerators */
2472 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2476 on_mail_operation_finished (ModestMailOperation *mail_op,
2479 ModestToolBarModes mode;
2480 ModestMailOperationTypeOperation op_type;
2482 ModestMainWindow *self;
2483 gboolean mode_changed;
2484 TnyAccount *account = NULL;
2485 ModestMainWindowPrivate *priv;
2487 self = MODEST_MAIN_WINDOW (user_data);
2488 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2490 /* The mail operation was not added to the progress objects if
2491 the account was the local account or the MMC one */
2492 op_type = modest_mail_operation_get_type_operation (mail_op);
2493 account = modest_mail_operation_get_account (mail_op);
2494 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2497 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2498 modest_tny_account_is_memory_card_account (account));
2500 g_object_unref (account);
2504 /* Remove old timeout */
2505 if (priv->opening_banner_timeout > 0) {
2506 g_source_remove (priv->opening_banner_timeout);
2507 priv->opening_banner_timeout = 0;
2510 /* Remove the banner if exists */
2511 if (priv->opening_banner) {
2512 gtk_widget_destroy (priv->opening_banner);
2513 priv->opening_banner = NULL;
2517 /* Not every mail operation has account, noop does not */
2519 g_object_unref (account);
2521 /* Get toolbar mode from operation id*/
2522 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2524 /* Change toolbar mode */
2525 tmp = priv->progress_widgets;
2526 if (mode == TOOLBAR_MODE_TRANSFER) {
2528 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2530 tmp = g_slist_next (tmp);
2533 /* If no more operations are being observed, NORMAL mode is enabled again */
2534 if (observers_empty (self)) {
2535 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2541 on_queue_changed (ModestMailOperationQueue *queue,
2542 ModestMailOperation *mail_op,
2543 ModestMailOperationQueueNotification type,
2544 ModestMainWindow *self)
2546 ModestMainWindowPrivate *priv;
2548 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2550 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2551 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2553 "operation-started",
2554 G_CALLBACK (on_mail_operation_started),
2556 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2558 "operation-finished",
2559 G_CALLBACK (on_mail_operation_finished),
2561 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2562 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2564 "operation-started");
2565 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2567 "operation-finished");
2572 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2574 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2576 ModestAccountMgr *mgr;
2577 ModestAccountSettings *settings;
2578 ModestServerAccountSettings *store_settings = NULL;
2580 /* Get account data */
2581 mgr = modest_runtime_get_account_mgr ();
2582 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2584 store_settings = modest_account_settings_get_store_settings (settings);
2586 /* Set the new visible & active account */
2587 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2588 const gchar *account_name;
2590 account_name = modest_account_settings_get_account_name (settings);
2592 modest_folder_view_set_account_id_of_visible_server_account
2594 modest_server_account_settings_get_account_name (store_settings));
2595 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2596 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2598 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2599 if (action != NULL) {
2600 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2601 modest_utils_toggle_action_set_active_block_notify (
2602 GTK_TOGGLE_ACTION (action),
2610 g_object_unref (store_settings);
2611 g_object_unref (settings);
2615 /* Make sure that at least one account is "viewed": */
2617 set_at_least_one_account_visible(ModestMainWindow *self)
2619 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2620 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2622 if (!(priv->folder_view)) {
2623 /* It is too early to do this. */
2627 const gchar *active_server_account_name =
2628 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2630 if (!active_server_account_name ||
2631 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2633 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2634 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2635 if (default_modest_name) {
2636 set_account_visible (self, default_modest_name);
2637 } else if (first_modest_name) {
2638 set_account_visible (self, first_modest_name);
2640 g_free (first_modest_name);
2641 g_free (default_modest_name);
2646 on_show_account_action_toggled (GtkToggleAction *action,
2649 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2651 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2652 if (gtk_toggle_action_get_active (action))
2653 set_account_visible (self, acc_name);
2657 refresh_account (const gchar *account_name)
2661 /* win must already exists here, obviously */
2662 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2665 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2669 /* If account_name == NULL, we must update all (option All) */
2671 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2673 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2678 on_refresh_account_action_activated (GtkAction *action,
2681 refresh_account ((const gchar*) user_data);
2685 on_send_receive_csm_activated (GtkMenuItem *item,
2688 refresh_account ((const gchar*) user_data);
2692 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2694 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2696 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2702 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2704 ModestMainWindow *main_window = NULL;
2706 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2707 main_window = MODEST_MAIN_WINDOW (userdata);
2709 /* Update toolbar dimming state */
2710 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2711 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2717 on_header_view_focus_in (GtkWidget *widget,
2718 GdkEventFocus *event,
2721 ModestMainWindow *main_window = NULL;
2723 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2725 main_window = MODEST_MAIN_WINDOW (userdata);
2727 /* Update toolbar dimming state */
2728 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2729 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2735 on_folder_selection_changed (ModestFolderView *folder_view,
2736 TnyFolderStore *folder_store,
2738 ModestMainWindow *main_window)
2740 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2741 GtkAction *action = NULL;
2742 gboolean show_reply = TRUE;
2743 gboolean show_forward = TRUE;
2744 gboolean show_cancel_send = FALSE;
2745 gboolean show_clipboard = TRUE;
2746 gboolean show_delete = TRUE;
2749 if (TNY_IS_ACCOUNT (folder_store)) {
2750 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2751 } else if (TNY_IS_FOLDER (folder_store)) {
2752 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2753 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2754 TNY_FOLDER (folder_store));
2755 switch (folder_type) {
2756 case TNY_FOLDER_TYPE_DRAFTS:
2757 show_clipboard = show_delete = TRUE;
2758 show_reply = show_forward = show_cancel_send = FALSE;
2760 case TNY_FOLDER_TYPE_SENT:
2761 show_forward = show_clipboard = show_delete = TRUE;
2762 show_reply = show_cancel_send = FALSE;
2764 case TNY_FOLDER_TYPE_OUTBOX:
2765 show_clipboard = show_delete = show_cancel_send = TRUE;
2766 show_reply = show_forward = FALSE;
2768 case TNY_FOLDER_TYPE_INVALID:
2769 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2772 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2773 show_cancel_send = FALSE;
2776 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2777 show_cancel_send = FALSE;
2782 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2783 gtk_action_set_visible (action, show_reply);
2784 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2785 gtk_action_set_visible (action, show_reply);
2786 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2787 gtk_action_set_visible (action, show_forward);
2788 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2789 gtk_action_set_visible (action, show_cancel_send);
2790 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2791 gtk_action_set_visible (action, show_delete);
2793 /* We finally call to the ui actions handler, after updating properly
2794 * the header view CSM */
2795 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2799 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2800 GtkTreeModel *model,
2801 GtkTreeRowReference *row_reference,
2802 ModestMainWindow *self)
2804 ModestMainWindowPrivate *priv = NULL;
2805 GtkTreeModel *header_model = NULL;
2806 GtkTreePath *path = NULL;
2808 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2809 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2810 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2812 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2813 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2815 /* Do nothing if we changed the folder in the main view */
2816 if (header_model != model)
2819 /* Select the message in the header view */
2820 path = gtk_tree_row_reference_get_path (row_reference);
2821 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2823 gtk_tree_path_free (path);
2829 updating_banner_destroyed (gpointer data,
2830 GObject *where_the_object_was)
2832 ModestMainWindowPrivate *priv = NULL;
2834 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2836 priv->updating_banner = NULL;
2840 show_updating_banner (gpointer user_data)
2842 ModestMainWindowPrivate *priv = NULL;
2844 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2846 if (priv->updating_banner == NULL) {
2848 /* We're outside the main lock */
2849 gdk_threads_enter ();
2850 priv->updating_banner =
2851 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2852 _CS ("ckdg_pb_updating"));
2854 /* We need this because banners in Maemo could be
2855 destroyed by dialogs so we need to properly update
2856 our reference to it */
2857 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2858 updating_banner_destroyed,
2860 gdk_threads_leave ();
2863 /* Remove timeout */
2864 priv->updating_banner_timeout = 0;
2869 * We use this function to show/hide a progress banner showing
2870 * "Updating" while the header view is being filled. We're not showing
2871 * it unless the update takes more than 2 seconds
2873 * If starting = TRUE then the refresh is starting, otherwise it means
2874 * that is has just finished
2877 on_updating_msg_list (ModestHeaderView *header_view,
2881 ModestMainWindowPrivate *priv = NULL;
2883 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2885 /* Remove old timeout */
2886 if (priv->updating_banner_timeout > 0) {
2887 g_source_remove (priv->updating_banner_timeout);
2888 priv->updating_banner_timeout = 0;
2891 /* Create a new timeout */
2893 priv->updating_banner_timeout =
2894 g_timeout_add (2000, show_updating_banner, user_data);
2896 /* Remove the banner if exists */
2897 if (priv->updating_banner) {
2898 gtk_widget_destroy (priv->updating_banner);
2899 priv->updating_banner = NULL;
2905 modest_main_window_screen_is_on (ModestMainWindow *self)
2907 ModestMainWindowPrivate *priv = NULL;
2909 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2911 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2913 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2917 remove_banners (ModestMainWindow *window)
2919 ModestMainWindowPrivate *priv;
2921 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2923 if (priv->opening_banner_timeout > 0) {
2924 g_source_remove (priv->opening_banner_timeout);
2925 priv->opening_banner_timeout = 0;
2928 if (priv->opening_banner != NULL) {
2929 gtk_widget_destroy (priv->opening_banner);
2930 priv->opening_banner = NULL;
2933 if (priv->updating_banner_timeout > 0) {
2934 g_source_remove (priv->updating_banner_timeout);
2935 priv->updating_banner_timeout = 0;
2938 if (priv->updating_banner != NULL) {
2939 gtk_widget_destroy (priv->updating_banner);
2940 priv->updating_banner = NULL;
2946 on_window_hide (GObject *gobject,
2950 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2952 if (!GTK_WIDGET_VISIBLE (gobject)) {
2953 TnyFolderStore *folder_store;
2954 ModestMainWindowPrivate *priv;
2956 /* Remove the currently shown banners */
2957 remove_banners (MODEST_MAIN_WINDOW (gobject));
2959 /* Force the folder view to sync the currently selected folder
2960 to save the read/unread status and to expunge messages */
2961 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2962 folder_store = modest_folder_view_get_selected (priv->folder_view);
2963 if (TNY_IS_FOLDER (folder_store)) {
2964 ModestMailOperation *mail_op;
2966 mail_op = modest_mail_operation_new (NULL);
2967 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2969 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2970 g_object_unref (mail_op);
2971 g_object_unref (folder_store);
2977 on_window_destroy (GtkObject *widget,
2980 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2982 remove_banners (MODEST_MAIN_WINDOW (widget));
2986 opening_banner_destroyed (gpointer data,
2987 GObject *where_the_object_was)
2989 ModestMainWindowPrivate *priv = NULL;
2991 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2993 priv->opening_banner = NULL;
2997 show_opening_banner (gpointer user_data)
2999 ModestMainWindowPrivate *priv = NULL;
3001 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
3003 if (priv->opening_banner == NULL) {
3005 /* We're outside the main lock */
3006 gdk_threads_enter ();
3007 priv->opening_banner =
3008 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
3009 _("mail_me_opening"));
3011 /* We need this because banners in Maemo could be
3012 destroyed by dialogs so we need to properly update
3013 our reference to it */
3014 g_object_weak_ref (G_OBJECT (priv->opening_banner),
3015 opening_banner_destroyed,
3018 /* We need this because banners in Maemo could be
3019 destroyed by dialogs so we need to properly update
3020 our reference to it */
3021 g_object_weak_ref (G_OBJECT (priv->updating_banner),
3022 updating_banner_destroyed,
3024 gdk_threads_leave ();
3027 /* Remove timeout */
3028 priv->opening_banner_timeout = 0;