1 /* Copyright (c) 2006, 2008 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"
67 #include <tny-gtk-folder-store-tree-model.h>
68 #include <modest-accounts-window.h>
70 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
77 /* 'private'/'protected' functions */
78 static void modest_main_window_class_init (ModestMainWindowClass *klass);
79 static void modest_main_window_init (ModestMainWindow *obj);
80 static void modest_main_window_finalize (GObject *obj);
82 static void connect_signals (ModestMainWindow *self);
84 static void modest_main_window_disconnect_signals (ModestWindow *self);
86 static void restore_settings (ModestMainWindow *self,
87 gboolean do_folder_view_too);
89 static void save_state (ModestWindow *self);
91 static void update_menus (ModestMainWindow* self);
93 static void modest_main_window_show_toolbar (ModestWindow *window,
94 gboolean show_toolbar);
96 static void cancel_progressbar (GtkToolButton *toolbutton,
97 ModestMainWindow *self);
99 static void on_queue_changed (ModestMailOperationQueue *queue,
100 ModestMailOperation *mail_op,
101 ModestMailOperationQueueNotification type,
102 ModestMainWindow *self);
104 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
106 static void on_account_inserted (TnyAccountStore *accoust_store,
110 static void on_account_removed (TnyAccountStore *accoust_store,
114 static void on_account_changed (TnyAccountStore *account_store,
118 static void on_default_account_changed (ModestAccountMgr* mgr,
121 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
125 static void on_configuration_key_changed (ModestConf* conf,
127 ModestConfEvent event,
128 ModestConfNotificationId id,
129 ModestMainWindow *self);
131 static void set_toolbar_mode (ModestMainWindow *self,
132 ModestToolBarModes mode);
134 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
136 static void on_show_account_action_toggled (GtkToggleAction *action,
139 static void on_refresh_account_action_activated (GtkAction *action,
142 static void on_send_receive_csm_activated (GtkMenuItem *item,
145 static void on_folder_view_row_activated (GtkTreeView *tree_view,
146 GtkTreePath *tree_path,
147 GtkTreeViewColumn *column,
149 static void on_msg_count_changed (ModestHeaderView *header_view,
151 TnyFolderChange *change,
152 ModestMainWindow *main_window);
154 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
157 static GtkWidget * create_empty_view (void);
159 static gboolean on_folder_view_focus_in (GtkWidget *widget,
160 GdkEventFocus *event,
163 static gboolean on_header_view_focus_in (GtkWidget *widget,
164 GdkEventFocus *event,
167 static void on_folder_selection_changed (ModestFolderView *folder_view,
168 TnyFolderStore *folder_store,
170 ModestMainWindow *main_window);
172 static void set_at_least_one_account_visible(ModestMainWindow *self);
174 static void on_updating_msg_list (ModestHeaderView *header_view,
178 static gboolean show_opening_banner (gpointer user_data);
180 static void on_window_destroy (GtkObject *widget,
183 static void on_window_hide (GObject *gobject,
187 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
188 struct _ModestMainWindowPrivate {
189 GtkWidget *main_vbox;
190 GtkWidget *contents_widget;
191 GtkWidget *empty_view;
193 /* Progress observers */
194 GtkWidget *progress_bar;
195 GSList *progress_widgets;
198 GtkWidget *progress_toolitem;
199 GtkWidget *cancel_toolitem;
200 GtkWidget *sort_toolitem;
201 GtkWidget *refresh_toolitem;
202 ModestToolBarModes current_toolbar_mode;
204 /* Merge ids used to add/remove accounts to the Accounts Menu*/
205 GByteArray *merge_ids;
206 GtkActionGroup *view_additions_group;
208 /* On-demand widgets */
209 GtkWidget *accounts_popup;
210 GtkWidget *details_widget;
212 /* Optimized view enabled */
213 gboolean optimized_view;
215 /* Optimized view enabled */
216 gboolean send_receive_in_progress;
218 ModestHeaderView *header_view;
219 ModestFolderView *folder_view;
221 ModestMainWindowStyle style;
222 ModestMainWindowContentsStyle contents_style;
223 gboolean wait_for_settings;
225 guint progress_bar_timeout;
227 /* Signal handler UIDs */
228 GList *queue_err_signals;
231 /* "Updating" banner for header view */
232 GtkWidget *updating_banner;
233 guint updating_banner_timeout;
235 /* "Opening" banner for header view */
236 GtkWidget *opening_banner;
237 guint opening_banner_timeout;
240 osso_display_state_t display_state;
242 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
243 MODEST_TYPE_MAIN_WINDOW, \
244 ModestMainWindowPrivate))
246 typedef struct _GetMsgAsyncHelper {
247 ModestMainWindowPrivate *main_window_private;
249 ModestTnyMsgReplyType reply_type;
250 ModestTnyMsgForwardType forward_type;
257 static GtkWindowClass *parent_class = NULL;
260 /* Private actions */
261 /* This is the context sensitive menu: */
262 static const GtkActionEntry modest_folder_view_action_entries [] = {
264 /* Folder View CSM actions */
265 { "FolderViewCSMNewFolder", NULL, N_("ckdg_fi_new_folder_name"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
266 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_rename_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
267 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
268 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_delete_messages"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
271 static const GtkActionEntry modest_header_view_action_entries [] = {
273 /* Header View CSM actions */
274 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
275 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
276 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
277 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
278 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
279 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
280 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
281 { "HeaderViewCSMDelete", NULL, N_("mcen_me_delete_messages"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
282 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
285 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
286 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
289 /************************************************************************/
292 modest_main_window_get_type (void)
294 static GType my_type = 0;
296 static const GTypeInfo my_info = {
297 sizeof(ModestMainWindowClass),
298 NULL, /* base init */
299 NULL, /* base finalize */
300 (GClassInitFunc) modest_main_window_class_init,
301 NULL, /* class finalize */
302 NULL, /* class data */
303 sizeof(ModestMainWindow),
305 (GInstanceInitFunc) modest_main_window_init,
308 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
316 modest_main_window_class_init (ModestMainWindowClass *klass)
318 GObjectClass *gobject_class;
319 gobject_class = (GObjectClass*) klass;
320 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
322 parent_class = g_type_class_peek_parent (klass);
323 gobject_class->finalize = modest_main_window_finalize;
325 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
327 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
328 modest_window_class->save_state_func = save_state;
329 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
330 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
331 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
335 modest_main_window_init (ModestMainWindow *obj)
337 ModestMainWindowPrivate *priv;
339 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
341 priv->queue_err_signals = NULL;
342 priv->main_vbox = NULL;
343 priv->header_view = NULL;
344 priv->folder_view = NULL;
345 priv->contents_widget = NULL;
346 priv->accounts_popup = NULL;
347 priv->details_widget = NULL;
348 priv->empty_view = NULL;
349 priv->progress_widgets = NULL;
350 priv->progress_bar = NULL;
351 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
352 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
353 priv->wait_for_settings = TRUE;
354 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
355 priv->merge_ids = NULL;
356 priv->optimized_view = FALSE;
357 priv->send_receive_in_progress = FALSE;
358 priv->progress_bar_timeout = 0;
359 priv->sighandlers = NULL;
360 priv->updating_banner = NULL;
361 priv->updating_banner_timeout = 0;
362 priv->opening_banner = NULL;
363 priv->opening_banner_timeout = 0;
364 priv->display_state = OSSO_DISPLAY_ON;
366 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
368 "applications_email_mainview");
372 modest_main_window_finalize (GObject *obj)
374 ModestMainWindowPrivate *priv;
376 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
378 /* Sanity check: shouldn't be needed, the window mgr should
379 call this function before */
380 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
381 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
383 if (priv->empty_view) {
384 g_object_unref (priv->empty_view);
385 priv->empty_view = NULL;
388 if (priv->header_view) {
389 g_object_unref (priv->header_view);
390 priv->header_view = NULL;
393 g_slist_free (priv->progress_widgets);
395 g_byte_array_free (priv->merge_ids, TRUE);
397 if (priv->progress_bar_timeout > 0) {
398 g_source_remove (priv->progress_bar_timeout);
399 priv->progress_bar_timeout = 0;
402 if (priv->updating_banner_timeout > 0) {
403 g_source_remove (priv->updating_banner_timeout);
404 priv->updating_banner_timeout = 0;
407 if (priv->updating_banner) {
408 gtk_widget_destroy (priv->updating_banner);
409 priv->updating_banner = NULL;
412 if (priv->opening_banner_timeout > 0) {
413 g_source_remove (priv->opening_banner_timeout);
414 priv->opening_banner_timeout = 0;
417 if (priv->opening_banner) {
418 gtk_widget_destroy (priv->opening_banner);
419 priv->opening_banner = NULL;
422 G_OBJECT_CLASS(parent_class)->finalize (obj);
426 modest_main_window_get_child_widget (ModestMainWindow *self,
427 ModestMainWindowWidgetType widget_type)
429 ModestMainWindowPrivate *priv;
432 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
433 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
436 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
438 switch (widget_type) {
439 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
440 widget = (GtkWidget*)priv->header_view; break;
441 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
442 widget = (GtkWidget*)priv->folder_view; break;
447 /* Note that the window could have been destroyed, and so
448 their children, but still have some references */
449 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
454 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
457 ModestMainWindowPrivate *priv;
459 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
461 conf = modest_runtime_get_conf ();
463 modest_widget_memory_restore (conf, G_OBJECT(self),
464 MODEST_CONF_MAIN_WINDOW_KEY);
466 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
467 MODEST_CONF_HEADER_VIEW_KEY);
469 if (do_folder_view_too)
470 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
471 MODEST_CONF_FOLDER_VIEW_KEY);
473 gtk_widget_show (GTK_WIDGET (self));
478 save_state (ModestWindow *window)
481 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
482 ModestMainWindowPrivate *priv;
484 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
485 conf = modest_runtime_get_conf ();
487 modest_widget_memory_save (conf,G_OBJECT(self),
488 MODEST_CONF_MAIN_WINDOW_KEY);
489 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
490 MODEST_CONF_FOLDER_VIEW_KEY);
494 compare_display_names (ModestAccountSettings *a,
495 ModestAccountSettings *b)
497 return g_utf8_collate (modest_account_settings_get_display_name (a),
498 modest_account_settings_get_display_name (b));
502 /* We use this function to prevent the send&receive CSM to be shown
503 when there are less than two account */
505 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
511 update_menus (ModestMainWindow* self)
513 GSList *account_names, *iter, *accounts;
514 ModestMainWindowPrivate *priv;
515 ModestWindowPrivate *parent_priv;
516 ModestAccountMgr *mgr;
517 gint i, num_accounts;
519 gchar *default_account;
520 const gchar *active_account_name;
521 GtkWidget *send_receive_button, *item;
522 GtkAction *send_receive_all = NULL;
525 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
526 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
528 /* Get enabled account IDs */
529 mgr = modest_runtime_get_account_mgr ();
530 account_names = modest_account_mgr_account_names (mgr, TRUE);
531 iter = account_names;
535 ModestAccountSettings *settings =
536 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
537 accounts = g_slist_prepend (accounts, settings);
541 modest_account_mgr_free_account_names (account_names);
542 account_names = NULL;
544 /* Order the list of accounts by its display name */
545 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
546 num_accounts = g_slist_length (accounts);
548 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
549 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
550 gtk_action_set_visible (send_receive_all, num_accounts > 0);
552 /* Delete old send&receive popup items. We can not just do a
553 menu_detach because it does not work well with
555 if (priv->accounts_popup)
556 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
557 (GtkCallback) gtk_widget_destroy, NULL);
559 /* Delete old entries in the View menu. Do not free groups, it
561 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
563 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
564 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
565 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
566 GTK_ACTION_GROUP (groups->data));
569 if (priv->merge_ids) {
570 for (i = 0; i < priv->merge_ids->len; i++)
571 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
572 g_byte_array_free (priv->merge_ids, TRUE);
574 /* We need to call this in order to ensure
575 that the new actions are added in the right
576 order (alphabetical) */
577 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
579 groups = g_list_next (groups);
581 priv->merge_ids = g_byte_array_sized_new (num_accounts);
583 /* Get send receive button */
584 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
585 "/ToolBar/ToolbarSendReceive");
587 /* Create the menu */
588 if (num_accounts > 1) {
589 if (!priv->accounts_popup)
590 priv->accounts_popup = gtk_menu_new ();
591 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
592 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
593 g_signal_connect (G_OBJECT (item),
595 G_CALLBACK (on_send_receive_csm_activated),
597 item = gtk_separator_menu_item_new ();
598 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
601 /* Create a new action group */
602 default_account = modest_account_mgr_get_default_account (mgr);
603 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
605 if (!active_account_name)
606 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
608 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
610 for (i = 0; i < num_accounts; i++) {
611 gchar *display_name = NULL;
612 const gchar *account_name;
613 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
616 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
619 account_name = modest_account_settings_get_account_name (settings);
621 if (default_account && account_name &&
622 !(strcmp (default_account, account_name) == 0)) {
623 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
624 modest_account_settings_get_display_name (settings));
626 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
627 modest_account_settings_get_display_name (settings));
632 /* Create action and add it to the action group. The
633 action name must be the account name, this way we
634 could know in the handlers the account to show */
635 if (settings && account_name) {
636 gchar* item_name, *refresh_action_name;
638 GtkAction *view_account_action, *refresh_account_action;
639 gchar *escaped_display_name;
641 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
643 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
644 escaped_display_name, NULL, NULL, 0));
645 g_free (escaped_display_name);
646 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
647 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
648 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
650 if (active_account_name) {
651 if (active_account_name && account_name &&
652 (strcmp (active_account_name, account_name) == 0)) {
653 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
657 /* Add ui from account data. We allow 2^9-1 account
658 changes in a single execution because we're
659 downcasting the guint to a guint8 in order to use a
660 GByteArray. It should be enough :-) */
661 item_name = g_strconcat (account_name, "Menu", NULL);
662 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
663 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
664 gtk_ui_manager_add_ui (parent_priv->ui_manager,
666 "/MenuBar/AccountsMenu/AccountsMenuAdditions",
669 GTK_UI_MANAGER_MENUITEM,
672 /* Connect the action signal "activate" */
673 g_signal_connect_after (G_OBJECT (view_account_action),
675 G_CALLBACK (on_show_account_action_toggled),
678 /* Create the items for the Tools->Send&Receive submenu */
679 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
680 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
681 display_name, NULL, NULL);
682 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
684 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
685 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
686 gtk_ui_manager_add_ui (parent_priv->ui_manager,
688 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
691 GTK_UI_MANAGER_MENUITEM,
693 g_free (refresh_action_name);
695 g_signal_connect_data (G_OBJECT (refresh_account_action),
697 G_CALLBACK (on_refresh_account_action_activated),
698 g_strdup (account_name),
699 (GClosureNotify) g_free,
702 /* Create item and add it to the send&receive
703 CSM. If there is only one account then
705 if (num_accounts > 1) {
706 GtkWidget *label = gtk_label_new(NULL);
707 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
708 if (default_account && (strcmp(account_name, default_account) == 0)) {
709 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
710 gtk_label_set_markup (GTK_LABEL (label), escaped);
713 gtk_label_set_text (GTK_LABEL (label), display_name);
716 item = gtk_menu_item_new ();
717 gtk_container_add (GTK_CONTAINER (item), label);
719 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
721 g_signal_connect_data (G_OBJECT (item),
723 G_CALLBACK (on_send_receive_csm_activated),
724 g_strdup (account_name),
725 (GClosureNotify) g_free,
732 g_free (display_name);
735 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
737 /* We cannot do this in the loop above because this relies on the action
738 * group being inserted. This makes the default account appear in bold.
739 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
740 for (i = 0; i < num_accounts; i++) {
741 gchar *item_name, *path;
743 ModestAccountSettings *settings;
744 const gchar *account_name;
747 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
748 account_name = modest_account_settings_get_account_name (settings);
749 is_default = (account_name && default_account && !strcmp (account_name, default_account));
751 /* Get the item of the view menu */
752 item_name = g_strconcat (account_name, "Menu", NULL);
753 path = g_strconcat ("/MenuBar/AccountsMenu/AccountsMenuAdditions/", item_name, NULL);
754 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
758 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
759 if (GTK_IS_LABEL (child)) {
760 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
762 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
763 gtk_label_set_markup (GTK_LABEL (child), bold_name);
769 /* Get the item of the tools menu */
770 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
771 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
775 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
776 if (GTK_IS_LABEL (child)) {
777 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
779 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
780 gtk_label_set_markup (GTK_LABEL (child), bold_name);
783 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
788 g_object_unref (settings);
791 if (num_accounts > 1) {
792 /* Disconnect the tap-and-hold-query if it's connected */
793 if (modest_signal_mgr_is_connected (priv->sighandlers,
794 G_OBJECT (send_receive_button),
795 "tap-and-hold-query"))
796 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
797 G_OBJECT (send_receive_button),
798 "tap-and-hold-query");
800 /* Mandatory in order to view the menu contents */
801 gtk_widget_show_all (priv->accounts_popup);
803 /* Setup tap_and_hold just if was not done before*/
804 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
805 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
807 /* Connect the tap-and-hold-query in order not to show the CSM */
808 if (!modest_signal_mgr_is_connected (priv->sighandlers,
809 G_OBJECT (send_receive_button),
810 "tap-and-hold-query"))
811 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
812 G_OBJECT (send_receive_button),
813 "tap-and-hold-query",
814 G_CALLBACK (tap_and_hold_query_cb),
819 g_slist_free (accounts);
820 g_free (default_account);
823 /* Make sure that at least one account is viewed if there are any
824 * accounts, for instance when adding the first account: */
825 set_at_least_one_account_visible (self);
829 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
831 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
832 gtk_scrolled_window_add_with_viewport
833 (GTK_SCROLLED_WINDOW(win), widget);
835 gtk_container_add (GTK_CONTAINER(win),
846 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
848 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
850 GList *oerrsignals = priv->queue_err_signals;
851 while (oerrsignals) {
852 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
853 g_signal_handler_disconnect (esignal->queue, esignal->signal);
854 g_slice_free (QueueErrorSignal, esignal);
855 oerrsignals = g_list_next (oerrsignals);
857 g_list_free (priv->queue_err_signals);
858 priv->queue_err_signals = NULL;
863 modest_main_window_disconnect_signals (ModestWindow *self)
865 ModestMainWindowPrivate *priv;
866 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
868 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
869 priv->sighandlers = NULL;
873 connect_signals (ModestMainWindow *self)
875 ModestWindowPrivate *parent_priv;
876 ModestMainWindowPrivate *priv;
878 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
879 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
884 modest_signal_mgr_connect (priv->sighandlers,
885 G_OBJECT(priv->folder_view), "key-press-event",
886 G_CALLBACK(on_inner_widgets_key_pressed), self);
888 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
889 "folder_selection_changed",
890 G_CALLBACK (on_folder_selection_changed),
893 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
894 "folder-display-name-changed",
895 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
898 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
900 G_CALLBACK (on_folder_view_focus_in),
903 /* folder view row activated */
904 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "row-activated",
905 G_CALLBACK(on_folder_view_row_activated),
910 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
911 G_CALLBACK(modest_ui_actions_on_header_selected), self);
913 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
914 G_CALLBACK(modest_ui_actions_on_header_activated), self);
916 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
917 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
919 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
920 G_CALLBACK(on_inner_widgets_key_pressed), self);
922 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
923 G_CALLBACK(on_msg_count_changed), self);
925 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
926 G_CALLBACK (on_header_view_focus_in), self);
928 modest_signal_mgr_connect (priv->sighandlers,
929 G_OBJECT (priv->header_view),
931 G_CALLBACK (on_updating_msg_list),
935 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
936 * in destroy stage */
937 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
939 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
941 /* Mail Operation Queue */
943 modest_signal_mgr_connect (priv->sighandlers,
944 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
946 G_CALLBACK (on_queue_changed), self);
948 /* Track changes in the device name */
950 modest_signal_mgr_connect (priv->sighandlers,
951 G_OBJECT(modest_runtime_get_conf ()),
953 G_CALLBACK (on_configuration_key_changed),
956 /* Track account changes. We need to refresh the toolbar */
958 modest_signal_mgr_connect (priv->sighandlers,
959 G_OBJECT (modest_runtime_get_account_store ()),
961 G_CALLBACK (on_account_inserted),
964 modest_signal_mgr_connect (priv->sighandlers,
965 G_OBJECT (modest_runtime_get_account_store ()),
967 G_CALLBACK (on_account_removed),
970 /* We need to refresh the send & receive menu to change the bold
971 * account when the default account changes. */
973 modest_signal_mgr_connect (priv->sighandlers,
974 G_OBJECT (modest_runtime_get_account_mgr ()),
975 "default_account_changed",
976 G_CALLBACK (on_default_account_changed),
981 modest_signal_mgr_connect (priv->sighandlers,
982 G_OBJECT (modest_runtime_get_account_store ()),
984 G_CALLBACK (on_account_changed),
989 on_hildon_program_is_topmost_notify(GObject *self,
990 GParamSpec *propert_param,
993 HildonProgram *app = HILDON_PROGRAM (self);
995 /* Note that use of hildon_program_set_can_hibernate()
996 * is generally referred to as "setting the killable flag",
997 * though hibernation does not seem equal to death.
1000 if (hildon_program_get_is_topmost (app)) {
1001 /* Prevent hibernation when the progam comes to the foreground,
1002 * because hibernation should only happen when the application
1003 * is in the background: */
1004 hildon_program_set_can_hibernate (app, FALSE);
1006 /* Remove new mail visual notifications */
1007 modest_platform_remove_new_mail_notifications (TRUE);
1009 /* Allow hibernation if the program has gone to the background: */
1011 /* However, prevent hibernation while the settings are being changed: */
1012 const gboolean hibernation_prevented =
1013 modest_window_mgr_get_hibernation_is_prevented (
1014 modest_runtime_get_window_mgr ());
1016 if (hibernation_prevented)
1017 hildon_program_set_can_hibernate (app, FALSE);
1019 /* Allow hibernation, after saving the state: */
1020 modest_osso_save_state();
1021 hildon_program_set_can_hibernate (app, TRUE);
1032 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1034 ShowHelper *helper = (ShowHelper *) user_data;
1035 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1037 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1038 modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self),
1039 MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS);
1040 gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->folder_view));
1042 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1044 /* Connect signals */
1045 connect_signals (MODEST_MAIN_WINDOW (self));
1047 /* Set account store */
1048 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1049 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1051 /* Load previous osso state, for instance if we are being restored from
1053 modest_osso_load_state ();
1055 /* Restore window & widget settings */
1056 priv->wait_for_settings = TRUE;
1057 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1058 priv->wait_for_settings = FALSE;
1060 /* Check if accounts exist and show the account wizard if not */
1061 gboolean accounts_exist =
1062 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1064 if (!accounts_exist) {
1065 /* This is necessary to have the main window shown behind the dialog
1066 It's an ugly hack... jschmid */
1067 gtk_widget_show_all(GTK_WIDGET(self));
1068 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1070 update_menus (MODEST_MAIN_WINDOW (self));
1073 /* Never call this function again (NOTE that it could happen
1074 as we hide the main window instead of closing it while
1075 there are operations ongoing) and free the helper */
1076 g_signal_handler_disconnect (self, helper->handler_id);
1077 g_slice_free (ShowHelper, helper);
1081 osso_display_event_cb (osso_display_state_t state,
1084 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1086 priv->display_state = state;
1088 /* Stop blinking if the screen becomes on */
1089 if (priv->display_state == OSSO_DISPLAY_ON)
1090 modest_platform_remove_new_mail_notifications (TRUE);
1094 modest_main_window_new (void)
1096 ModestMainWindow *self = NULL;
1097 ModestMainWindowPrivate *priv = NULL;
1098 ModestWindowPrivate *parent_priv = NULL;
1099 ModestDimmingRulesGroup *menu_rules_group = NULL;
1100 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1101 GtkActionGroup *action_group = NULL;
1102 GError *error = NULL;
1104 GdkPixbuf *window_icon;
1107 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1108 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1109 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1111 parent_priv->ui_manager = gtk_ui_manager_new();
1112 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1114 action_group = gtk_action_group_new ("ModestMainWindowActions");
1115 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1117 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1118 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1120 /* Add common actions */
1121 gtk_action_group_add_actions (action_group,
1122 modest_action_entries,
1123 G_N_ELEMENTS (modest_action_entries),
1126 gtk_action_group_add_actions (action_group,
1127 modest_folder_view_action_entries,
1128 G_N_ELEMENTS (modest_folder_view_action_entries),
1131 gtk_action_group_add_actions (action_group,
1132 modest_header_view_action_entries,
1133 G_N_ELEMENTS (modest_header_view_action_entries),
1136 gtk_action_group_add_toggle_actions (action_group,
1137 modest_main_window_toggle_action_entries,
1138 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1141 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1142 g_object_unref (action_group);
1144 /* Load the UI definition */
1145 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1146 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1147 if (error != NULL) {
1148 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1149 g_error_free (error);
1153 /* Add common dimming rules */
1154 modest_dimming_rules_group_add_rules (menu_rules_group,
1155 modest_main_window_menu_dimming_entries,
1156 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1157 MODEST_WINDOW (self));
1158 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1159 modest_main_window_toolbar_dimming_entries,
1160 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1161 MODEST_WINDOW (self));
1163 /* Insert dimming rules group for this window */
1164 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1165 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1166 g_object_unref (menu_rules_group);
1167 g_object_unref (toolbar_rules_group);
1169 /* Add accelerators */
1170 gtk_window_add_accel_group (GTK_WINDOW (self),
1171 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1173 /* Menubar. Update the state of some toggles */
1174 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1175 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1176 gtk_widget_show (parent_priv->menubar);
1178 /* Get device name */
1179 modest_maemo_utils_get_device_name ();
1183 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1184 g_object_ref (priv->header_view);
1185 if (!priv->header_view)
1186 g_printerr ("modest: cannot instantiate header view\n");
1187 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1188 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1189 MODEST_CONF_HEADER_VIEW_KEY);
1191 /* Other style properties of header view */
1192 g_object_set (G_OBJECT (priv->header_view),
1193 "rules-hint", FALSE,
1195 /* gtk_widget_show (priv->header_view); */
1198 priv->empty_view = create_empty_view ();
1199 gtk_widget_show (priv->empty_view);
1200 g_object_ref (priv->empty_view);
1202 /* Create scrolled windows */
1203 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1204 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1206 GTK_POLICY_AUTOMATIC);
1207 /* gtk_widget_show (priv->contents_widget); */
1209 /* putting it all together... */
1210 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1211 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->contents_widget, TRUE, TRUE,0);
1212 gtk_widget_show (priv->main_vbox);
1214 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1216 app = hildon_program_get_instance ();
1217 hildon_program_add_window (app, HILDON_WINDOW (self));
1219 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1220 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1222 /* Connect to "show" action. We delay the creation of some
1223 elements until that moment */
1224 helper = g_slice_new0 (ShowHelper);
1225 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1226 G_CALLBACK (modest_main_window_on_show),
1229 /* Set window icon */
1230 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1232 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1233 g_object_unref (window_icon);
1236 /* Listen for changes in the screen, we don't want to show a
1237 led pattern when the display is on for example */
1238 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1239 osso_display_event_cb,
1242 /* Dont't restore settings here,
1243 * because it requires a gtk_widget_show(),
1244 * and we don't want to do that until later,
1245 * so that the UI is not visible for non-menu D-Bus activation.
1248 return MODEST_WINDOW(self);
1252 modest_main_window_set_style (ModestMainWindow *self,
1253 ModestMainWindowStyle style)
1255 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1257 /* We only provide simple style */
1261 ModestMainWindowStyle
1262 modest_main_window_get_style (ModestMainWindow *self)
1264 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1266 return MODEST_MAIN_WINDOW_STYLE_SIMPLE;
1270 toolbar_resize (ModestMainWindow *self)
1272 ModestMainWindowPrivate *priv = NULL;
1273 ModestWindowPrivate *parent_priv = NULL;
1275 gint static_button_size;
1276 ModestWindowMgr *mgr;
1278 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1279 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1280 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1282 mgr = modest_runtime_get_window_mgr ();
1283 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1285 if (parent_priv->toolbar) {
1286 /* left size buttons */
1287 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1288 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1289 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1290 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1291 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1292 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1293 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1294 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1295 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1296 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1297 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1298 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1299 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1300 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1301 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1302 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1304 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1305 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1306 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1307 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1308 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1309 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1310 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1311 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1317 modest_main_window_show_toolbar (ModestWindow *self,
1318 gboolean show_toolbar)
1320 ModestMainWindowPrivate *priv = NULL;
1321 ModestWindowPrivate *parent_priv = NULL;
1322 GtkWidget *reply_button = NULL, *menu = NULL;
1323 GtkWidget *placeholder = NULL;
1326 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1327 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1328 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1330 /* Set optimized view status */
1331 priv->optimized_view = !show_toolbar;
1333 if (!parent_priv->toolbar) {
1334 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1336 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1338 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1339 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1340 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1341 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1342 toolbar_resize (MODEST_MAIN_WINDOW (self));
1344 /* Add ProgressBar (Transfer toolbar) */
1345 priv->progress_bar = modest_progress_bar_new ();
1346 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1347 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1348 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1349 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1350 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1352 /* Connect cancel 'clicked' signal to abort progress mode */
1353 g_signal_connect(priv->cancel_toolitem, "clicked",
1354 G_CALLBACK(cancel_progressbar),
1357 /* Add it to the observers list */
1358 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1361 hildon_window_add_toolbar (HILDON_WINDOW (self),
1362 GTK_TOOLBAR (parent_priv->toolbar));
1364 /* Set reply button tap and hold menu */
1365 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1366 "/ToolBar/ToolbarMessageReply");
1367 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1368 "/ToolbarReplyCSM");
1369 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1371 /* Set send & receive button tap and hold menu */
1372 update_menus (MODEST_MAIN_WINDOW (self));
1376 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1377 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1378 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1380 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1381 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1382 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1384 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1386 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1392 on_account_inserted (TnyAccountStore *accoust_store,
1393 TnyAccount *account,
1396 /* Transport accounts and local ones (MMC and the Local
1397 folders account do now cause menu changes */
1398 if (TNY_IS_STORE_ACCOUNT (account) &&
1399 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1401 update_menus (MODEST_MAIN_WINDOW (user_data));
1406 on_default_account_changed (ModestAccountMgr* mgr,
1409 update_menus (MODEST_MAIN_WINDOW (user_data));
1413 on_account_removed (TnyAccountStore *accoust_store,
1414 TnyAccount *account,
1417 /* Transport accounts and local ones (MMC and the Local
1418 folders account do now cause menu changes */
1419 if (TNY_IS_STORE_ACCOUNT (account) &&
1420 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1421 update_menus (MODEST_MAIN_WINDOW (user_data));
1425 on_account_changed (TnyAccountStore *account_store,
1426 TnyAccount *account,
1429 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1431 /* Transport accounts and local ones (MMC and the Local
1432 folders account do now cause menu changes */
1433 if (TNY_IS_STORE_ACCOUNT (account)) {
1434 /* Update the menus as well, name could change */
1435 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1436 update_menus (MODEST_MAIN_WINDOW (win));
1441 * This function manages the key events used to navigate between
1442 * header and folder views (when the window is in split view)
1445 * -------------------------------------------------
1446 * HeaderView GDK_Left Move focus to folder view
1447 * FolderView GDK_Right Move focus to header view
1449 * There is no need to scroll to selected row, the widgets will be the
1450 * responsibles of doing that (probably managing the focus-in event
1453 on_inner_widgets_key_pressed (GtkWidget *widget,
1457 ModestMainWindowPrivate *priv;
1459 if (event->type == GDK_KEY_RELEASE)
1462 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1464 /* Do nothing if we're in SIMPLE style */
1465 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1468 if (MODEST_IS_HEADER_VIEW (widget)) {
1469 if (event->keyval == GDK_Left)
1470 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1471 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1472 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1473 if (selected_headers > 1) {
1474 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1477 GtkTreePath * cursor_path;
1478 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1479 if (cursor_path == NULL) {
1480 GtkTreeSelection *selection;
1482 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1483 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1486 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1487 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1492 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1493 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1494 GtkTreePath *selected_path = NULL;
1495 GtkTreePath *start_path = NULL;
1496 GtkTreePath *end_path = NULL;
1498 GtkTreeSelection *selection;
1500 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1501 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1502 if (selected != NULL) {
1503 selected_path = (GtkTreePath *) selected->data;
1504 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1508 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1509 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1511 /* Scroll to first path */
1512 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1521 gtk_tree_path_free (start_path);
1523 gtk_tree_path_free (end_path);
1524 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1525 g_list_free (selected);
1527 #endif /* GTK_CHECK_VERSION */
1529 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1536 create_empty_view (void)
1538 GtkLabel *label = NULL;
1539 GtkWidget *align = NULL;
1541 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1542 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1543 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1544 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1546 return GTK_WIDGET(align);
1551 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1553 ModestMainWindowPrivate *priv = NULL;
1555 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1557 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1559 return priv->send_receive_in_progress;
1563 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1565 GtkAction *action = NULL;
1566 GtkWidget *widget = NULL;
1567 ModestMainWindowPrivate *priv = NULL;
1569 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1570 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1572 priv->send_receive_in_progress = TRUE;
1574 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1575 gtk_action_set_sensitive (action, FALSE);
1576 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1577 /* gtk_action_set_sensitive (action, FALSE); */
1578 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1579 gtk_widget_set_sensitive (widget, FALSE);
1583 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1585 GtkAction *action = NULL;
1586 GtkWidget *widget = NULL;
1587 ModestMainWindowPrivate *priv = NULL;
1589 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1590 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1592 priv->send_receive_in_progress = FALSE;
1594 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1595 gtk_action_set_sensitive (action, TRUE);
1596 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1597 /* gtk_action_set_sensitive (action, TRUE); */
1598 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1599 gtk_widget_set_sensitive (widget, TRUE);
1604 on_msg_count_changed (ModestHeaderView *header_view,
1606 TnyFolderChange *change,
1607 ModestMainWindow *main_window)
1609 gboolean refilter = FALSE;
1610 gboolean folder_empty = FALSE;
1611 gboolean all_marked_as_deleted = FALSE;
1612 ModestMainWindowPrivate *priv;
1614 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1615 g_return_if_fail (TNY_IS_FOLDER(folder));
1616 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1618 if (change != NULL) {
1619 TnyFolderChangeChanged changed;
1621 changed = tny_folder_change_get_changed (change);
1622 /* If something changes */
1623 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1624 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1626 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1628 /* Play a sound (if configured) and make the LED blink */
1629 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1630 modest_platform_push_email_notification ();
1633 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1636 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1639 /* Check if all messages are marked to be deleted */
1640 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1641 folder_empty = folder_empty || all_marked_as_deleted;
1643 /* Set contents style of headers view */
1644 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY ||
1645 priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1647 modest_main_window_set_contents_style (main_window,
1648 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1649 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1651 modest_main_window_set_contents_style (main_window,
1652 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1657 modest_header_view_refilter (header_view);
1662 modest_main_window_set_contents_style (ModestMainWindow *self,
1663 ModestMainWindowContentsStyle style)
1665 ModestMainWindowPrivate *priv;
1667 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1669 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1671 /* We allow to set the same content style than the previously
1672 set if there are details, because it could happen when we're
1673 selecting different accounts consecutively */
1674 if ((priv->contents_style == style) &&
1675 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1678 /* Remove previous child. Delete it if it was an account
1680 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1682 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1683 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1686 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1689 priv->contents_style = style;
1691 switch (priv->contents_style) {
1692 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS:
1693 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->folder_view));
1694 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1696 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1698 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1699 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1700 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1702 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1703 gtk_widget_show (GTK_WIDGET (priv->header_view));
1705 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1706 g_message ("This view is not supported in Fremantle style");
1708 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1709 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1710 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1712 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1713 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
1716 g_return_if_reached ();
1720 gtk_widget_show_all (priv->contents_widget);
1723 ModestMainWindowContentsStyle
1724 modest_main_window_get_contents_style (ModestMainWindow *self)
1726 ModestMainWindowPrivate *priv;
1728 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1730 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1731 return priv->contents_style;
1736 on_configuration_key_changed (ModestConf* conf,
1738 ModestConfEvent event,
1739 ModestConfNotificationId id,
1740 ModestMainWindow *self)
1742 /* TODO: remove this handler. Now we don't support details view,
1743 * so this must be removed */
1749 set_toolbar_transfer_mode (ModestMainWindow *self)
1751 ModestMainWindowPrivate *priv = NULL;
1753 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1755 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1757 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1759 if (priv->progress_bar_timeout > 0) {
1760 g_source_remove (priv->progress_bar_timeout);
1761 priv->progress_bar_timeout = 0;
1768 set_toolbar_mode (ModestMainWindow *self,
1769 ModestToolBarModes mode)
1771 ModestWindowPrivate *parent_priv = NULL;
1772 ModestMainWindowPrivate *priv = NULL;
1773 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1775 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1777 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1778 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1780 /* In case this was called before the toolbar exists: */
1781 if (!(parent_priv->toolbar))
1784 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1786 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1787 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1788 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1790 /* Sets current toolbar mode */
1791 priv->current_toolbar_mode = mode;
1793 /* Checks the dimming rules */
1794 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1795 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1797 /* Show and hide toolbar items */
1799 case TOOLBAR_MODE_NORMAL:
1801 gtk_action_set_visible (sort_action, TRUE);
1803 gtk_action_set_visible (refresh_action, TRUE);
1804 if (priv->progress_toolitem) {
1805 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1806 gtk_widget_hide (priv->progress_toolitem);
1808 if (priv->progress_bar)
1809 gtk_widget_hide (priv->progress_bar);
1812 gtk_action_set_visible (cancel_action, FALSE);
1814 /* Hide toolbar if optimized view is enabled */
1815 if (priv->optimized_view)
1816 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1818 case TOOLBAR_MODE_TRANSFER:
1820 gtk_action_set_visible (sort_action, FALSE);
1822 gtk_action_set_visible (refresh_action, FALSE);
1824 gtk_action_set_visible (cancel_action, TRUE);
1825 if (priv->progress_bar)
1826 gtk_widget_show (priv->progress_bar);
1827 if (priv->progress_toolitem) {
1828 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1829 gtk_widget_show (priv->progress_toolitem);
1832 /* Show toolbar if it's hiden (optimized view ) */
1833 if (priv->optimized_view)
1834 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1837 g_return_if_reached ();
1842 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1844 ModestMainWindowPrivate *priv;
1846 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1847 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1849 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1853 cancel_progressbar (GtkToolButton *toolbutton,
1854 ModestMainWindow *self)
1857 ModestMainWindowPrivate *priv;
1859 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1861 /* Get operation observers and cancel all the operations */
1862 tmp = priv->progress_widgets;
1864 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1865 tmp=g_slist_next(tmp);
1870 observers_empty (ModestMainWindow *self)
1873 ModestMainWindowPrivate *priv;
1874 gboolean is_empty = TRUE;
1875 guint pending_ops = 0;
1877 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1878 tmp = priv->progress_widgets;
1880 /* Check all observers */
1881 while (tmp && is_empty) {
1882 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1883 is_empty = pending_ops == 0;
1885 tmp = g_slist_next(tmp);
1893 * Gets the toolbar mode needed for each mail operation. It stores in
1894 * @mode_changed if the toolbar mode has changed or not
1896 static ModestToolBarModes
1897 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
1898 ModestMailOperation *mail_op,
1899 gboolean *mode_changed)
1901 ModestToolBarModes mode;
1902 ModestMainWindowPrivate *priv;
1904 *mode_changed = FALSE;
1905 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1907 /* Get toolbar mode from operation id*/
1908 switch (modest_mail_operation_get_type_operation (mail_op)) {
1909 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
1910 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1911 mode = TOOLBAR_MODE_TRANSFER;
1912 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1913 *mode_changed = TRUE;
1916 mode = TOOLBAR_MODE_NORMAL;
1922 on_mail_operation_started (ModestMailOperation *mail_op,
1925 ModestMainWindow *self;
1926 ModestMailOperationTypeOperation op_type;
1927 ModestMainWindowPrivate *priv;
1928 ModestToolBarModes mode;
1930 gboolean mode_changed = FALSE;
1931 TnyAccount *account = NULL;
1933 self = MODEST_MAIN_WINDOW (user_data);
1934 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1936 /* Do not show progress for receiving operations if the
1937 account is the local account or the MMC one */
1938 op_type = modest_mail_operation_get_type_operation (mail_op);
1939 account = modest_mail_operation_get_account (mail_op);
1940 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
1943 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
1944 modest_tny_account_is_memory_card_account (account));
1946 g_object_unref (account);
1950 /* Show information banner. Remove old timeout */
1951 if (priv->opening_banner_timeout > 0) {
1952 g_source_remove (priv->opening_banner_timeout);
1953 priv->opening_banner_timeout = 0;
1955 /* Create a new timeout */
1956 priv->opening_banner_timeout =
1957 g_timeout_add (2000, show_opening_banner, self);
1960 /* Not every mail operation has account, noop does not */
1962 g_object_unref (account);
1964 /* Get toolbar mode from operation id*/
1965 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
1967 /* Add operation observers and change toolbar if neccessary*/
1968 tmp = priv->progress_widgets;
1969 if (mode == TOOLBAR_MODE_TRANSFER) {
1971 GObject *source = modest_mail_operation_get_source(mail_op);
1972 if (G_OBJECT (self) == source) {
1973 set_toolbar_transfer_mode(self);
1975 g_object_unref (source);
1979 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1981 tmp = g_slist_next (tmp);
1985 /* Update the main menu as well, we need to explicitely do
1986 this in order to enable/disable accelerators */
1987 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1991 on_mail_operation_finished (ModestMailOperation *mail_op,
1994 ModestToolBarModes mode;
1995 ModestMailOperationTypeOperation op_type;
1997 ModestMainWindow *self;
1998 gboolean mode_changed;
1999 TnyAccount *account = NULL;
2000 ModestMainWindowPrivate *priv;
2002 self = MODEST_MAIN_WINDOW (user_data);
2003 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2005 /* The mail operation was not added to the progress objects if
2006 the account was the local account or the MMC one */
2007 op_type = modest_mail_operation_get_type_operation (mail_op);
2008 account = modest_mail_operation_get_account (mail_op);
2009 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2012 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2013 modest_tny_account_is_memory_card_account (account));
2015 g_object_unref (account);
2019 /* Remove old timeout */
2020 if (priv->opening_banner_timeout > 0) {
2021 g_source_remove (priv->opening_banner_timeout);
2022 priv->opening_banner_timeout = 0;
2025 /* Remove the banner if exists */
2026 if (priv->opening_banner) {
2027 gtk_widget_destroy (priv->opening_banner);
2028 priv->opening_banner = NULL;
2032 /* Not every mail operation has account, noop does not */
2034 g_object_unref (account);
2036 /* Get toolbar mode from operation id*/
2037 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2039 /* Change toolbar mode */
2040 tmp = priv->progress_widgets;
2041 if (mode == TOOLBAR_MODE_TRANSFER) {
2043 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2045 tmp = g_slist_next (tmp);
2048 /* If no more operations are being observed, NORMAL mode is enabled again */
2049 if (observers_empty (self)) {
2050 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2056 on_queue_changed (ModestMailOperationQueue *queue,
2057 ModestMailOperation *mail_op,
2058 ModestMailOperationQueueNotification type,
2059 ModestMainWindow *self)
2061 ModestMainWindowPrivate *priv;
2063 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2065 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2066 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2068 "operation-started",
2069 G_CALLBACK (on_mail_operation_started),
2071 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2073 "operation-finished",
2074 G_CALLBACK (on_mail_operation_finished),
2076 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2077 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2079 "operation-started");
2080 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2082 "operation-finished");
2087 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2089 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2091 ModestAccountMgr *mgr;
2092 ModestAccountSettings *settings;
2093 ModestServerAccountSettings *store_settings = NULL;
2095 /* GtkWidget *folder_window; */
2097 /* folder_window = GTK_WIDGET (modest_folder_window_new (NULL)); */
2098 /* modest_window_mgr_register_window (modest_runtime_get_window_mgr (), */
2099 /* MODEST_WINDOW (folder_window), */
2100 /* MODEST_WINDOW (self)); */
2101 /* gtk_widget_show (folder_window); */
2102 GtkWidget *accounts_window;
2104 accounts_window = GTK_WIDGET (modest_accounts_window_new ());
2105 modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
2106 MODEST_WINDOW (accounts_window),
2107 MODEST_WINDOW (self));
2108 gtk_widget_show (accounts_window);
2110 /* Get account data */
2111 mgr = modest_runtime_get_account_mgr ();
2112 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2114 store_settings = modest_account_settings_get_store_settings (settings);
2116 /* Set the new visible & active account */
2117 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2118 const gchar *account_name;
2120 account_name = modest_account_settings_get_account_name (settings);
2122 modest_folder_view_set_account_id_of_visible_server_account
2124 modest_server_account_settings_get_account_name (store_settings));
2125 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2126 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2128 /* modest_folder_window_set_account (MODEST_FOLDER_WINDOW (folder_window), acc_name); */
2130 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2131 if (action != NULL) {
2132 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2133 modest_utils_toggle_action_set_active_block_notify (
2134 GTK_TOGGLE_ACTION (action),
2142 g_object_unref (store_settings);
2143 g_object_unref (settings);
2148 /* Make sure that at least one account is "viewed": */
2150 set_at_least_one_account_visible(ModestMainWindow *self)
2152 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2153 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2155 if (!(priv->folder_view)) {
2156 /* It is too early to do this. */
2160 const gchar *active_server_account_name =
2161 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2163 if (!active_server_account_name ||
2164 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2166 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2167 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2168 if (default_modest_name) {
2169 set_account_visible (self, default_modest_name);
2170 } else if (first_modest_name) {
2171 set_account_visible (self, first_modest_name);
2173 g_free (first_modest_name);
2174 g_free (default_modest_name);
2179 on_show_account_action_toggled (GtkToggleAction *action,
2182 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2184 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2185 if (gtk_toggle_action_get_active (action))
2186 set_account_visible (self, acc_name);
2190 refresh_account (const gchar *account_name)
2194 /* win must already exists here, obviously */
2195 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2198 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2202 /* If account_name == NULL, we must update all (option All) */
2204 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2206 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2211 on_refresh_account_action_activated (GtkAction *action,
2214 refresh_account ((const gchar*) user_data);
2218 on_send_receive_csm_activated (GtkMenuItem *item,
2221 refresh_account ((const gchar*) user_data);
2225 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2227 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2229 hildon_banner_show_information (NULL, NULL, _CS("ckct_ib_cannot_zoom_here"));
2235 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2237 ModestMainWindow *main_window = NULL;
2239 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2240 main_window = MODEST_MAIN_WINDOW (userdata);
2242 /* Update toolbar dimming state */
2243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2244 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2250 on_header_view_focus_in (GtkWidget *widget,
2251 GdkEventFocus *event,
2254 ModestMainWindow *main_window = NULL;
2256 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2258 main_window = MODEST_MAIN_WINDOW (userdata);
2260 /* Update toolbar dimming state */
2261 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2262 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2268 on_folder_selection_changed (ModestFolderView *folder_view,
2269 TnyFolderStore *folder_store,
2271 ModestMainWindow *main_window)
2273 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2274 GtkAction *action = NULL;
2275 gboolean show_reply = TRUE;
2276 gboolean show_forward = TRUE;
2277 gboolean show_cancel_send = FALSE;
2278 gboolean show_clipboard = TRUE;
2279 gboolean show_delete = TRUE;
2282 if (TNY_IS_ACCOUNT (folder_store)) {
2283 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2284 } else if (TNY_IS_FOLDER (folder_store)) {
2285 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2286 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2287 TNY_FOLDER (folder_store));
2288 switch (folder_type) {
2289 case TNY_FOLDER_TYPE_DRAFTS:
2290 show_clipboard = show_delete = TRUE;
2291 show_reply = show_forward = show_cancel_send = FALSE;
2293 case TNY_FOLDER_TYPE_SENT:
2294 show_forward = show_clipboard = show_delete = TRUE;
2295 show_reply = show_cancel_send = FALSE;
2297 case TNY_FOLDER_TYPE_OUTBOX:
2298 show_clipboard = show_delete = show_cancel_send = TRUE;
2299 show_reply = show_forward = FALSE;
2301 case TNY_FOLDER_TYPE_INVALID:
2302 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2305 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2306 show_cancel_send = FALSE;
2309 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2310 show_cancel_send = FALSE;
2315 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2316 gtk_action_set_visible (action, show_reply);
2317 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2318 gtk_action_set_visible (action, show_reply);
2319 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2320 gtk_action_set_visible (action, show_forward);
2321 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2322 gtk_action_set_visible (action, show_cancel_send);
2323 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2324 gtk_action_set_visible (action, show_delete);
2329 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2330 GtkTreeModel *model,
2331 GtkTreeRowReference *row_reference,
2332 ModestMainWindow *self)
2334 ModestMainWindowPrivate *priv = NULL;
2335 GtkTreeModel *header_model = NULL;
2336 GtkTreePath *path = NULL;
2338 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2339 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2340 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2342 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2343 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2345 /* Do nothing if we changed the folder in the main view */
2346 if (header_model != model)
2349 /* Select the message in the header view */
2350 path = gtk_tree_row_reference_get_path (row_reference);
2351 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2353 gtk_tree_path_free (path);
2359 updating_banner_destroyed (gpointer data,
2360 GObject *where_the_object_was)
2362 ModestMainWindowPrivate *priv = NULL;
2364 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2366 priv->updating_banner = NULL;
2370 show_updating_banner (gpointer user_data)
2372 ModestMainWindowPrivate *priv = NULL;
2374 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2376 if (priv->updating_banner == NULL) {
2378 /* We're outside the main lock */
2379 gdk_threads_enter ();
2380 priv->updating_banner =
2381 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2382 _CS ("ckdg_pb_updating"));
2384 /* We need this because banners in Maemo could be
2385 destroyed by dialogs so we need to properly update
2386 our reference to it */
2387 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2388 updating_banner_destroyed,
2390 gdk_threads_leave ();
2393 /* Remove timeout */
2394 priv->updating_banner_timeout = 0;
2399 * We use this function to show/hide a progress banner showing
2400 * "Updating" while the header view is being filled. We're not showing
2401 * it unless the update takes more than 2 seconds
2403 * If starting = TRUE then the refresh is starting, otherwise it means
2404 * that is has just finished
2407 on_updating_msg_list (ModestHeaderView *header_view,
2411 ModestMainWindowPrivate *priv = NULL;
2413 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2415 /* Remove old timeout */
2416 if (priv->updating_banner_timeout > 0) {
2417 g_source_remove (priv->updating_banner_timeout);
2418 priv->updating_banner_timeout = 0;
2421 /* Create a new timeout */
2423 priv->updating_banner_timeout =
2424 g_timeout_add (2000, show_updating_banner, user_data);
2426 /* Remove the banner if exists */
2427 if (priv->updating_banner) {
2428 gtk_widget_destroy (priv->updating_banner);
2429 priv->updating_banner = NULL;
2434 static void on_folder_view_row_activated (GtkTreeView *tree_view,
2435 GtkTreePath *tree_path,
2436 GtkTreeViewColumn *column,
2439 GtkTreeModel *model;
2441 TnyFolderStore *folder_store = NULL;
2442 ModestMainWindow *self = (ModestMainWindow *) userdata;
2443 ModestMainWindowPrivate *priv = NULL;
2445 g_return_if_fail (MODEST_IS_MAIN_WINDOW(self));
2446 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2448 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
2450 if (gtk_tree_model_get_iter (model, &iter, tree_path)) {
2451 gtk_tree_model_get (model, &iter,
2452 TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder_store,
2454 if (folder_store && TNY_IS_FOLDER (folder_store)) {
2455 modest_header_view_set_folder (MODEST_HEADER_VIEW (priv->header_view),
2456 TNY_FOLDER (folder_store), TRUE, MODEST_WINDOW (self),
2458 modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self),
2459 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2460 modest_widget_memory_restore (modest_runtime_get_conf (),
2461 G_OBJECT(priv->header_view),
2462 MODEST_CONF_HEADER_VIEW_KEY);
2463 on_msg_count_changed (MODEST_HEADER_VIEW (priv->header_view), TNY_FOLDER (folder_store), NULL, self);
2467 g_object_unref (folder_store);
2470 g_message ("FOLDER VIEW CELL ACTIVATED");
2475 modest_main_window_screen_is_on (ModestMainWindow *self)
2477 ModestMainWindowPrivate *priv = NULL;
2479 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2481 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2483 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2487 remove_banners (ModestMainWindow *window)
2489 ModestMainWindowPrivate *priv;
2491 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2493 if (priv->opening_banner_timeout > 0) {
2494 g_source_remove (priv->opening_banner_timeout);
2495 priv->opening_banner_timeout = 0;
2498 if (priv->opening_banner != NULL) {
2499 gtk_widget_destroy (priv->opening_banner);
2500 priv->opening_banner = NULL;
2503 if (priv->updating_banner_timeout > 0) {
2504 g_source_remove (priv->updating_banner_timeout);
2505 priv->updating_banner_timeout = 0;
2508 if (priv->updating_banner != NULL) {
2509 gtk_widget_destroy (priv->updating_banner);
2510 priv->updating_banner = NULL;
2516 on_window_hide (GObject *gobject,
2520 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2522 if (!GTK_WIDGET_VISIBLE (gobject)) {
2523 TnyFolderStore *folder_store;
2524 ModestMainWindowPrivate *priv;
2526 /* Remove the currently shown banners */
2527 remove_banners (MODEST_MAIN_WINDOW (gobject));
2529 /* Force the folder view to sync the currently selected folder
2530 to save the read/unread status and to expunge messages */
2531 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2532 folder_store = modest_folder_view_get_selected (priv->folder_view);
2533 if (TNY_IS_FOLDER (folder_store)) {
2534 ModestMailOperation *mail_op;
2536 mail_op = modest_mail_operation_new (NULL);
2537 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2539 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2540 g_object_unref (mail_op);
2541 g_object_unref (folder_store);
2547 on_window_destroy (GtkObject *widget,
2550 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2552 remove_banners (MODEST_MAIN_WINDOW (widget));
2556 opening_banner_destroyed (gpointer data,
2557 GObject *where_the_object_was)
2559 ModestMainWindowPrivate *priv = NULL;
2561 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2563 priv->opening_banner = NULL;
2567 show_opening_banner (gpointer user_data)
2569 ModestMainWindowPrivate *priv = NULL;
2571 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2573 if (priv->opening_banner == NULL) {
2575 /* We're outside the main lock */
2576 gdk_threads_enter ();
2577 priv->opening_banner =
2578 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2579 _("mail_me_opening"));
2581 /* We need this because banners in Maemo could be
2582 destroyed by dialogs so we need to properly update
2583 our reference to it */
2584 g_object_weak_ref (G_OBJECT (priv->opening_banner),
2585 opening_banner_destroyed,
2588 /* We need this because banners in Maemo could be
2589 destroyed by dialogs so we need to properly update
2590 our reference to it */
2591 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2592 updating_banner_destroyed,
2594 gdk_threads_leave ();
2597 /* Remove timeout */
2598 priv->opening_banner_timeout = 0;