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-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.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-widget.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "maemo/modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
66 #include "modest-signal-mgr.h"
68 #ifdef MODEST_HAVE_HILDON0_WIDGETS
69 #include <hildon-widgets/hildon-program.h>
71 #include <hildon/hildon-program.h>
72 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
74 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
81 /* 'private'/'protected' functions */
82 static void modest_main_window_class_init (ModestMainWindowClass *klass);
83 static void modest_main_window_init (ModestMainWindow *obj);
84 static void modest_main_window_finalize (GObject *obj);
86 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
87 GdkEventWindowState *event,
90 static void connect_signals (ModestMainWindow *self);
92 static void modest_main_window_disconnect_signals (ModestWindow *self);
94 static void restore_settings (ModestMainWindow *self,
95 gboolean do_folder_view_too);
97 static void save_state (ModestWindow *self);
99 static void update_menus (ModestMainWindow* self);
101 static void modest_main_window_show_toolbar (ModestWindow *window,
102 gboolean show_toolbar);
104 static void cancel_progressbar (GtkToolButton *toolbutton,
105 ModestMainWindow *self);
107 static void on_queue_changed (ModestMailOperationQueue *queue,
108 ModestMailOperation *mail_op,
109 ModestMailOperationQueueNotification type,
110 ModestMainWindow *self);
112 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
115 on_account_inserted (TnyAccountStore *accoust_store,
120 on_account_removed (TnyAccountStore *accoust_store,
124 static void on_default_account_changed (ModestAccountMgr* mgr,
127 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
131 static void on_configuration_key_changed (ModestConf* conf,
133 ModestConfEvent event,
134 ModestConfNotificationId id,
135 ModestMainWindow *self);
137 static void set_toolbar_mode (ModestMainWindow *self,
138 ModestToolBarModes mode);
140 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
142 static void on_show_account_action_toggled (GtkToggleAction *action,
145 static void on_refresh_account_action_activated (GtkAction *action,
148 static void on_send_receive_csm_activated (GtkMenuItem *item,
151 static void on_msg_count_changed (ModestHeaderView *header_view,
153 TnyFolderChange *change,
154 ModestMainWindow *main_window);
156 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
159 static GtkWidget * create_empty_view (void);
161 static gboolean on_folder_view_focus_in (GtkWidget *widget,
162 GdkEventFocus *event,
165 static gboolean on_header_view_focus_in (GtkWidget *widget,
166 GdkEventFocus *event,
169 static void modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
170 TnyFolderStore *folder_store,
172 ModestMainWindow *main_window);
174 static void set_at_least_one_account_visible(ModestMainWindow *self);
176 static void on_updating_msg_list (ModestHeaderView *header_view,
180 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
181 struct _ModestMainWindowPrivate {
182 GtkWidget *msg_paned;
183 GtkWidget *main_paned;
184 GtkWidget *main_vbox;
185 GtkWidget *contents_widget;
186 GtkWidget *empty_view;
188 /* Progress observers */
189 GtkWidget *progress_bar;
190 GSList *progress_widgets;
193 GtkWidget *progress_toolitem;
194 GtkWidget *cancel_toolitem;
195 GtkWidget *sort_toolitem;
196 GtkWidget *refresh_toolitem;
197 ModestToolBarModes current_toolbar_mode;
199 /* Merge ids used to add/remove accounts to the ViewMenu*/
200 GByteArray *merge_ids;
201 GtkActionGroup *view_additions_group;
203 /* On-demand widgets */
204 GtkWidget *accounts_popup;
205 GtkWidget *details_widget;
207 /* Optimized view enabled */
208 gboolean optimized_view;
210 /* Optimized view enabled */
211 gboolean send_receive_in_progress;
213 ModestHeaderView *header_view;
214 ModestFolderView *folder_view;
216 ModestMainWindowStyle style;
217 ModestMainWindowContentsStyle contents_style;
219 guint progress_bar_timeout;
221 /* Signal handler UIDs */
222 GList *queue_err_signals;
225 /* "Updating" banner for header view */
226 GtkWidget *updating_banner;
227 guint updating_banner_timeout;
229 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
230 MODEST_TYPE_MAIN_WINDOW, \
231 ModestMainWindowPrivate))
233 typedef struct _GetMsgAsyncHelper {
234 ModestMainWindowPrivate *main_window_private;
236 ModestTnyMsgReplyType reply_type;
237 ModestTnyMsgForwardType forward_type;
244 static GtkWindowClass *parent_class = NULL;
247 /* Private actions */
248 /* This is the context sensitive menu: */
249 static const GtkActionEntry modest_folder_view_action_entries [] = {
251 /* Folder View CSM actions */
252 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
253 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
254 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
255 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
256 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
257 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
260 static const GtkActionEntry modest_header_view_action_entries [] = {
262 /* Header View CSM actions */
263 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
264 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
265 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
266 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
267 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
268 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
269 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
270 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
271 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
272 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
275 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
276 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
279 /************************************************************************/
282 modest_main_window_get_type (void)
284 static GType my_type = 0;
286 static const GTypeInfo my_info = {
287 sizeof(ModestMainWindowClass),
288 NULL, /* base init */
289 NULL, /* base finalize */
290 (GClassInitFunc) modest_main_window_class_init,
291 NULL, /* class finalize */
292 NULL, /* class data */
293 sizeof(ModestMainWindow),
295 (GInstanceInitFunc) modest_main_window_init,
298 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
306 modest_main_window_class_init (ModestMainWindowClass *klass)
308 GObjectClass *gobject_class;
309 gobject_class = (GObjectClass*) klass;
310 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
312 parent_class = g_type_class_peek_parent (klass);
313 gobject_class->finalize = modest_main_window_finalize;
315 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
317 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
318 modest_window_class->save_state_func = save_state;
319 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
320 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
321 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
325 modest_main_window_init (ModestMainWindow *obj)
327 ModestMainWindowPrivate *priv;
329 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
331 priv->queue_err_signals = NULL;
332 priv->msg_paned = NULL;
333 priv->main_paned = NULL;
334 priv->main_vbox = NULL;
335 priv->header_view = NULL;
336 priv->folder_view = NULL;
337 priv->contents_widget = NULL;
338 priv->accounts_popup = NULL;
339 priv->details_widget = NULL;
340 priv->empty_view = NULL;
341 priv->progress_widgets = NULL;
342 priv->progress_bar = NULL;
343 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
344 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
345 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
346 priv->merge_ids = NULL;
347 priv->optimized_view = FALSE;
348 priv->send_receive_in_progress = FALSE;
349 priv->progress_bar_timeout = 0;
350 priv->sighandlers = NULL;
351 priv->updating_banner = NULL;
352 priv->updating_banner_timeout = 0;
356 modest_main_window_finalize (GObject *obj)
358 ModestMainWindowPrivate *priv;
360 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
362 /* Sanity check: shouldn't be needed, the window mgr should
363 call this function before */
364 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
366 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
368 g_slist_free (priv->progress_widgets);
370 g_byte_array_free (priv->merge_ids, TRUE);
372 if (priv->progress_bar_timeout > 0) {
373 g_source_remove (priv->progress_bar_timeout);
374 priv->progress_bar_timeout = 0;
377 if (priv->updating_banner_timeout > 0) {
378 g_source_remove (priv->updating_banner_timeout);
379 priv->updating_banner_timeout = 0;
382 G_OBJECT_CLASS(parent_class)->finalize (obj);
386 modest_main_window_get_child_widget (ModestMainWindow *self,
387 ModestMainWindowWidgetType widget_type)
389 ModestMainWindowPrivate *priv;
392 g_return_val_if_fail (self, NULL);
393 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
396 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
398 switch (widget_type) {
399 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
400 widget = (GtkWidget*)priv->header_view; break;
401 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
402 widget = (GtkWidget*)priv->folder_view; break;
407 return widget ? GTK_WIDGET(widget) : NULL;
412 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
415 ModestMainWindowPrivate *priv;
417 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
419 conf = modest_runtime_get_conf ();
421 modest_widget_memory_restore (conf, G_OBJECT(self),
422 MODEST_CONF_MAIN_WINDOW_KEY);
424 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
425 MODEST_CONF_HEADER_VIEW_KEY);
427 if (do_folder_view_too)
428 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
429 MODEST_CONF_FOLDER_VIEW_KEY);
431 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
432 MODEST_CONF_MAIN_PANED_KEY);
434 /* We need to force a redraw here in order to get the right
435 position of the horizontal paned separator */
436 gtk_widget_show (GTK_WIDGET (self));
441 save_state (ModestWindow *window)
444 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
445 ModestMainWindowPrivate *priv;
447 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
448 conf = modest_runtime_get_conf ();
450 modest_widget_memory_save (conf,G_OBJECT(self),
451 MODEST_CONF_MAIN_WINDOW_KEY);
452 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
453 MODEST_CONF_MAIN_PANED_KEY);
454 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
455 // MODEST_CONF_HEADER_VIEW_KEY);
456 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
457 MODEST_CONF_FOLDER_VIEW_KEY);
461 compare_display_names (ModestAccountData *a,
462 ModestAccountData *b)
464 return strcmp (a->display_name, b->display_name);
468 update_menus (ModestMainWindow* self)
470 GSList *account_names, *iter, *accounts;
471 ModestMainWindowPrivate *priv;
472 ModestWindowPrivate *parent_priv;
473 ModestAccountMgr *mgr;
474 gint i, num_accounts;
476 gchar *default_account;
477 GtkWidget *send_receive_button, *item;
478 GtkAction *send_receive_all = NULL;
481 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
482 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
484 /* Get enabled account IDs */
485 mgr = modest_runtime_get_account_mgr ();
486 account_names = modest_account_mgr_account_names (mgr, TRUE);
487 iter = account_names;
491 ModestAccountData *account_data =
492 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
493 accounts = g_slist_prepend (accounts, account_data);
497 modest_account_mgr_free_account_names (account_names);
498 account_names = NULL;
500 /* Order the list of accounts by its display name */
501 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
502 num_accounts = g_slist_length (accounts);
504 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
505 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
506 gtk_action_set_visible (send_receive_all, num_accounts > 1);
508 /* Delete old send&receive popup items. We can not just do a
509 menu_detach because it does not work well with
511 if (priv->accounts_popup)
512 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
513 (GtkCallback) gtk_widget_destroy, NULL);
515 /* Delete old entries in the View menu. Do not free groups, it
517 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
519 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
520 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
521 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
522 GTK_ACTION_GROUP (groups->data));
525 if (priv->merge_ids) {
526 for (i = 0; i < priv->merge_ids->len; i++)
527 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
528 g_byte_array_free (priv->merge_ids, TRUE);
530 /* We need to call this in order to ensure
531 that the new actions are added in the right
532 order (alphabetical) */
533 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
535 groups = g_list_next (groups);
537 priv->merge_ids = g_byte_array_sized_new (num_accounts);
539 /* Get send receive button */
540 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
541 "/ToolBar/ToolbarSendReceive");
543 /* Create the menu */
544 if (num_accounts > 1) {
545 if (!priv->accounts_popup)
546 priv->accounts_popup = gtk_menu_new ();
547 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
548 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
549 g_signal_connect (G_OBJECT (item),
551 G_CALLBACK (on_send_receive_csm_activated),
553 item = gtk_separator_menu_item_new ();
554 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
557 /* Create a new action group */
558 default_account = modest_account_mgr_get_default_account (mgr);
559 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
561 for (i = 0; i < num_accounts; i++) {
562 gchar *display_name = NULL;
563 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
565 if (default_account && account_data->account_name &&
566 !(strcmp (default_account, account_data->account_name) == 0)) {
567 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
568 account_data->display_name);
571 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
572 account_data->display_name);
575 /* Create action and add it to the action group. The
576 action name must be the account name, this way we
577 could know in the handlers the account to show */
578 if(account_data && account_data->account_name) {
579 gchar* item_name, *refresh_action_name;
581 GtkAction *view_account_action, *refresh_account_action;
583 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
584 display_name, NULL, NULL, 0));
585 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
586 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
587 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
589 if (default_account && account_data->account_name &&
590 (strcmp (default_account, account_data->account_name) == 0)) {
591 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
594 /* Add ui from account data. We allow 2^9-1 account
595 changes in a single execution because we're
596 downcasting the guint to a guint8 in order to use a
597 GByteArray. It should be enough. */
598 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
599 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
600 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
601 gtk_ui_manager_add_ui (parent_priv->ui_manager,
603 "/MenuBar/ViewMenu/ViewMenuAdditions",
605 account_data->account_name,
606 GTK_UI_MANAGER_MENUITEM,
609 /* Connect the action signal "activate" */
610 g_signal_connect_after (G_OBJECT (view_account_action),
612 G_CALLBACK (on_show_account_action_toggled),
615 /* Create the items for the Tools->Send&Receive submenu */
616 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
617 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
618 display_name, NULL, NULL);
619 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
621 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
622 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
623 gtk_ui_manager_add_ui (parent_priv->ui_manager,
625 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
628 GTK_UI_MANAGER_MENUITEM,
630 g_free (refresh_action_name);
632 g_signal_connect_data (G_OBJECT (refresh_account_action),
634 G_CALLBACK (on_refresh_account_action_activated),
635 g_strdup (account_data->account_name),
636 (GClosureNotify) g_free,
639 /* Create item and add it to the send&receive
640 CSM. If there is only one account then
642 if (priv->accounts_popup) {
643 GtkWidget *label = gtk_label_new(NULL);
644 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
645 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
647 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
648 gtk_label_set_markup (GTK_LABEL (label), escaped);
653 gtk_label_set_text (GTK_LABEL (label), display_name);
656 item = gtk_menu_item_new ();
657 gtk_container_add (GTK_CONTAINER (item), label);
659 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
660 g_signal_connect_data (G_OBJECT (item),
662 G_CALLBACK (on_send_receive_csm_activated),
663 g_strdup (account_data->account_name),
664 (GClosureNotify) g_free,
671 g_free (display_name);
674 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
676 /* We cannot do this in the loop above because this relies on the action
677 * group being inserted. This makes the default account appear in bold.
678 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
679 for (i = 0; i < num_accounts; i++) {
680 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
682 if(account_data->account_name && default_account &&
683 strcmp (account_data->account_name, default_account) == 0) {
684 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
686 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
687 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
691 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
692 if (GTK_IS_LABEL (child)) {
693 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
694 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
695 gtk_label_set_markup (GTK_LABEL (child), bold_name);
700 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
701 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
705 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
706 if (GTK_IS_LABEL (child)) {
707 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
708 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
709 gtk_label_set_markup (GTK_LABEL (child), bold_name);
717 modest_account_mgr_free_account_data (mgr, account_data);
720 if (priv->accounts_popup) {
721 /* Mandatory in order to view the menu contents */
722 gtk_widget_show_all (priv->accounts_popup);
724 /* Setup tap_and_hold just if was not done before*/
725 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
726 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
730 g_slist_free (accounts);
731 g_free (default_account);
734 /* Make sure that at least one account is viewed if there are any
735 * accounts, for instance when adding the first account: */
736 set_at_least_one_account_visible (self);
740 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
742 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
743 gtk_scrolled_window_add_with_viewport
744 (GTK_SCROLLED_WINDOW(win), widget);
746 gtk_container_add (GTK_CONTAINER(win),
757 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
759 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
761 GList *oerrsignals = priv->queue_err_signals;
762 while (oerrsignals) {
763 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
764 g_signal_handler_disconnect (esignal->queue, esignal->signal);
765 g_slice_free (QueueErrorSignal, esignal);
766 oerrsignals = g_list_next (oerrsignals);
768 g_list_free (priv->queue_err_signals);
769 priv->queue_err_signals = NULL;
774 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
776 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
779 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
783 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
785 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
787 /* Update visibility */
790 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
794 modest_main_window_disconnect_signals (ModestWindow *self)
796 ModestMainWindowPrivate *priv;
797 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
799 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
800 priv->sighandlers = NULL;
804 connect_signals (ModestMainWindow *self)
806 ModestWindowPrivate *parent_priv;
807 ModestMainWindowPrivate *priv;
810 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
811 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
816 modest_signal_mgr_connect (priv->sighandlers,
817 G_OBJECT(priv->folder_view), "key-press-event",
818 G_CALLBACK(on_inner_widgets_key_pressed), self);
820 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
821 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
823 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
824 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
826 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
827 G_CALLBACK (on_folder_view_focus_in), self);
829 /* Folder view CSM */
830 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
831 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
832 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
833 G_CALLBACK(_folder_view_csm_menu_activated),
837 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
838 G_CALLBACK(modest_ui_actions_on_header_selected), self);
840 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
841 G_CALLBACK(modest_ui_actions_on_header_activated), self);
843 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
844 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
846 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
847 G_CALLBACK(on_inner_widgets_key_pressed), self);
849 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
850 G_CALLBACK(on_msg_count_changed), self);
852 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
853 G_CALLBACK (on_header_view_focus_in), self);
855 modest_signal_mgr_connect (priv->sighandlers,
856 G_OBJECT (priv->header_view),
858 G_CALLBACK (on_updating_msg_list),
861 /* Header view CSM */
862 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
863 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
864 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
865 G_CALLBACK(_header_view_csm_menu_activated),
869 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
870 G_CALLBACK (modest_main_window_window_state_event),
873 /* Mail Operation Queue */
875 modest_signal_mgr_connect (priv->sighandlers,
876 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
878 G_CALLBACK (on_queue_changed), self);
880 /* Track changes in the device name */
882 modest_signal_mgr_connect (priv->sighandlers,
883 G_OBJECT(modest_runtime_get_conf ()),
885 G_CALLBACK (on_configuration_key_changed),
888 /* Track account changes. We need to refresh the toolbar */
890 modest_signal_mgr_connect (priv->sighandlers,
891 G_OBJECT (modest_runtime_get_account_store ()),
893 G_CALLBACK (on_account_inserted),
896 modest_signal_mgr_connect (priv->sighandlers,
897 G_OBJECT (modest_runtime_get_account_store ()),
899 G_CALLBACK (on_account_removed),
902 /* We need to refresh the send & receive menu to change the bold
903 * account when the default account changes. */
905 modest_signal_mgr_connect (priv->sighandlers,
906 G_OBJECT (modest_runtime_get_account_mgr ()),
907 "default_account_changed",
908 G_CALLBACK (on_default_account_changed),
913 modest_signal_mgr_connect (priv->sighandlers,
914 G_OBJECT (modest_runtime_get_account_store()),
915 "password_requested",
916 G_CALLBACK (modest_ui_actions_on_password_requested),
921 /** Idle handler, to send/receive at startup .*/
923 sync_accounts_cb (ModestMainWindow *win)
925 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
926 return FALSE; /* Do not call this idle handler again. */
931 on_hildon_program_is_topmost_notify(GObject *self,
932 GParamSpec *propert_param, gpointer user_data)
934 HildonProgram *app = HILDON_PROGRAM (self);
937 ModestWindow* self = MODEST_WINDOW(user_data);
940 /* Note that use of hildon_program_set_can_hibernate()
941 * is generally referred to as "setting the killable flag",
942 * though hibernation does not seem equal to death.
945 if (hildon_program_get_is_topmost (app)) {
946 /* Prevent hibernation when the progam comes to the foreground,
947 * because hibernation should only happen when the application
948 * is in the background: */
949 hildon_program_set_can_hibernate (app, FALSE);
951 /* Allow hibernation if the program has gone to the background: */
953 /* However, prevent hibernation while the settings are being changed: */
954 const gboolean hibernation_prevented =
955 modest_window_mgr_get_hibernation_is_prevented (
956 modest_runtime_get_window_mgr ());
958 if (hibernation_prevented)
959 hildon_program_set_can_hibernate (app, FALSE);
961 /* Allow hibernation, after saving the state: */
962 modest_osso_save_state();
963 hildon_program_set_can_hibernate (app, TRUE);
970 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
972 GtkWidget *folder_win = (GtkWidget *) user_data;
973 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
975 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
976 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
977 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
979 gtk_widget_show (GTK_WIDGET (priv->folder_view));
981 /* Connect signals */
982 connect_signals (MODEST_MAIN_WINDOW (self));
984 /* Set account store */
985 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
986 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
988 /* Load previous osso state, for instance if we are being restored from
990 modest_osso_load_state ();
992 /* Restore window & widget settings */
994 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
996 /* The UI spec wants us to show a connection dialog when the application is
997 * started by the user, if there is no connection.
998 * Do this before showing the account wizard,
999 * because wizard needs a connection to discover capabilities. */
1000 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
1002 /* Check if accounts exist and show the account wizard if not */
1003 gboolean accounts_exist =
1004 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1006 if (!accounts_exist) {
1007 /* This is necessary to have the main window shown behind the dialog
1008 It's an ugly hack... jschmid */
1009 gtk_widget_show_all(GTK_WIDGET(self));
1010 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1013 GtkAction *send_receive_all;
1014 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1015 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1016 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1017 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1018 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1019 modest_account_mgr_free_account_names (accounts);
1024 modest_main_window_new (void)
1026 ModestMainWindow *self = NULL;
1027 ModestMainWindowPrivate *priv = NULL;
1028 ModestWindowPrivate *parent_priv = NULL;
1029 GtkWidget *folder_win = NULL;
1030 ModestDimmingRulesGroup *menu_rules_group = NULL;
1031 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1032 GtkActionGroup *action_group = NULL;
1033 GError *error = NULL;
1034 ModestConf *conf = NULL;
1035 GtkAction *action = NULL;
1036 GdkPixbuf *window_icon;
1038 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1039 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1040 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1042 parent_priv->ui_manager = gtk_ui_manager_new();
1043 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1045 action_group = gtk_action_group_new ("ModestMainWindowActions");
1046 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1048 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1049 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1051 /* Add common actions */
1052 gtk_action_group_add_actions (action_group,
1053 modest_action_entries,
1054 G_N_ELEMENTS (modest_action_entries),
1057 gtk_action_group_add_actions (action_group,
1058 modest_folder_view_action_entries,
1059 G_N_ELEMENTS (modest_folder_view_action_entries),
1062 gtk_action_group_add_actions (action_group,
1063 modest_header_view_action_entries,
1064 G_N_ELEMENTS (modest_header_view_action_entries),
1067 gtk_action_group_add_toggle_actions (action_group,
1068 modest_toggle_action_entries,
1069 G_N_ELEMENTS (modest_toggle_action_entries),
1072 gtk_action_group_add_toggle_actions (action_group,
1073 modest_main_window_toggle_action_entries,
1074 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1077 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1078 g_object_unref (action_group);
1080 /* Load the UI definition */
1081 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1082 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1083 if (error != NULL) {
1084 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1085 g_error_free (error);
1089 /* Add common dimming rules */
1090 modest_dimming_rules_group_add_rules (menu_rules_group,
1091 modest_main_window_menu_dimming_entries,
1092 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1093 MODEST_WINDOW (self));
1094 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1095 modest_main_window_toolbar_dimming_entries,
1096 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1097 MODEST_WINDOW (self));
1099 /* Insert dimming rules group for this window */
1100 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1101 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1102 g_object_unref (menu_rules_group);
1103 g_object_unref (toolbar_rules_group);
1105 /* Add accelerators */
1106 gtk_window_add_accel_group (GTK_WINDOW (self),
1107 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1109 /* Menubar. Update the state of some toggles */
1110 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1111 conf = modest_runtime_get_conf ();
1112 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1113 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1114 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1115 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1116 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1117 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1118 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1119 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1120 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1121 gtk_widget_show (parent_priv->menubar);
1123 /* Get device name */
1124 modest_maemo_utils_get_device_name ();
1128 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1129 if (!priv->header_view)
1130 g_printerr ("modest: cannot instantiate header view\n");
1131 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1132 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1133 MODEST_CONF_HEADER_VIEW_KEY);
1135 /* Other style properties of header view */
1136 g_object_set (G_OBJECT (priv->header_view),
1137 "rules-hint", FALSE,
1139 /* gtk_widget_show (priv->header_view); */
1142 priv->empty_view = create_empty_view ();
1143 gtk_widget_show (priv->empty_view);
1145 /* Create scrolled windows */
1146 folder_win = gtk_scrolled_window_new (NULL, NULL);
1147 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1148 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1150 GTK_POLICY_AUTOMATIC);
1151 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1153 GTK_POLICY_AUTOMATIC);
1154 /* gtk_widget_show (priv->contents_widget); */
1157 priv->main_paned = gtk_hpaned_new ();
1158 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1159 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1160 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1162 /* putting it all together... */
1163 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1164 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1165 gtk_widget_show (priv->main_vbox);
1167 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1169 HildonProgram *app = hildon_program_get_instance ();
1170 hildon_program_add_window (app, HILDON_WINDOW (self));
1172 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1173 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1175 g_signal_connect (G_OBJECT(self), "show",
1176 G_CALLBACK (modest_main_window_on_show), folder_win);
1178 /* Set window icon */
1179 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1181 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1182 g_object_unref (window_icon);
1185 /* Dont't restore settings here,
1186 * because it requires a gtk_widget_show(),
1187 * and we don't want to do that until later,
1188 * so that the UI is not visible for non-menu D-Bus activation.
1190 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1192 return MODEST_WINDOW(self);
1196 modest_main_window_close_all (ModestMainWindow *self)
1199 GtkResponseType response;
1201 /* Create the confirmation dialog MSG-NOT308 */
1202 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1203 _("emev_nc_close_windows"),
1204 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1205 _("mcen_bd_no"), GTK_RESPONSE_NO,
1208 response = gtk_dialog_run (GTK_DIALOG (note));
1209 gtk_widget_destroy (GTK_WIDGET (note));
1211 if (response == GTK_RESPONSE_YES)
1219 modest_main_window_set_style (ModestMainWindow *self,
1220 ModestMainWindowStyle style)
1222 ModestMainWindowPrivate *priv;
1223 ModestWindowPrivate *parent_priv;
1227 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1229 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1230 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1232 /* no change -> nothing to do */
1233 if (priv->style == style)
1236 /* Get toggle button and update the state if needed. This will
1237 happen only when the set_style is not invoked from the UI,
1238 for example when it's called from widget memory */
1239 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1240 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1241 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1242 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1243 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1244 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1245 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1248 priv->style = style;
1250 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1251 /* Remove main paned */
1252 g_object_ref (priv->main_paned);
1253 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1255 /* Reparent the contents widget to the main vbox */
1256 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1259 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1260 /* Remove header view */
1261 g_object_ref (priv->contents_widget);
1262 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1264 /* Reparent the main paned */
1265 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1266 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1270 g_return_if_reached ();
1273 /* Let header view grab the focus if it's being shown */
1274 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1275 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1277 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1280 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1283 ModestMainWindowStyle
1284 modest_main_window_get_style (ModestMainWindow *self)
1286 ModestMainWindowPrivate *priv;
1288 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1290 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1297 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1299 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1300 ModestWindowPrivate *parent_priv;
1301 ModestWindowMgr *mgr;
1302 gboolean is_fullscreen;
1303 GtkAction *fs_toggle_action;
1306 mgr = modest_runtime_get_window_mgr ();
1308 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1310 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1312 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1313 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1314 if (is_fullscreen != active) {
1315 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1324 set_homogeneous (GtkWidget *widget,
1327 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1328 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1332 modest_main_window_show_toolbar (ModestWindow *self,
1333 gboolean show_toolbar)
1335 ModestMainWindowPrivate *priv = NULL;
1336 ModestWindowPrivate *parent_priv = NULL;
1337 GtkWidget *reply_button = NULL, *menu = NULL;
1338 GtkWidget *placeholder = NULL;
1340 const gchar *action_name;
1343 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1344 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1345 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1347 /* Set optimized view status */
1348 priv->optimized_view = !show_toolbar;
1350 if (!parent_priv->toolbar) {
1351 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1353 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1355 /* Set homogeneous toolbar */
1356 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1357 set_homogeneous, NULL);
1359 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1360 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1361 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1362 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1363 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1364 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1365 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1366 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1368 /* Add ProgressBar (Transfer toolbar) */
1369 priv->progress_bar = modest_progress_bar_widget_new ();
1370 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1371 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1372 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1373 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1374 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1376 /* Connect cancel 'clicked' signal to abort progress mode */
1377 g_signal_connect(priv->cancel_toolitem, "clicked",
1378 G_CALLBACK(cancel_progressbar),
1381 /* Add it to the observers list */
1382 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1385 hildon_window_add_toolbar (HILDON_WINDOW (self),
1386 GTK_TOOLBAR (parent_priv->toolbar));
1388 /* Set reply button tap and hold menu */
1389 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1390 "/ToolBar/ToolbarMessageReply");
1391 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1392 "/ToolbarReplyCSM");
1393 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1395 /* Set send & receive button tap and hold menu */
1396 update_menus (MODEST_MAIN_WINDOW (self));
1400 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1401 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1402 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1404 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1405 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1407 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1411 /* Update also the actions (to update the toggles in the
1412 menus), we have to do it manually because some other window
1413 of the same time could have changed it (remember that the
1414 toolbar fullscreen mode is shared by all the windows of the
1416 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1417 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1419 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1421 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1422 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1427 on_account_inserted (TnyAccountStore *accoust_store,
1428 TnyAccount *account,
1431 update_menus (MODEST_MAIN_WINDOW (user_data));
1435 on_default_account_changed (ModestAccountMgr* mgr,
1438 update_menus (MODEST_MAIN_WINDOW (user_data));
1442 on_account_removed (TnyAccountStore *accoust_store,
1443 TnyAccount *account,
1446 update_menus (MODEST_MAIN_WINDOW (user_data));
1450 * This function manages the key events used to navigate between
1451 * header and folder views (when the window is in split view)
1454 * -------------------------------------------------
1455 * HeaderView GDK_Left Move focus to folder view
1456 * FolderView GDK_Right Move focus to header view
1458 * There is no need to scroll to selected row, the widgets will be the
1459 * responsibles of doing that (probably managing the focus-in event
1462 on_inner_widgets_key_pressed (GtkWidget *widget,
1466 ModestMainWindowPrivate *priv;
1468 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1470 /* Do nothing if we're in SIMPLE style */
1471 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1474 if (MODEST_IS_HEADER_VIEW (widget)) {
1475 if (event->keyval == GDK_Left)
1476 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1477 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1478 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1481 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1482 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1488 set_alignment (GtkWidget *widget,
1491 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1492 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1496 create_empty_view (void)
1498 GtkLabel *label = NULL;
1499 GtkWidget *align = NULL;
1501 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1502 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1503 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1504 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1506 return GTK_WIDGET(align);
1510 * Free the returned string
1513 get_gray_color_markup (GtkWidget *styled_widget)
1515 gchar *gray_color_markup;
1517 /* Obtain the secondary text color. We need a realized widget, that's why
1518 we get styled_widget from outside */
1519 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1521 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1522 gray_color_markup = modest_text_utils_get_color_string (&color);
1524 gray_color_markup = g_strdup ("#BBBBBB");
1526 return gray_color_markup;
1530 * Free the returned string
1533 create_device_name_visual_string (const gchar *device_name,
1534 const gchar *gray_color_markup)
1538 /* We have to use "" to fill the %s of the translation. We can
1539 not just use the device name because the device name is
1540 shown in a different color, so it could not be included
1541 into the <span> tag */
1542 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1543 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1553 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1555 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1560 gchar *gray_color_markup;
1562 vbox = gtk_vbox_new (FALSE, 0);
1564 gray_color_markup = get_gray_color_markup (styled_widget);
1566 /* Account description: */
1567 if (modest_tny_account_is_virtual_local_folders (account)
1568 || (modest_tny_account_is_memory_card_account (account))) {
1570 /* Get device name */
1571 gchar *device_name = NULL;
1572 if (modest_tny_account_is_virtual_local_folders (account))
1573 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1574 MODEST_CONF_DEVICE_NAME, NULL);
1576 device_name = g_strdup (tny_account_get_name (account));
1578 label = create_device_name_visual_string ((const gchar *) device_name,
1579 (const gchar *) gray_color_markup);
1580 label_w = gtk_label_new (NULL);
1581 gtk_label_set_markup (GTK_LABEL (label_w), label);
1582 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1583 g_free (device_name);
1586 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1587 gtk_box_pack_start (GTK_BOX (vbox),
1588 gtk_label_new (tny_account_get_name (account)),
1591 /* Other accounts, such as IMAP and POP: */
1596 /* Put proto in uppercase */
1597 proto = g_string_new (tny_account_get_proto (account));
1598 proto = g_string_ascii_up (proto);
1600 /* note: mcen_fi_localroot_description is something like "%s account"
1601 * however, we should display "%s account: %s"... therefore, ugly tmp */
1602 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1603 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1604 gray_color_markup, tmp, tny_account_get_name (account));
1607 label_w = gtk_label_new (NULL);
1608 gtk_label_set_markup (GTK_LABEL (label_w), label);
1609 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1610 g_string_free (proto, TRUE);
1616 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1617 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1618 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1619 modest_tny_folder_store_get_message_count (folder_store));
1620 label_w = gtk_label_new (NULL);
1621 gtk_label_set_markup (GTK_LABEL (label_w), label);
1622 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1626 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1628 _("mcen_fi_rootfolder_folders"),
1629 modest_tny_folder_store_get_folder_count (folder_store));
1630 label_w = gtk_label_new (NULL);
1631 gtk_label_set_markup (GTK_LABEL (label_w), label);
1632 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1636 if (modest_tny_account_is_virtual_local_folders (account)
1637 || modest_tny_account_is_memory_card_account (account)) {
1639 gchar *size = modest_text_utils_get_display_size (
1640 modest_tny_folder_store_get_local_size (folder_store));
1642 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1643 gray_color_markup, _("mcen_fi_rootfolder_size"),
1647 label_w = gtk_label_new (NULL);
1648 gtk_label_set_markup (GTK_LABEL (label_w), label);
1649 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1651 } else if (TNY_IS_ACCOUNT(folder_store)) {
1652 TnyAccount *account = TNY_ACCOUNT(folder_store);
1654 time_t last_updated;
1655 gchar *last_updated_string;
1656 /* Get last updated from configuration */
1657 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1658 tny_account_get_id (account));
1660 if (last_updated > 0)
1661 last_updated_string = modest_text_utils_get_display_date(last_updated);
1663 last_updated_string = g_strdup (_("mcen_va_never"));
1665 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1666 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1667 label_w = gtk_label_new (NULL);
1668 gtk_label_set_markup (GTK_LABEL (label_w), label);
1669 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1670 g_free (last_updated_string);
1674 g_free (gray_color_markup);
1677 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1683 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1685 ModestMainWindowPrivate *priv = NULL;
1687 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1689 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1691 return priv->send_receive_in_progress;
1695 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1697 GtkAction *action = NULL;
1698 GtkWidget *widget = NULL;
1699 ModestMainWindowPrivate *priv = NULL;
1701 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1702 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1704 priv->send_receive_in_progress = TRUE;
1706 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1707 gtk_action_set_sensitive (action, FALSE);
1708 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1709 /* gtk_action_set_sensitive (action, FALSE); */
1710 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1711 gtk_widget_set_sensitive (widget, FALSE);
1715 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1717 GtkAction *action = NULL;
1718 GtkWidget *widget = NULL;
1719 ModestMainWindowPrivate *priv = NULL;
1721 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1722 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1724 priv->send_receive_in_progress = FALSE;
1726 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1727 gtk_action_set_sensitive (action, TRUE);
1728 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1729 /* gtk_action_set_sensitive (action, TRUE); */
1730 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1731 gtk_widget_set_sensitive (widget, TRUE);
1736 on_msg_count_changed (ModestHeaderView *header_view,
1738 TnyFolderChange *change,
1739 ModestMainWindow *main_window)
1741 gboolean folder_empty = FALSE;
1742 gboolean all_marked_as_deleted = FALSE;
1743 TnyFolderChangeChanged changed;
1744 ModestMainWindowPrivate *priv;
1746 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1747 g_return_if_fail (TNY_IS_FOLDER(folder));
1748 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1749 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1751 changed = tny_folder_change_get_changed (change);
1753 /* If something changes */
1754 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1755 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1757 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1759 /* Check header removed (hide marked as DELETED headers) */
1760 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1761 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1764 /* Check if all messages are marked to be deleted */
1765 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1766 folder_empty = folder_empty || all_marked_as_deleted ;
1768 /* Set contents style of headers view */
1770 modest_main_window_set_contents_style (main_window,
1771 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1772 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1775 modest_main_window_set_contents_style (main_window,
1776 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1782 modest_main_window_set_contents_style (ModestMainWindow *self,
1783 ModestMainWindowContentsStyle style)
1785 ModestMainWindowPrivate *priv;
1787 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1789 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1791 /* We allow to set the same content style than the previously
1792 set if there are details, because it could happen when we're
1793 selecting different accounts consecutively */
1794 if ((priv->contents_style == style) &&
1795 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1798 /* Remove previous child. Delete it if it was an account
1800 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1802 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1803 g_object_ref (content);
1804 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1805 g_object_ref (priv->empty_view);
1806 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1809 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1812 priv->contents_style = style;
1814 switch (priv->contents_style) {
1815 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1816 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1817 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1820 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1822 /* if we're started without main win, there may not be a folder
1823 * view. this fixes a GLib-Critical */
1824 if (priv->folder_view) {
1825 TnyFolderStore *selected_folderstore =
1826 modest_folder_view_get_selected (priv->folder_view);
1827 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1828 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1829 TNY_ACCOUNT (selected_folderstore));
1831 wrap_in_scrolled_window (priv->contents_widget,
1832 priv->details_widget);
1834 g_object_unref (selected_folderstore);
1835 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1840 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1841 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1842 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1846 g_return_if_reached ();
1850 gtk_widget_show_all (priv->contents_widget);
1853 ModestMainWindowContentsStyle
1854 modest_main_window_get_contents_style (ModestMainWindow *self)
1856 ModestMainWindowPrivate *priv;
1858 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1860 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1861 return priv->contents_style;
1866 on_configuration_key_changed (ModestConf* conf,
1868 ModestConfEvent event,
1869 ModestConfNotificationId id,
1870 ModestMainWindow *self)
1872 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1873 TnyAccount *account = NULL;
1875 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1878 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1881 if (priv->folder_view)
1882 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1884 if (account && TNY_IS_ACCOUNT (account) &&
1885 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1888 const gchar *device_name;
1889 gchar *new_text, *gray_color_markup;
1892 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1893 label = GTK_LABEL (children->data);
1895 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1896 MODEST_CONF_DEVICE_NAME, NULL);
1898 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1899 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1901 gtk_label_set_markup (label, new_text);
1902 gtk_widget_show (GTK_WIDGET (label));
1904 g_free (gray_color_markup);
1906 g_list_free (children);
1908 g_object_unref (account);
1912 set_toolbar_transfer_mode (ModestMainWindow *self)
1914 ModestMainWindowPrivate *priv = NULL;
1916 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1918 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1920 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1922 if (priv->progress_bar_timeout > 0) {
1923 g_source_remove (priv->progress_bar_timeout);
1924 priv->progress_bar_timeout = 0;
1931 set_toolbar_mode (ModestMainWindow *self,
1932 ModestToolBarModes mode)
1934 ModestWindowPrivate *parent_priv = NULL;
1935 ModestMainWindowPrivate *priv = NULL;
1936 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1938 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1940 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1941 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1943 /* In case this was called before the toolbar exists: */
1944 if (!(parent_priv->toolbar))
1947 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1949 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1950 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1951 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1953 /* Sets current toolbar mode */
1954 priv->current_toolbar_mode = mode;
1956 /* Checks the dimming rules */
1957 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1959 /* Show and hide toolbar items */
1961 case TOOLBAR_MODE_NORMAL:
1963 gtk_action_set_visible (sort_action, TRUE);
1965 gtk_action_set_visible (refresh_action, TRUE);
1966 if (priv->progress_toolitem) {
1967 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1968 gtk_widget_hide (priv->progress_toolitem);
1970 if (priv->progress_bar)
1971 gtk_widget_hide (priv->progress_bar);
1974 gtk_action_set_visible (cancel_action, FALSE);
1976 /* Hide toolbar if optimized view is enabled */
1977 if (priv->optimized_view)
1978 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1980 case TOOLBAR_MODE_TRANSFER:
1982 gtk_action_set_visible (sort_action, FALSE);
1984 gtk_action_set_visible (refresh_action, FALSE);
1986 gtk_action_set_visible (cancel_action, TRUE);
1987 if (priv->progress_toolitem) {
1988 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1989 gtk_widget_show (priv->progress_toolitem);
1991 if (priv->progress_bar)
1992 gtk_widget_show (priv->progress_bar);
1994 /* Show toolbar if it's hiden (optimized view ) */
1995 if (priv->optimized_view)
1996 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1999 g_return_if_reached ();
2004 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2006 ModestMainWindowPrivate *priv;
2008 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2009 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2011 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2015 cancel_progressbar (GtkToolButton *toolbutton,
2016 ModestMainWindow *self)
2019 ModestMainWindowPrivate *priv;
2021 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2023 /* Get operation observers and cancel all the operations */
2024 tmp = priv->progress_widgets;
2026 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2027 tmp=g_slist_next(tmp);
2032 observers_empty (ModestMainWindow *self)
2035 ModestMainWindowPrivate *priv;
2036 gboolean is_empty = TRUE;
2037 guint pending_ops = 0;
2039 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2040 tmp = priv->progress_widgets;
2042 /* Check all observers */
2043 while (tmp && is_empty) {
2044 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2045 is_empty = pending_ops == 0;
2047 tmp = g_slist_next(tmp);
2055 * Gets the toolbar mode needed for each mail operation. It stores in
2056 * @mode_changed if the toolbar mode has changed or not
2058 static ModestToolBarModes
2059 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2060 ModestMailOperation *mail_op,
2061 gboolean *mode_changed)
2063 ModestToolBarModes mode;
2064 ModestMainWindowPrivate *priv;
2066 *mode_changed = FALSE;
2067 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2069 /* Get toolbar mode from operation id*/
2070 switch (modest_mail_operation_get_type_operation (mail_op)) {
2071 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2072 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2073 mode = TOOLBAR_MODE_TRANSFER;
2074 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2075 *mode_changed = TRUE;
2078 mode = TOOLBAR_MODE_NORMAL;
2084 on_mail_operation_started (ModestMailOperation *mail_op,
2087 ModestMainWindow *self;
2088 ModestMailOperationTypeOperation op_type;
2089 ModestMainWindowPrivate *priv;
2090 ModestToolBarModes mode;
2092 gboolean mode_changed = FALSE;
2093 TnyAccount *account;
2095 self = MODEST_MAIN_WINDOW (user_data);
2096 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2098 /* Do not show progress for receiving operations if the
2099 account is the local account or the MMC one */
2100 op_type = modest_mail_operation_get_type_operation (mail_op);
2101 account = modest_mail_operation_get_account (mail_op);
2102 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2105 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2106 modest_tny_account_is_memory_card_account (account));
2107 g_object_unref (account);
2112 /* Get toolbar mode from operation id*/
2113 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2115 /* Add operation observers and change toolbar if neccessary*/
2116 tmp = priv->progress_widgets;
2117 if (mode == TOOLBAR_MODE_TRANSFER) {
2119 set_toolbar_transfer_mode(self);
2122 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2124 tmp = g_slist_next (tmp);
2130 on_mail_operation_finished (ModestMailOperation *mail_op,
2133 ModestToolBarModes mode;
2134 ModestMailOperationTypeOperation op_type;
2136 ModestMainWindow *self;
2137 gboolean mode_changed;
2138 TnyAccount *account;
2139 ModestMainWindowPrivate *priv;
2141 self = MODEST_MAIN_WINDOW (user_data);
2142 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2144 /* The mail operation was not added to the progress objects if
2145 the account was the local account or the MMC one */
2146 op_type = modest_mail_operation_get_type_operation (mail_op);
2147 account = modest_mail_operation_get_account (mail_op);
2148 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2151 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2152 modest_tny_account_is_memory_card_account (account));
2153 g_object_unref (account);
2158 /* Get toolbar mode from operation id*/
2159 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2161 /* Change toolbar mode */
2162 tmp = priv->progress_widgets;
2163 if (mode == TOOLBAR_MODE_TRANSFER) {
2165 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2167 tmp = g_slist_next (tmp);
2170 /* If no more operations are being observed, NORMAL mode is enabled again */
2171 if (observers_empty (self)) {
2172 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2178 on_queue_changed (ModestMailOperationQueue *queue,
2179 ModestMailOperation *mail_op,
2180 ModestMailOperationQueueNotification type,
2181 ModestMainWindow *self)
2183 ModestMainWindowPrivate *priv;
2185 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2187 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2188 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2190 "operation-started",
2191 G_CALLBACK (on_mail_operation_started),
2193 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2195 "operation-finished",
2196 G_CALLBACK (on_mail_operation_finished),
2198 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2199 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2201 "operation-started");
2202 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2204 "operation-finished");
2209 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2211 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2214 /* Get account data */
2215 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2216 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2218 /* Set the new visible & active account */
2219 if (acc_data && acc_data->store_account) {
2220 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2221 acc_data->store_account->account_name);
2222 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2223 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2224 if (action != NULL) {
2225 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2226 modest_maemo_toggle_action_set_active_block_notify (
2227 GTK_TOGGLE_ACTION (action),
2233 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2238 modest_account_mgr_free_account_data (mgr, acc_data);
2241 /* Make sure that at least one account is "viewed": */
2243 set_at_least_one_account_visible(ModestMainWindow *self)
2245 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2246 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2248 if (!(priv->folder_view)) {
2249 /* It is too early to do this. */
2253 const gchar *active_server_account_name =
2254 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2255 if (!active_server_account_name ||
2256 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2258 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2259 if (first_modest_name) {
2260 set_account_visible (self, first_modest_name);
2261 g_free (first_modest_name);
2267 on_show_account_action_toggled (GtkToggleAction *action,
2270 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2272 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2273 if (gtk_toggle_action_get_active (action))
2274 set_account_visible (self, acc_name);
2278 refresh_account (const gchar *account_name)
2282 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2284 /* If account_name == NULL, we must update all (option All) */
2286 modest_ui_actions_do_send_receive_all (win);
2288 modest_ui_actions_do_send_receive (account_name, win);
2293 on_refresh_account_action_activated (GtkAction *action,
2296 refresh_account ((const gchar*) user_data);
2300 on_send_receive_csm_activated (GtkMenuItem *item,
2303 refresh_account ((const gchar*) user_data);
2307 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2309 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2311 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2317 on_folder_view_focus_in (GtkWidget *widget,
2318 GdkEventFocus *event,
2321 ModestMainWindow *main_window = NULL;
2323 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2324 main_window = MODEST_MAIN_WINDOW (userdata);
2326 /* Update toolbar dimming state */
2327 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2333 on_header_view_focus_in (GtkWidget *widget,
2334 GdkEventFocus *event,
2337 ModestMainWindow *main_window = NULL;
2338 ModestMainWindowPrivate *priv = NULL;
2340 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2341 main_window = MODEST_MAIN_WINDOW (userdata);
2342 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2344 /* Update toolbar dimming state */
2345 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2351 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2352 TnyFolderStore *folder_store,
2354 ModestMainWindow *main_window)
2356 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2357 GtkAction *action = NULL;
2358 gboolean show_reply = TRUE;
2359 gboolean show_forward = TRUE;
2360 gboolean show_cancel_send = FALSE;
2361 gboolean show_clipboard = TRUE;
2362 gboolean show_delete = TRUE;
2365 if (TNY_IS_ACCOUNT (folder_store)) {
2366 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2367 } else if (TNY_IS_FOLDER (folder_store)) {
2368 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2369 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2370 TNY_FOLDER (folder_store));
2371 switch (folder_type) {
2372 case TNY_FOLDER_TYPE_DRAFTS:
2373 show_clipboard = show_delete = TRUE;
2374 show_reply = show_forward = show_cancel_send = FALSE;
2376 case TNY_FOLDER_TYPE_SENT:
2377 show_forward = show_clipboard = show_delete = TRUE;
2378 show_reply = show_cancel_send = FALSE;
2380 case TNY_FOLDER_TYPE_OUTBOX:
2381 show_clipboard = show_delete = show_cancel_send = TRUE;
2382 show_reply = show_forward = FALSE;
2385 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2386 show_cancel_send = FALSE;
2389 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2390 show_cancel_send = FALSE;
2395 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2396 gtk_action_set_visible (action, show_reply);
2397 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2398 gtk_action_set_visible (action, show_reply);
2399 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2400 gtk_action_set_visible (action, show_forward);
2401 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2402 gtk_action_set_visible (action, show_cancel_send);
2403 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2404 gtk_action_set_visible (action, show_delete);
2406 /* We finally call to the ui actions handler, after updating properly
2407 * the header view CSM */
2408 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2412 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2413 GtkTreeModel *model,
2414 GtkTreeRowReference *row_reference,
2415 ModestMainWindow *self)
2417 ModestMainWindowPrivate *priv = NULL;
2418 GtkTreeModel *header_model = NULL;
2419 GtkTreePath *path = NULL;
2421 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2422 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2423 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2425 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2426 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2428 /* Do nothing if we changed the folder in the main view */
2429 if (header_model != model)
2432 /* Select the message in the header view */
2433 path = gtk_tree_row_reference_get_path (row_reference);
2434 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2436 gtk_tree_path_free (path);
2442 show_updating_banner (gpointer user_data)
2444 ModestMainWindowPrivate *priv = NULL;
2446 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2448 priv->updating_banner =
2449 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2450 _CS ("ckdg_pb_updating"));
2452 /* Remove timeout */
2453 priv->updating_banner_timeout = 0;
2458 * We use this function to show/hide a progress banner showing
2459 * "Updating" while the header view is being filled. We're not showing
2460 * it unless the update takes more than 2 seconds
2462 * If starting = TRUE then the refresh is starting, otherwise it means
2463 * that is has just finished
2466 on_updating_msg_list (ModestHeaderView *header_view,
2470 ModestMainWindowPrivate *priv = NULL;
2472 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2474 /* Remove old timeout */
2475 if (priv->updating_banner_timeout > 0) {
2476 g_source_remove (priv->updating_banner_timeout);
2477 priv->updating_banner_timeout = 0;
2480 /* Create a new timeout */
2482 priv->updating_banner_timeout =
2483 g_timeout_add (2000, show_updating_banner, user_data);
2485 /* Remove the banner if exists */
2486 if (priv->updating_banner) {
2487 gtk_widget_destroy (priv->updating_banner);
2488 priv->updating_banner = NULL;