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);
865 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
866 G_CALLBACK(_header_view_csm_menu_activated),
871 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
872 G_CALLBACK (modest_main_window_window_state_event),
875 /* Mail Operation Queue */
877 modest_signal_mgr_connect (priv->sighandlers,
878 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
880 G_CALLBACK (on_queue_changed), self);
882 /* Track changes in the device name */
884 modest_signal_mgr_connect (priv->sighandlers,
885 G_OBJECT(modest_runtime_get_conf ()),
887 G_CALLBACK (on_configuration_key_changed),
890 /* Track account changes. We need to refresh the toolbar */
892 modest_signal_mgr_connect (priv->sighandlers,
893 G_OBJECT (modest_runtime_get_account_store ()),
895 G_CALLBACK (on_account_inserted),
898 modest_signal_mgr_connect (priv->sighandlers,
899 G_OBJECT (modest_runtime_get_account_store ()),
901 G_CALLBACK (on_account_removed),
904 /* We need to refresh the send & receive menu to change the bold
905 * account when the default account changes. */
907 modest_signal_mgr_connect (priv->sighandlers,
908 G_OBJECT (modest_runtime_get_account_mgr ()),
909 "default_account_changed",
910 G_CALLBACK (on_default_account_changed),
915 modest_signal_mgr_connect (priv->sighandlers,
916 G_OBJECT (modest_runtime_get_account_store()),
917 "password_requested",
918 G_CALLBACK (modest_ui_actions_on_password_requested),
923 /** Idle handler, to send/receive at startup .*/
925 sync_accounts_cb (ModestMainWindow *win)
927 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
928 return FALSE; /* Do not call this idle handler again. */
933 on_hildon_program_is_topmost_notify(GObject *self,
934 GParamSpec *propert_param, gpointer user_data)
936 HildonProgram *app = HILDON_PROGRAM (self);
939 ModestWindow* self = MODEST_WINDOW(user_data);
942 /* Note that use of hildon_program_set_can_hibernate()
943 * is generally referred to as "setting the killable flag",
944 * though hibernation does not seem equal to death.
947 if (hildon_program_get_is_topmost (app)) {
948 /* Prevent hibernation when the progam comes to the foreground,
949 * because hibernation should only happen when the application
950 * is in the background: */
951 hildon_program_set_can_hibernate (app, FALSE);
953 /* Allow hibernation if the program has gone to the background: */
955 /* However, prevent hibernation while the settings are being changed: */
956 const gboolean hibernation_prevented =
957 modest_window_mgr_get_hibernation_is_prevented (
958 modest_runtime_get_window_mgr ());
960 if (hibernation_prevented)
961 hildon_program_set_can_hibernate (app, FALSE);
963 /* Allow hibernation, after saving the state: */
964 modest_osso_save_state();
965 hildon_program_set_can_hibernate (app, TRUE);
972 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
974 GtkWidget *folder_win = (GtkWidget *) user_data;
975 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
977 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
978 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
979 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
981 gtk_widget_show (GTK_WIDGET (priv->folder_view));
983 /* Connect signals */
984 connect_signals (MODEST_MAIN_WINDOW (self));
986 /* Set account store */
987 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
988 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
990 /* Load previous osso state, for instance if we are being restored from
992 modest_osso_load_state ();
994 /* Restore window & widget settings */
995 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
997 /* /\* The UI spec wants us to show a connection dialog when the application is */
998 /* * started by the user, if there is no connection. */
999 /* * Do this before showing the account wizard, */
1000 /* * because wizard needs a connection to discover capabilities. *\/ */
1001 /* modest_platform_connect_and_wait (GTK_WINDOW (self), NULL); */
1003 /* Check if accounts exist and show the account wizard if not */
1004 gboolean accounts_exist =
1005 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1007 if (!accounts_exist) {
1008 /* This is necessary to have the main window shown behind the dialog
1009 It's an ugly hack... jschmid */
1010 gtk_widget_show_all(GTK_WIDGET(self));
1011 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1014 GtkAction *send_receive_all;
1015 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1016 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1017 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1018 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1019 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1020 modest_account_mgr_free_account_names (accounts);
1025 modest_main_window_new (void)
1027 ModestMainWindow *self = NULL;
1028 ModestMainWindowPrivate *priv = NULL;
1029 ModestWindowPrivate *parent_priv = NULL;
1030 GtkWidget *folder_win = NULL;
1031 ModestDimmingRulesGroup *menu_rules_group = NULL;
1032 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1033 GtkActionGroup *action_group = NULL;
1034 GError *error = NULL;
1035 ModestConf *conf = NULL;
1036 GtkAction *action = NULL;
1037 GdkPixbuf *window_icon;
1039 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1040 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1041 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1043 parent_priv->ui_manager = gtk_ui_manager_new();
1044 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1046 action_group = gtk_action_group_new ("ModestMainWindowActions");
1047 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1049 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1050 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1052 /* Add common actions */
1053 gtk_action_group_add_actions (action_group,
1054 modest_action_entries,
1055 G_N_ELEMENTS (modest_action_entries),
1058 gtk_action_group_add_actions (action_group,
1059 modest_folder_view_action_entries,
1060 G_N_ELEMENTS (modest_folder_view_action_entries),
1063 gtk_action_group_add_actions (action_group,
1064 modest_header_view_action_entries,
1065 G_N_ELEMENTS (modest_header_view_action_entries),
1068 gtk_action_group_add_toggle_actions (action_group,
1069 modest_toggle_action_entries,
1070 G_N_ELEMENTS (modest_toggle_action_entries),
1073 gtk_action_group_add_toggle_actions (action_group,
1074 modest_main_window_toggle_action_entries,
1075 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1078 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1079 g_object_unref (action_group);
1081 /* Load the UI definition */
1082 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1083 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1084 if (error != NULL) {
1085 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1086 g_error_free (error);
1090 /* Add common dimming rules */
1091 modest_dimming_rules_group_add_rules (menu_rules_group,
1092 modest_main_window_menu_dimming_entries,
1093 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1094 MODEST_WINDOW (self));
1095 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1096 modest_main_window_toolbar_dimming_entries,
1097 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1098 MODEST_WINDOW (self));
1100 /* Insert dimming rules group for this window */
1101 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1102 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1103 g_object_unref (menu_rules_group);
1104 g_object_unref (toolbar_rules_group);
1106 /* Add accelerators */
1107 gtk_window_add_accel_group (GTK_WINDOW (self),
1108 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1110 /* Menubar. Update the state of some toggles */
1111 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1112 conf = modest_runtime_get_conf ();
1113 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1114 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1115 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1116 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1117 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1118 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1119 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1120 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1121 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1122 gtk_widget_show (parent_priv->menubar);
1124 /* Get device name */
1125 modest_maemo_utils_get_device_name ();
1129 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1130 if (!priv->header_view)
1131 g_printerr ("modest: cannot instantiate header view\n");
1132 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1133 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1134 MODEST_CONF_HEADER_VIEW_KEY);
1136 /* Other style properties of header view */
1137 g_object_set (G_OBJECT (priv->header_view),
1138 "rules-hint", FALSE,
1140 /* gtk_widget_show (priv->header_view); */
1143 priv->empty_view = create_empty_view ();
1144 gtk_widget_show (priv->empty_view);
1146 /* Create scrolled windows */
1147 folder_win = gtk_scrolled_window_new (NULL, NULL);
1148 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1149 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1151 GTK_POLICY_AUTOMATIC);
1152 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1154 GTK_POLICY_AUTOMATIC);
1155 /* gtk_widget_show (priv->contents_widget); */
1158 priv->main_paned = gtk_hpaned_new ();
1159 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1160 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1161 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1163 /* putting it all together... */
1164 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1165 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1166 gtk_widget_show (priv->main_vbox);
1168 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1170 HildonProgram *app = hildon_program_get_instance ();
1171 hildon_program_add_window (app, HILDON_WINDOW (self));
1173 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1174 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1176 g_signal_connect (G_OBJECT(self), "show",
1177 G_CALLBACK (modest_main_window_on_show), folder_win);
1179 /* Set window icon */
1180 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1182 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1183 g_object_unref (window_icon);
1186 /* Dont't restore settings here,
1187 * because it requires a gtk_widget_show(),
1188 * and we don't want to do that until later,
1189 * so that the UI is not visible for non-menu D-Bus activation.
1191 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1193 return MODEST_WINDOW(self);
1197 modest_main_window_close_all (ModestMainWindow *self)
1200 GtkResponseType response;
1202 /* Create the confirmation dialog MSG-NOT308 */
1203 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1204 _("emev_nc_close_windows"),
1205 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1206 _("mcen_bd_no"), GTK_RESPONSE_NO,
1209 response = gtk_dialog_run (GTK_DIALOG (note));
1210 gtk_widget_destroy (GTK_WIDGET (note));
1212 if (response == GTK_RESPONSE_YES)
1220 modest_main_window_set_style (ModestMainWindow *self,
1221 ModestMainWindowStyle style)
1223 ModestMainWindowPrivate *priv;
1224 ModestWindowPrivate *parent_priv;
1228 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1230 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1231 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1233 /* no change -> nothing to do */
1234 if (priv->style == style)
1237 /* Get toggle button and update the state if needed. This will
1238 happen only when the set_style is not invoked from the UI,
1239 for example when it's called from widget memory */
1240 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1241 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1242 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1243 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1244 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1245 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1246 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1249 priv->style = style;
1251 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1252 /* Remove main paned */
1253 g_object_ref (priv->main_paned);
1254 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1256 /* Reparent the contents widget to the main vbox */
1257 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1260 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1261 /* Remove header view */
1262 g_object_ref (priv->contents_widget);
1263 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1265 /* Reparent the main paned */
1266 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1267 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1271 g_return_if_reached ();
1274 /* Let header view grab the focus if it's being shown */
1275 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1276 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1278 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1281 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1284 ModestMainWindowStyle
1285 modest_main_window_get_style (ModestMainWindow *self)
1287 ModestMainWindowPrivate *priv;
1289 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1291 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1298 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1300 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1301 ModestWindowPrivate *parent_priv;
1302 ModestWindowMgr *mgr;
1303 gboolean is_fullscreen;
1304 GtkAction *fs_toggle_action;
1307 mgr = modest_runtime_get_window_mgr ();
1309 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1311 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1313 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1314 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1315 if (is_fullscreen != active) {
1316 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1325 set_homogeneous (GtkWidget *widget,
1328 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1329 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1333 modest_main_window_show_toolbar (ModestWindow *self,
1334 gboolean show_toolbar)
1336 ModestMainWindowPrivate *priv = NULL;
1337 ModestWindowPrivate *parent_priv = NULL;
1338 GtkWidget *reply_button = NULL, *menu = NULL;
1339 GtkWidget *placeholder = NULL;
1341 const gchar *action_name;
1344 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1345 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1346 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1348 /* Set optimized view status */
1349 priv->optimized_view = !show_toolbar;
1351 if (!parent_priv->toolbar) {
1352 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1354 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1356 /* Set homogeneous toolbar */
1357 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1358 set_homogeneous, NULL);
1360 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1361 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1362 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1363 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1364 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1365 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1366 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1367 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1369 /* Add ProgressBar (Transfer toolbar) */
1370 priv->progress_bar = modest_progress_bar_widget_new ();
1371 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1372 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1373 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1374 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1375 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1377 /* Connect cancel 'clicked' signal to abort progress mode */
1378 g_signal_connect(priv->cancel_toolitem, "clicked",
1379 G_CALLBACK(cancel_progressbar),
1382 /* Add it to the observers list */
1383 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1386 hildon_window_add_toolbar (HILDON_WINDOW (self),
1387 GTK_TOOLBAR (parent_priv->toolbar));
1389 /* Set reply button tap and hold menu */
1390 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1391 "/ToolBar/ToolbarMessageReply");
1392 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1393 "/ToolbarReplyCSM");
1394 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1396 /* Set send & receive button tap and hold menu */
1397 update_menus (MODEST_MAIN_WINDOW (self));
1401 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1402 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1403 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1405 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1406 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1408 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1412 /* Update also the actions (to update the toggles in the
1413 menus), we have to do it manually because some other window
1414 of the same time could have changed it (remember that the
1415 toolbar fullscreen mode is shared by all the windows of the
1417 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1418 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1420 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1422 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1423 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1428 on_account_inserted (TnyAccountStore *accoust_store,
1429 TnyAccount *account,
1432 update_menus (MODEST_MAIN_WINDOW (user_data));
1436 on_default_account_changed (ModestAccountMgr* mgr,
1439 update_menus (MODEST_MAIN_WINDOW (user_data));
1443 on_account_removed (TnyAccountStore *accoust_store,
1444 TnyAccount *account,
1447 update_menus (MODEST_MAIN_WINDOW (user_data));
1451 * This function manages the key events used to navigate between
1452 * header and folder views (when the window is in split view)
1455 * -------------------------------------------------
1456 * HeaderView GDK_Left Move focus to folder view
1457 * FolderView GDK_Right Move focus to header view
1459 * There is no need to scroll to selected row, the widgets will be the
1460 * responsibles of doing that (probably managing the focus-in event
1463 on_inner_widgets_key_pressed (GtkWidget *widget,
1467 ModestMainWindowPrivate *priv;
1469 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1471 /* Do nothing if we're in SIMPLE style */
1472 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1475 if (MODEST_IS_HEADER_VIEW (widget)) {
1476 if (event->keyval == GDK_Left)
1477 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1478 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1479 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1482 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1483 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1489 set_alignment (GtkWidget *widget,
1492 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1493 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1497 create_empty_view (void)
1499 GtkLabel *label = NULL;
1500 GtkWidget *align = NULL;
1502 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1503 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1504 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1505 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1507 return GTK_WIDGET(align);
1511 * Free the returned string
1514 get_gray_color_markup (GtkWidget *styled_widget)
1516 gchar *gray_color_markup;
1518 /* Obtain the secondary text color. We need a realized widget, that's why
1519 we get styled_widget from outside */
1520 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1522 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1523 gray_color_markup = modest_text_utils_get_color_string (&color);
1525 gray_color_markup = g_strdup ("#BBBBBB");
1527 return gray_color_markup;
1531 * Free the returned string
1534 create_device_name_visual_string (const gchar *device_name,
1535 const gchar *gray_color_markup)
1539 /* We have to use "" to fill the %s of the translation. We can
1540 not just use the device name because the device name is
1541 shown in a different color, so it could not be included
1542 into the <span> tag */
1543 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1544 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1554 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1556 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1561 gchar *gray_color_markup;
1563 vbox = gtk_vbox_new (FALSE, 0);
1565 gray_color_markup = get_gray_color_markup (styled_widget);
1567 /* Account description: */
1568 if (modest_tny_account_is_virtual_local_folders (account)
1569 || (modest_tny_account_is_memory_card_account (account))) {
1571 /* Get device name */
1572 gchar *device_name = NULL;
1573 if (modest_tny_account_is_virtual_local_folders (account))
1574 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1575 MODEST_CONF_DEVICE_NAME, NULL);
1577 device_name = g_strdup (tny_account_get_name (account));
1579 label = create_device_name_visual_string ((const gchar *) device_name,
1580 (const gchar *) gray_color_markup);
1581 label_w = gtk_label_new (NULL);
1582 gtk_label_set_markup (GTK_LABEL (label_w), label);
1583 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1584 g_free (device_name);
1587 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1588 gtk_box_pack_start (GTK_BOX (vbox),
1589 gtk_label_new (tny_account_get_name (account)),
1592 /* Other accounts, such as IMAP and POP: */
1597 /* Put proto in uppercase */
1598 proto = g_string_new (tny_account_get_proto (account));
1599 proto = g_string_ascii_up (proto);
1601 /* note: mcen_fi_localroot_description is something like "%s account"
1602 * however, we should display "%s account: %s"... therefore, ugly tmp */
1603 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1604 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1605 gray_color_markup, tmp, tny_account_get_name (account));
1608 label_w = gtk_label_new (NULL);
1609 gtk_label_set_markup (GTK_LABEL (label_w), label);
1610 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1611 g_string_free (proto, TRUE);
1617 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1618 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1619 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1620 modest_tny_folder_store_get_message_count (folder_store));
1621 label_w = gtk_label_new (NULL);
1622 gtk_label_set_markup (GTK_LABEL (label_w), label);
1623 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1627 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1629 _("mcen_fi_rootfolder_folders"),
1630 modest_tny_folder_store_get_folder_count (folder_store));
1631 label_w = gtk_label_new (NULL);
1632 gtk_label_set_markup (GTK_LABEL (label_w), label);
1633 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1637 if (modest_tny_account_is_virtual_local_folders (account)
1638 || modest_tny_account_is_memory_card_account (account)) {
1640 gchar *size = modest_text_utils_get_display_size (
1641 modest_tny_folder_store_get_local_size (folder_store));
1643 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1644 gray_color_markup, _("mcen_fi_rootfolder_size"),
1648 label_w = gtk_label_new (NULL);
1649 gtk_label_set_markup (GTK_LABEL (label_w), label);
1650 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1652 } else if (TNY_IS_ACCOUNT(folder_store)) {
1653 TnyAccount *account = TNY_ACCOUNT(folder_store);
1655 time_t last_updated;
1656 gchar *last_updated_string;
1657 /* Get last updated from configuration */
1658 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1659 tny_account_get_id (account));
1661 if (last_updated > 0)
1662 last_updated_string = modest_text_utils_get_display_date(last_updated);
1664 last_updated_string = g_strdup (_("mcen_va_never"));
1666 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1667 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1668 label_w = gtk_label_new (NULL);
1669 gtk_label_set_markup (GTK_LABEL (label_w), label);
1670 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1671 g_free (last_updated_string);
1675 g_free (gray_color_markup);
1678 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1684 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1686 ModestMainWindowPrivate *priv = NULL;
1688 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1690 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1692 return priv->send_receive_in_progress;
1696 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1698 GtkAction *action = NULL;
1699 GtkWidget *widget = NULL;
1700 ModestMainWindowPrivate *priv = NULL;
1702 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1703 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1705 priv->send_receive_in_progress = TRUE;
1707 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1708 gtk_action_set_sensitive (action, FALSE);
1709 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1710 /* gtk_action_set_sensitive (action, FALSE); */
1711 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1712 gtk_widget_set_sensitive (widget, FALSE);
1716 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1718 GtkAction *action = NULL;
1719 GtkWidget *widget = NULL;
1720 ModestMainWindowPrivate *priv = NULL;
1722 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1723 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1725 priv->send_receive_in_progress = FALSE;
1727 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1728 gtk_action_set_sensitive (action, TRUE);
1729 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1730 /* gtk_action_set_sensitive (action, TRUE); */
1731 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1732 gtk_widget_set_sensitive (widget, TRUE);
1737 on_msg_count_changed (ModestHeaderView *header_view,
1739 TnyFolderChange *change,
1740 ModestMainWindow *main_window)
1742 gboolean folder_empty = FALSE;
1743 gboolean all_marked_as_deleted = FALSE;
1744 TnyFolderChangeChanged changed;
1745 ModestMainWindowPrivate *priv;
1747 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1748 g_return_if_fail (TNY_IS_FOLDER(folder));
1749 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1750 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1752 changed = tny_folder_change_get_changed (change);
1754 /* If something changes */
1755 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1756 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1758 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1760 /* Check header removed (hide marked as DELETED headers) */
1761 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1762 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1765 /* Check if all messages are marked to be deleted */
1766 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1767 folder_empty = folder_empty || all_marked_as_deleted ;
1769 /* Set contents style of headers view */
1771 modest_main_window_set_contents_style (main_window,
1772 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1773 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1776 modest_main_window_set_contents_style (main_window,
1777 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1783 modest_main_window_set_contents_style (ModestMainWindow *self,
1784 ModestMainWindowContentsStyle style)
1786 ModestMainWindowPrivate *priv;
1788 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1790 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1792 /* We allow to set the same content style than the previously
1793 set if there are details, because it could happen when we're
1794 selecting different accounts consecutively */
1795 if ((priv->contents_style == style) &&
1796 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1799 /* Remove previous child. Delete it if it was an account
1801 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1803 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1804 g_object_ref (content);
1805 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1806 g_object_ref (priv->empty_view);
1807 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1810 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1813 priv->contents_style = style;
1815 switch (priv->contents_style) {
1816 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1817 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1818 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1821 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1823 /* if we're started without main win, there may not be a folder
1824 * view. this fixes a GLib-Critical */
1825 if (priv->folder_view) {
1826 TnyFolderStore *selected_folderstore =
1827 modest_folder_view_get_selected (priv->folder_view);
1828 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1829 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1830 TNY_ACCOUNT (selected_folderstore));
1832 wrap_in_scrolled_window (priv->contents_widget,
1833 priv->details_widget);
1835 g_object_unref (selected_folderstore);
1836 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1841 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1842 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1843 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1847 g_return_if_reached ();
1851 gtk_widget_show_all (priv->contents_widget);
1854 ModestMainWindowContentsStyle
1855 modest_main_window_get_contents_style (ModestMainWindow *self)
1857 ModestMainWindowPrivate *priv;
1859 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1861 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1862 return priv->contents_style;
1867 on_configuration_key_changed (ModestConf* conf,
1869 ModestConfEvent event,
1870 ModestConfNotificationId id,
1871 ModestMainWindow *self)
1873 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1874 TnyAccount *account = NULL;
1876 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1879 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1882 if (priv->folder_view)
1883 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1885 if (account && TNY_IS_ACCOUNT (account) &&
1886 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1889 const gchar *device_name;
1890 gchar *new_text, *gray_color_markup;
1893 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1894 label = GTK_LABEL (children->data);
1896 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1897 MODEST_CONF_DEVICE_NAME, NULL);
1899 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1900 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1902 gtk_label_set_markup (label, new_text);
1903 gtk_widget_show (GTK_WIDGET (label));
1905 g_free (gray_color_markup);
1907 g_list_free (children);
1909 g_object_unref (account);
1913 set_toolbar_transfer_mode (ModestMainWindow *self)
1915 ModestMainWindowPrivate *priv = NULL;
1917 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1919 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1921 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1923 if (priv->progress_bar_timeout > 0) {
1924 g_source_remove (priv->progress_bar_timeout);
1925 priv->progress_bar_timeout = 0;
1932 set_toolbar_mode (ModestMainWindow *self,
1933 ModestToolBarModes mode)
1935 ModestWindowPrivate *parent_priv = NULL;
1936 ModestMainWindowPrivate *priv = NULL;
1937 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1939 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1941 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1942 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1944 /* In case this was called before the toolbar exists: */
1945 if (!(parent_priv->toolbar))
1948 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1950 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1951 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1952 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1954 /* Sets current toolbar mode */
1955 priv->current_toolbar_mode = mode;
1957 /* Checks the dimming rules */
1958 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1960 /* Show and hide toolbar items */
1962 case TOOLBAR_MODE_NORMAL:
1964 gtk_action_set_visible (sort_action, TRUE);
1966 gtk_action_set_visible (refresh_action, TRUE);
1967 if (priv->progress_toolitem) {
1968 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1969 gtk_widget_hide (priv->progress_toolitem);
1971 if (priv->progress_bar)
1972 gtk_widget_hide (priv->progress_bar);
1975 gtk_action_set_visible (cancel_action, FALSE);
1977 /* Hide toolbar if optimized view is enabled */
1978 if (priv->optimized_view)
1979 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1981 case TOOLBAR_MODE_TRANSFER:
1983 gtk_action_set_visible (sort_action, FALSE);
1985 gtk_action_set_visible (refresh_action, FALSE);
1987 gtk_action_set_visible (cancel_action, TRUE);
1988 if (priv->progress_toolitem) {
1989 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1990 gtk_widget_show (priv->progress_toolitem);
1992 if (priv->progress_bar)
1993 gtk_widget_show (priv->progress_bar);
1995 /* Show toolbar if it's hiden (optimized view ) */
1996 if (priv->optimized_view)
1997 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2000 g_return_if_reached ();
2005 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2007 ModestMainWindowPrivate *priv;
2009 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2010 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2012 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2016 cancel_progressbar (GtkToolButton *toolbutton,
2017 ModestMainWindow *self)
2020 ModestMainWindowPrivate *priv;
2022 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2024 /* Get operation observers and cancel all the operations */
2025 tmp = priv->progress_widgets;
2027 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2028 tmp=g_slist_next(tmp);
2033 observers_empty (ModestMainWindow *self)
2036 ModestMainWindowPrivate *priv;
2037 gboolean is_empty = TRUE;
2038 guint pending_ops = 0;
2040 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2041 tmp = priv->progress_widgets;
2043 /* Check all observers */
2044 while (tmp && is_empty) {
2045 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2046 is_empty = pending_ops == 0;
2048 tmp = g_slist_next(tmp);
2056 * Gets the toolbar mode needed for each mail operation. It stores in
2057 * @mode_changed if the toolbar mode has changed or not
2059 static ModestToolBarModes
2060 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2061 ModestMailOperation *mail_op,
2062 gboolean *mode_changed)
2064 ModestToolBarModes mode;
2065 ModestMainWindowPrivate *priv;
2067 *mode_changed = FALSE;
2068 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2070 /* Get toolbar mode from operation id*/
2071 switch (modest_mail_operation_get_type_operation (mail_op)) {
2072 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2073 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2074 mode = TOOLBAR_MODE_TRANSFER;
2075 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2076 *mode_changed = TRUE;
2079 mode = TOOLBAR_MODE_NORMAL;
2085 on_mail_operation_started (ModestMailOperation *mail_op,
2088 ModestMainWindow *self;
2089 ModestMailOperationTypeOperation op_type;
2090 ModestMainWindowPrivate *priv;
2091 ModestToolBarModes mode;
2093 gboolean mode_changed = FALSE;
2094 TnyAccount *account;
2096 self = MODEST_MAIN_WINDOW (user_data);
2097 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2099 /* Do not show progress for receiving operations if the
2100 account is the local account or the MMC one */
2101 op_type = modest_mail_operation_get_type_operation (mail_op);
2102 account = modest_mail_operation_get_account (mail_op);
2103 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2106 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2107 modest_tny_account_is_memory_card_account (account));
2108 g_object_unref (account);
2113 /* Get toolbar mode from operation id*/
2114 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2116 /* Add operation observers and change toolbar if neccessary*/
2117 tmp = priv->progress_widgets;
2118 if (mode == TOOLBAR_MODE_TRANSFER) {
2120 set_toolbar_transfer_mode(self);
2123 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2125 tmp = g_slist_next (tmp);
2131 on_mail_operation_finished (ModestMailOperation *mail_op,
2134 ModestToolBarModes mode;
2135 ModestMailOperationTypeOperation op_type;
2137 ModestMainWindow *self;
2138 gboolean mode_changed;
2139 TnyAccount *account;
2140 ModestMainWindowPrivate *priv;
2142 self = MODEST_MAIN_WINDOW (user_data);
2143 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2145 /* The mail operation was not added to the progress objects if
2146 the account was the local account or the MMC one */
2147 op_type = modest_mail_operation_get_type_operation (mail_op);
2148 account = modest_mail_operation_get_account (mail_op);
2149 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2152 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2153 modest_tny_account_is_memory_card_account (account));
2154 g_object_unref (account);
2159 /* Get toolbar mode from operation id*/
2160 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2162 /* Change toolbar mode */
2163 tmp = priv->progress_widgets;
2164 if (mode == TOOLBAR_MODE_TRANSFER) {
2166 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2168 tmp = g_slist_next (tmp);
2171 /* If no more operations are being observed, NORMAL mode is enabled again */
2172 if (observers_empty (self)) {
2173 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2179 on_queue_changed (ModestMailOperationQueue *queue,
2180 ModestMailOperation *mail_op,
2181 ModestMailOperationQueueNotification type,
2182 ModestMainWindow *self)
2184 ModestMainWindowPrivate *priv;
2186 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2188 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2189 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2191 "operation-started",
2192 G_CALLBACK (on_mail_operation_started),
2194 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2196 "operation-finished",
2197 G_CALLBACK (on_mail_operation_finished),
2199 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2200 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2202 "operation-started");
2203 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2205 "operation-finished");
2210 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2212 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2215 /* Get account data */
2216 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2217 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2219 /* Set the new visible & active account */
2220 if (acc_data && acc_data->store_account) {
2221 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2222 acc_data->store_account->account_name);
2223 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2224 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2225 if (action != NULL) {
2226 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2227 modest_maemo_toggle_action_set_active_block_notify (
2228 GTK_TOGGLE_ACTION (action),
2234 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2239 modest_account_mgr_free_account_data (mgr, acc_data);
2242 /* Make sure that at least one account is "viewed": */
2244 set_at_least_one_account_visible(ModestMainWindow *self)
2246 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2247 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2249 if (!(priv->folder_view)) {
2250 /* It is too early to do this. */
2254 const gchar *active_server_account_name =
2255 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2256 if (!active_server_account_name ||
2257 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2259 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2260 if (first_modest_name) {
2261 set_account_visible (self, first_modest_name);
2262 g_free (first_modest_name);
2268 on_show_account_action_toggled (GtkToggleAction *action,
2271 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2273 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2274 if (gtk_toggle_action_get_active (action))
2275 set_account_visible (self, acc_name);
2279 refresh_account (const gchar *account_name)
2283 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2285 /* If account_name == NULL, we must update all (option All) */
2287 modest_ui_actions_do_send_receive_all (win);
2289 modest_ui_actions_do_send_receive (account_name, win);
2294 on_refresh_account_action_activated (GtkAction *action,
2297 refresh_account ((const gchar*) user_data);
2301 on_send_receive_csm_activated (GtkMenuItem *item,
2304 refresh_account ((const gchar*) user_data);
2308 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2310 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2312 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2318 on_folder_view_focus_in (GtkWidget *widget,
2319 GdkEventFocus *event,
2322 ModestMainWindow *main_window = NULL;
2324 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2325 main_window = MODEST_MAIN_WINDOW (userdata);
2327 /* Update toolbar dimming state */
2328 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2334 on_header_view_focus_in (GtkWidget *widget,
2335 GdkEventFocus *event,
2338 ModestMainWindow *main_window = NULL;
2339 ModestMainWindowPrivate *priv = NULL;
2341 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2342 main_window = MODEST_MAIN_WINDOW (userdata);
2343 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2345 /* Update toolbar dimming state */
2346 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2352 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2353 TnyFolderStore *folder_store,
2355 ModestMainWindow *main_window)
2357 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2358 GtkAction *action = NULL;
2359 gboolean show_reply = TRUE;
2360 gboolean show_forward = TRUE;
2361 gboolean show_cancel_send = FALSE;
2362 gboolean show_clipboard = TRUE;
2363 gboolean show_delete = TRUE;
2366 if (TNY_IS_ACCOUNT (folder_store)) {
2367 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2368 } else if (TNY_IS_FOLDER (folder_store)) {
2369 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2370 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2371 TNY_FOLDER (folder_store));
2372 switch (folder_type) {
2373 case TNY_FOLDER_TYPE_DRAFTS:
2374 show_clipboard = show_delete = TRUE;
2375 show_reply = show_forward = show_cancel_send = FALSE;
2377 case TNY_FOLDER_TYPE_SENT:
2378 show_forward = show_clipboard = show_delete = TRUE;
2379 show_reply = show_cancel_send = FALSE;
2381 case TNY_FOLDER_TYPE_OUTBOX:
2382 show_clipboard = show_delete = show_cancel_send = TRUE;
2383 show_reply = show_forward = FALSE;
2386 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2387 show_cancel_send = FALSE;
2390 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2391 show_cancel_send = FALSE;
2396 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2397 gtk_action_set_visible (action, show_reply);
2398 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2399 gtk_action_set_visible (action, show_reply);
2400 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2401 gtk_action_set_visible (action, show_forward);
2402 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2403 gtk_action_set_visible (action, show_cancel_send);
2404 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2405 gtk_action_set_visible (action, show_delete);
2407 /* We finally call to the ui actions handler, after updating properly
2408 * the header view CSM */
2409 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2413 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2414 GtkTreeModel *model,
2415 GtkTreeRowReference *row_reference,
2416 ModestMainWindow *self)
2418 ModestMainWindowPrivate *priv = NULL;
2419 GtkTreeModel *header_model = NULL;
2420 GtkTreePath *path = NULL;
2422 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2423 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2424 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2426 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2427 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2429 /* Do nothing if we changed the folder in the main view */
2430 if (header_model != model)
2433 /* Select the message in the header view */
2434 path = gtk_tree_row_reference_get_path (row_reference);
2435 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2437 gtk_tree_path_free (path);
2443 show_updating_banner (gpointer user_data)
2445 ModestMainWindowPrivate *priv = NULL;
2447 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2449 priv->updating_banner =
2450 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2451 _CS ("ckdg_pb_updating"));
2453 /* Remove timeout */
2454 priv->updating_banner_timeout = 0;
2459 * We use this function to show/hide a progress banner showing
2460 * "Updating" while the header view is being filled. We're not showing
2461 * it unless the update takes more than 2 seconds
2463 * If starting = TRUE then the refresh is starting, otherwise it means
2464 * that is has just finished
2467 on_updating_msg_list (ModestHeaderView *header_view,
2471 ModestMainWindowPrivate *priv = NULL;
2473 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2475 /* Remove old timeout */
2476 if (priv->updating_banner_timeout > 0) {
2477 g_source_remove (priv->updating_banner_timeout);
2478 priv->updating_banner_timeout = 0;
2481 /* Create a new timeout */
2483 priv->updating_banner_timeout =
2484 g_timeout_add (2000, show_updating_banner, user_data);
2486 /* Remove the banner if exists */
2487 if (priv->updating_banner) {
2488 gtk_widget_destroy (priv->updating_banner);
2489 priv->updating_banner = NULL;