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 gboolean modest_main_window_window_state_event (GtkWidget *widget,
81 GdkEventWindowState *event,
84 static void connect_signals (ModestMainWindow *self);
86 static void modest_main_window_disconnect_signals (ModestWindow *self);
88 static void restore_settings (ModestMainWindow *self,
89 gboolean do_folder_view_too);
91 static void save_state (ModestWindow *self);
93 static void update_menus (ModestMainWindow* self);
95 static void modest_main_window_show_toolbar (ModestWindow *window,
96 gboolean show_toolbar);
98 static void cancel_progressbar (GtkToolButton *toolbutton,
99 ModestMainWindow *self);
101 static void on_queue_changed (ModestMailOperationQueue *queue,
102 ModestMailOperation *mail_op,
103 ModestMailOperationQueueNotification type,
104 ModestMainWindow *self);
106 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
108 static void on_account_inserted (TnyAccountStore *accoust_store,
112 static void on_account_removed (TnyAccountStore *accoust_store,
116 static void on_account_changed (TnyAccountStore *account_store,
120 static void on_default_account_changed (ModestAccountMgr* mgr,
123 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
127 static void on_configuration_key_changed (ModestConf* conf,
129 ModestConfEvent event,
130 ModestConfNotificationId id,
131 ModestMainWindow *self);
133 static void set_toolbar_mode (ModestMainWindow *self,
134 ModestToolBarModes mode);
136 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
138 static void on_show_account_action_toggled (GtkToggleAction *action,
141 static void on_refresh_account_action_activated (GtkAction *action,
144 static void on_send_receive_csm_activated (GtkMenuItem *item,
147 static void on_msg_count_changed (ModestHeaderView *header_view,
149 TnyFolderChange *change,
150 ModestMainWindow *main_window);
152 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
155 static GtkWidget * create_empty_view (void);
157 static gboolean on_folder_view_focus_in (GtkWidget *widget,
158 GdkEventFocus *event,
161 static gboolean on_header_view_focus_in (GtkWidget *widget,
162 GdkEventFocus *event,
165 static void on_folder_selection_changed (ModestFolderView *folder_view,
166 TnyFolderStore *folder_store,
168 ModestMainWindow *main_window);
170 static void set_at_least_one_account_visible(ModestMainWindow *self);
172 static void on_updating_msg_list (ModestHeaderView *header_view,
176 static gboolean restore_paned_timeout_handler (gpointer *data);
178 static gboolean show_opening_banner (gpointer user_data);
180 static void on_window_destroy (GtkObject *widget,
183 static void on_window_hide (GObject *gobject,
187 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
188 struct _ModestMainWindowPrivate {
189 GtkWidget *msg_paned;
190 GtkWidget *main_paned;
191 GtkWidget *main_vbox;
192 GtkWidget *contents_widget;
193 GtkWidget *empty_view;
195 /* Progress observers */
196 GtkWidget *progress_bar;
197 GSList *progress_widgets;
200 GtkWidget *progress_toolitem;
201 GtkWidget *cancel_toolitem;
202 GtkWidget *sort_toolitem;
203 GtkWidget *refresh_toolitem;
204 ModestToolBarModes current_toolbar_mode;
206 /* Merge ids used to add/remove accounts to the ViewMenu*/
207 GByteArray *merge_ids;
208 GtkActionGroup *view_additions_group;
210 /* On-demand widgets */
211 GtkWidget *accounts_popup;
212 GtkWidget *details_widget;
214 /* Optimized view enabled */
215 gboolean optimized_view;
217 /* Optimized view enabled */
218 gboolean send_receive_in_progress;
220 ModestHeaderView *header_view;
221 ModestFolderView *folder_view;
223 ModestMainWindowStyle style;
224 ModestMainWindowContentsStyle contents_style;
225 gboolean wait_for_settings;
227 guint progress_bar_timeout;
228 guint restore_paned_timeout;
230 /* Signal handler UIDs */
231 GList *queue_err_signals;
234 /* "Updating" banner for header view */
235 GtkWidget *updating_banner;
236 guint updating_banner_timeout;
238 /* "Opening" banner for header view */
239 GtkWidget *opening_banner;
240 guint opening_banner_timeout;
243 osso_display_state_t display_state;
245 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
246 MODEST_TYPE_MAIN_WINDOW, \
247 ModestMainWindowPrivate))
249 typedef struct _GetMsgAsyncHelper {
250 ModestMainWindowPrivate *main_window_private;
252 ModestTnyMsgReplyType reply_type;
253 ModestTnyMsgForwardType forward_type;
260 static GtkWindowClass *parent_class = NULL;
263 /* Private actions */
264 /* This is the context sensitive menu: */
265 static const GtkActionEntry modest_folder_view_action_entries [] = {
267 /* Folder View CSM actions */
268 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
269 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
270 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
271 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
272 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
275 static const GtkActionEntry modest_header_view_action_entries [] = {
277 /* Header View CSM actions */
278 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
279 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
280 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
281 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
282 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
283 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
284 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
285 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
286 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
287 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
290 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
291 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
294 /************************************************************************/
297 modest_main_window_get_type (void)
299 static GType my_type = 0;
301 static const GTypeInfo my_info = {
302 sizeof(ModestMainWindowClass),
303 NULL, /* base init */
304 NULL, /* base finalize */
305 (GClassInitFunc) modest_main_window_class_init,
306 NULL, /* class finalize */
307 NULL, /* class data */
308 sizeof(ModestMainWindow),
310 (GInstanceInitFunc) modest_main_window_init,
313 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
321 modest_main_window_class_init (ModestMainWindowClass *klass)
323 GObjectClass *gobject_class;
324 gobject_class = (GObjectClass*) klass;
325 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
327 parent_class = g_type_class_peek_parent (klass);
328 gobject_class->finalize = modest_main_window_finalize;
330 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
332 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
333 modest_window_class->save_state_func = save_state;
334 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
335 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
336 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
340 modest_main_window_init (ModestMainWindow *obj)
342 ModestMainWindowPrivate *priv;
344 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
346 priv->queue_err_signals = NULL;
347 priv->msg_paned = NULL;
348 priv->main_paned = NULL;
349 priv->main_vbox = NULL;
350 priv->header_view = NULL;
351 priv->folder_view = NULL;
352 priv->contents_widget = NULL;
353 priv->accounts_popup = NULL;
354 priv->details_widget = NULL;
355 priv->empty_view = NULL;
356 priv->progress_widgets = NULL;
357 priv->progress_bar = NULL;
358 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
359 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
360 priv->wait_for_settings = TRUE;
361 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
362 priv->merge_ids = NULL;
363 priv->optimized_view = FALSE;
364 priv->send_receive_in_progress = FALSE;
365 priv->progress_bar_timeout = 0;
366 priv->restore_paned_timeout = 0;
367 priv->sighandlers = NULL;
368 priv->updating_banner = NULL;
369 priv->updating_banner_timeout = 0;
370 priv->opening_banner = NULL;
371 priv->opening_banner_timeout = 0;
372 priv->display_state = OSSO_DISPLAY_ON;
374 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
376 "applications_email_mainview");
380 modest_main_window_finalize (GObject *obj)
382 ModestMainWindowPrivate *priv;
384 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
386 /* Sanity check: shouldn't be needed, the window mgr should
387 call this function before */
388 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
389 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
391 if (priv->empty_view) {
392 g_object_unref (priv->empty_view);
393 priv->empty_view = NULL;
396 if (priv->header_view) {
397 g_object_unref (priv->header_view);
398 priv->header_view = NULL;
401 g_slist_free (priv->progress_widgets);
403 g_byte_array_free (priv->merge_ids, TRUE);
405 if (priv->progress_bar_timeout > 0) {
406 g_source_remove (priv->progress_bar_timeout);
407 priv->progress_bar_timeout = 0;
410 if (priv->updating_banner_timeout > 0) {
411 g_source_remove (priv->updating_banner_timeout);
412 priv->updating_banner_timeout = 0;
415 if (priv->updating_banner) {
416 gtk_widget_destroy (priv->updating_banner);
417 priv->updating_banner = NULL;
420 if (priv->opening_banner_timeout > 0) {
421 g_source_remove (priv->opening_banner_timeout);
422 priv->opening_banner_timeout = 0;
425 if (priv->opening_banner) {
426 gtk_widget_destroy (priv->opening_banner);
427 priv->opening_banner = NULL;
430 if (priv->restore_paned_timeout > 0) {
431 g_source_remove (priv->restore_paned_timeout);
432 priv->restore_paned_timeout = 0;
435 G_OBJECT_CLASS(parent_class)->finalize (obj);
439 modest_main_window_get_child_widget (ModestMainWindow *self,
440 ModestMainWindowWidgetType widget_type)
442 ModestMainWindowPrivate *priv;
445 g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
446 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
449 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
451 switch (widget_type) {
452 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
453 widget = (GtkWidget*)priv->header_view; break;
454 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
455 widget = (GtkWidget*)priv->folder_view; break;
460 /* Note that the window could have been destroyed, and so
461 their children, but still have some references */
462 return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
466 restore_paned_timeout_handler (gpointer *data)
468 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
469 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
472 /* Timeouts are outside the main lock */
473 gdk_threads_enter ();
474 if (GTK_WIDGET_VISIBLE (main_window)) {
475 conf = modest_runtime_get_conf ();
476 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
477 MODEST_CONF_MAIN_PANED_KEY);
479 gdk_threads_leave ();
486 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
489 ModestMainWindowPrivate *priv;
491 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
493 conf = modest_runtime_get_conf ();
495 modest_widget_memory_restore (conf, G_OBJECT(self),
496 MODEST_CONF_MAIN_WINDOW_KEY);
498 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
499 MODEST_CONF_HEADER_VIEW_KEY);
501 if (do_folder_view_too)
502 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
503 MODEST_CONF_FOLDER_VIEW_KEY);
505 /* modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
506 /* MODEST_CONF_MAIN_PANED_KEY); */
508 g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
510 /* We need to force a redraw here in order to get the right
511 position of the horizontal paned separator */
512 gtk_widget_show (GTK_WIDGET (self));
517 save_state (ModestWindow *window)
520 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
521 ModestMainWindowPrivate *priv;
523 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
524 conf = modest_runtime_get_conf ();
526 modest_widget_memory_save (conf,G_OBJECT(self),
527 MODEST_CONF_MAIN_WINDOW_KEY);
528 /* Only save main paned position if we're in split mode */
529 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
530 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
531 MODEST_CONF_MAIN_PANED_KEY);
532 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
533 MODEST_CONF_FOLDER_VIEW_KEY);
537 compare_display_names (ModestAccountSettings *a,
538 ModestAccountSettings *b)
540 return g_utf8_collate (modest_account_settings_get_display_name (a),
541 modest_account_settings_get_display_name (b));
545 /* We use this function to prevent the send&receive CSM to be shown
546 when there are less than two account */
548 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
554 update_menus (ModestMainWindow* self)
556 GSList *account_names, *iter, *accounts;
557 ModestMainWindowPrivate *priv;
558 ModestWindowPrivate *parent_priv;
559 ModestAccountMgr *mgr;
560 gint i, num_accounts;
562 gchar *default_account;
563 const gchar *active_account_name;
564 GtkWidget *send_receive_button, *item;
565 GtkAction *send_receive_all = NULL;
568 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
569 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
571 /* Get enabled account IDs */
572 mgr = modest_runtime_get_account_mgr ();
573 account_names = modest_account_mgr_account_names (mgr, TRUE);
574 iter = account_names;
578 ModestAccountSettings *settings =
579 modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
580 accounts = g_slist_prepend (accounts, settings);
584 modest_account_mgr_free_account_names (account_names);
585 account_names = NULL;
587 /* Order the list of accounts by its display name */
588 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
589 num_accounts = g_slist_length (accounts);
591 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
592 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
593 gtk_action_set_visible (send_receive_all, num_accounts > 0);
595 /* Delete old send&receive popup items. We can not just do a
596 menu_detach because it does not work well with
598 if (priv->accounts_popup)
599 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
600 (GtkCallback) gtk_widget_destroy, NULL);
602 /* Delete old entries in the View menu. Do not free groups, it
604 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
606 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
607 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
608 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
609 GTK_ACTION_GROUP (groups->data));
612 if (priv->merge_ids) {
613 for (i = 0; i < priv->merge_ids->len; i++)
614 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
615 g_byte_array_free (priv->merge_ids, TRUE);
617 /* We need to call this in order to ensure
618 that the new actions are added in the right
619 order (alphabetical) */
620 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
622 groups = g_list_next (groups);
624 priv->merge_ids = g_byte_array_sized_new (num_accounts);
626 /* Get send receive button */
627 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
628 "/ToolBar/ToolbarSendReceive");
630 /* Create the menu */
631 if (num_accounts > 1) {
632 if (!priv->accounts_popup)
633 priv->accounts_popup = gtk_menu_new ();
634 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
635 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
636 g_signal_connect (G_OBJECT (item),
638 G_CALLBACK (on_send_receive_csm_activated),
640 item = gtk_separator_menu_item_new ();
641 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
644 /* Create a new action group */
645 default_account = modest_account_mgr_get_default_account (mgr);
646 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
648 if (!active_account_name)
649 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
651 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
653 for (i = 0; i < num_accounts; i++) {
654 gchar *display_name = NULL;
655 const gchar *account_name;
656 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
659 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
662 account_name = modest_account_settings_get_account_name (settings);
664 if (default_account && account_name &&
665 !(strcmp (default_account, account_name) == 0)) {
666 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
667 modest_account_settings_get_display_name (settings));
669 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
670 modest_account_settings_get_display_name (settings));
675 /* Create action and add it to the action group. The
676 action name must be the account name, this way we
677 could know in the handlers the account to show */
678 if (settings && account_name) {
679 gchar* item_name, *refresh_action_name;
681 GtkAction *view_account_action, *refresh_account_action;
682 gchar *escaped_display_name;
684 escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
686 view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
687 escaped_display_name, NULL, NULL, 0));
688 g_free (escaped_display_name);
689 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
690 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
691 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
693 if (active_account_name) {
694 if (active_account_name && account_name &&
695 (strcmp (active_account_name, account_name) == 0)) {
696 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
700 /* Add ui from account data. We allow 2^9-1 account
701 changes in a single execution because we're
702 downcasting the guint to a guint8 in order to use a
703 GByteArray. It should be enough :-) */
704 item_name = g_strconcat (account_name, "Menu", NULL);
705 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
706 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
707 gtk_ui_manager_add_ui (parent_priv->ui_manager,
709 "/MenuBar/AccountsMenu/AccountsMenuAdditions",
712 GTK_UI_MANAGER_MENUITEM,
715 /* Connect the action signal "activate" */
716 g_signal_connect_after (G_OBJECT (view_account_action),
718 G_CALLBACK (on_show_account_action_toggled),
721 /* Create the items for the Tools->Send&Receive submenu */
722 refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
723 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
724 display_name, NULL, NULL);
725 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
727 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
728 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
729 gtk_ui_manager_add_ui (parent_priv->ui_manager,
731 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
734 GTK_UI_MANAGER_MENUITEM,
736 g_free (refresh_action_name);
738 g_signal_connect_data (G_OBJECT (refresh_account_action),
740 G_CALLBACK (on_refresh_account_action_activated),
741 g_strdup (account_name),
742 (GClosureNotify) g_free,
745 /* Create item and add it to the send&receive
746 CSM. If there is only one account then
748 if (num_accounts > 1) {
749 GtkWidget *label = gtk_label_new(NULL);
750 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
751 if (default_account && (strcmp(account_name, default_account) == 0)) {
752 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
753 gtk_label_set_markup (GTK_LABEL (label), escaped);
756 gtk_label_set_text (GTK_LABEL (label), display_name);
759 item = gtk_menu_item_new ();
760 gtk_container_add (GTK_CONTAINER (item), label);
762 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup),
764 g_signal_connect_data (G_OBJECT (item),
766 G_CALLBACK (on_send_receive_csm_activated),
767 g_strdup (account_name),
768 (GClosureNotify) g_free,
775 g_free (display_name);
778 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
780 /* We cannot do this in the loop above because this relies on the action
781 * group being inserted. This makes the default account appear in bold.
782 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
783 for (i = 0; i < num_accounts; i++) {
784 gchar *item_name, *path;
786 ModestAccountSettings *settings;
787 const gchar *account_name;
790 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
791 account_name = modest_account_settings_get_account_name (settings);
792 is_default = (account_name && default_account && !strcmp (account_name, default_account));
794 /* Get the item of the view menu */
795 item_name = g_strconcat (account_name, "Menu", NULL);
796 path = g_strconcat ("/MenuBar/AccountsMenu/AccountsMenuAdditions/", item_name, NULL);
797 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
801 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
802 if (GTK_IS_LABEL (child)) {
803 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
805 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
806 gtk_label_set_markup (GTK_LABEL (child), bold_name);
809 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
813 /* Get the item of the tools menu */
814 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
815 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
819 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
820 if (GTK_IS_LABEL (child)) {
821 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
823 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
824 gtk_label_set_markup (GTK_LABEL (child), bold_name);
827 gtk_label_set_ellipsize (GTK_LABEL (child), PANGO_ELLIPSIZE_END);
832 g_object_unref (settings);
835 if (num_accounts > 1) {
836 /* Disconnect the tap-and-hold-query if it's connected */
837 if (modest_signal_mgr_is_connected (priv->sighandlers,
838 G_OBJECT (send_receive_button),
839 "tap-and-hold-query"))
840 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
841 G_OBJECT (send_receive_button),
842 "tap-and-hold-query");
844 /* Mandatory in order to view the menu contents */
845 gtk_widget_show_all (priv->accounts_popup);
847 /* Setup tap_and_hold just if was not done before*/
848 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
849 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
851 /* Connect the tap-and-hold-query in order not to show the CSM */
852 if (!modest_signal_mgr_is_connected (priv->sighandlers,
853 G_OBJECT (send_receive_button),
854 "tap-and-hold-query"))
855 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
856 G_OBJECT (send_receive_button),
857 "tap-and-hold-query",
858 G_CALLBACK (tap_and_hold_query_cb),
863 g_slist_free (accounts);
864 g_free (default_account);
867 /* Make sure that at least one account is viewed if there are any
868 * accounts, for instance when adding the first account: */
869 set_at_least_one_account_visible (self);
873 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
875 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
876 gtk_scrolled_window_add_with_viewport
877 (GTK_SCROLLED_WINDOW(win), widget);
879 gtk_container_add (GTK_CONTAINER(win),
890 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
892 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
894 GList *oerrsignals = priv->queue_err_signals;
895 while (oerrsignals) {
896 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
897 g_signal_handler_disconnect (esignal->queue, esignal->signal);
898 g_slice_free (QueueErrorSignal, esignal);
899 oerrsignals = g_list_next (oerrsignals);
901 g_list_free (priv->queue_err_signals);
902 priv->queue_err_signals = NULL;
907 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
909 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
912 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
916 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
918 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
920 /* Update visibility */
923 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
927 modest_main_window_disconnect_signals (ModestWindow *self)
929 ModestMainWindowPrivate *priv;
930 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
932 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
933 priv->sighandlers = NULL;
937 connect_signals (ModestMainWindow *self)
939 ModestWindowPrivate *parent_priv;
940 ModestMainWindowPrivate *priv;
943 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
944 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
949 modest_signal_mgr_connect (priv->sighandlers,
950 G_OBJECT(priv->folder_view), "key-press-event",
951 G_CALLBACK(on_inner_widgets_key_pressed), self);
953 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
954 "folder_selection_changed",
955 G_CALLBACK (on_folder_selection_changed),
958 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
959 "folder-display-name-changed",
960 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
963 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
965 G_CALLBACK (on_folder_view_focus_in),
968 /* Folder view CSM */
969 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
970 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
971 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
972 G_CALLBACK(_folder_view_csm_menu_activated),
976 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
977 G_CALLBACK(modest_ui_actions_on_header_selected), self);
979 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
980 G_CALLBACK(modest_ui_actions_on_header_activated), self);
982 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
983 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
985 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
986 G_CALLBACK(on_inner_widgets_key_pressed), self);
988 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
989 G_CALLBACK(on_msg_count_changed), self);
991 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
992 G_CALLBACK (on_header_view_focus_in), self);
994 modest_signal_mgr_connect (priv->sighandlers,
995 G_OBJECT (priv->header_view),
997 G_CALLBACK (on_updating_msg_list),
1000 /* Header view CSM */
1001 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1002 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1004 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1005 G_CALLBACK(_header_view_csm_menu_activated),
1010 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1011 G_CALLBACK (modest_main_window_window_state_event),
1013 /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1014 * in destroy stage */
1015 g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1017 g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1019 /* Mail Operation Queue */
1021 modest_signal_mgr_connect (priv->sighandlers,
1022 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1024 G_CALLBACK (on_queue_changed), self);
1026 /* Track changes in the device name */
1028 modest_signal_mgr_connect (priv->sighandlers,
1029 G_OBJECT(modest_runtime_get_conf ()),
1031 G_CALLBACK (on_configuration_key_changed),
1034 /* Track account changes. We need to refresh the toolbar */
1036 modest_signal_mgr_connect (priv->sighandlers,
1037 G_OBJECT (modest_runtime_get_account_store ()),
1039 G_CALLBACK (on_account_inserted),
1042 modest_signal_mgr_connect (priv->sighandlers,
1043 G_OBJECT (modest_runtime_get_account_store ()),
1045 G_CALLBACK (on_account_removed),
1048 /* We need to refresh the send & receive menu to change the bold
1049 * account when the default account changes. */
1051 modest_signal_mgr_connect (priv->sighandlers,
1052 G_OBJECT (modest_runtime_get_account_mgr ()),
1053 "default_account_changed",
1054 G_CALLBACK (on_default_account_changed),
1059 modest_signal_mgr_connect (priv->sighandlers,
1060 G_OBJECT (modest_runtime_get_account_store ()),
1062 G_CALLBACK (on_account_changed),
1067 on_hildon_program_is_topmost_notify(GObject *self,
1068 GParamSpec *propert_param,
1071 HildonProgram *app = HILDON_PROGRAM (self);
1073 /* Note that use of hildon_program_set_can_hibernate()
1074 * is generally referred to as "setting the killable flag",
1075 * though hibernation does not seem equal to death.
1078 if (hildon_program_get_is_topmost (app)) {
1079 /* Prevent hibernation when the progam comes to the foreground,
1080 * because hibernation should only happen when the application
1081 * is in the background: */
1082 hildon_program_set_can_hibernate (app, FALSE);
1084 /* Remove new mail visual notifications */
1085 modest_platform_remove_new_mail_notifications (TRUE);
1087 /* Allow hibernation if the program has gone to the background: */
1089 /* However, prevent hibernation while the settings are being changed: */
1090 const gboolean hibernation_prevented =
1091 modest_window_mgr_get_hibernation_is_prevented (
1092 modest_runtime_get_window_mgr ());
1094 if (hibernation_prevented)
1095 hildon_program_set_can_hibernate (app, FALSE);
1097 /* Allow hibernation, after saving the state: */
1098 modest_osso_save_state();
1099 hildon_program_set_can_hibernate (app, TRUE);
1106 GtkWidget *folder_win;
1111 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1113 ShowHelper *helper = (ShowHelper *) user_data;
1114 GtkWidget *folder_win = helper->folder_win;
1115 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1117 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1118 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1120 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1122 /* Connect signals */
1123 connect_signals (MODEST_MAIN_WINDOW (self));
1125 /* Set account store */
1126 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1127 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1129 /* Load previous osso state, for instance if we are being restored from
1131 modest_osso_load_state ();
1133 /* Restore window & widget settings */
1134 priv->wait_for_settings = TRUE;
1135 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1136 priv->wait_for_settings = FALSE;
1138 /* Check if accounts exist and show the account wizard if not */
1139 gboolean accounts_exist =
1140 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1142 if (!accounts_exist) {
1143 /* This is necessary to have the main window shown behind the dialog
1144 It's an ugly hack... jschmid */
1145 gtk_widget_show_all(GTK_WIDGET(self));
1146 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1148 update_menus (MODEST_MAIN_WINDOW (self));
1151 /* Never call this function again (NOTE that it could happen
1152 as we hide the main window instead of closing it while
1153 there are operations ongoing) and free the helper */
1154 g_signal_handler_disconnect (self, helper->handler_id);
1155 g_slice_free (ShowHelper, helper);
1159 osso_display_event_cb (osso_display_state_t state,
1162 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1164 priv->display_state = state;
1166 /* Stop blinking if the screen becomes on */
1167 if (priv->display_state == OSSO_DISPLAY_ON)
1168 modest_platform_remove_new_mail_notifications (TRUE);
1172 modest_main_window_new (void)
1174 ModestMainWindow *self = NULL;
1175 ModestMainWindowPrivate *priv = NULL;
1176 ModestWindowPrivate *parent_priv = NULL;
1177 GtkWidget *folder_win = NULL;
1178 ModestDimmingRulesGroup *menu_rules_group = NULL;
1179 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1180 GtkActionGroup *action_group = NULL;
1181 GError *error = NULL;
1183 GdkPixbuf *window_icon;
1186 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1187 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1188 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1190 parent_priv->ui_manager = gtk_ui_manager_new();
1191 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1193 action_group = gtk_action_group_new ("ModestMainWindowActions");
1194 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1196 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1197 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1199 /* Add common actions */
1200 gtk_action_group_add_actions (action_group,
1201 modest_action_entries,
1202 G_N_ELEMENTS (modest_action_entries),
1205 gtk_action_group_add_actions (action_group,
1206 modest_folder_view_action_entries,
1207 G_N_ELEMENTS (modest_folder_view_action_entries),
1210 gtk_action_group_add_actions (action_group,
1211 modest_header_view_action_entries,
1212 G_N_ELEMENTS (modest_header_view_action_entries),
1215 gtk_action_group_add_toggle_actions (action_group,
1216 modest_toggle_action_entries,
1217 G_N_ELEMENTS (modest_toggle_action_entries),
1220 gtk_action_group_add_toggle_actions (action_group,
1221 modest_main_window_toggle_action_entries,
1222 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1225 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1226 g_object_unref (action_group);
1228 /* Load the UI definition */
1229 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1230 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1231 if (error != NULL) {
1232 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1233 g_error_free (error);
1237 /* Add common dimming rules */
1238 modest_dimming_rules_group_add_rules (menu_rules_group,
1239 modest_main_window_menu_dimming_entries,
1240 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1241 MODEST_WINDOW (self));
1242 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1243 modest_main_window_toolbar_dimming_entries,
1244 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1245 MODEST_WINDOW (self));
1247 /* Insert dimming rules group for this window */
1248 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1249 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1250 g_object_unref (menu_rules_group);
1251 g_object_unref (toolbar_rules_group);
1253 /* Add accelerators */
1254 gtk_window_add_accel_group (GTK_WINDOW (self),
1255 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1257 /* Menubar. Update the state of some toggles */
1258 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1259 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1260 gtk_widget_show (parent_priv->menubar);
1262 /* Get device name */
1263 modest_maemo_utils_get_device_name ();
1267 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1268 g_object_ref (priv->header_view);
1269 if (!priv->header_view)
1270 g_printerr ("modest: cannot instantiate header view\n");
1271 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1272 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1273 MODEST_CONF_HEADER_VIEW_KEY);
1275 /* Other style properties of header view */
1276 g_object_set (G_OBJECT (priv->header_view),
1277 "rules-hint", FALSE,
1279 /* gtk_widget_show (priv->header_view); */
1282 priv->empty_view = create_empty_view ();
1283 gtk_widget_show (priv->empty_view);
1284 g_object_ref (priv->empty_view);
1286 /* Create scrolled windows */
1287 folder_win = gtk_scrolled_window_new (NULL, NULL);
1288 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1289 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1291 GTK_POLICY_AUTOMATIC);
1292 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1294 GTK_POLICY_AUTOMATIC);
1295 /* gtk_widget_show (priv->contents_widget); */
1298 priv->main_paned = gtk_hpaned_new ();
1299 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1300 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1301 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1303 /* putting it all together... */
1304 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1305 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1306 gtk_widget_show (priv->main_vbox);
1308 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1310 app = hildon_program_get_instance ();
1311 hildon_program_add_window (app, HILDON_WINDOW (self));
1313 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1314 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1316 /* Connect to "show" action. We delay the creation of some
1317 elements until that moment */
1318 helper = g_slice_new0 (ShowHelper);
1319 helper->folder_win = folder_win;
1320 helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1321 G_CALLBACK (modest_main_window_on_show),
1324 /* Set window icon */
1325 window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1327 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1328 g_object_unref (window_icon);
1331 /* Listen for changes in the screen, we don't want to show a
1332 led pattern when the display is on for example */
1333 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1334 osso_display_event_cb,
1337 /* Dont't restore settings here,
1338 * because it requires a gtk_widget_show(),
1339 * and we don't want to do that until later,
1340 * so that the UI is not visible for non-menu D-Bus activation.
1343 return MODEST_WINDOW(self);
1347 modest_main_window_set_style (ModestMainWindow *self,
1348 ModestMainWindowStyle style)
1350 ModestMainWindowPrivate *priv;
1351 ModestWindowPrivate *parent_priv;
1354 GtkTreeSelection *sel;
1357 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1359 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1360 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1362 /* no change -> nothing to do */
1363 if (priv->style == style)
1366 /* Get toggle button and update the state if needed. This will
1367 happen only when the set_style is not invoked from the UI,
1368 for example when it's called from widget memory */
1369 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1370 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1371 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1372 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1373 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1374 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1375 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1378 /* We need to store the selection because it's lost when the
1379 widget is reparented */
1380 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1381 rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1383 priv->style = style;
1385 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1387 if (!priv->wait_for_settings)
1388 modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1389 MODEST_CONF_MAIN_PANED_KEY);
1390 /* Remove main paned */
1391 g_object_ref (priv->main_paned);
1392 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1394 /* Reparent the contents widget to the main vbox */
1395 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1398 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1399 /* Remove header view */
1400 g_object_ref (priv->contents_widget);
1401 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1403 /* Reparent the main paned */
1404 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1405 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1407 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1411 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1413 g_return_if_reached ();
1416 /* Reselect the previously selected folders. We disable the
1417 dimming rules execution during that time because there is
1418 no need to work out it again and it could take a lot of
1419 time if all the headers are selected */
1421 modest_window_disable_dimming (MODEST_WINDOW (self));
1423 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1424 list = g_list_next (list);
1426 modest_window_enable_dimming (MODEST_WINDOW (self));
1429 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1432 /* Let header view grab the focus if it's being shown */
1433 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1434 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1436 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1437 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1439 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1442 /* Check dimming rules */
1443 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1444 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1447 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1450 ModestMainWindowStyle
1451 modest_main_window_get_style (ModestMainWindow *self)
1453 ModestMainWindowPrivate *priv;
1455 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1457 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1462 toolbar_resize (ModestMainWindow *self)
1464 ModestMainWindowPrivate *priv = NULL;
1465 ModestWindowPrivate *parent_priv = NULL;
1467 gint static_button_size;
1468 ModestWindowMgr *mgr;
1470 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1471 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1472 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1474 mgr = modest_runtime_get_window_mgr ();
1475 static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1477 if (parent_priv->toolbar) {
1478 /* left size buttons */
1479 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1480 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1481 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1482 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1483 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1484 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1485 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1486 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1487 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1488 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1489 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1490 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1491 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1492 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1493 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1494 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1496 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1497 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1498 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1499 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1500 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1501 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1502 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1503 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1511 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1513 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1514 ModestWindowPrivate *parent_priv;
1515 ModestWindowMgr *mgr;
1516 gboolean is_fullscreen;
1517 GtkAction *fs_toggle_action;
1520 mgr = modest_runtime_get_window_mgr ();
1522 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1524 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1526 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1527 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1528 if (is_fullscreen != active) {
1529 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1532 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1540 modest_main_window_show_toolbar (ModestWindow *self,
1541 gboolean show_toolbar)
1543 ModestMainWindowPrivate *priv = NULL;
1544 ModestWindowPrivate *parent_priv = NULL;
1545 GtkWidget *reply_button = NULL, *menu = NULL;
1546 GtkWidget *placeholder = NULL;
1549 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1550 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1551 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1553 /* Set optimized view status */
1554 priv->optimized_view = !show_toolbar;
1556 if (!parent_priv->toolbar) {
1557 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1559 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1561 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1562 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1563 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1564 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1565 toolbar_resize (MODEST_MAIN_WINDOW (self));
1567 /* Add ProgressBar (Transfer toolbar) */
1568 priv->progress_bar = modest_progress_bar_new ();
1569 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1570 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1571 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1572 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1573 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1575 /* Connect cancel 'clicked' signal to abort progress mode */
1576 g_signal_connect(priv->cancel_toolitem, "clicked",
1577 G_CALLBACK(cancel_progressbar),
1580 /* Add it to the observers list */
1581 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1584 hildon_window_add_toolbar (HILDON_WINDOW (self),
1585 GTK_TOOLBAR (parent_priv->toolbar));
1587 /* Set reply button tap and hold menu */
1588 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1589 "/ToolBar/ToolbarMessageReply");
1590 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1591 "/ToolbarReplyCSM");
1592 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1594 /* Set send & receive button tap and hold menu */
1595 update_menus (MODEST_MAIN_WINDOW (self));
1599 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1600 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1601 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1603 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1604 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1605 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1607 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1609 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1615 on_account_inserted (TnyAccountStore *accoust_store,
1616 TnyAccount *account,
1619 /* Transport accounts and local ones (MMC and the Local
1620 folders account do now cause menu changes */
1621 if (TNY_IS_STORE_ACCOUNT (account) &&
1622 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1624 update_menus (MODEST_MAIN_WINDOW (user_data));
1629 on_default_account_changed (ModestAccountMgr* mgr,
1632 update_menus (MODEST_MAIN_WINDOW (user_data));
1636 on_account_removed (TnyAccountStore *accoust_store,
1637 TnyAccount *account,
1640 /* Transport accounts and local ones (MMC and the Local
1641 folders account do now cause menu changes */
1642 if (TNY_IS_STORE_ACCOUNT (account) &&
1643 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1644 update_menus (MODEST_MAIN_WINDOW (user_data));
1648 on_account_changed (TnyAccountStore *account_store,
1649 TnyAccount *account,
1652 ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1654 /* Transport accounts and local ones (MMC and the Local
1655 folders account do now cause menu changes */
1656 if (TNY_IS_STORE_ACCOUNT (account)) {
1657 /* We need to refresh the details widget because it could have changed */
1658 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1659 modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1661 /* Update the menus as well, name could change */
1662 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1663 update_menus (MODEST_MAIN_WINDOW (user_data));
1668 * This function manages the key events used to navigate between
1669 * header and folder views (when the window is in split view)
1672 * -------------------------------------------------
1673 * HeaderView GDK_Left Move focus to folder view
1674 * FolderView GDK_Right Move focus to header view
1676 * There is no need to scroll to selected row, the widgets will be the
1677 * responsibles of doing that (probably managing the focus-in event
1680 on_inner_widgets_key_pressed (GtkWidget *widget,
1684 ModestMainWindowPrivate *priv;
1686 if (event->type == GDK_KEY_RELEASE)
1689 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1691 /* Do nothing if we're in SIMPLE style */
1692 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1695 if (MODEST_IS_HEADER_VIEW (widget)) {
1696 if (event->keyval == GDK_Left)
1697 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1698 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1699 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1700 if (selected_headers > 1) {
1701 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1704 GtkTreePath * cursor_path;
1705 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1706 if (cursor_path == NULL) {
1707 GtkTreeSelection *selection;
1709 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1710 list = gtk_tree_selection_get_selected_rows (selection, NULL);
1713 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1714 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1719 } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1720 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1721 GtkTreePath *selected_path = NULL;
1722 GtkTreePath *start_path = NULL;
1723 GtkTreePath *end_path = NULL;
1725 GtkTreeSelection *selection;
1727 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1728 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1729 if (selected != NULL) {
1730 selected_path = (GtkTreePath *) selected->data;
1731 if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1735 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1736 (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1738 /* Scroll to first path */
1739 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1748 gtk_tree_path_free (start_path);
1750 gtk_tree_path_free (end_path);
1751 g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1752 g_list_free (selected);
1754 #endif /* GTK_CHECK_VERSION */
1756 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1763 set_alignment (GtkWidget *widget,
1766 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1767 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1771 create_empty_view (void)
1773 GtkLabel *label = NULL;
1774 GtkWidget *align = NULL;
1776 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1777 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1778 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1779 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1781 return GTK_WIDGET(align);
1785 * Free the returned string
1788 get_gray_color_markup (GtkWidget *styled_widget)
1790 gchar *gray_color_markup = NULL;
1791 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1792 /* Obtain the secondary text color. We need a realized widget, that's why
1793 we get styled_widget from outside */
1795 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1796 gray_color_markup = modest_text_utils_get_color_string (&color);
1797 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1799 if (!gray_color_markup)
1800 gray_color_markup = g_strdup ("#BBBBBB");
1802 return gray_color_markup;
1806 * Free the returned string
1809 create_device_name_visual_string (const gchar *device_name,
1810 const gchar *gray_color_markup)
1814 /* We have to use "" to fill the %s of the translation. We can
1815 not just use the device name because the device name is
1816 shown in a different color, so it could not be included
1817 into the <span> tag */
1818 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1819 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1830 GtkWidget *count_label;
1831 GtkWidget *msg_count_label;
1832 GtkWidget *size_label;
1833 gchar *color_markup;
1837 create_uint_label (const gchar *markup,
1841 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1845 create_gchar_label (const gchar *markup,
1849 return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1853 update_folder_stats_status_cb (ModestFolderStats stats,
1856 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1859 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1860 gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1863 label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1864 gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1867 if (widgets->size_label) {
1868 tmp = modest_text_utils_get_display_size (stats.local_size);
1869 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1870 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1877 update_folder_stats_cb (ModestFolderStats stats,
1880 DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1883 update_folder_stats_status_cb (stats, user_data);
1885 /* frees. Note that the widgets could have been destroyed but
1886 we still keep a reference */
1887 g_free (widgets->color_markup);
1888 if (widgets->count_label)
1889 g_object_unref (widgets->count_label);
1890 if (widgets->msg_count_label)
1891 g_object_unref (widgets->msg_count_label);
1892 if (widgets->size_label)
1893 g_object_unref (widgets->size_label);
1894 g_slice_free (DetailsWidgets, widgets);
1898 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1900 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1905 gchar *gray_color_markup;
1906 DetailsWidgets *widgets;
1908 vbox = gtk_vbox_new (FALSE, 0);
1909 widgets = g_slice_new0 (DetailsWidgets);
1911 gray_color_markup = get_gray_color_markup (styled_widget);
1912 widgets->color_markup = g_strdup (gray_color_markup);
1914 /* Account description: */
1915 if (modest_tny_account_is_virtual_local_folders (account)
1916 || (modest_tny_account_is_memory_card_account (account))) {
1918 /* Get device name */
1919 gchar *device_name = NULL;
1920 if (modest_tny_account_is_virtual_local_folders (account))
1921 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1922 MODEST_CONF_DEVICE_NAME, NULL);
1924 device_name = g_strdup (tny_account_get_name (account));
1926 label = create_device_name_visual_string ((const gchar *) device_name,
1927 (const gchar *) gray_color_markup);
1928 label_w = gtk_label_new (NULL);
1929 gtk_label_set_markup (GTK_LABEL (label_w), label);
1930 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1931 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1932 g_free (device_name);
1935 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1936 gtk_box_pack_start (GTK_BOX (vbox),
1937 gtk_label_new (tny_account_get_name (account)),
1940 /* Other accounts, such as IMAP and POP: */
1945 /* Put proto in uppercase */
1946 proto = g_string_new (tny_account_get_proto (account));
1947 proto = g_string_ascii_up (proto);
1949 /* note: mcen_fi_localroot_description is something like "%s account"
1950 * however, we should display "%s account: %s"... therefore, ugly tmp */
1951 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1952 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1953 gray_color_markup, tmp, tny_account_get_name (account));
1956 label_w = gtk_label_new (NULL);
1957 gtk_label_set_markup (GTK_LABEL (label_w), label);
1958 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1959 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1960 g_string_free (proto, TRUE);
1966 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1967 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1968 label_w = gtk_label_new (NULL);
1969 gtk_label_set_markup (GTK_LABEL (label_w), label);
1970 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1971 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1974 widgets->msg_count_label = g_object_ref (label_w);
1977 label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
1978 label_w = gtk_label_new (NULL);
1979 gtk_label_set_markup (GTK_LABEL (label_w), label);
1980 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1981 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1984 widgets->count_label = g_object_ref (label_w);
1987 if (modest_tny_account_is_virtual_local_folders (account)
1988 || modest_tny_account_is_memory_card_account (account)) {
1990 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
1992 label_w = gtk_label_new (NULL);
1993 gtk_label_set_markup (GTK_LABEL (label_w), label);
1994 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
1995 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1998 widgets->size_label = g_object_ref (label_w);
2000 } else if (TNY_IS_ACCOUNT(folder_store)) {
2001 TnyAccount *account = TNY_ACCOUNT(folder_store);
2003 time_t last_updated;
2004 const gchar *last_updated_string;
2005 /* Get last updated from configuration */
2006 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
2007 tny_account_get_id (account));
2009 if (last_updated > 0)
2010 last_updated_string = modest_text_utils_get_display_date(last_updated);
2012 last_updated_string = g_strdup (_("mcen_va_never"));
2014 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
2015 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
2016 label_w = gtk_label_new (NULL);
2017 gtk_label_set_markup (GTK_LABEL (label_w), label);
2018 gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END);
2019 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2023 g_free (gray_color_markup);
2025 /* Refresh folder stats asynchronously */
2026 modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
2027 update_folder_stats_cb,
2028 update_folder_stats_status_cb,
2032 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2038 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2040 ModestMainWindowPrivate *priv = NULL;
2042 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2044 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2046 return priv->send_receive_in_progress;
2050 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2052 GtkAction *action = NULL;
2053 GtkWidget *widget = NULL;
2054 ModestMainWindowPrivate *priv = NULL;
2056 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2057 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2059 priv->send_receive_in_progress = TRUE;
2061 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2062 gtk_action_set_sensitive (action, FALSE);
2063 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2064 /* gtk_action_set_sensitive (action, FALSE); */
2065 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2066 gtk_widget_set_sensitive (widget, FALSE);
2070 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2072 GtkAction *action = NULL;
2073 GtkWidget *widget = NULL;
2074 ModestMainWindowPrivate *priv = NULL;
2076 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2077 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2079 priv->send_receive_in_progress = FALSE;
2081 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
2082 gtk_action_set_sensitive (action, TRUE);
2083 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2084 /* gtk_action_set_sensitive (action, TRUE); */
2085 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
2086 gtk_widget_set_sensitive (widget, TRUE);
2091 on_msg_count_changed (ModestHeaderView *header_view,
2093 TnyFolderChange *change,
2094 ModestMainWindow *main_window)
2096 gboolean refilter = FALSE;
2097 gboolean folder_empty = FALSE;
2098 gboolean all_marked_as_deleted = FALSE;
2099 ModestMainWindowPrivate *priv;
2101 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2102 g_return_if_fail (TNY_IS_FOLDER(folder));
2103 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2105 if (change != NULL) {
2106 TnyFolderChangeChanged changed;
2108 changed = tny_folder_change_get_changed (change);
2109 /* If something changes */
2110 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2111 folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2113 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2115 /* Play a sound (if configured) and make the LED blink */
2116 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2117 modest_platform_push_email_notification ();
2120 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2123 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2126 /* Check if all messages are marked to be deleted */
2127 all_marked_as_deleted = modest_header_view_is_empty (header_view);
2128 folder_empty = folder_empty || all_marked_as_deleted;
2130 /* Set contents style of headers view */
2132 modest_main_window_set_contents_style (main_window,
2133 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2134 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2136 modest_main_window_set_contents_style (main_window,
2137 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2141 modest_header_view_refilter (header_view);
2146 modest_main_window_set_contents_style (ModestMainWindow *self,
2147 ModestMainWindowContentsStyle style)
2149 ModestMainWindowPrivate *priv;
2151 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2153 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2155 /* We allow to set the same content style than the previously
2156 set if there are details, because it could happen when we're
2157 selecting different accounts consecutively */
2158 if ((priv->contents_style == style) &&
2159 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2162 /* Remove previous child. Delete it if it was an account
2164 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2166 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2167 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2170 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2173 priv->contents_style = style;
2175 switch (priv->contents_style) {
2176 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2177 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2178 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2180 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2181 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2183 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2185 /* if we're started without main win, there may not be a folder
2186 * view. this fixes a GLib-Critical */
2187 if (priv->folder_view) {
2188 TnyFolderStore *selected_folderstore =
2189 modest_folder_view_get_selected (priv->folder_view);
2190 if (TNY_IS_ACCOUNT (selected_folderstore)) {
2191 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2192 TNY_ACCOUNT (selected_folderstore));
2194 wrap_in_scrolled_window (priv->contents_widget,
2195 priv->details_widget);
2197 if (selected_folderstore)
2198 g_object_unref (selected_folderstore);
2199 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2202 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2203 gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2206 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2207 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2208 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2210 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2211 gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2214 g_return_if_reached ();
2218 gtk_widget_show_all (priv->contents_widget);
2221 ModestMainWindowContentsStyle
2222 modest_main_window_get_contents_style (ModestMainWindow *self)
2224 ModestMainWindowPrivate *priv;
2226 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2228 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2229 return priv->contents_style;
2234 on_configuration_key_changed (ModestConf* conf,
2236 ModestConfEvent event,
2237 ModestConfNotificationId id,
2238 ModestMainWindow *self)
2240 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2241 TnyAccount *account = NULL;
2243 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2246 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2249 if (priv->folder_view)
2250 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2252 if (account && TNY_IS_ACCOUNT (account) &&
2253 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2256 const gchar *device_name;
2257 gchar *new_text, *gray_color_markup;
2260 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2261 label = GTK_LABEL (children->data);
2263 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2264 MODEST_CONF_DEVICE_NAME, NULL);
2266 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
2267 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2269 gtk_label_set_markup (label, new_text);
2270 gtk_widget_show (GTK_WIDGET (label));
2272 g_free (gray_color_markup);
2274 g_list_free (children);
2276 g_object_unref (account);
2280 set_toolbar_transfer_mode (ModestMainWindow *self)
2282 ModestMainWindowPrivate *priv = NULL;
2284 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2286 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2288 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2290 if (priv->progress_bar_timeout > 0) {
2291 g_source_remove (priv->progress_bar_timeout);
2292 priv->progress_bar_timeout = 0;
2299 set_toolbar_mode (ModestMainWindow *self,
2300 ModestToolBarModes mode)
2302 ModestWindowPrivate *parent_priv = NULL;
2303 ModestMainWindowPrivate *priv = NULL;
2304 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2306 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2308 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2311 /* In case this was called before the toolbar exists: */
2312 if (!(parent_priv->toolbar))
2315 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
2317 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2318 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2319 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2321 /* Sets current toolbar mode */
2322 priv->current_toolbar_mode = mode;
2324 /* Checks the dimming rules */
2325 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2326 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2328 /* Show and hide toolbar items */
2330 case TOOLBAR_MODE_NORMAL:
2332 gtk_action_set_visible (sort_action, TRUE);
2334 gtk_action_set_visible (refresh_action, TRUE);
2335 if (priv->progress_toolitem) {
2336 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2337 gtk_widget_hide (priv->progress_toolitem);
2339 if (priv->progress_bar)
2340 gtk_widget_hide (priv->progress_bar);
2343 gtk_action_set_visible (cancel_action, FALSE);
2345 /* Hide toolbar if optimized view is enabled */
2346 if (priv->optimized_view)
2347 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2349 case TOOLBAR_MODE_TRANSFER:
2351 gtk_action_set_visible (sort_action, FALSE);
2353 gtk_action_set_visible (refresh_action, FALSE);
2355 gtk_action_set_visible (cancel_action, TRUE);
2356 if (priv->progress_bar)
2357 gtk_widget_show (priv->progress_bar);
2358 if (priv->progress_toolitem) {
2359 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2360 gtk_widget_show (priv->progress_toolitem);
2363 /* Show toolbar if it's hiden (optimized view ) */
2364 if (priv->optimized_view)
2365 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2368 g_return_if_reached ();
2373 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2375 ModestMainWindowPrivate *priv;
2377 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2378 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2380 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2384 cancel_progressbar (GtkToolButton *toolbutton,
2385 ModestMainWindow *self)
2388 ModestMainWindowPrivate *priv;
2390 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2392 /* Get operation observers and cancel all the operations */
2393 tmp = priv->progress_widgets;
2395 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2396 tmp=g_slist_next(tmp);
2401 observers_empty (ModestMainWindow *self)
2404 ModestMainWindowPrivate *priv;
2405 gboolean is_empty = TRUE;
2406 guint pending_ops = 0;
2408 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2409 tmp = priv->progress_widgets;
2411 /* Check all observers */
2412 while (tmp && is_empty) {
2413 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2414 is_empty = pending_ops == 0;
2416 tmp = g_slist_next(tmp);
2424 * Gets the toolbar mode needed for each mail operation. It stores in
2425 * @mode_changed if the toolbar mode has changed or not
2427 static ModestToolBarModes
2428 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2429 ModestMailOperation *mail_op,
2430 gboolean *mode_changed)
2432 ModestToolBarModes mode;
2433 ModestMainWindowPrivate *priv;
2435 *mode_changed = FALSE;
2436 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2438 /* Get toolbar mode from operation id*/
2439 switch (modest_mail_operation_get_type_operation (mail_op)) {
2440 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2441 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2442 mode = TOOLBAR_MODE_TRANSFER;
2443 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2444 *mode_changed = TRUE;
2447 mode = TOOLBAR_MODE_NORMAL;
2453 on_mail_operation_started (ModestMailOperation *mail_op,
2456 ModestMainWindow *self;
2457 ModestMailOperationTypeOperation op_type;
2458 ModestMainWindowPrivate *priv;
2459 ModestToolBarModes mode;
2461 gboolean mode_changed = FALSE;
2462 TnyAccount *account = NULL;
2464 self = MODEST_MAIN_WINDOW (user_data);
2465 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2467 /* Do not show progress for receiving operations if the
2468 account is the local account or the MMC one */
2469 op_type = modest_mail_operation_get_type_operation (mail_op);
2470 account = modest_mail_operation_get_account (mail_op);
2471 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2474 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2475 modest_tny_account_is_memory_card_account (account));
2477 g_object_unref (account);
2481 /* Show information banner. Remove old timeout */
2482 if (priv->opening_banner_timeout > 0) {
2483 g_source_remove (priv->opening_banner_timeout);
2484 priv->opening_banner_timeout = 0;
2486 /* Create a new timeout */
2487 priv->opening_banner_timeout =
2488 g_timeout_add (2000, show_opening_banner, self);
2491 /* Not every mail operation has account, noop does not */
2493 g_object_unref (account);
2495 /* Get toolbar mode from operation id*/
2496 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2498 /* Add operation observers and change toolbar if neccessary*/
2499 tmp = priv->progress_widgets;
2500 if (mode == TOOLBAR_MODE_TRANSFER) {
2502 GObject *source = modest_mail_operation_get_source(mail_op);
2503 if (G_OBJECT (self) == source) {
2504 set_toolbar_transfer_mode(self);
2506 g_object_unref (source);
2510 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2512 tmp = g_slist_next (tmp);
2516 /* Update the main menu as well, we need to explicitely do
2517 this in order to enable/disable accelerators */
2518 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2522 on_mail_operation_finished (ModestMailOperation *mail_op,
2525 ModestToolBarModes mode;
2526 ModestMailOperationTypeOperation op_type;
2528 ModestMainWindow *self;
2529 gboolean mode_changed;
2530 TnyAccount *account = NULL;
2531 ModestMainWindowPrivate *priv;
2533 self = MODEST_MAIN_WINDOW (user_data);
2534 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2536 /* The mail operation was not added to the progress objects if
2537 the account was the local account or the MMC one */
2538 op_type = modest_mail_operation_get_type_operation (mail_op);
2539 account = modest_mail_operation_get_account (mail_op);
2540 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2543 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2544 modest_tny_account_is_memory_card_account (account));
2546 g_object_unref (account);
2550 /* Remove old timeout */
2551 if (priv->opening_banner_timeout > 0) {
2552 g_source_remove (priv->opening_banner_timeout);
2553 priv->opening_banner_timeout = 0;
2556 /* Remove the banner if exists */
2557 if (priv->opening_banner) {
2558 gtk_widget_destroy (priv->opening_banner);
2559 priv->opening_banner = NULL;
2563 /* Not every mail operation has account, noop does not */
2565 g_object_unref (account);
2567 /* Get toolbar mode from operation id*/
2568 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2570 /* Change toolbar mode */
2571 tmp = priv->progress_widgets;
2572 if (mode == TOOLBAR_MODE_TRANSFER) {
2574 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2576 tmp = g_slist_next (tmp);
2579 /* If no more operations are being observed, NORMAL mode is enabled again */
2580 if (observers_empty (self)) {
2581 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2587 on_queue_changed (ModestMailOperationQueue *queue,
2588 ModestMailOperation *mail_op,
2589 ModestMailOperationQueueNotification type,
2590 ModestMainWindow *self)
2592 ModestMainWindowPrivate *priv;
2594 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2596 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2597 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2599 "operation-started",
2600 G_CALLBACK (on_mail_operation_started),
2602 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2604 "operation-finished",
2605 G_CALLBACK (on_mail_operation_finished),
2607 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2608 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2610 "operation-started");
2611 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2613 "operation-finished");
2618 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2620 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2622 ModestAccountMgr *mgr;
2623 ModestAccountSettings *settings;
2624 ModestServerAccountSettings *store_settings = NULL;
2626 /* Get account data */
2627 mgr = modest_runtime_get_account_mgr ();
2628 settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2630 store_settings = modest_account_settings_get_store_settings (settings);
2632 /* Set the new visible & active account */
2633 if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) {
2634 const gchar *account_name;
2636 account_name = modest_account_settings_get_account_name (settings);
2638 modest_folder_view_set_account_id_of_visible_server_account
2640 modest_server_account_settings_get_account_name (store_settings));
2641 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2642 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2644 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2645 if (action != NULL) {
2646 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2647 modest_utils_toggle_action_set_active_block_notify (
2648 GTK_TOGGLE_ACTION (action),
2656 g_object_unref (store_settings);
2657 g_object_unref (settings);
2661 /* Make sure that at least one account is "viewed": */
2663 set_at_least_one_account_visible(ModestMainWindow *self)
2665 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2666 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2668 if (!(priv->folder_view)) {
2669 /* It is too early to do this. */
2673 const gchar *active_server_account_name =
2674 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2676 if (!active_server_account_name ||
2677 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2679 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2680 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2681 if (default_modest_name) {
2682 set_account_visible (self, default_modest_name);
2683 } else if (first_modest_name) {
2684 set_account_visible (self, first_modest_name);
2686 g_free (first_modest_name);
2687 g_free (default_modest_name);
2692 on_show_account_action_toggled (GtkToggleAction *action,
2695 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2697 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2698 if (gtk_toggle_action_get_active (action))
2699 set_account_visible (self, acc_name);
2703 refresh_account (const gchar *account_name)
2707 /* win must already exists here, obviously */
2708 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2711 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2715 /* If account_name == NULL, we must update all (option All) */
2717 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2719 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2724 on_refresh_account_action_activated (GtkAction *action,
2727 refresh_account ((const gchar*) user_data);
2731 on_send_receive_csm_activated (GtkMenuItem *item,
2734 refresh_account ((const gchar*) user_data);
2738 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2740 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2742 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2748 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2750 ModestMainWindow *main_window = NULL;
2752 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2753 main_window = MODEST_MAIN_WINDOW (userdata);
2755 /* Update toolbar dimming state */
2756 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2757 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2763 on_header_view_focus_in (GtkWidget *widget,
2764 GdkEventFocus *event,
2767 ModestMainWindow *main_window = NULL;
2769 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2771 main_window = MODEST_MAIN_WINDOW (userdata);
2773 /* Update toolbar dimming state */
2774 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2775 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2781 on_folder_selection_changed (ModestFolderView *folder_view,
2782 TnyFolderStore *folder_store,
2784 ModestMainWindow *main_window)
2786 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2787 GtkAction *action = NULL;
2788 gboolean show_reply = TRUE;
2789 gboolean show_forward = TRUE;
2790 gboolean show_cancel_send = FALSE;
2791 gboolean show_clipboard = TRUE;
2792 gboolean show_delete = TRUE;
2795 if (TNY_IS_ACCOUNT (folder_store)) {
2796 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2797 } else if (TNY_IS_FOLDER (folder_store)) {
2798 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2799 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2800 TNY_FOLDER (folder_store));
2801 switch (folder_type) {
2802 case TNY_FOLDER_TYPE_DRAFTS:
2803 show_clipboard = show_delete = TRUE;
2804 show_reply = show_forward = show_cancel_send = FALSE;
2806 case TNY_FOLDER_TYPE_SENT:
2807 show_forward = show_clipboard = show_delete = TRUE;
2808 show_reply = show_cancel_send = FALSE;
2810 case TNY_FOLDER_TYPE_OUTBOX:
2811 show_clipboard = show_delete = show_cancel_send = TRUE;
2812 show_reply = show_forward = FALSE;
2814 case TNY_FOLDER_TYPE_INVALID:
2815 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2818 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2819 show_cancel_send = FALSE;
2822 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2823 show_cancel_send = FALSE;
2828 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2829 gtk_action_set_visible (action, show_reply);
2830 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2831 gtk_action_set_visible (action, show_reply);
2832 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2833 gtk_action_set_visible (action, show_forward);
2834 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2835 gtk_action_set_visible (action, show_cancel_send);
2836 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2837 gtk_action_set_visible (action, show_delete);
2839 /* We finally call to the ui actions handler, after updating properly
2840 * the header view CSM */
2841 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2845 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2846 GtkTreeModel *model,
2847 GtkTreeRowReference *row_reference,
2848 ModestMainWindow *self)
2850 ModestMainWindowPrivate *priv = NULL;
2851 GtkTreeModel *header_model = NULL;
2852 GtkTreePath *path = NULL;
2854 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2855 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2856 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2858 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2859 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2861 /* Do nothing if we changed the folder in the main view */
2862 if (header_model != model)
2865 /* Select the message in the header view */
2866 path = gtk_tree_row_reference_get_path (row_reference);
2867 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2869 gtk_tree_path_free (path);
2875 updating_banner_destroyed (gpointer data,
2876 GObject *where_the_object_was)
2878 ModestMainWindowPrivate *priv = NULL;
2880 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2882 priv->updating_banner = NULL;
2886 show_updating_banner (gpointer user_data)
2888 ModestMainWindowPrivate *priv = NULL;
2890 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2892 if (priv->updating_banner == NULL) {
2894 /* We're outside the main lock */
2895 gdk_threads_enter ();
2896 priv->updating_banner =
2897 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2898 _CS ("ckdg_pb_updating"));
2900 /* We need this because banners in Maemo could be
2901 destroyed by dialogs so we need to properly update
2902 our reference to it */
2903 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2904 updating_banner_destroyed,
2906 gdk_threads_leave ();
2909 /* Remove timeout */
2910 priv->updating_banner_timeout = 0;
2915 * We use this function to show/hide a progress banner showing
2916 * "Updating" while the header view is being filled. We're not showing
2917 * it unless the update takes more than 2 seconds
2919 * If starting = TRUE then the refresh is starting, otherwise it means
2920 * that is has just finished
2923 on_updating_msg_list (ModestHeaderView *header_view,
2927 ModestMainWindowPrivate *priv = NULL;
2929 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2931 /* Remove old timeout */
2932 if (priv->updating_banner_timeout > 0) {
2933 g_source_remove (priv->updating_banner_timeout);
2934 priv->updating_banner_timeout = 0;
2937 /* Create a new timeout */
2939 priv->updating_banner_timeout =
2940 g_timeout_add (2000, show_updating_banner, user_data);
2942 /* Remove the banner if exists */
2943 if (priv->updating_banner) {
2944 gtk_widget_destroy (priv->updating_banner);
2945 priv->updating_banner = NULL;
2951 modest_main_window_screen_is_on (ModestMainWindow *self)
2953 ModestMainWindowPrivate *priv = NULL;
2955 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2957 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2959 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2963 remove_banners (ModestMainWindow *window)
2965 ModestMainWindowPrivate *priv;
2967 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2969 if (priv->opening_banner_timeout > 0) {
2970 g_source_remove (priv->opening_banner_timeout);
2971 priv->opening_banner_timeout = 0;
2974 if (priv->opening_banner != NULL) {
2975 gtk_widget_destroy (priv->opening_banner);
2976 priv->opening_banner = NULL;
2979 if (priv->updating_banner_timeout > 0) {
2980 g_source_remove (priv->updating_banner_timeout);
2981 priv->updating_banner_timeout = 0;
2984 if (priv->updating_banner != NULL) {
2985 gtk_widget_destroy (priv->updating_banner);
2986 priv->updating_banner = NULL;
2992 on_window_hide (GObject *gobject,
2996 g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2998 if (!GTK_WIDGET_VISIBLE (gobject)) {
2999 TnyFolderStore *folder_store;
3000 ModestMainWindowPrivate *priv;
3002 /* Remove the currently shown banners */
3003 remove_banners (MODEST_MAIN_WINDOW (gobject));
3005 /* Force the folder view to sync the currently selected folder
3006 to save the read/unread status and to expunge messages */
3007 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
3008 folder_store = modest_folder_view_get_selected (priv->folder_view);
3009 if (TNY_IS_FOLDER (folder_store)) {
3010 ModestMailOperation *mail_op;
3012 mail_op = modest_mail_operation_new (NULL);
3013 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3015 modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
3016 g_object_unref (mail_op);
3017 g_object_unref (folder_store);
3023 on_window_destroy (GtkObject *widget,
3026 g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
3028 remove_banners (MODEST_MAIN_WINDOW (widget));
3032 opening_banner_destroyed (gpointer data,
3033 GObject *where_the_object_was)
3035 ModestMainWindowPrivate *priv = NULL;
3037 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
3039 priv->opening_banner = NULL;
3043 show_opening_banner (gpointer user_data)
3045 ModestMainWindowPrivate *priv = NULL;
3047 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
3049 if (priv->opening_banner == NULL) {
3051 /* We're outside the main lock */
3052 gdk_threads_enter ();
3053 priv->opening_banner =
3054 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
3055 _("mail_me_opening"));
3057 /* We need this because banners in Maemo could be
3058 destroyed by dialogs so we need to properly update
3059 our reference to it */
3060 g_object_weak_ref (G_OBJECT (priv->opening_banner),
3061 opening_banner_destroyed,
3064 /* We need this because banners in Maemo could be
3065 destroyed by dialogs so we need to properly update
3066 our reference to it */
3067 g_object_weak_ref (G_OBJECT (priv->updating_banner),
3068 updating_banner_destroyed,
3070 gdk_threads_leave ();
3073 /* Remove timeout */
3074 priv->opening_banner_timeout = 0;