1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-error.h>
37 #include "modest-hildon-includes.h"
38 #include "modest-defs.h"
40 #include "widgets/modest-header-view-priv.h"
41 #include "widgets/modest-main-window.h"
42 #include "widgets/modest-msg-edit-window.h"
43 #include "widgets/modest-account-view-window.h"
44 #include "modest-runtime.h"
45 #include "modest-account-mgr-helpers.h"
46 #include "modest-platform.h"
47 #include "modest-widget-memory.h"
48 #include "modest-window-priv.h"
49 #include "modest-main-window-ui.h"
50 #include "modest-main-window-ui-dimming.h"
51 #include "modest-account-mgr.h"
52 #include "modest-tny-account.h"
53 #include "modest-tny-folder.h"
54 #include "modest-conf.h"
55 #include <modest-utils.h>
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
66 #include "modest-signal-mgr.h"
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
75 /* 'private'/'protected' functions */
76 static void modest_main_window_class_init (ModestMainWindowClass *klass);
77 static void modest_main_window_init (ModestMainWindow *obj);
78 static void modest_main_window_finalize (GObject *obj);
80 static void connect_signals (ModestMainWindow *self);
82 static void modest_main_window_disconnect_signals (ModestWindow *self);
84 static void restore_settings (ModestMainWindow *self,
85 gboolean do_folder_view_too);
87 static void save_state (ModestWindow *self);
89 static void update_menus (ModestMainWindow* self);
91 static void modest_main_window_show_toolbar (ModestWindow *window,
92 gboolean show_toolbar);
94 static void cancel_progressbar (GtkToolButton *toolbutton,
95 ModestMainWindow *self);
97 static void on_queue_changed (ModestMailOperationQueue *queue,
98 ModestMailOperation *mail_op,
99 ModestMailOperationQueueNotification type,
100 ModestMainWindow *self);
102 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
104 static void on_account_inserted (TnyAccountStore *accoust_store,
108 static void on_account_removed (TnyAccountStore *accoust_store,
112 static void on_account_changed (TnyAccountStore *account_store,
116 static void on_default_account_changed (ModestAccountMgr* mgr,
119 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
123 static void on_configuration_key_changed (ModestConf* conf,
125 ModestConfEvent event,
126 ModestConfNotificationId id,
127 ModestMainWindow *self);
129 static void set_toolbar_mode (ModestMainWindow *self,
130 ModestToolBarModes mode);
132 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
134 static void on_show_account_action_toggled (GtkToggleAction *action,
137 static void on_refresh_account_action_activated (GtkAction *action,
140 static void on_send_receive_csm_activated (GtkMenuItem *item,
143 static void on_msg_count_changed (ModestHeaderView *header_view,
145 TnyFolderChange *change,
146 ModestMainWindow *main_window);
148 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
151 static GtkWidget * create_empty_view (void);
153 static gboolean on_folder_view_focus_in (GtkWidget *widget,
154 GdkEventFocus *event,
157 static gboolean on_header_view_focus_in (GtkWidget *widget,
158 GdkEventFocus *event,
161 static void on_folder_selection_changed (ModestFolderView *folder_view,
162 TnyFolderStore *folder_store,
164 ModestMainWindow *main_window);
166 static void set_at_least_one_account_visible(ModestMainWindow *self);
168 static void on_updating_msg_list (ModestHeaderView *header_view,
172 static gboolean restore_paned_timeout_handler (gpointer *data);
174 static gboolean show_opening_banner (gpointer user_data);
176 static void on_window_destroy (GtkObject *widget,
179 static void on_window_hide (GObject *gobject,
183 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
184 struct _ModestMainWindowPrivate {
185 GtkWidget *msg_paned;
186 GtkWidget *main_paned;
187 GtkWidget *main_vbox;
188 GtkWidget *contents_widget;
189 GtkWidget *empty_view;
191 /* Progress observers */
192 GtkWidget *progress_bar;
193 GSList *progress_widgets;
196 GtkWidget *progress_toolitem;
197 GtkWidget *cancel_toolitem;
198 GtkWidget *sort_toolitem;
199 GtkWidget *refresh_toolitem;
200 ModestToolBarModes current_toolbar_mode;
202 /* Merge ids used to add/remove accounts to the Accounts Menu*/
203 GByteArray *merge_ids;
204 GtkActionGroup *view_additions_group;
206 /* On-demand widgets */
207 GtkWidget *accounts_popup;
208 GtkWidget *details_widget;
210 /* Optimized view enabled */
211 gboolean optimized_view;
213 /* Optimized view enabled */
214 gboolean send_receive_in_progress;
216 ModestHeaderView *header_view;
217 ModestFolderView *folder_view;
219 ModestMainWindowStyle style;
220 ModestMainWindowContentsStyle contents_style;
221 gboolean wait_for_settings;
223 guint progress_bar_timeout;
224 guint restore_paned_timeout;
226 /* Signal handler UIDs */
227 GList *queue_err_signals;
230 /* "Updating" banner for header view */
231 GtkWidget *updating_banner;
232 guint updating_banner_timeout;
234 /* "Opening" banner for header view */
235 GtkWidget *opening_banner;
236 guint opening_banner_timeout;
239 osso_display_state_t display_state;
241 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
242 MODEST_TYPE_MAIN_WINDOW, \
243 ModestMainWindowPrivate))
245 typedef struct _GetMsgAsyncHelper {
246 ModestMainWindowPrivate *main_window_private;
248 ModestTnyMsgReplyType reply_type;
249 ModestTnyMsgForwardType forward_type;
256 static GtkWindowClass *parent_class = NULL;
259 /* Private actions */
260 /* This is the context sensitive menu: */
261 static const GtkActionEntry modest_folder_view_action_entries [] = {
263 /* Folder View CSM actions */
264 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
265 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
266 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
267 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
268 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
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_inbox_delete"), 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) },
283 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
286 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
287 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
290 /************************************************************************/
293 modest_main_window_get_type (void)
295 static GType my_type = 0;
297 static const GTypeInfo my_info = {
298 sizeof(ModestMainWindowClass),
299 NULL, /* base init */
300 NULL, /* base finalize */
301 (GClassInitFunc) modest_main_window_class_init,
302 NULL, /* class finalize */
303 NULL, /* class data */
304 sizeof(ModestMainWindow),
306 (GInstanceInitFunc) modest_main_window_init,
309 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
317 modest_main_window_class_init (ModestMainWindowClass *klass)
319 GObjectClass *gobject_class;
320 gobject_class = (GObjectClass*) klass;
321 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
323 parent_class = g_type_class_peek_parent (klass);
324 gobject_class->finalize = modest_main_window_finalize;
326 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
328 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
329 modest_window_class->save_state_func = save_state;
330 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
331 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
332 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
336 modest_main_window_init (ModestMainWindow *obj)
338 ModestMainWindowPrivate *priv;
340 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
342 priv->queue_err_signals = NULL;
343 priv->msg_paned = NULL;
344 priv->main_paned = NULL;
345 priv->main_vbox = NULL;
346 priv->header_view = NULL;
347 priv->folder_view = NULL;
348 priv->contents_widget = NULL;
349 priv->accounts_popup = NULL;
350 priv->details_widget = NULL;
351 priv->empty_view = NULL;
352 priv->progress_widgets = NULL;
353 priv->progress_bar = NULL;
354 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
355 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
356 priv->wait_for_settings = TRUE;
357 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
358 priv->merge_ids = NULL;
359 priv->optimized_view = FALSE;
360 priv->send_receive_in_progress = FALSE;
361 priv->progress_bar_timeout = 0;
362 priv->restore_paned_timeout = 0;
363 priv->sighandlers = NULL;
364 priv->updating_banner = NULL;
365 priv->updating_banner_timeout = 0;
366 priv->opening_banner = NULL;
367 priv->opening_banner_timeout = 0;
368 priv->display_state = OSSO_DISPLAY_ON;
370 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
372 "applications_email_mainview");
376 modest_main_window_finalize (GObject *obj)
378 ModestMainWindowPrivate *priv;
380 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
382 /* Sanity check: shouldn't be needed, the window mgr should
383 call this function before */
384 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
385 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
387 if (priv->empty_view) {
388 g_object_unref (priv->empty_view);
389 priv->empty_view = NULL;
392 if (priv->header_view) {
393 g_object_unref (priv->header_view);
394 priv->header_view = NULL;
397 g_slist_free (priv->progress_widgets);
399 g_byte_array_free (priv->merge_ids, TRUE);
401 if (priv->progress_bar_timeout > 0) {
402 g_source_remove (priv->progress_bar_timeout);
403 priv->progress_bar_timeout = 0;
406 if (priv->updating_banner_timeout > 0) {
407 g_source_remove (priv->updating_banner_timeout);
408 priv->updating_banner_timeout = 0;
411 if (priv->updating_banner) {
412 gtk_widget_destroy (priv->updating_banner);
413 priv->updating_banner = NULL;
416 if (priv->opening_banner_timeout > 0) {
417 g_source_remove (priv->opening_banner_timeout);
418 priv->opening_banner_timeout = 0;
421 if (priv->opening_banner) {
422 gtk_widget_destroy (priv->opening_banner);
423 priv->opening_banner = NULL;
426 if (priv->restore_paned_timeout > 0) {
427 g_source_remove (priv->restore_paned_timeout);
428 priv->restore_paned_timeout = 0;
431 G_OBJECT_CLASS(parent_class)->finalize (obj);
435 modest_main_window_get_child_widget (ModestMainWindow *self,
436 ModestMainWindowWidgetType widget_type)
438 ModestMainWindowPrivate *priv;
441 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
442 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
445 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
447 switch (widget_type) {
448 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
449 widget = (GtkWidget*)priv->header_view; break;
450 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
451 widget = (GtkWidget*)priv->folder_view; break;
456 /* Note that the window could have been destroyed, and so
457 their children, but still have some references */
458 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
462 restore_paned_timeout_handler (gpointer *data)
464 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
465 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
468 /* Timeouts are outside the main lock */
469 gdk_threads_enter ();
470 if (GTK_WIDGET_VISIBLE (main_window)) {
471 conf = modest_runtime_get_conf ();
472 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
473 MODEST_CONF_MAIN_PANED_KEY);
475 gdk_threads_leave ();
482 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
485 ModestMainWindowPrivate *priv;
487 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
489 conf = modest_runtime_get_conf ();
491 modest_widget_memory_restore (conf, G_OBJECT(self),
492 MODEST_CONF_MAIN_WINDOW_KEY);
494 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
495 MODEST_CONF_HEADER_VIEW_KEY);
497 if (do_folder_view_too)
498 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
499 MODEST_CONF_FOLDER_VIEW_KEY);
501 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
502 /* MODEST_CONF_MAIN_PANED_KEY); */
504 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
506 /* We need to force a redraw here in order to get the right
507 position of the horizontal paned separator */
508 gtk_widget_show (GTK_WIDGET (self));
513 save_state (ModestWindow *window)
516 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
517 ModestMainWindowPrivate *priv;
519 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
520 conf = modest_runtime_get_conf ();
522 modest_widget_memory_save (conf,G_OBJECT(self),
523 MODEST_CONF_MAIN_WINDOW_KEY);
524 /* Only save main paned position if we're in split mode */
525 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
526 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
527 MODEST_CONF_MAIN_PANED_KEY);
528 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
529 MODEST_CONF_FOLDER_VIEW_KEY);
533 compare_display_names (ModestAccountSettings *a,
534 ModestAccountSettings *b)
536 return g_utf8_collate (modest_account_settings_get_display_name (a),
537 modest_account_settings_get_display_name (b));
541 /* We use this function to prevent the send&receive CSM to be shown
542 when there are less than two account */
544 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
550 update_menus (ModestMainWindow* self)
552 GSList *account_names, *iter, *accounts;
553 ModestMainWindowPrivate *priv;
554 ModestWindowPrivate *parent_priv;
555 ModestAccountMgr *mgr;
556 gint i, num_accounts;
558 gchar *default_account;
559 const gchar *active_account_name;
560 GtkWidget *send_receive_button, *item;
561 GtkAction *send_receive_all = NULL;
564 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
565 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
567 /* Get enabled account IDs */
568 mgr = modest_runtime_get_account_mgr ();
569 account_names = modest_account_mgr_account_names (mgr, TRUE);
570 iter = account_names;
574 ModestAccountSettings *settings =
575 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
576 accounts = g_slist_prepend (accounts, settings);
580 modest_account_mgr_free_account_names (account_names);
581 account_names = NULL;
583 /* Order the list of accounts by its display name */
584 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
585 num_accounts = g_slist_length (accounts);
587 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
588 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
589 gtk_action_set_visible (send_receive_all, num_accounts > 0);
591 /* Delete old send&receive popup items. We can not just do a
592 menu_detach because it does not work well with
594 if (priv->accounts_popup)
595 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
596 (GtkCallback) gtk_widget_destroy, NULL);
598 /* Delete old entries in the View menu. Do not free groups, it
600 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
602 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
603 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
604 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
605 GTK_ACTION_GROUP (groups->data));
608 if (priv->merge_ids) {
609 for (i = 0; i < priv->merge_ids->len; i++)
610 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
611 g_byte_array_free (priv->merge_ids, TRUE);
613 /* We need to call this in order to ensure
614 that the new actions are added in the right
615 order (alphabetical) */
616 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
618 groups = g_list_next (groups);
620 priv->merge_ids = g_byte_array_sized_new (num_accounts);
622 /* Get send receive button */
623 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
624 "/ToolBar/ToolbarSendReceive");
626 /* Create the menu */
627 if (num_accounts > 1) {
628 if (!priv->accounts_popup)
629 priv->accounts_popup = gtk_menu_new ();
630 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
631 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
632 g_signal_connect (G_OBJECT (item),
634 G_CALLBACK (on_send_receive_csm_activated),
636 item = gtk_separator_menu_item_new ();
637 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
640 /* Create a new action group */
641 default_account = modest_account_mgr_get_default_account (mgr);
642 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
644 if (!active_account_name)
645 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
647 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
649 for (i = 0; i < num_accounts; i++) {
650 gchar *display_name = NULL;
651 const gchar *account_name;
652 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
655 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
658 account_name = modest_account_settings_get_account_name (settings);
660 if (default_account && account_name &&
661 !(strcmp (default_account, account_name) == 0)) {
662 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
663 modest_account_settings_get_display_name (settings));
665 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
666 modest_account_settings_get_display_name (settings));
671 /* Create action and add it to the action group. The
672 action name must be the account name, this way we
673 could know in the handlers the account to show */
674 if (settings && account_name) {
675 gchar* item_name, *refresh_action_name;
677 GtkAction *view_account_action, *refresh_account_action;
678 gchar *escaped_display_name;
680 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
682 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
683 escaped_display_name, NULL, NULL, 0));
684 g_free (escaped_display_name);
685 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
686 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
687 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
689 if (active_account_name) {
690 if (active_account_name && account_name &&
691 (strcmp (active_account_name, account_name) == 0)) {
692 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
696 /* Add ui from account data. We allow 2^9-1 account
697 changes in a single execution because we're
698 downcasting the guint to a guint8 in order to use a
699 GByteArray. It should be enough :-) */
700 item_name = g_strconcat (account_name, "Menu", NULL);
701 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
702 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
703 gtk_ui_manager_add_ui (parent_priv->ui_manager,
705 "/MenuBar/AccountsMenu/AccountsMenuAdditions",
708 GTK_UI_MANAGER_MENUITEM,
711 /* Connect the action signal "activate" */
712 g_signal_connect_after (G_OBJECT (view_account_action),
714 G_CALLBACK (on_show_account_action_toggled),
717 /* Create the items for the Tools->Send&Receive submenu */
718 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
719 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
720 display_name, NULL, NULL);
721 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
723 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
724 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
725 gtk_ui_manager_add_ui (parent_priv->ui_manager,
727 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
730 GTK_UI_MANAGER_MENUITEM,
732 g_free (refresh_action_name);
734 g_signal_connect_data (G_OBJECT (refresh_account_action),
736 G_CALLBACK (on_refresh_account_action_activated),
737 g_strdup (account_name),
738 (GClosureNotify) g_free,
741 /* Create item and add it to the send&receive
742 CSM. If there is only one account then
744 if (num_accounts > 1) {
745 GtkWidget *label = gtk_label_new(NULL);
746 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
747 if (default_account && (strcmp(account_name, default_account) == 0)) {
748 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
749 gtk_label_set_markup (GTK_LABEL (label), escaped);
752 gtk_label_set_text (GTK_LABEL (label), display_name);
755 item = gtk_menu_item_new ();
756 gtk_container_add (GTK_CONTAINER (item), label);
758 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
760 g_signal_connect_data (G_OBJECT (item),
762 G_CALLBACK (on_send_receive_csm_activated),
763 g_strdup (account_name),
764 (GClosureNotify) g_free,
771 g_free (display_name);
774 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
776 /* We cannot do this in the loop above because this relies on the action
777 * group being inserted. This makes the default account appear in bold.
778 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
779 for (i = 0; i < num_accounts; i++) {
780 gchar *item_name, *path;
782 ModestAccountSettings *settings;
783 const gchar *account_name;
786 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
787 account_name = modest_account_settings_get_account_name (settings);
788 is_default = (account_name && default_account && !strcmp (account_name, default_account));
790 /* Get the item of the view menu */
791 item_name = g_strconcat (account_name, "Menu", NULL);
792 path = g_strconcat ("/MenuBar/AccountsMenu/AccountsMenuAdditions/", item_name, NULL);
793 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
797 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
798 if (GTK_IS_LABEL (child)) {
799 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
801 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
802 gtk_label_set_markup (GTK_LABEL (child), bold_name);
805 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
809 /* Get the item of the tools menu */
810 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
811 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
815 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
816 if (GTK_IS_LABEL (child)) {
817 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
819 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
820 gtk_label_set_markup (GTK_LABEL (child), bold_name);
823 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
828 g_object_unref (settings);
831 if (num_accounts > 1) {
832 /* Disconnect the tap-and-hold-query if it's connected */
833 if (modest_signal_mgr_is_connected (priv->sighandlers,
834 G_OBJECT (send_receive_button),
835 "tap-and-hold-query"))
836 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
837 G_OBJECT (send_receive_button),
838 "tap-and-hold-query");
840 /* Mandatory in order to view the menu contents */
841 gtk_widget_show_all (priv->accounts_popup);
843 /* Setup tap_and_hold just if was not done before*/
844 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
845 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
847 /* Connect the tap-and-hold-query in order not to show the CSM */
848 if (!modest_signal_mgr_is_connected (priv->sighandlers,
849 G_OBJECT (send_receive_button),
850 "tap-and-hold-query"))
851 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
852 G_OBJECT (send_receive_button),
853 "tap-and-hold-query",
854 G_CALLBACK (tap_and_hold_query_cb),
859 g_slist_free (accounts);
860 g_free (default_account);
863 /* Make sure that at least one account is viewed if there are any
864 * accounts, for instance when adding the first account: */
865 set_at_least_one_account_visible (self);
869 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
871 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
872 gtk_scrolled_window_add_with_viewport
873 (GTK_SCROLLED_WINDOW(win), widget);
875 gtk_container_add (GTK_CONTAINER(win),
886 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
888 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
890 GList *oerrsignals = priv->queue_err_signals;
891 while (oerrsignals) {
892 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
893 g_signal_handler_disconnect (esignal->queue, esignal->signal);
894 g_slice_free (QueueErrorSignal, esignal);
895 oerrsignals = g_list_next (oerrsignals);
897 g_list_free (priv->queue_err_signals);
898 priv->queue_err_signals = NULL;
903 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
905 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
908 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
912 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
914 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
916 /* Update visibility */
919 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
923 modest_main_window_disconnect_signals (ModestWindow *self)
925 ModestMainWindowPrivate *priv;
926 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
928 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
929 priv->sighandlers = NULL;
933 connect_signals (ModestMainWindow *self)
935 ModestWindowPrivate *parent_priv;
936 ModestMainWindowPrivate *priv;
939 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
940 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
945 modest_signal_mgr_connect (priv->sighandlers,
946 G_OBJECT(priv->folder_view), "key-press-event",
947 G_CALLBACK(on_inner_widgets_key_pressed), self);
949 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
950 "folder_selection_changed",
951 G_CALLBACK (on_folder_selection_changed),
954 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
955 "folder-display-name-changed",
956 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
959 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
961 G_CALLBACK (on_folder_view_focus_in),
964 /* Folder view CSM */
965 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
966 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
967 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
968 G_CALLBACK(_folder_view_csm_menu_activated),
972 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
973 G_CALLBACK(modest_ui_actions_on_header_selected), self);
975 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
976 G_CALLBACK(modest_ui_actions_on_header_activated), self);
978 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
979 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
981 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
982 G_CALLBACK(on_inner_widgets_key_pressed), self);
984 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
985 G_CALLBACK(on_msg_count_changed), self);
987 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
988 G_CALLBACK (on_header_view_focus_in), self);
990 modest_signal_mgr_connect (priv->sighandlers,
991 G_OBJECT (priv->header_view),
993 G_CALLBACK (on_updating_msg_list),
996 /* Header view CSM */
997 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
998 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1000 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1001 G_CALLBACK(_header_view_csm_menu_activated),
1005 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1006 * in destroy stage */
1007 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1009 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1011 /* Mail Operation Queue */
1013 modest_signal_mgr_connect (priv->sighandlers,
1014 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1016 G_CALLBACK (on_queue_changed), self);
1018 /* Track changes in the device name */
1020 modest_signal_mgr_connect (priv->sighandlers,
1021 G_OBJECT(modest_runtime_get_conf ()),
1023 G_CALLBACK (on_configuration_key_changed),
1026 /* Track account changes. We need to refresh the toolbar */
1028 modest_signal_mgr_connect (priv->sighandlers,
1029 G_OBJECT (modest_runtime_get_account_store ()),
1031 G_CALLBACK (on_account_inserted),
1034 modest_signal_mgr_connect (priv->sighandlers,
1035 G_OBJECT (modest_runtime_get_account_store ()),
1037 G_CALLBACK (on_account_removed),
1040 /* We need to refresh the send & receive menu to change the bold
1041 * account when the default account changes. */
1043 modest_signal_mgr_connect (priv->sighandlers,
1044 G_OBJECT (modest_runtime_get_account_mgr ()),
1045 "default_account_changed",
1046 G_CALLBACK (on_default_account_changed),
1051 modest_signal_mgr_connect (priv->sighandlers,
1052 G_OBJECT (modest_runtime_get_account_store ()),
1054 G_CALLBACK (on_account_changed),
1059 on_hildon_program_is_topmost_notify(GObject *self,
1060 GParamSpec *propert_param,
1063 HildonProgram *app = HILDON_PROGRAM (self);
1065 /* Note that use of hildon_program_set_can_hibernate()
1066 * is generally referred to as "setting the killable flag",
1067 * though hibernation does not seem equal to death.
1070 if (hildon_program_get_is_topmost (app)) {
1071 /* Prevent hibernation when the progam comes to the foreground,
1072 * because hibernation should only happen when the application
1073 * is in the background: */
1074 hildon_program_set_can_hibernate (app, FALSE);
1076 /* Remove new mail visual notifications */
1077 modest_platform_remove_new_mail_notifications (TRUE);
1079 /* Allow hibernation if the program has gone to the background: */
1081 /* However, prevent hibernation while the settings are being changed: */
1082 const gboolean hibernation_prevented =
1083 modest_window_mgr_get_hibernation_is_prevented (
1084 modest_runtime_get_window_mgr ());
1086 if (hibernation_prevented)
1087 hildon_program_set_can_hibernate (app, FALSE);
1089 /* Allow hibernation, after saving the state: */
1090 modest_osso_save_state();
1091 hildon_program_set_can_hibernate (app, TRUE);
1098 GtkWidget *folder_win;
1103 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1105 ShowHelper *helper = (ShowHelper *) user_data;
1106 GtkWidget *folder_win = helper->folder_win;
1107 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1109 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1110 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1112 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1114 /* Connect signals */
1115 connect_signals (MODEST_MAIN_WINDOW (self));
1117 /* Set account store */
1118 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1119 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1121 /* Load previous osso state, for instance if we are being restored from
1123 modest_osso_load_state ();
1125 /* Restore window & widget settings */
1126 priv->wait_for_settings = TRUE;
1127 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1128 priv->wait_for_settings = FALSE;
1130 /* Check if accounts exist and show the account wizard if not */
1131 gboolean accounts_exist =
1132 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1134 if (!accounts_exist) {
1135 /* This is necessary to have the main window shown behind the dialog
1136 It's an ugly hack... jschmid */
1137 gtk_widget_show_all(GTK_WIDGET(self));
1138 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1140 update_menus (MODEST_MAIN_WINDOW (self));
1143 /* Never call this function again (NOTE that it could happen
1144 as we hide the main window instead of closing it while
1145 there are operations ongoing) and free the helper */
1146 g_signal_handler_disconnect (self, helper->handler_id);
1147 g_slice_free (ShowHelper, helper);
1151 osso_display_event_cb (osso_display_state_t state,
1154 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1156 priv->display_state = state;
1158 /* Stop blinking if the screen becomes on */
1159 if (priv->display_state == OSSO_DISPLAY_ON)
1160 modest_platform_remove_new_mail_notifications (TRUE);
1164 modest_main_window_new (void)
1166 ModestMainWindow *self = NULL;
1167 ModestMainWindowPrivate *priv = NULL;
1168 ModestWindowPrivate *parent_priv = NULL;
1169 GtkWidget *folder_win = NULL;
1170 ModestDimmingRulesGroup *menu_rules_group = NULL;
1171 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1172 GtkActionGroup *action_group = NULL;
1173 GError *error = NULL;
1175 GdkPixbuf *window_icon;
1178 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1179 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1180 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1182 parent_priv->ui_manager = gtk_ui_manager_new();
1183 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1185 action_group = gtk_action_group_new ("ModestMainWindowActions");
1186 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1188 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1189 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1191 /* Add common actions */
1192 gtk_action_group_add_actions (action_group,
1193 modest_action_entries,
1194 G_N_ELEMENTS (modest_action_entries),
1197 gtk_action_group_add_actions (action_group,
1198 modest_folder_view_action_entries,
1199 G_N_ELEMENTS (modest_folder_view_action_entries),
1202 gtk_action_group_add_actions (action_group,
1203 modest_header_view_action_entries,
1204 G_N_ELEMENTS (modest_header_view_action_entries),
1207 gtk_action_group_add_toggle_actions (action_group,
1208 modest_main_window_toggle_action_entries,
1209 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1212 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1213 g_object_unref (action_group);
1215 /* Load the UI definition */
1216 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1217 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1218 if (error != NULL) {
1219 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1220 g_error_free (error);
1224 /* Add common dimming rules */
1225 modest_dimming_rules_group_add_rules (menu_rules_group,
1226 modest_main_window_menu_dimming_entries,
1227 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1228 MODEST_WINDOW (self));
1229 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1230 modest_main_window_toolbar_dimming_entries,
1231 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1232 MODEST_WINDOW (self));
1234 /* Insert dimming rules group for this window */
1235 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1236 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1237 g_object_unref (menu_rules_group);
1238 g_object_unref (toolbar_rules_group);
1240 /* Add accelerators */
1241 gtk_window_add_accel_group (GTK_WINDOW (self),
1242 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1244 /* Menubar. Update the state of some toggles */
1245 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1246 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1247 gtk_widget_show (parent_priv->menubar);
1249 /* Get device name */
1250 modest_maemo_utils_get_device_name ();
1254 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1255 g_object_ref (priv->header_view);
1256 if (!priv->header_view)
1257 g_printerr ("modest: cannot instantiate header view\n");
1258 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1259 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1260 MODEST_CONF_HEADER_VIEW_KEY);
1262 /* Other style properties of header view */
1263 g_object_set (G_OBJECT (priv->header_view),
1264 "rules-hint", FALSE,
1266 /* gtk_widget_show (priv->header_view); */
1269 priv->empty_view = create_empty_view ();
1270 gtk_widget_show (priv->empty_view);
1271 g_object_ref (priv->empty_view);
1273 /* Create scrolled windows */
1274 folder_win = gtk_scrolled_window_new (NULL, NULL);
1275 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1276 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1278 GTK_POLICY_AUTOMATIC);
1279 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1281 GTK_POLICY_AUTOMATIC);
1282 /* gtk_widget_show (priv->contents_widget); */
1285 priv->main_paned = gtk_hpaned_new ();
1286 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1287 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1288 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1290 /* putting it all together... */
1291 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1292 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1293 gtk_widget_show (priv->main_vbox);
1295 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1297 app = hildon_program_get_instance ();
1298 hildon_program_add_window (app, HILDON_WINDOW (self));
1300 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1301 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1303 /* Connect to "show" action. We delay the creation of some
1304 elements until that moment */
1305 helper = g_slice_new0 (ShowHelper);
1306 helper->folder_win = folder_win;
1307 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1308 G_CALLBACK (modest_main_window_on_show),
1311 /* Set window icon */
1312 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1314 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1315 g_object_unref (window_icon);
1318 /* Listen for changes in the screen, we don't want to show a
1319 led pattern when the display is on for example */
1320 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1321 osso_display_event_cb,
1324 /* Dont't restore settings here,
1325 * because it requires a gtk_widget_show(),
1326 * and we don't want to do that until later,
1327 * so that the UI is not visible for non-menu D-Bus activation.
1330 return MODEST_WINDOW(self);
1334 modest_main_window_set_style (ModestMainWindow *self,
1335 ModestMainWindowStyle style)
1337 ModestMainWindowPrivate *priv;
1338 ModestWindowPrivate *parent_priv;
1341 GtkTreeSelection *sel;
1344 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1347 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1349 /* no change -> nothing to do */
1350 if (priv->style == style)
1353 /* Get toggle button and update the state if needed. This will
1354 happen only when the set_style is not invoked from the UI,
1355 for example when it's called from widget memory */
1356 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1357 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1358 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1359 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1360 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1361 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1362 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1365 /* We need to store the selection because it's lost when the
1366 widget is reparented */
1367 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1368 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1370 priv->style = style;
1372 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1374 if (!priv->wait_for_settings)
1375 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1376 MODEST_CONF_MAIN_PANED_KEY);
1377 /* Remove main paned */
1378 g_object_ref (priv->main_paned);
1379 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1381 /* Reparent the contents widget to the main vbox */
1382 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1385 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1386 /* Remove header view */
1387 g_object_ref (priv->contents_widget);
1388 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1390 /* Reparent the main paned */
1391 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1392 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1394 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1398 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1400 g_return_if_reached ();
1403 /* Reselect the previously selected folders. We disable the
1404 dimming rules execution during that time because there is
1405 no need to work out it again and it could take a lot of
1406 time if all the headers are selected */
1408 modest_window_disable_dimming (MODEST_WINDOW (self));
1410 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1411 list = g_list_next (list);
1413 modest_window_enable_dimming (MODEST_WINDOW (self));
1416 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1419 /* Let header view grab the focus if it's being shown */
1420 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1421 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1423 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1424 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1426 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1429 /* Check dimming rules */
1430 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1431 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1434 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1437 ModestMainWindowStyle
1438 modest_main_window_get_style (ModestMainWindow *self)
1440 ModestMainWindowPrivate *priv;
1442 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1444 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1449 toolbar_resize (ModestMainWindow *self)
1451 ModestMainWindowPrivate *priv = NULL;
1452 ModestWindowPrivate *parent_priv = NULL;
1454 gint static_button_size;
1455 ModestWindowMgr *mgr;
1457 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1458 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1459 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1461 mgr = modest_runtime_get_window_mgr ();
1462 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1464 if (parent_priv->toolbar) {
1465 /* left size buttons */
1466 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1467 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1468 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1469 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1470 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1471 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1472 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1473 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1474 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1475 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1476 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1477 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1478 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1479 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1480 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1481 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1483 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1484 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1485 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1486 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1487 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1488 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1489 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1490 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1496 modest_main_window_show_toolbar (ModestWindow *self,
1497 gboolean show_toolbar)
1499 ModestMainWindowPrivate *priv = NULL;
1500 ModestWindowPrivate *parent_priv = NULL;
1501 GtkWidget *reply_button = NULL, *menu = NULL;
1502 GtkWidget *placeholder = NULL;
1505 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1506 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1507 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1509 /* Set optimized view status */
1510 priv->optimized_view = !show_toolbar;
1512 if (!parent_priv->toolbar) {
1513 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1515 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1517 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1518 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1519 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1520 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1521 toolbar_resize (MODEST_MAIN_WINDOW (self));
1523 /* Add ProgressBar (Transfer toolbar) */
1524 priv->progress_bar = modest_progress_bar_new ();
1525 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1526 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1527 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1528 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1529 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1531 /* Connect cancel 'clicked' signal to abort progress mode */
1532 g_signal_connect(priv->cancel_toolitem, "clicked",
1533 G_CALLBACK(cancel_progressbar),
1536 /* Add it to the observers list */
1537 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1540 hildon_window_add_toolbar (HILDON_WINDOW (self),
1541 GTK_TOOLBAR (parent_priv->toolbar));
1543 /* Set reply button tap and hold menu */
1544 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1545 "/ToolBar/ToolbarMessageReply");
1546 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1547 "/ToolbarReplyCSM");
1548 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1550 /* Set send & receive button tap and hold menu */
1551 update_menus (MODEST_MAIN_WINDOW (self));
1555 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1556 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1557 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1559 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1560 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1561 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1563 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1565 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1571 on_account_inserted (TnyAccountStore *accoust_store,
1572 TnyAccount *account,
1575 /* Transport accounts and local ones (MMC and the Local
1576 folders account do now cause menu changes */
1577 if (TNY_IS_STORE_ACCOUNT (account) &&
1578 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1580 update_menus (MODEST_MAIN_WINDOW (user_data));
1585 on_default_account_changed (ModestAccountMgr* mgr,
1588 update_menus (MODEST_MAIN_WINDOW (user_data));
1592 on_account_removed (TnyAccountStore *accoust_store,
1593 TnyAccount *account,
1596 /* Transport accounts and local ones (MMC and the Local
1597 folders account do now cause menu changes */
1598 if (TNY_IS_STORE_ACCOUNT (account) &&
1599 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1600 update_menus (MODEST_MAIN_WINDOW (user_data));
1604 on_account_changed (TnyAccountStore *account_store,
1605 TnyAccount *account,
1608 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1610 /* Transport accounts and local ones (MMC and the Local
1611 folders account do now cause menu changes */
1612 if (TNY_IS_STORE_ACCOUNT (account)) {
1613 /* We need to refresh the details widget because it could have changed */
1614 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1615 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1617 /* Update the menus as well, name could change */
1618 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1619 update_menus (MODEST_MAIN_WINDOW (user_data));
1624 * This function manages the key events used to navigate between
1625 * header and folder views (when the window is in split view)
1628 * -------------------------------------------------
1629 * HeaderView GDK_Left Move focus to folder view
1630 * FolderView GDK_Right Move focus to header view
1632 * There is no need to scroll to selected row, the widgets will be the
1633 * responsibles of doing that (probably managing the focus-in event
1636 on_inner_widgets_key_pressed (GtkWidget *widget,
1640 ModestMainWindowPrivate *priv;
1642 if (event->type == GDK_KEY_RELEASE)
1645 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1647 /* Do nothing if we're in SIMPLE style */
1648 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1651 if (MODEST_IS_HEADER_VIEW (widget)) {
1652 if (event->keyval == GDK_Left)
1653 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1654 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1655 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1656 if (selected_headers > 1) {
1657 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1660 GtkTreePath * cursor_path;
1661 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1662 if (cursor_path == NULL) {
1663 GtkTreeSelection *selection;
1665 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1666 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1669 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1670 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1675 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1676 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1677 GtkTreePath *selected_path = NULL;
1678 GtkTreePath *start_path = NULL;
1679 GtkTreePath *end_path = NULL;
1681 GtkTreeSelection *selection;
1683 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1684 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1685 if (selected != NULL) {
1686 selected_path = (GtkTreePath *) selected->data;
1687 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1691 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1692 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1694 /* Scroll to first path */
1695 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1704 gtk_tree_path_free (start_path);
1706 gtk_tree_path_free (end_path);
1707 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1708 g_list_free (selected);
1710 #endif /* GTK_CHECK_VERSION */
1712 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1719 set_alignment (GtkWidget *widget,
1722 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1723 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1727 create_empty_view (void)
1729 GtkLabel *label = NULL;
1730 GtkWidget *align = NULL;
1732 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1733 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1734 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1735 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1737 return GTK_WIDGET(align);
1741 * Free the returned string
1744 get_gray_color_markup (GtkWidget *styled_widget)
1746 gchar *gray_color_markup = NULL;
1747 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1748 /* Obtain the secondary text color. We need a realized widget, that's why
1749 we get styled_widget from outside */
1751 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1752 gray_color_markup = modest_text_utils_get_color_string (&color);
1753 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1755 if (!gray_color_markup)
1756 gray_color_markup = g_strdup ("#BBBBBB");
1758 return gray_color_markup;
1762 * Free the returned string
1765 create_device_name_visual_string (const gchar *device_name,
1766 const gchar *gray_color_markup)
1770 /* We have to use "" to fill the %s of the translation. We can
1771 not just use the device name because the device name is
1772 shown in a different color, so it could not be included
1773 into the <span> tag */
1774 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1775 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1786 GtkWidget *count_label;
1787 GtkWidget *msg_count_label;
1788 GtkWidget *size_label;
1789 gchar *color_markup;
1793 create_uint_label (const gchar *markup,
1797 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1801 create_gchar_label (const gchar *markup,
1805 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1809 update_folder_stats_status_cb (ModestFolderStats stats,
1812 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1815 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1816 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1819 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1820 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1823 if (widgets->size_label) {
1824 tmp = modest_text_utils_get_display_size (stats.local_size);
1825 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1826 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1833 update_folder_stats_cb (ModestFolderStats stats,
1836 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1839 update_folder_stats_status_cb (stats, user_data);
1841 /* frees. Note that the widgets could have been destroyed but
1842 we still keep a reference */
1843 g_free (widgets->color_markup);
1844 if (widgets->count_label)
1845 g_object_unref (widgets->count_label);
1846 if (widgets->msg_count_label)
1847 g_object_unref (widgets->msg_count_label);
1848 if (widgets->size_label)
1849 g_object_unref (widgets->size_label);
1850 g_slice_free (DetailsWidgets, widgets);
1854 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1856 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1861 gchar *gray_color_markup;
1862 DetailsWidgets *widgets;
1864 vbox = gtk_vbox_new (FALSE, 0);
1865 widgets = g_slice_new0 (DetailsWidgets);
1867 gray_color_markup = get_gray_color_markup (styled_widget);
1868 widgets->color_markup = g_strdup (gray_color_markup);
1870 /* Account description: */
1871 if (modest_tny_account_is_virtual_local_folders (account)
1872 || (modest_tny_account_is_memory_card_account (account))) {
1874 /* Get device name */
1875 gchar *device_name = NULL;
1876 if (modest_tny_account_is_virtual_local_folders (account))
1877 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1878 MODEST_CONF_DEVICE_NAME, NULL);
1880 device_name = g_strdup (tny_account_get_name (account));
1882 label = create_device_name_visual_string ((const gchar *) device_name,
1883 (const gchar *) gray_color_markup);
1884 label_w = gtk_label_new (NULL);
1885 gtk_label_set_markup (GTK_LABEL (label_w), label);
1886 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1887 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1888 g_free (device_name);
1891 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1892 gtk_box_pack_start (GTK_BOX (vbox),
1893 gtk_label_new (tny_account_get_name (account)),
1896 /* Other accounts, such as IMAP and POP: */
1901 /* Put proto in uppercase */
1902 proto = g_string_new (tny_account_get_proto (account));
1903 proto = g_string_ascii_up (proto);
1905 /* note: mcen_fi_localroot_description is something like "%s account"
1906 * however, we should display "%s account: %s"... therefore, ugly tmp */
1907 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1908 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1909 gray_color_markup, tmp, tny_account_get_name (account));
1912 label_w = gtk_label_new (NULL);
1913 gtk_label_set_markup (GTK_LABEL (label_w), label);
1914 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1915 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1916 g_string_free (proto, TRUE);
1922 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1923 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1924 label_w = gtk_label_new (NULL);
1925 gtk_label_set_markup (GTK_LABEL (label_w), label);
1926 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1927 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1930 widgets->msg_count_label = g_object_ref (label_w);
1933 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1934 label_w = gtk_label_new (NULL);
1935 gtk_label_set_markup (GTK_LABEL (label_w), label);
1936 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1937 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1940 widgets->count_label = g_object_ref (label_w);
1943 if (modest_tny_account_is_virtual_local_folders (account)
1944 || modest_tny_account_is_memory_card_account (account)) {
1946 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1948 label_w = gtk_label_new (NULL);
1949 gtk_label_set_markup (GTK_LABEL (label_w), label);
1950 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1951 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1954 widgets->size_label = g_object_ref (label_w);
1956 } else if (TNY_IS_ACCOUNT(folder_store)) {
1957 TnyAccount *account = TNY_ACCOUNT(folder_store);
1959 time_t last_updated;
1960 const gchar *last_updated_string;
1961 /* Get last updated from configuration */
1962 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1963 tny_account_get_id (account));
1965 if (last_updated > 0)
1966 last_updated_string = modest_text_utils_get_display_date(last_updated);
1968 last_updated_string = g_strdup (_("mcen_va_never"));
1970 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1971 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1972 label_w = gtk_label_new (NULL);
1973 gtk_label_set_markup (GTK_LABEL (label_w), label);
1974 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1975 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1979 g_free (gray_color_markup);
1981 /* Refresh folder stats asynchronously */
1982 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
1983 update_folder_stats_cb,
1984 update_folder_stats_status_cb,
1988 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1994 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1996 ModestMainWindowPrivate *priv = NULL;
1998 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2000 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2002 return priv->send_receive_in_progress;
2006 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2008 GtkAction *action = NULL;
2009 GtkWidget *widget = NULL;
2010 ModestMainWindowPrivate *priv = NULL;
2012 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2013 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2015 priv->send_receive_in_progress = TRUE;
2017 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2018 gtk_action_set_sensitive (action, FALSE);
2019 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2020 /* gtk_action_set_sensitive (action, FALSE); */
2021 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2022 gtk_widget_set_sensitive (widget, FALSE);
2026 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2028 GtkAction *action = NULL;
2029 GtkWidget *widget = NULL;
2030 ModestMainWindowPrivate *priv = NULL;
2032 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2033 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2035 priv->send_receive_in_progress = FALSE;
2037 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2038 gtk_action_set_sensitive (action, TRUE);
2039 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2040 /* gtk_action_set_sensitive (action, TRUE); */
2041 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2042 gtk_widget_set_sensitive (widget, TRUE);
2047 on_msg_count_changed (ModestHeaderView *header_view,
2049 TnyFolderChange *change,
2050 ModestMainWindow *main_window)
2052 gboolean refilter = FALSE;
2053 gboolean folder_empty = FALSE;
2054 gboolean all_marked_as_deleted = FALSE;
2055 ModestMainWindowPrivate *priv;
2057 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2058 g_return_if_fail (TNY_IS_FOLDER(folder));
2059 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2061 if (change != NULL) {
2062 TnyFolderChangeChanged changed;
2064 changed = tny_folder_change_get_changed (change);
2065 /* If something changes */
2066 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2067 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2069 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2071 /* Play a sound (if configured) and make the LED blink */
2072 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2073 modest_platform_push_email_notification ();
2076 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2079 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2082 /* Check if all messages are marked to be deleted */
2083 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2084 folder_empty = folder_empty || all_marked_as_deleted;
2086 /* Set contents style of headers view */
2088 modest_main_window_set_contents_style (main_window,
2089 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2090 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2092 modest_main_window_set_contents_style (main_window,
2093 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2097 modest_header_view_refilter (header_view);
2102 modest_main_window_set_contents_style (ModestMainWindow *self,
2103 ModestMainWindowContentsStyle style)
2105 ModestMainWindowPrivate *priv;
2107 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2109 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2111 /* We allow to set the same content style than the previously
2112 set if there are details, because it could happen when we're
2113 selecting different accounts consecutively */
2114 if ((priv->contents_style == style) &&
2115 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2118 /* Remove previous child. Delete it if it was an account
2120 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2122 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2123 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2126 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2129 priv->contents_style = style;
2131 switch (priv->contents_style) {
2132 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2133 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2134 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2136 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2137 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2139 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2141 /* if we're started without main win, there may not be a folder
2142 * view. this fixes a GLib-Critical */
2143 if (priv->folder_view) {
2144 TnyFolderStore *selected_folderstore =
2145 modest_folder_view_get_selected (priv->folder_view);
2146 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2147 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2148 TNY_ACCOUNT (selected_folderstore));
2150 wrap_in_scrolled_window (priv->contents_widget,
2151 priv->details_widget);
2153 if (selected_folderstore)
2154 g_object_unref (selected_folderstore);
2155 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2158 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2159 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2162 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2163 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2164 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2166 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2167 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2170 g_return_if_reached ();
2174 gtk_widget_show_all (priv->contents_widget);
2177 ModestMainWindowContentsStyle
2178 modest_main_window_get_contents_style (ModestMainWindow *self)
2180 ModestMainWindowPrivate *priv;
2182 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2184 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2185 return priv->contents_style;
2190 on_configuration_key_changed (ModestConf* conf,
2192 ModestConfEvent event,
2193 ModestConfNotificationId id,
2194 ModestMainWindow *self)
2196 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2197 TnyAccount *account = NULL;
2199 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2202 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2205 if (priv->folder_view)
2206 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2208 if (account && TNY_IS_ACCOUNT (account) &&
2209 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2212 const gchar *device_name;
2213 gchar *new_text, *gray_color_markup;
2216 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2217 label = GTK_LABEL (children->data);
2219 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2220 MODEST_CONF_DEVICE_NAME, NULL);
2222 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2223 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2225 gtk_label_set_markup (label, new_text);
2226 gtk_widget_show (GTK_WIDGET (label));
2228 g_free (gray_color_markup);
2230 g_list_free (children);
2232 g_object_unref (account);
2236 set_toolbar_transfer_mode (ModestMainWindow *self)
2238 ModestMainWindowPrivate *priv = NULL;
2240 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2242 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2244 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2246 if (priv->progress_bar_timeout > 0) {
2247 g_source_remove (priv->progress_bar_timeout);
2248 priv->progress_bar_timeout = 0;
2255 set_toolbar_mode (ModestMainWindow *self,
2256 ModestToolBarModes mode)
2258 ModestWindowPrivate *parent_priv = NULL;
2259 ModestMainWindowPrivate *priv = NULL;
2260 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2262 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2264 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2265 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2267 /* In case this was called before the toolbar exists: */
2268 if (!(parent_priv->toolbar))
2271 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2273 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2274 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2275 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2277 /* Sets current toolbar mode */
2278 priv->current_toolbar_mode = mode;
2280 /* Checks the dimming rules */
2281 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2282 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2284 /* Show and hide toolbar items */
2286 case TOOLBAR_MODE_NORMAL:
2288 gtk_action_set_visible (sort_action, TRUE);
2290 gtk_action_set_visible (refresh_action, TRUE);
2291 if (priv->progress_toolitem) {
2292 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2293 gtk_widget_hide (priv->progress_toolitem);
2295 if (priv->progress_bar)
2296 gtk_widget_hide (priv->progress_bar);
2299 gtk_action_set_visible (cancel_action, FALSE);
2301 /* Hide toolbar if optimized view is enabled */
2302 if (priv->optimized_view)
2303 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2305 case TOOLBAR_MODE_TRANSFER:
2307 gtk_action_set_visible (sort_action, FALSE);
2309 gtk_action_set_visible (refresh_action, FALSE);
2311 gtk_action_set_visible (cancel_action, TRUE);
2312 if (priv->progress_bar)
2313 gtk_widget_show (priv->progress_bar);
2314 if (priv->progress_toolitem) {
2315 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2316 gtk_widget_show (priv->progress_toolitem);
2319 /* Show toolbar if it's hiden (optimized view ) */
2320 if (priv->optimized_view)
2321 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2324 g_return_if_reached ();
2329 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2331 ModestMainWindowPrivate *priv;
2333 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2334 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2336 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2340 cancel_progressbar (GtkToolButton *toolbutton,
2341 ModestMainWindow *self)
2344 ModestMainWindowPrivate *priv;
2346 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2348 /* Get operation observers and cancel all the operations */
2349 tmp = priv->progress_widgets;
2351 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2352 tmp=g_slist_next(tmp);
2357 observers_empty (ModestMainWindow *self)
2360 ModestMainWindowPrivate *priv;
2361 gboolean is_empty = TRUE;
2362 guint pending_ops = 0;
2364 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2365 tmp = priv->progress_widgets;
2367 /* Check all observers */
2368 while (tmp && is_empty) {
2369 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2370 is_empty = pending_ops == 0;
2372 tmp = g_slist_next(tmp);
2380 * Gets the toolbar mode needed for each mail operation. It stores in
2381 * @mode_changed if the toolbar mode has changed or not
2383 static ModestToolBarModes
2384 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2385 ModestMailOperation *mail_op,
2386 gboolean *mode_changed)
2388 ModestToolBarModes mode;
2389 ModestMainWindowPrivate *priv;
2391 *mode_changed = FALSE;
2392 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2394 /* Get toolbar mode from operation id*/
2395 switch (modest_mail_operation_get_type_operation (mail_op)) {
2396 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2397 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2398 mode = TOOLBAR_MODE_TRANSFER;
2399 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2400 *mode_changed = TRUE;
2403 mode = TOOLBAR_MODE_NORMAL;
2409 on_mail_operation_started (ModestMailOperation *mail_op,
2412 ModestMainWindow *self;
2413 ModestMailOperationTypeOperation op_type;
2414 ModestMainWindowPrivate *priv;
2415 ModestToolBarModes mode;
2417 gboolean mode_changed = FALSE;
2418 TnyAccount *account = NULL;
2420 self = MODEST_MAIN_WINDOW (user_data);
2421 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2423 /* Do not show progress for receiving operations if the
2424 account is the local account or the MMC one */
2425 op_type = modest_mail_operation_get_type_operation (mail_op);
2426 account = modest_mail_operation_get_account (mail_op);
2427 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2430 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2431 modest_tny_account_is_memory_card_account (account));
2433 g_object_unref (account);
2437 /* Show information banner. Remove old timeout */
2438 if (priv->opening_banner_timeout > 0) {
2439 g_source_remove (priv->opening_banner_timeout);
2440 priv->opening_banner_timeout = 0;
2442 /* Create a new timeout */
2443 priv->opening_banner_timeout =
2444 g_timeout_add (2000, show_opening_banner, self);
2447 /* Not every mail operation has account, noop does not */
2449 g_object_unref (account);
2451 /* Get toolbar mode from operation id*/
2452 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2454 /* Add operation observers and change toolbar if neccessary*/
2455 tmp = priv->progress_widgets;
2456 if (mode == TOOLBAR_MODE_TRANSFER) {
2458 GObject *source = modest_mail_operation_get_source(mail_op);
2459 if (G_OBJECT (self) == source) {
2460 set_toolbar_transfer_mode(self);
2462 g_object_unref (source);
2466 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2468 tmp = g_slist_next (tmp);
2472 /* Update the main menu as well, we need to explicitely do
2473 this in order to enable/disable accelerators */
2474 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2478 on_mail_operation_finished (ModestMailOperation *mail_op,
2481 ModestToolBarModes mode;
2482 ModestMailOperationTypeOperation op_type;
2484 ModestMainWindow *self;
2485 gboolean mode_changed;
2486 TnyAccount *account = NULL;
2487 ModestMainWindowPrivate *priv;
2489 self = MODEST_MAIN_WINDOW (user_data);
2490 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2492 /* The mail operation was not added to the progress objects if
2493 the account was the local account or the MMC one */
2494 op_type = modest_mail_operation_get_type_operation (mail_op);
2495 account = modest_mail_operation_get_account (mail_op);
2496 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2499 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2500 modest_tny_account_is_memory_card_account (account));
2502 g_object_unref (account);
2506 /* Remove old timeout */
2507 if (priv->opening_banner_timeout > 0) {
2508 g_source_remove (priv->opening_banner_timeout);
2509 priv->opening_banner_timeout = 0;
2512 /* Remove the banner if exists */
2513 if (priv->opening_banner) {
2514 gtk_widget_destroy (priv->opening_banner);
2515 priv->opening_banner = NULL;
2519 /* Not every mail operation has account, noop does not */
2521 g_object_unref (account);
2523 /* Get toolbar mode from operation id*/
2524 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2526 /* Change toolbar mode */
2527 tmp = priv->progress_widgets;
2528 if (mode == TOOLBAR_MODE_TRANSFER) {
2530 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2532 tmp = g_slist_next (tmp);
2535 /* If no more operations are being observed, NORMAL mode is enabled again */
2536 if (observers_empty (self)) {
2537 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2543 on_queue_changed (ModestMailOperationQueue *queue,
2544 ModestMailOperation *mail_op,
2545 ModestMailOperationQueueNotification type,
2546 ModestMainWindow *self)
2548 ModestMainWindowPrivate *priv;
2550 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2552 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2553 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2555 "operation-started",
2556 G_CALLBACK (on_mail_operation_started),
2558 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2560 "operation-finished",
2561 G_CALLBACK (on_mail_operation_finished),
2563 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2564 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2566 "operation-started");
2567 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2569 "operation-finished");
2574 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2576 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2578 ModestAccountMgr *mgr;
2579 ModestAccountSettings *settings;
2580 ModestServerAccountSettings *store_settings = NULL;
2582 /* Get account data */
2583 mgr = modest_runtime_get_account_mgr ();
2584 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2586 store_settings = modest_account_settings_get_store_settings (settings);
2588 /* Set the new visible & active account */
2589 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2590 const gchar *account_name;
2592 account_name = modest_account_settings_get_account_name (settings);
2594 modest_folder_view_set_account_id_of_visible_server_account
2596 modest_server_account_settings_get_account_name (store_settings));
2597 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2598 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2600 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2601 if (action != NULL) {
2602 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2603 modest_utils_toggle_action_set_active_block_notify (
2604 GTK_TOGGLE_ACTION (action),
2612 g_object_unref (store_settings);
2613 g_object_unref (settings);
2617 /* Make sure that at least one account is "viewed": */
2619 set_at_least_one_account_visible(ModestMainWindow *self)
2621 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2622 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2624 if (!(priv->folder_view)) {
2625 /* It is too early to do this. */
2629 const gchar *active_server_account_name =
2630 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2632 if (!active_server_account_name ||
2633 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2635 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2636 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2637 if (default_modest_name) {
2638 set_account_visible (self, default_modest_name);
2639 } else if (first_modest_name) {
2640 set_account_visible (self, first_modest_name);
2642 g_free (first_modest_name);
2643 g_free (default_modest_name);
2648 on_show_account_action_toggled (GtkToggleAction *action,
2651 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2653 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2654 if (gtk_toggle_action_get_active (action))
2655 set_account_visible (self, acc_name);
2659 refresh_account (const gchar *account_name)
2663 /* win must already exists here, obviously */
2664 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2667 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2671 /* If account_name == NULL, we must update all (option All) */
2673 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2675 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2680 on_refresh_account_action_activated (GtkAction *action,
2683 refresh_account ((const gchar*) user_data);
2687 on_send_receive_csm_activated (GtkMenuItem *item,
2690 refresh_account ((const gchar*) user_data);
2694 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2696 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2698 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2704 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2706 ModestMainWindow *main_window = NULL;
2708 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2709 main_window = MODEST_MAIN_WINDOW (userdata);
2711 /* Update toolbar dimming state */
2712 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2713 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2719 on_header_view_focus_in (GtkWidget *widget,
2720 GdkEventFocus *event,
2723 ModestMainWindow *main_window = NULL;
2725 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2727 main_window = MODEST_MAIN_WINDOW (userdata);
2729 /* Update toolbar dimming state */
2730 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2731 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2737 on_folder_selection_changed (ModestFolderView *folder_view,
2738 TnyFolderStore *folder_store,
2740 ModestMainWindow *main_window)
2742 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2743 GtkAction *action = NULL;
2744 gboolean show_reply = TRUE;
2745 gboolean show_forward = TRUE;
2746 gboolean show_cancel_send = FALSE;
2747 gboolean show_clipboard = TRUE;
2748 gboolean show_delete = TRUE;
2751 if (TNY_IS_ACCOUNT (folder_store)) {
2752 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2753 } else if (TNY_IS_FOLDER (folder_store)) {
2754 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2755 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2756 TNY_FOLDER (folder_store));
2757 switch (folder_type) {
2758 case TNY_FOLDER_TYPE_DRAFTS:
2759 show_clipboard = show_delete = TRUE;
2760 show_reply = show_forward = show_cancel_send = FALSE;
2762 case TNY_FOLDER_TYPE_SENT:
2763 show_forward = show_clipboard = show_delete = TRUE;
2764 show_reply = show_cancel_send = FALSE;
2766 case TNY_FOLDER_TYPE_OUTBOX:
2767 show_clipboard = show_delete = show_cancel_send = TRUE;
2768 show_reply = show_forward = FALSE;
2770 case TNY_FOLDER_TYPE_INVALID:
2771 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2774 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2775 show_cancel_send = FALSE;
2778 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2779 show_cancel_send = FALSE;
2784 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2785 gtk_action_set_visible (action, show_reply);
2786 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2787 gtk_action_set_visible (action, show_reply);
2788 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2789 gtk_action_set_visible (action, show_forward);
2790 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2791 gtk_action_set_visible (action, show_cancel_send);
2792 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2793 gtk_action_set_visible (action, show_delete);
2795 /* We finally call to the ui actions handler, after updating properly
2796 * the header view CSM */
2797 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2801 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2802 GtkTreeModel *model,
2803 GtkTreeRowReference *row_reference,
2804 ModestMainWindow *self)
2806 ModestMainWindowPrivate *priv = NULL;
2807 GtkTreeModel *header_model = NULL;
2808 GtkTreePath *path = NULL;
2810 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2811 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2812 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2814 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2815 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2817 /* Do nothing if we changed the folder in the main view */
2818 if (header_model != model)
2821 /* Select the message in the header view */
2822 path = gtk_tree_row_reference_get_path (row_reference);
2823 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2825 gtk_tree_path_free (path);
2831 updating_banner_destroyed (gpointer data,
2832 GObject *where_the_object_was)
2834 ModestMainWindowPrivate *priv = NULL;
2836 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2838 priv->updating_banner = NULL;
2842 show_updating_banner (gpointer user_data)
2844 ModestMainWindowPrivate *priv = NULL;
2846 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2848 if (priv->updating_banner == NULL) {
2850 /* We're outside the main lock */
2851 gdk_threads_enter ();
2852 priv->updating_banner =
2853 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2854 _CS ("ckdg_pb_updating"));
2856 /* We need this because banners in Maemo could be
2857 destroyed by dialogs so we need to properly update
2858 our reference to it */
2859 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2860 updating_banner_destroyed,
2862 gdk_threads_leave ();
2865 /* Remove timeout */
2866 priv->updating_banner_timeout = 0;
2871 * We use this function to show/hide a progress banner showing
2872 * "Updating" while the header view is being filled. We're not showing
2873 * it unless the update takes more than 2 seconds
2875 * If starting = TRUE then the refresh is starting, otherwise it means
2876 * that is has just finished
2879 on_updating_msg_list (ModestHeaderView *header_view,
2883 ModestMainWindowPrivate *priv = NULL;
2885 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2887 /* Remove old timeout */
2888 if (priv->updating_banner_timeout > 0) {
2889 g_source_remove (priv->updating_banner_timeout);
2890 priv->updating_banner_timeout = 0;
2893 /* Create a new timeout */
2895 priv->updating_banner_timeout =
2896 g_timeout_add (2000, show_updating_banner, user_data);
2898 /* Remove the banner if exists */
2899 if (priv->updating_banner) {
2900 gtk_widget_destroy (priv->updating_banner);
2901 priv->updating_banner = NULL;
2907 modest_main_window_screen_is_on (ModestMainWindow *self)
2909 ModestMainWindowPrivate *priv = NULL;
2911 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2913 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2915 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2919 remove_banners (ModestMainWindow *window)
2921 ModestMainWindowPrivate *priv;
2923 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2925 if (priv->opening_banner_timeout > 0) {
2926 g_source_remove (priv->opening_banner_timeout);
2927 priv->opening_banner_timeout = 0;
2930 if (priv->opening_banner != NULL) {
2931 gtk_widget_destroy (priv->opening_banner);
2932 priv->opening_banner = NULL;
2935 if (priv->updating_banner_timeout > 0) {
2936 g_source_remove (priv->updating_banner_timeout);
2937 priv->updating_banner_timeout = 0;
2940 if (priv->updating_banner != NULL) {
2941 gtk_widget_destroy (priv->updating_banner);
2942 priv->updating_banner = NULL;
2948 on_window_hide (GObject *gobject,
2952 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2954 if (!GTK_WIDGET_VISIBLE (gobject)) {
2955 TnyFolderStore *folder_store;
2956 ModestMainWindowPrivate *priv;
2958 /* Remove the currently shown banners */
2959 remove_banners (MODEST_MAIN_WINDOW (gobject));
2961 /* Force the folder view to sync the currently selected folder
2962 to save the read/unread status and to expunge messages */
2963 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2964 folder_store = modest_folder_view_get_selected (priv->folder_view);
2965 if (TNY_IS_FOLDER (folder_store)) {
2966 ModestMailOperation *mail_op;
2968 mail_op = modest_mail_operation_new (NULL);
2969 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2971 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2972 g_object_unref (mail_op);
2973 g_object_unref (folder_store);
2979 on_window_destroy (GtkObject *widget,
2982 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2984 remove_banners (MODEST_MAIN_WINDOW (widget));
2988 opening_banner_destroyed (gpointer data,
2989 GObject *where_the_object_was)
2991 ModestMainWindowPrivate *priv = NULL;
2993 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2995 priv->opening_banner = NULL;
2999 show_opening_banner (gpointer user_data)
3001 ModestMainWindowPrivate *priv = NULL;
3003 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
3005 if (priv->opening_banner == NULL) {
3007 /* We're outside the main lock */
3008 gdk_threads_enter ();
3009 priv->opening_banner =
3010 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
3011 _("mail_me_opening"));
3013 /* We need this because banners in Maemo could be
3014 destroyed by dialogs so we need to properly update
3015 our reference to it */
3016 g_object_weak_ref (G_OBJECT (priv->opening_banner),
3017 opening_banner_destroyed,
3020 /* We need this because banners in Maemo could be
3021 destroyed by dialogs so we need to properly update
3022 our reference to it */
3023 g_object_weak_ref (G_OBJECT (priv->updating_banner),
3024 updating_banner_destroyed,
3026 gdk_threads_leave ();
3029 /* Remove timeout */
3030 priv->opening_banner_timeout = 0;