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-text-utils.h"
65 #include "modest-signal-mgr.h"
66 #include <tny-gtk-folder-store-tree-model.h>
67 #include <modest-accounts-window.h>
69 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
76 /* 'private'/'protected' functions */
77 static void modest_main_window_class_init (ModestMainWindowClass *klass);
78 static void modest_main_window_init (ModestMainWindow *obj);
79 static void modest_main_window_finalize (GObject *obj);
81 static void connect_signals (ModestMainWindow *self);
83 static void modest_main_window_disconnect_signals (ModestWindow *self);
85 static void restore_settings (ModestMainWindow *self,
86 gboolean do_folder_view_too);
88 static void save_state (ModestWindow *self);
90 static void update_menus (ModestMainWindow* self);
92 static void modest_main_window_show_toolbar (ModestWindow *window,
93 gboolean show_toolbar);
95 static void cancel_progressbar (GtkToolButton *toolbutton,
96 ModestMainWindow *self);
98 static void on_queue_changed (ModestMailOperationQueue *queue,
99 ModestMailOperation *mail_op,
100 ModestMailOperationQueueNotification type,
101 ModestMainWindow *self);
103 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
105 static void on_account_inserted (TnyAccountStore *accoust_store,
109 static void on_account_removed (TnyAccountStore *accoust_store,
113 static void on_account_changed (TnyAccountStore *account_store,
117 static void on_default_account_changed (ModestAccountMgr* mgr,
120 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
124 static void on_configuration_key_changed (ModestConf* conf,
126 ModestConfEvent event,
127 ModestConfNotificationId id,
128 ModestMainWindow *self);
130 static void set_toolbar_mode (ModestMainWindow *self,
131 ModestToolBarModes mode);
133 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
135 static void on_show_account_action_toggled (GtkToggleAction *action,
138 static void on_refresh_account_action_activated (GtkAction *action,
141 static void on_send_receive_csm_activated (GtkMenuItem *item,
144 static void on_folder_view_row_activated (GtkTreeView *tree_view,
145 GtkTreePath *tree_path,
146 GtkTreeViewColumn *column,
148 static void on_msg_count_changed (ModestHeaderView *header_view,
150 TnyFolderChange *change,
151 ModestMainWindow *main_window);
153 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
156 static GtkWidget * create_empty_view (void);
158 static gboolean on_folder_view_focus_in (GtkWidget *widget,
159 GdkEventFocus *event,
162 static gboolean on_header_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static void on_folder_selection_changed (ModestFolderView *folder_view,
167 TnyFolderStore *folder_store,
169 ModestMainWindow *main_window);
171 static void set_at_least_one_account_visible(ModestMainWindow *self);
173 static void on_updating_msg_list (ModestHeaderView *header_view,
177 static gboolean show_opening_banner (gpointer user_data);
179 static void on_window_destroy (GtkObject *widget,
182 static void on_window_hide (GObject *gobject,
186 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
187 struct _ModestMainWindowPrivate {
188 GtkWidget *main_vbox;
189 GtkWidget *contents_widget;
190 GtkWidget *empty_view;
192 /* Progress observers */
193 GtkWidget *progress_bar;
194 GSList *progress_widgets;
197 GtkWidget *progress_toolitem;
198 GtkWidget *cancel_toolitem;
199 GtkWidget *sort_toolitem;
200 GtkWidget *refresh_toolitem;
201 ModestToolBarModes current_toolbar_mode;
203 /* Merge ids used to add/remove accounts to the Accounts Menu*/
204 GByteArray *merge_ids;
205 GtkActionGroup *view_additions_group;
207 /* On-demand widgets */
208 GtkWidget *accounts_popup;
209 GtkWidget *details_widget;
211 /* Optimized view enabled */
212 gboolean optimized_view;
214 /* Optimized view enabled */
215 gboolean send_receive_in_progress;
217 ModestHeaderView *header_view;
218 ModestFolderView *folder_view;
220 ModestMainWindowStyle style;
221 ModestMainWindowContentsStyle contents_style;
222 gboolean wait_for_settings;
224 guint progress_bar_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_("ckdg_fi_new_folder_name"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
265 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_rename_folder"), 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_delete_messages"), 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_delete_messages"), 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->main_vbox = NULL;
342 priv->header_view = NULL;
343 priv->folder_view = NULL;
344 priv->contents_widget = NULL;
345 priv->accounts_popup = NULL;
346 priv->details_widget = NULL;
347 priv->empty_view = NULL;
348 priv->progress_widgets = NULL;
349 priv->progress_bar = NULL;
350 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
351 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
352 priv->wait_for_settings = TRUE;
353 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
354 priv->merge_ids = NULL;
355 priv->optimized_view = FALSE;
356 priv->send_receive_in_progress = FALSE;
357 priv->progress_bar_timeout = 0;
358 priv->sighandlers = NULL;
359 priv->updating_banner = NULL;
360 priv->updating_banner_timeout = 0;
361 priv->opening_banner = NULL;
362 priv->opening_banner_timeout = 0;
363 priv->display_state = OSSO_DISPLAY_ON;
365 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
367 "applications_email_mainview");
371 modest_main_window_finalize (GObject *obj)
373 ModestMainWindowPrivate *priv;
375 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
377 /* Sanity check: shouldn't be needed, the window mgr should
378 call this function before */
379 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
380 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
382 if (priv->empty_view) {
383 g_object_unref (priv->empty_view);
384 priv->empty_view = NULL;
387 if (priv->header_view) {
388 g_object_unref (priv->header_view);
389 priv->header_view = NULL;
392 g_slist_free (priv->progress_widgets);
394 g_byte_array_free (priv->merge_ids, TRUE);
396 if (priv->progress_bar_timeout > 0) {
397 g_source_remove (priv->progress_bar_timeout);
398 priv->progress_bar_timeout = 0;
401 if (priv->updating_banner_timeout > 0) {
402 g_source_remove (priv->updating_banner_timeout);
403 priv->updating_banner_timeout = 0;
406 if (priv->updating_banner) {
407 gtk_widget_destroy (priv->updating_banner);
408 priv->updating_banner = NULL;
411 if (priv->opening_banner_timeout > 0) {
412 g_source_remove (priv->opening_banner_timeout);
413 priv->opening_banner_timeout = 0;
416 if (priv->opening_banner) {
417 gtk_widget_destroy (priv->opening_banner);
418 priv->opening_banner = NULL;
421 G_OBJECT_CLASS(parent_class)->finalize (obj);
425 modest_main_window_get_child_widget (ModestMainWindow *self,
426 ModestMainWindowWidgetType widget_type)
428 ModestMainWindowPrivate *priv;
431 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
432 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
435 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
437 switch (widget_type) {
438 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
439 widget = (GtkWidget*)priv->header_view; break;
440 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
441 widget = (GtkWidget*)priv->folder_view; break;
446 /* Note that the window could have been destroyed, and so
447 their children, but still have some references */
448 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
453 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
456 ModestMainWindowPrivate *priv;
458 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
460 conf = modest_runtime_get_conf ();
462 modest_widget_memory_restore (conf, G_OBJECT(self),
463 MODEST_CONF_MAIN_WINDOW_KEY);
465 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
466 MODEST_CONF_HEADER_VIEW_KEY);
468 if (do_folder_view_too)
469 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
470 MODEST_CONF_FOLDER_VIEW_KEY);
472 gtk_widget_show (GTK_WIDGET (self));
477 save_state (ModestWindow *window)
480 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
484 conf = modest_runtime_get_conf ();
486 modest_widget_memory_save (conf,G_OBJECT(self),
487 MODEST_CONF_MAIN_WINDOW_KEY);
488 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
489 MODEST_CONF_FOLDER_VIEW_KEY);
493 compare_display_names (ModestAccountSettings *a,
494 ModestAccountSettings *b)
496 return g_utf8_collate (modest_account_settings_get_display_name (a),
497 modest_account_settings_get_display_name (b));
501 /* We use this function to prevent the send&receive CSM to be shown
502 when there are less than two account */
504 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
510 update_menus (ModestMainWindow* self)
512 GSList *account_names, *iter, *accounts;
513 ModestMainWindowPrivate *priv;
514 ModestWindowPrivate *parent_priv;
515 ModestAccountMgr *mgr;
516 gint i, num_accounts;
518 gchar *default_account;
519 const gchar *active_account_name;
520 GtkWidget *send_receive_button, *item;
521 GtkAction *send_receive_all = NULL;
524 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
525 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
527 /* Get enabled account IDs */
528 mgr = modest_runtime_get_account_mgr ();
529 account_names = modest_account_mgr_account_names (mgr, TRUE);
530 iter = account_names;
534 ModestAccountSettings *settings =
535 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
536 accounts = g_slist_prepend (accounts, settings);
540 modest_account_mgr_free_account_names (account_names);
541 account_names = NULL;
543 /* Order the list of accounts by its display name */
544 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
545 num_accounts = g_slist_length (accounts);
547 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
548 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
549 gtk_action_set_visible (send_receive_all, num_accounts > 0);
551 /* Delete old send&receive popup items. We can not just do a
552 menu_detach because it does not work well with
554 if (priv->accounts_popup)
555 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
556 (GtkCallback) gtk_widget_destroy, NULL);
558 /* Delete old entries in the View menu. Do not free groups, it
560 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
562 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
563 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
564 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
565 GTK_ACTION_GROUP (groups->data));
568 if (priv->merge_ids) {
569 for (i = 0; i < priv->merge_ids->len; i++)
570 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
571 g_byte_array_free (priv->merge_ids, TRUE);
573 /* We need to call this in order to ensure
574 that the new actions are added in the right
575 order (alphabetical) */
576 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
578 groups = g_list_next (groups);
580 priv->merge_ids = g_byte_array_sized_new (num_accounts);
582 /* Get send receive button */
583 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
584 "/ToolBar/ToolbarSendReceive");
586 /* Create the menu */
587 if (num_accounts > 1) {
588 if (!priv->accounts_popup)
589 priv->accounts_popup = gtk_menu_new ();
590 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
591 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
592 g_signal_connect (G_OBJECT (item),
594 G_CALLBACK (on_send_receive_csm_activated),
596 item = gtk_separator_menu_item_new ();
597 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
600 /* Create a new action group */
601 default_account = modest_account_mgr_get_default_account (mgr);
602 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
604 if (!active_account_name)
605 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
607 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
609 for (i = 0; i < num_accounts; i++) {
610 gchar *display_name = NULL;
611 const gchar *account_name;
612 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
615 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
618 account_name = modest_account_settings_get_account_name (settings);
620 if (default_account && account_name &&
621 !(strcmp (default_account, account_name) == 0)) {
622 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
623 modest_account_settings_get_display_name (settings));
625 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
626 modest_account_settings_get_display_name (settings));
631 /* Create action and add it to the action group. The
632 action name must be the account name, this way we
633 could know in the handlers the account to show */
634 if (settings && account_name) {
635 gchar* item_name, *refresh_action_name;
637 GtkAction *view_account_action, *refresh_account_action;
638 gchar *escaped_display_name;
640 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
642 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
643 escaped_display_name, NULL, NULL, 0));
644 g_free (escaped_display_name);
645 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
646 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
647 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
649 if (active_account_name) {
650 if (active_account_name && account_name &&
651 (strcmp (active_account_name, account_name) == 0)) {
652 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
656 /* Add ui from account data. We allow 2^9-1 account
657 changes in a single execution because we're
658 downcasting the guint to a guint8 in order to use a
659 GByteArray. It should be enough :-) */
660 item_name = g_strconcat (account_name, "Menu", NULL);
661 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
662 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
663 gtk_ui_manager_add_ui (parent_priv->ui_manager,
665 "/MenuBar/AccountsMenu/AccountsMenuAdditions",
668 GTK_UI_MANAGER_MENUITEM,
671 /* Connect the action signal "activate" */
672 g_signal_connect_after (G_OBJECT (view_account_action),
674 G_CALLBACK (on_show_account_action_toggled),
677 /* Create the items for the Tools->Send&Receive submenu */
678 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
679 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
680 display_name, NULL, NULL);
681 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
683 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
684 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
685 gtk_ui_manager_add_ui (parent_priv->ui_manager,
687 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
690 GTK_UI_MANAGER_MENUITEM,
692 g_free (refresh_action_name);
694 g_signal_connect_data (G_OBJECT (refresh_account_action),
696 G_CALLBACK (on_refresh_account_action_activated),
697 g_strdup (account_name),
698 (GClosureNotify) g_free,
701 /* Create item and add it to the send&receive
702 CSM. If there is only one account then
704 if (num_accounts > 1) {
705 GtkWidget *label = gtk_label_new(NULL);
706 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
707 if (default_account && (strcmp(account_name, default_account) == 0)) {
708 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
709 gtk_label_set_markup (GTK_LABEL (label), escaped);
712 gtk_label_set_text (GTK_LABEL (label), display_name);
715 item = gtk_menu_item_new ();
716 gtk_container_add (GTK_CONTAINER (item), label);
718 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
720 g_signal_connect_data (G_OBJECT (item),
722 G_CALLBACK (on_send_receive_csm_activated),
723 g_strdup (account_name),
724 (GClosureNotify) g_free,
731 g_free (display_name);
734 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
736 /* We cannot do this in the loop above because this relies on the action
737 * group being inserted. This makes the default account appear in bold.
738 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
739 for (i = 0; i < num_accounts; i++) {
740 gchar *item_name, *path;
742 ModestAccountSettings *settings;
743 const gchar *account_name;
746 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
747 account_name = modest_account_settings_get_account_name (settings);
748 is_default = (account_name && default_account && !strcmp (account_name, default_account));
750 /* Get the item of the view menu */
751 item_name = g_strconcat (account_name, "Menu", NULL);
752 path = g_strconcat ("/MenuBar/AccountsMenu/AccountsMenuAdditions/", item_name, NULL);
753 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
757 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
758 if (GTK_IS_LABEL (child)) {
759 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
761 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
762 gtk_label_set_markup (GTK_LABEL (child), bold_name);
768 /* Get the item of the tools menu */
769 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
770 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
774 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
775 if (GTK_IS_LABEL (child)) {
776 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
778 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
779 gtk_label_set_markup (GTK_LABEL (child), bold_name);
782 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
787 g_object_unref (settings);
790 if (num_accounts > 1) {
791 /* Disconnect the tap-and-hold-query if it's connected */
792 if (modest_signal_mgr_is_connected (priv->sighandlers,
793 G_OBJECT (send_receive_button),
794 "tap-and-hold-query"))
795 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
796 G_OBJECT (send_receive_button),
797 "tap-and-hold-query");
799 /* Mandatory in order to view the menu contents */
800 gtk_widget_show_all (priv->accounts_popup);
802 /* Setup tap_and_hold just if was not done before*/
803 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
804 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
806 /* Connect the tap-and-hold-query in order not to show the CSM */
807 if (!modest_signal_mgr_is_connected (priv->sighandlers,
808 G_OBJECT (send_receive_button),
809 "tap-and-hold-query"))
810 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
811 G_OBJECT (send_receive_button),
812 "tap-and-hold-query",
813 G_CALLBACK (tap_and_hold_query_cb),
818 g_slist_free (accounts);
819 g_free (default_account);
822 /* Make sure that at least one account is viewed if there are any
823 * accounts, for instance when adding the first account: */
824 set_at_least_one_account_visible (self);
828 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
830 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
831 gtk_scrolled_window_add_with_viewport
832 (GTK_SCROLLED_WINDOW(win), widget);
834 gtk_container_add (GTK_CONTAINER(win),
845 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
847 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
849 GList *oerrsignals = priv->queue_err_signals;
850 while (oerrsignals) {
851 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
852 g_signal_handler_disconnect (esignal->queue, esignal->signal);
853 g_slice_free (QueueErrorSignal, esignal);
854 oerrsignals = g_list_next (oerrsignals);
856 g_list_free (priv->queue_err_signals);
857 priv->queue_err_signals = NULL;
862 modest_main_window_disconnect_signals (ModestWindow *self)
864 ModestMainWindowPrivate *priv;
865 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
867 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
868 priv->sighandlers = NULL;
872 connect_signals (ModestMainWindow *self)
874 ModestWindowPrivate *parent_priv;
875 ModestMainWindowPrivate *priv;
877 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
878 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
883 modest_signal_mgr_connect (priv->sighandlers,
884 G_OBJECT(priv->folder_view), "key-press-event",
885 G_CALLBACK(on_inner_widgets_key_pressed), self);
887 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
888 "folder_selection_changed",
889 G_CALLBACK (on_folder_selection_changed),
892 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
893 "folder-display-name-changed",
894 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
897 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
899 G_CALLBACK (on_folder_view_focus_in),
902 /* folder view row activated */
903 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "row-activated",
904 G_CALLBACK(on_folder_view_row_activated),
909 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
910 G_CALLBACK(modest_ui_actions_on_header_selected), self);
912 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
913 G_CALLBACK(modest_ui_actions_on_header_activated), self);
915 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
916 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
918 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
919 G_CALLBACK(on_inner_widgets_key_pressed), self);
921 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
922 G_CALLBACK(on_msg_count_changed), self);
924 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
925 G_CALLBACK (on_header_view_focus_in), self);
927 modest_signal_mgr_connect (priv->sighandlers,
928 G_OBJECT (priv->header_view),
930 G_CALLBACK (on_updating_msg_list),
934 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
935 * in destroy stage */
936 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
938 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
940 /* Mail Operation Queue */
942 modest_signal_mgr_connect (priv->sighandlers,
943 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
945 G_CALLBACK (on_queue_changed), self);
947 /* Track changes in the device name */
949 modest_signal_mgr_connect (priv->sighandlers,
950 G_OBJECT(modest_runtime_get_conf ()),
952 G_CALLBACK (on_configuration_key_changed),
955 /* Track account changes. We need to refresh the toolbar */
957 modest_signal_mgr_connect (priv->sighandlers,
958 G_OBJECT (modest_runtime_get_account_store ()),
960 G_CALLBACK (on_account_inserted),
963 modest_signal_mgr_connect (priv->sighandlers,
964 G_OBJECT (modest_runtime_get_account_store ()),
966 G_CALLBACK (on_account_removed),
969 /* We need to refresh the send & receive menu to change the bold
970 * account when the default account changes. */
972 modest_signal_mgr_connect (priv->sighandlers,
973 G_OBJECT (modest_runtime_get_account_mgr ()),
974 "default_account_changed",
975 G_CALLBACK (on_default_account_changed),
980 modest_signal_mgr_connect (priv->sighandlers,
981 G_OBJECT (modest_runtime_get_account_store ()),
983 G_CALLBACK (on_account_changed),
988 on_hildon_program_is_topmost_notify(GObject *self,
989 GParamSpec *propert_param,
992 HildonProgram *app = HILDON_PROGRAM (self);
994 /* Note that use of hildon_program_set_can_hibernate()
995 * is generally referred to as "setting the killable flag",
996 * though hibernation does not seem equal to death.
999 if (hildon_program_get_is_topmost (app)) {
1000 /* Prevent hibernation when the progam comes to the foreground,
1001 * because hibernation should only happen when the application
1002 * is in the background: */
1003 hildon_program_set_can_hibernate (app, FALSE);
1005 /* Remove new mail visual notifications */
1006 modest_platform_remove_new_mail_notifications (TRUE);
1008 /* Allow hibernation if the program has gone to the background: */
1010 /* However, prevent hibernation while the settings are being changed: */
1011 const gboolean hibernation_prevented =
1012 modest_window_mgr_get_hibernation_is_prevented (
1013 modest_runtime_get_window_mgr ());
1015 if (hibernation_prevented)
1016 hildon_program_set_can_hibernate (app, FALSE);
1018 /* Allow hibernation, after saving the state: */
1019 hildon_program_set_can_hibernate (app, TRUE);
1030 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1032 ShowHelper *helper = (ShowHelper *) user_data;
1033 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1035 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1036 modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self),
1037 MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS);
1038 gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->folder_view));
1040 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1042 /* Connect signals */
1043 connect_signals (MODEST_MAIN_WINDOW (self));
1045 /* Set account store */
1046 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1047 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1049 /* Restore window & widget settings */
1050 priv->wait_for_settings = TRUE;
1051 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1052 priv->wait_for_settings = FALSE;
1054 /* Check if accounts exist and show the account wizard if not */
1055 gboolean accounts_exist =
1056 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1058 if (!accounts_exist) {
1059 /* This is necessary to have the main window shown behind the dialog
1060 It's an ugly hack... jschmid */
1061 gtk_widget_show_all(GTK_WIDGET(self));
1062 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1064 update_menus (MODEST_MAIN_WINDOW (self));
1067 /* Never call this function again (NOTE that it could happen
1068 as we hide the main window instead of closing it while
1069 there are operations ongoing) and free the helper */
1070 g_signal_handler_disconnect (self, helper->handler_id);
1071 g_slice_free (ShowHelper, helper);
1075 osso_display_event_cb (osso_display_state_t state,
1078 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1080 priv->display_state = state;
1082 /* Stop blinking if the screen becomes on */
1083 if (priv->display_state == OSSO_DISPLAY_ON)
1084 modest_platform_remove_new_mail_notifications (TRUE);
1088 modest_main_window_new (void)
1090 ModestMainWindow *self = NULL;
1091 ModestMainWindowPrivate *priv = NULL;
1092 ModestWindowPrivate *parent_priv = NULL;
1093 ModestDimmingRulesGroup *menu_rules_group = NULL;
1094 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1095 GtkActionGroup *action_group = NULL;
1096 GError *error = NULL;
1098 GdkPixbuf *window_icon;
1101 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1102 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1103 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1105 parent_priv->ui_manager = gtk_ui_manager_new();
1106 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1108 action_group = gtk_action_group_new ("ModestMainWindowActions");
1109 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1111 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1112 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1114 /* Add common actions */
1115 gtk_action_group_add_actions (action_group,
1116 modest_action_entries,
1117 G_N_ELEMENTS (modest_action_entries),
1120 gtk_action_group_add_actions (action_group,
1121 modest_folder_view_action_entries,
1122 G_N_ELEMENTS (modest_folder_view_action_entries),
1125 gtk_action_group_add_actions (action_group,
1126 modest_header_view_action_entries,
1127 G_N_ELEMENTS (modest_header_view_action_entries),
1130 gtk_action_group_add_toggle_actions (action_group,
1131 modest_main_window_toggle_action_entries,
1132 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1135 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1136 g_object_unref (action_group);
1138 /* Load the UI definition */
1139 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1140 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1141 if (error != NULL) {
1142 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1143 g_error_free (error);
1147 /* Add common dimming rules */
1148 modest_dimming_rules_group_add_rules (menu_rules_group,
1149 modest_main_window_menu_dimming_entries,
1150 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1151 MODEST_WINDOW (self));
1152 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1153 modest_main_window_toolbar_dimming_entries,
1154 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1155 MODEST_WINDOW (self));
1157 /* Insert dimming rules group for this window */
1158 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1159 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1160 g_object_unref (menu_rules_group);
1161 g_object_unref (toolbar_rules_group);
1163 /* Add accelerators */
1164 gtk_window_add_accel_group (GTK_WINDOW (self),
1165 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1167 /* Menubar. Update the state of some toggles */
1168 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1169 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1170 gtk_widget_show (parent_priv->menubar);
1172 /* Get device name */
1173 modest_maemo_utils_get_device_name ();
1177 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1178 g_object_ref (priv->header_view);
1179 if (!priv->header_view)
1180 g_printerr ("modest: cannot instantiate header view\n");
1181 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1182 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1183 MODEST_CONF_HEADER_VIEW_KEY);
1185 /* Other style properties of header view */
1186 g_object_set (G_OBJECT (priv->header_view),
1187 "rules-hint", FALSE,
1189 /* gtk_widget_show (priv->header_view); */
1192 priv->empty_view = create_empty_view ();
1193 gtk_widget_show (priv->empty_view);
1194 g_object_ref (priv->empty_view);
1196 /* Create scrolled windows */
1197 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1198 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1200 GTK_POLICY_AUTOMATIC);
1201 /* gtk_widget_show (priv->contents_widget); */
1203 /* putting it all together... */
1204 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1205 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->contents_widget, TRUE, TRUE,0);
1206 gtk_widget_show (priv->main_vbox);
1208 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1210 app = hildon_program_get_instance ();
1211 hildon_program_add_window (app, HILDON_WINDOW (self));
1213 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1214 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1216 /* Connect to "show" action. We delay the creation of some
1217 elements until that moment */
1218 helper = g_slice_new0 (ShowHelper);
1219 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1220 G_CALLBACK (modest_main_window_on_show),
1223 /* Set window icon */
1224 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1226 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1227 g_object_unref (window_icon);
1230 /* Listen for changes in the screen, we don't want to show a
1231 led pattern when the display is on for example */
1232 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1233 osso_display_event_cb,
1236 /* Dont't restore settings here,
1237 * because it requires a gtk_widget_show(),
1238 * and we don't want to do that until later,
1239 * so that the UI is not visible for non-menu D-Bus activation.
1242 return MODEST_WINDOW(self);
1246 modest_main_window_set_style (ModestMainWindow *self,
1247 ModestMainWindowStyle style)
1249 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1251 /* We only provide simple style */
1255 ModestMainWindowStyle
1256 modest_main_window_get_style (ModestMainWindow *self)
1258 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1260 return MODEST_MAIN_WINDOW_STYLE_SIMPLE;
1264 toolbar_resize (ModestMainWindow *self)
1266 ModestMainWindowPrivate *priv = NULL;
1267 ModestWindowPrivate *parent_priv = NULL;
1269 gint static_button_size;
1270 ModestWindowMgr *mgr;
1272 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1273 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1274 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1276 mgr = modest_runtime_get_window_mgr ();
1277 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1279 if (parent_priv->toolbar) {
1280 /* left size buttons */
1281 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1282 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1283 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1284 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1285 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1286 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1287 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1288 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1289 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1290 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1291 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1292 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1293 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1294 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1295 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1296 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1298 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1299 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1300 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1301 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1302 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1303 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1304 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1305 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1311 modest_main_window_show_toolbar (ModestWindow *self,
1312 gboolean show_toolbar)
1314 ModestMainWindowPrivate *priv = NULL;
1315 ModestWindowPrivate *parent_priv = NULL;
1316 GtkWidget *reply_button = NULL, *menu = NULL;
1317 GtkWidget *placeholder = NULL;
1320 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1321 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1322 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1324 /* Set optimized view status */
1325 priv->optimized_view = !show_toolbar;
1327 if (!parent_priv->toolbar) {
1328 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1330 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1332 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1333 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1334 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1335 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1336 toolbar_resize (MODEST_MAIN_WINDOW (self));
1338 /* Add ProgressBar (Transfer toolbar) */
1339 priv->progress_bar = modest_progress_bar_new ();
1340 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1341 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1342 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1343 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1344 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1346 /* Connect cancel 'clicked' signal to abort progress mode */
1347 g_signal_connect(priv->cancel_toolitem, "clicked",
1348 G_CALLBACK(cancel_progressbar),
1351 /* Add it to the observers list */
1352 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1355 hildon_window_add_toolbar (HILDON_WINDOW (self),
1356 GTK_TOOLBAR (parent_priv->toolbar));
1358 /* Set reply button tap and hold menu */
1359 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1360 "/ToolBar/ToolbarMessageReply");
1361 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1362 "/ToolbarReplyCSM");
1363 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1365 /* Set send & receive button tap and hold menu */
1366 update_menus (MODEST_MAIN_WINDOW (self));
1370 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1371 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1372 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1374 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1375 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1376 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1378 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1380 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1386 on_account_inserted (TnyAccountStore *accoust_store,
1387 TnyAccount *account,
1390 /* Transport accounts and local ones (MMC and the Local
1391 folders account do now cause menu changes */
1392 if (TNY_IS_STORE_ACCOUNT (account) &&
1393 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1395 update_menus (MODEST_MAIN_WINDOW (user_data));
1400 on_default_account_changed (ModestAccountMgr* mgr,
1403 update_menus (MODEST_MAIN_WINDOW (user_data));
1407 on_account_removed (TnyAccountStore *accoust_store,
1408 TnyAccount *account,
1411 /* Transport accounts and local ones (MMC and the Local
1412 folders account do now cause menu changes */
1413 if (TNY_IS_STORE_ACCOUNT (account) &&
1414 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1415 update_menus (MODEST_MAIN_WINDOW (user_data));
1419 on_account_changed (TnyAccountStore *account_store,
1420 TnyAccount *account,
1423 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1425 /* Transport accounts and local ones (MMC and the Local
1426 folders account do now cause menu changes */
1427 if (TNY_IS_STORE_ACCOUNT (account)) {
1428 /* Update the menus as well, name could change */
1429 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1430 update_menus (MODEST_MAIN_WINDOW (win));
1435 * This function manages the key events used to navigate between
1436 * header and folder views (when the window is in split view)
1439 * -------------------------------------------------
1440 * HeaderView GDK_Left Move focus to folder view
1441 * FolderView GDK_Right Move focus to header view
1443 * There is no need to scroll to selected row, the widgets will be the
1444 * responsibles of doing that (probably managing the focus-in event
1447 on_inner_widgets_key_pressed (GtkWidget *widget,
1451 ModestMainWindowPrivate *priv;
1453 if (event->type == GDK_KEY_RELEASE)
1456 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1458 /* Do nothing if we're in SIMPLE style */
1459 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1462 if (MODEST_IS_HEADER_VIEW (widget)) {
1463 if (event->keyval == GDK_Left)
1464 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1465 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1466 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1467 if (selected_headers > 1) {
1468 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1471 GtkTreePath * cursor_path;
1472 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1473 if (cursor_path == NULL) {
1474 GtkTreeSelection *selection;
1476 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1477 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1480 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1481 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1486 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1487 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1488 GtkTreePath *selected_path = NULL;
1489 GtkTreePath *start_path = NULL;
1490 GtkTreePath *end_path = NULL;
1492 GtkTreeSelection *selection;
1494 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1495 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1496 if (selected != NULL) {
1497 selected_path = (GtkTreePath *) selected->data;
1498 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1502 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1503 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1505 /* Scroll to first path */
1506 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1515 gtk_tree_path_free (start_path);
1517 gtk_tree_path_free (end_path);
1518 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1519 g_list_free (selected);
1521 #endif /* GTK_CHECK_VERSION */
1523 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1530 create_empty_view (void)
1532 GtkLabel *label = NULL;
1533 GtkWidget *align = NULL;
1535 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1536 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1537 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1538 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1540 return GTK_WIDGET(align);
1545 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1547 ModestMainWindowPrivate *priv = NULL;
1549 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1551 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1553 return priv->send_receive_in_progress;
1557 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1559 GtkAction *action = NULL;
1560 GtkWidget *widget = NULL;
1561 ModestMainWindowPrivate *priv = NULL;
1563 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1564 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1566 priv->send_receive_in_progress = TRUE;
1568 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1569 gtk_action_set_sensitive (action, FALSE);
1570 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1571 /* gtk_action_set_sensitive (action, FALSE); */
1572 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1573 gtk_widget_set_sensitive (widget, FALSE);
1577 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1579 GtkAction *action = NULL;
1580 GtkWidget *widget = NULL;
1581 ModestMainWindowPrivate *priv = NULL;
1583 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1584 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1586 priv->send_receive_in_progress = FALSE;
1588 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1589 gtk_action_set_sensitive (action, TRUE);
1590 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1591 /* gtk_action_set_sensitive (action, TRUE); */
1592 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1593 gtk_widget_set_sensitive (widget, TRUE);
1598 on_msg_count_changed (ModestHeaderView *header_view,
1600 TnyFolderChange *change,
1601 ModestMainWindow *main_window)
1603 gboolean refilter = FALSE;
1604 gboolean folder_empty = FALSE;
1605 gboolean all_marked_as_deleted = FALSE;
1606 ModestMainWindowPrivate *priv;
1608 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1609 g_return_if_fail (TNY_IS_FOLDER(folder));
1610 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1612 if (change != NULL) {
1613 TnyFolderChangeChanged changed;
1615 changed = tny_folder_change_get_changed (change);
1616 /* If something changes */
1617 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1618 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1620 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1622 /* Play a sound (if configured) and make the LED blink */
1623 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1624 modest_platform_push_email_notification ();
1627 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1630 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1633 /* Check if all messages are marked to be deleted */
1634 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1635 folder_empty = folder_empty || all_marked_as_deleted;
1637 /* Set contents style of headers view */
1638 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY ||
1639 priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1641 modest_main_window_set_contents_style (main_window,
1642 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1643 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1645 modest_main_window_set_contents_style (main_window,
1646 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1651 modest_header_view_refilter (header_view);
1656 modest_main_window_set_contents_style (ModestMainWindow *self,
1657 ModestMainWindowContentsStyle style)
1659 ModestMainWindowPrivate *priv;
1661 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1663 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1665 /* We allow to set the same content style than the previously
1666 set if there are details, because it could happen when we're
1667 selecting different accounts consecutively */
1668 if ((priv->contents_style == style) &&
1669 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1672 /* Remove previous child. Delete it if it was an account
1674 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1676 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1677 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1680 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1683 priv->contents_style = style;
1685 switch (priv->contents_style) {
1686 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS:
1687 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->folder_view));
1688 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1690 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1692 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1693 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1694 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1696 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1697 gtk_widget_show (GTK_WIDGET (priv->header_view));
1699 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1700 g_warning ("This view is not supported in Fremantle style");
1702 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1703 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1704 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1706 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1707 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
1710 g_return_if_reached ();
1714 gtk_widget_show_all (priv->contents_widget);
1717 ModestMainWindowContentsStyle
1718 modest_main_window_get_contents_style (ModestMainWindow *self)
1720 ModestMainWindowPrivate *priv;
1722 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1724 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1725 return priv->contents_style;
1730 on_configuration_key_changed (ModestConf* conf,
1732 ModestConfEvent event,
1733 ModestConfNotificationId id,
1734 ModestMainWindow *self)
1736 /* TODO: remove this handler. Now we don't support details view,
1737 * so this must be removed */
1743 set_toolbar_transfer_mode (ModestMainWindow *self)
1745 ModestMainWindowPrivate *priv = NULL;
1747 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1749 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1751 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1753 if (priv->progress_bar_timeout > 0) {
1754 g_source_remove (priv->progress_bar_timeout);
1755 priv->progress_bar_timeout = 0;
1762 set_toolbar_mode (ModestMainWindow *self,
1763 ModestToolBarModes mode)
1765 ModestWindowPrivate *parent_priv = NULL;
1766 ModestMainWindowPrivate *priv = NULL;
1767 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1769 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1771 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1772 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1774 /* In case this was called before the toolbar exists: */
1775 if (!(parent_priv->toolbar))
1778 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1780 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1781 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1782 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1784 /* Sets current toolbar mode */
1785 priv->current_toolbar_mode = mode;
1787 /* Checks the dimming rules */
1788 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1789 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1791 /* Show and hide toolbar items */
1793 case TOOLBAR_MODE_NORMAL:
1795 gtk_action_set_visible (sort_action, TRUE);
1797 gtk_action_set_visible (refresh_action, TRUE);
1798 if (priv->progress_toolitem) {
1799 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1800 gtk_widget_hide (priv->progress_toolitem);
1802 if (priv->progress_bar)
1803 gtk_widget_hide (priv->progress_bar);
1806 gtk_action_set_visible (cancel_action, FALSE);
1808 /* Hide toolbar if optimized view is enabled */
1809 if (priv->optimized_view)
1810 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1812 case TOOLBAR_MODE_TRANSFER:
1814 gtk_action_set_visible (sort_action, FALSE);
1816 gtk_action_set_visible (refresh_action, FALSE);
1818 gtk_action_set_visible (cancel_action, TRUE);
1819 if (priv->progress_bar)
1820 gtk_widget_show (priv->progress_bar);
1821 if (priv->progress_toolitem) {
1822 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1823 gtk_widget_show (priv->progress_toolitem);
1826 /* Show toolbar if it's hiden (optimized view ) */
1827 if (priv->optimized_view)
1828 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1831 g_return_if_reached ();
1836 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1838 ModestMainWindowPrivate *priv;
1840 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1841 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1843 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1847 cancel_progressbar (GtkToolButton *toolbutton,
1848 ModestMainWindow *self)
1851 ModestMainWindowPrivate *priv;
1853 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1855 /* Get operation observers and cancel all the operations */
1856 tmp = priv->progress_widgets;
1858 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1859 tmp=g_slist_next(tmp);
1864 observers_empty (ModestMainWindow *self)
1867 ModestMainWindowPrivate *priv;
1868 gboolean is_empty = TRUE;
1869 guint pending_ops = 0;
1871 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1872 tmp = priv->progress_widgets;
1874 /* Check all observers */
1875 while (tmp && is_empty) {
1876 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1877 is_empty = pending_ops == 0;
1879 tmp = g_slist_next(tmp);
1887 * Gets the toolbar mode needed for each mail operation. It stores in
1888 * @mode_changed if the toolbar mode has changed or not
1890 static ModestToolBarModes
1891 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
1892 ModestMailOperation *mail_op,
1893 gboolean *mode_changed)
1895 ModestToolBarModes mode;
1896 ModestMainWindowPrivate *priv;
1898 *mode_changed = FALSE;
1899 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1901 /* Get toolbar mode from operation id*/
1902 switch (modest_mail_operation_get_type_operation (mail_op)) {
1903 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
1904 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1905 mode = TOOLBAR_MODE_TRANSFER;
1906 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1907 *mode_changed = TRUE;
1910 mode = TOOLBAR_MODE_NORMAL;
1916 on_mail_operation_started (ModestMailOperation *mail_op,
1919 ModestMainWindow *self;
1920 ModestMailOperationTypeOperation op_type;
1921 ModestMainWindowPrivate *priv;
1922 ModestToolBarModes mode;
1924 gboolean mode_changed = FALSE;
1925 TnyAccount *account = NULL;
1927 self = MODEST_MAIN_WINDOW (user_data);
1928 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1930 /* Do not show progress for receiving operations if the
1931 account is the local account or the MMC one */
1932 op_type = modest_mail_operation_get_type_operation (mail_op);
1933 account = modest_mail_operation_get_account (mail_op);
1934 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
1937 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
1938 modest_tny_account_is_memory_card_account (account));
1940 g_object_unref (account);
1944 /* Show information banner. Remove old timeout */
1945 if (priv->opening_banner_timeout > 0) {
1946 g_source_remove (priv->opening_banner_timeout);
1947 priv->opening_banner_timeout = 0;
1949 /* Create a new timeout */
1950 priv->opening_banner_timeout =
1951 g_timeout_add (2000, show_opening_banner, self);
1954 /* Not every mail operation has account, noop does not */
1956 g_object_unref (account);
1958 /* Get toolbar mode from operation id*/
1959 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
1961 /* Add operation observers and change toolbar if neccessary*/
1962 tmp = priv->progress_widgets;
1963 if (mode == TOOLBAR_MODE_TRANSFER) {
1965 GObject *source = modest_mail_operation_get_source(mail_op);
1966 if (G_OBJECT (self) == source) {
1967 set_toolbar_transfer_mode(self);
1969 g_object_unref (source);
1973 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1975 tmp = g_slist_next (tmp);
1979 /* Update the main menu as well, we need to explicitely do
1980 this in order to enable/disable accelerators */
1981 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1985 on_mail_operation_finished (ModestMailOperation *mail_op,
1988 ModestToolBarModes mode;
1989 ModestMailOperationTypeOperation op_type;
1991 ModestMainWindow *self;
1992 gboolean mode_changed;
1993 TnyAccount *account = NULL;
1994 ModestMainWindowPrivate *priv;
1996 self = MODEST_MAIN_WINDOW (user_data);
1997 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1999 /* The mail operation was not added to the progress objects if
2000 the account was the local account or the MMC one */
2001 op_type = modest_mail_operation_get_type_operation (mail_op);
2002 account = modest_mail_operation_get_account (mail_op);
2003 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2006 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2007 modest_tny_account_is_memory_card_account (account));
2009 g_object_unref (account);
2013 /* Remove old timeout */
2014 if (priv->opening_banner_timeout > 0) {
2015 g_source_remove (priv->opening_banner_timeout);
2016 priv->opening_banner_timeout = 0;
2019 /* Remove the banner if exists */
2020 if (priv->opening_banner) {
2021 gtk_widget_destroy (priv->opening_banner);
2022 priv->opening_banner = NULL;
2026 /* Not every mail operation has account, noop does not */
2028 g_object_unref (account);
2030 /* Get toolbar mode from operation id*/
2031 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2033 /* Change toolbar mode */
2034 tmp = priv->progress_widgets;
2035 if (mode == TOOLBAR_MODE_TRANSFER) {
2037 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2039 tmp = g_slist_next (tmp);
2042 /* If no more operations are being observed, NORMAL mode is enabled again */
2043 if (observers_empty (self)) {
2044 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2050 on_queue_changed (ModestMailOperationQueue *queue,
2051 ModestMailOperation *mail_op,
2052 ModestMailOperationQueueNotification type,
2053 ModestMainWindow *self)
2055 ModestMainWindowPrivate *priv;
2057 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2059 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2060 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2062 "operation-started",
2063 G_CALLBACK (on_mail_operation_started),
2065 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2067 "operation-finished",
2068 G_CALLBACK (on_mail_operation_finished),
2070 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2071 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2073 "operation-started");
2074 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2076 "operation-finished");
2081 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2083 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2085 ModestAccountMgr *mgr;
2086 ModestAccountSettings *settings;
2087 ModestServerAccountSettings *store_settings = NULL;
2089 /* GtkWidget *folder_window; */
2091 /* folder_window = GTK_WIDGET (modest_folder_window_new (NULL)); */
2092 /* modest_window_mgr_register_window (modest_runtime_get_window_mgr (), */
2093 /* MODEST_WINDOW (folder_window), */
2094 /* MODEST_WINDOW (self)); */
2095 /* gtk_widget_show (folder_window); */
2096 GtkWidget *accounts_window;
2098 accounts_window = GTK_WIDGET (modest_accounts_window_new ());
2099 modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
2100 MODEST_WINDOW (accounts_window),
2101 MODEST_WINDOW (self));
2102 gtk_widget_show (accounts_window);
2104 /* Get account data */
2105 mgr = modest_runtime_get_account_mgr ();
2106 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2108 store_settings = modest_account_settings_get_store_settings (settings);
2110 /* Set the new visible & active account */
2111 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2112 const gchar *account_name;
2114 account_name = modest_account_settings_get_account_name (settings);
2116 modest_folder_view_set_account_id_of_visible_server_account
2118 modest_server_account_settings_get_account_name (store_settings));
2119 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2120 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2122 /* modest_folder_window_set_account (MODEST_FOLDER_WINDOW (folder_window), acc_name); */
2124 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2125 if (action != NULL) {
2126 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2127 modest_utils_toggle_action_set_active_block_notify (
2128 GTK_TOGGLE_ACTION (action),
2136 g_object_unref (store_settings);
2137 g_object_unref (settings);
2142 /* Make sure that at least one account is "viewed": */
2144 set_at_least_one_account_visible(ModestMainWindow *self)
2146 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2147 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2149 if (!(priv->folder_view)) {
2150 /* It is too early to do this. */
2154 const gchar *active_server_account_name =
2155 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2157 if (!active_server_account_name ||
2158 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2160 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2161 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2162 if (default_modest_name) {
2163 set_account_visible (self, default_modest_name);
2164 } else if (first_modest_name) {
2165 set_account_visible (self, first_modest_name);
2167 g_free (first_modest_name);
2168 g_free (default_modest_name);
2173 on_show_account_action_toggled (GtkToggleAction *action,
2176 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2178 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2179 if (gtk_toggle_action_get_active (action))
2180 set_account_visible (self, acc_name);
2184 refresh_account (const gchar *account_name)
2188 /* win must already exists here, obviously */
2189 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2192 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2196 /* If account_name == NULL, we must update all (option All) */
2198 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2200 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2205 on_refresh_account_action_activated (GtkAction *action,
2208 refresh_account ((const gchar*) user_data);
2212 on_send_receive_csm_activated (GtkMenuItem *item,
2215 refresh_account ((const gchar*) user_data);
2219 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2221 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2223 hildon_banner_show_information (NULL, NULL, _CS("ckct_ib_cannot_zoom_here"));
2229 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2231 ModestMainWindow *main_window = NULL;
2233 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2234 main_window = MODEST_MAIN_WINDOW (userdata);
2236 /* Update toolbar dimming state */
2237 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2238 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2244 on_header_view_focus_in (GtkWidget *widget,
2245 GdkEventFocus *event,
2248 ModestMainWindow *main_window = NULL;
2250 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2252 main_window = MODEST_MAIN_WINDOW (userdata);
2254 /* Update toolbar dimming state */
2255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2262 on_folder_selection_changed (ModestFolderView *folder_view,
2263 TnyFolderStore *folder_store,
2265 ModestMainWindow *main_window)
2267 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2268 GtkAction *action = NULL;
2269 gboolean show_reply = TRUE;
2270 gboolean show_forward = TRUE;
2271 gboolean show_cancel_send = FALSE;
2272 gboolean show_clipboard = TRUE;
2273 gboolean show_delete = TRUE;
2276 if (TNY_IS_ACCOUNT (folder_store)) {
2277 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2278 } else if (TNY_IS_FOLDER (folder_store)) {
2279 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2280 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2281 TNY_FOLDER (folder_store));
2282 switch (folder_type) {
2283 case TNY_FOLDER_TYPE_DRAFTS:
2284 show_clipboard = show_delete = TRUE;
2285 show_reply = show_forward = show_cancel_send = FALSE;
2287 case TNY_FOLDER_TYPE_SENT:
2288 show_forward = show_clipboard = show_delete = TRUE;
2289 show_reply = show_cancel_send = FALSE;
2291 case TNY_FOLDER_TYPE_OUTBOX:
2292 show_clipboard = show_delete = show_cancel_send = TRUE;
2293 show_reply = show_forward = FALSE;
2295 case TNY_FOLDER_TYPE_INVALID:
2296 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2299 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2300 show_cancel_send = FALSE;
2303 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2304 show_cancel_send = FALSE;
2309 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2310 gtk_action_set_visible (action, show_reply);
2311 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2312 gtk_action_set_visible (action, show_reply);
2313 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2314 gtk_action_set_visible (action, show_forward);
2315 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2316 gtk_action_set_visible (action, show_cancel_send);
2317 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2318 gtk_action_set_visible (action, show_delete);
2323 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2324 GtkTreeModel *model,
2325 GtkTreeRowReference *row_reference,
2326 ModestMainWindow *self)
2328 ModestMainWindowPrivate *priv = NULL;
2329 GtkTreeModel *header_model = NULL;
2330 GtkTreePath *path = NULL;
2332 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2333 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2334 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2336 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2337 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2339 /* Do nothing if we changed the folder in the main view */
2340 if (header_model != model)
2343 /* Select the message in the header view */
2344 path = gtk_tree_row_reference_get_path (row_reference);
2345 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2347 gtk_tree_path_free (path);
2353 updating_banner_destroyed (gpointer data,
2354 GObject *where_the_object_was)
2356 ModestMainWindowPrivate *priv = NULL;
2358 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2360 priv->updating_banner = NULL;
2364 show_updating_banner (gpointer user_data)
2366 ModestMainWindowPrivate *priv = NULL;
2368 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2370 if (priv->updating_banner == NULL) {
2372 /* We're outside the main lock */
2373 gdk_threads_enter ();
2374 priv->updating_banner =
2375 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2376 _CS ("ckdg_pb_updating"));
2378 /* We need this because banners in Maemo could be
2379 destroyed by dialogs so we need to properly update
2380 our reference to it */
2381 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2382 updating_banner_destroyed,
2384 gdk_threads_leave ();
2387 /* Remove timeout */
2388 priv->updating_banner_timeout = 0;
2393 * We use this function to show/hide a progress banner showing
2394 * "Updating" while the header view is being filled. We're not showing
2395 * it unless the update takes more than 2 seconds
2397 * If starting = TRUE then the refresh is starting, otherwise it means
2398 * that is has just finished
2401 on_updating_msg_list (ModestHeaderView *header_view,
2405 ModestMainWindowPrivate *priv = NULL;
2407 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2409 /* Remove old timeout */
2410 if (priv->updating_banner_timeout > 0) {
2411 g_source_remove (priv->updating_banner_timeout);
2412 priv->updating_banner_timeout = 0;
2415 /* Create a new timeout */
2417 priv->updating_banner_timeout =
2418 g_timeout_add (2000, show_updating_banner, user_data);
2420 /* Remove the banner if exists */
2421 if (priv->updating_banner) {
2422 gtk_widget_destroy (priv->updating_banner);
2423 priv->updating_banner = NULL;
2428 static void on_folder_view_row_activated (GtkTreeView *tree_view,
2429 GtkTreePath *tree_path,
2430 GtkTreeViewColumn *column,
2433 GtkTreeModel *model;
2435 TnyFolderStore *folder_store = NULL;
2436 ModestMainWindow *self = (ModestMainWindow *) userdata;
2437 ModestMainWindowPrivate *priv = NULL;
2439 g_return_if_fail (MODEST_IS_MAIN_WINDOW(self));
2440 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2442 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
2444 if (gtk_tree_model_get_iter (model, &iter, tree_path)) {
2445 gtk_tree_model_get (model, &iter,
2446 TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder_store,
2448 if (folder_store && TNY_IS_FOLDER (folder_store)) {
2449 modest_header_view_set_folder (MODEST_HEADER_VIEW (priv->header_view),
2450 TNY_FOLDER (folder_store), TRUE, MODEST_WINDOW (self),
2452 modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self),
2453 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2454 modest_widget_memory_restore (modest_runtime_get_conf (),
2455 G_OBJECT(priv->header_view),
2456 MODEST_CONF_HEADER_VIEW_KEY);
2457 on_msg_count_changed (MODEST_HEADER_VIEW (priv->header_view), TNY_FOLDER (folder_store), NULL, self);
2461 g_object_unref (folder_store);
2464 g_debug ("FOLDER VIEW CELL ACTIVATED");
2469 modest_main_window_screen_is_on (ModestMainWindow *self)
2471 ModestMainWindowPrivate *priv = NULL;
2473 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2475 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2477 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2481 remove_banners (ModestMainWindow *window)
2483 ModestMainWindowPrivate *priv;
2485 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2487 if (priv->opening_banner_timeout > 0) {
2488 g_source_remove (priv->opening_banner_timeout);
2489 priv->opening_banner_timeout = 0;
2492 if (priv->opening_banner != NULL) {
2493 gtk_widget_destroy (priv->opening_banner);
2494 priv->opening_banner = NULL;
2497 if (priv->updating_banner_timeout > 0) {
2498 g_source_remove (priv->updating_banner_timeout);
2499 priv->updating_banner_timeout = 0;
2502 if (priv->updating_banner != NULL) {
2503 gtk_widget_destroy (priv->updating_banner);
2504 priv->updating_banner = NULL;
2510 on_window_hide (GObject *gobject,
2514 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2516 if (!GTK_WIDGET_VISIBLE (gobject)) {
2517 TnyFolderStore *folder_store;
2518 ModestMainWindowPrivate *priv;
2520 /* Remove the currently shown banners */
2521 remove_banners (MODEST_MAIN_WINDOW (gobject));
2523 /* Force the folder view to sync the currently selected folder
2524 to save the read/unread status and to expunge messages */
2525 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2526 folder_store = modest_folder_view_get_selected (priv->folder_view);
2527 if (TNY_IS_FOLDER (folder_store)) {
2528 ModestMailOperation *mail_op;
2530 mail_op = modest_mail_operation_new (NULL);
2531 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2533 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE, NULL, NULL);
2534 g_object_unref (mail_op);
2535 g_object_unref (folder_store);
2541 on_window_destroy (GtkObject *widget,
2544 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2546 remove_banners (MODEST_MAIN_WINDOW (widget));
2550 opening_banner_destroyed (gpointer data,
2551 GObject *where_the_object_was)
2553 ModestMainWindowPrivate *priv = NULL;
2555 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2557 priv->opening_banner = NULL;
2561 show_opening_banner (gpointer user_data)
2563 ModestMainWindowPrivate *priv = NULL;
2565 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2567 if (priv->opening_banner == NULL) {
2569 /* We're outside the main lock */
2570 gdk_threads_enter ();
2571 priv->opening_banner =
2572 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2573 _("mail_me_opening"));
2575 /* We need this because banners in Maemo could be
2576 destroyed by dialogs so we need to properly update
2577 our reference to it */
2578 g_object_weak_ref (G_OBJECT (priv->opening_banner),
2579 opening_banner_destroyed,
2582 /* We need this because banners in Maemo could be
2583 destroyed by dialogs so we need to properly update
2584 our reference to it */
2585 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2586 updating_banner_destroyed,
2588 gdk_threads_leave ();
2591 /* Remove timeout */
2592 priv->opening_banner_timeout = 0;