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 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
177 struct _ModestMainWindowPrivate {
178 GtkWidget *msg_paned;
179 GtkWidget *main_paned;
180 GtkWidget *main_vbox;
181 GtkWidget *contents_widget;
182 GtkWidget *empty_view;
184 /* Progress observers */
185 GtkWidget *progress_bar;
186 GSList *progress_widgets;
189 GtkWidget *progress_toolitem;
190 GtkWidget *cancel_toolitem;
191 GtkWidget *sort_toolitem;
192 GtkWidget *refresh_toolitem;
193 ModestToolBarModes current_toolbar_mode;
195 /* Merge ids used to add/remove accounts to the ViewMenu*/
196 GByteArray *merge_ids;
197 GtkActionGroup *view_additions_group;
199 /* On-demand widgets */
200 GtkWidget *accounts_popup;
201 GtkWidget *details_widget;
203 /* Optimized view enabled */
204 gboolean optimized_view;
206 /* Optimized view enabled */
207 gboolean send_receive_in_progress;
209 ModestHeaderView *header_view;
210 ModestFolderView *folder_view;
212 ModestMainWindowStyle style;
213 ModestMainWindowContentsStyle contents_style;
215 guint progress_bar_timeout;
217 /* Signal handler UIDs */
218 GList *queue_err_signals;
221 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
222 MODEST_TYPE_MAIN_WINDOW, \
223 ModestMainWindowPrivate))
225 typedef struct _GetMsgAsyncHelper {
226 ModestMainWindowPrivate *main_window_private;
228 ModestTnyMsgReplyType reply_type;
229 ModestTnyMsgForwardType forward_type;
236 static GtkWindowClass *parent_class = NULL;
239 /* Private actions */
240 /* This is the context sensitive menu: */
241 static const GtkActionEntry modest_folder_view_action_entries [] = {
243 /* Folder View CSM actions */
244 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
245 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
246 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
247 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
248 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
249 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
252 static const GtkActionEntry modest_header_view_action_entries [] = {
254 /* Header View CSM actions */
255 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
256 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
257 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
258 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
259 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
260 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
261 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
262 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
263 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
264 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
267 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
268 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
271 /************************************************************************/
274 modest_main_window_get_type (void)
276 static GType my_type = 0;
278 static const GTypeInfo my_info = {
279 sizeof(ModestMainWindowClass),
280 NULL, /* base init */
281 NULL, /* base finalize */
282 (GClassInitFunc) modest_main_window_class_init,
283 NULL, /* class finalize */
284 NULL, /* class data */
285 sizeof(ModestMainWindow),
287 (GInstanceInitFunc) modest_main_window_init,
290 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
298 modest_main_window_class_init (ModestMainWindowClass *klass)
300 GObjectClass *gobject_class;
301 gobject_class = (GObjectClass*) klass;
302 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
304 parent_class = g_type_class_peek_parent (klass);
305 gobject_class->finalize = modest_main_window_finalize;
307 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
309 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
310 modest_window_class->save_state_func = save_state;
311 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
312 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
313 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
317 modest_main_window_init (ModestMainWindow *obj)
319 ModestMainWindowPrivate *priv;
321 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
323 priv->queue_err_signals = NULL;
324 priv->msg_paned = NULL;
325 priv->main_paned = NULL;
326 priv->main_vbox = NULL;
327 priv->header_view = NULL;
328 priv->folder_view = NULL;
329 priv->contents_widget = NULL;
330 priv->accounts_popup = NULL;
331 priv->details_widget = NULL;
332 priv->empty_view = NULL;
333 priv->progress_widgets = NULL;
334 priv->progress_bar = NULL;
335 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
336 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
337 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
338 priv->merge_ids = NULL;
339 priv->optimized_view = FALSE;
340 priv->send_receive_in_progress = FALSE;
341 priv->progress_bar_timeout = 0;
342 priv->sighandlers = NULL;
346 modest_main_window_finalize (GObject *obj)
348 ModestMainWindowPrivate *priv;
350 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
352 /* Sanity check: shouldn't be needed, the window mgr should
353 call this function before */
354 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
356 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
358 g_slist_free (priv->progress_widgets);
360 g_byte_array_free (priv->merge_ids, TRUE);
362 if (priv->progress_bar_timeout > 0) {
363 g_source_remove (priv->progress_bar_timeout);
364 priv->progress_bar_timeout = 0;
367 G_OBJECT_CLASS(parent_class)->finalize (obj);
371 modest_main_window_get_child_widget (ModestMainWindow *self,
372 ModestMainWindowWidgetType widget_type)
374 ModestMainWindowPrivate *priv;
377 g_return_val_if_fail (self, NULL);
378 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
381 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
383 switch (widget_type) {
384 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
385 widget = (GtkWidget*)priv->header_view; break;
386 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
387 widget = (GtkWidget*)priv->folder_view; break;
392 return widget ? GTK_WIDGET(widget) : NULL;
397 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
400 ModestMainWindowPrivate *priv;
402 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
404 conf = modest_runtime_get_conf ();
406 modest_widget_memory_restore (conf, G_OBJECT(self),
407 MODEST_CONF_MAIN_WINDOW_KEY);
409 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
410 MODEST_CONF_HEADER_VIEW_KEY);
412 if (do_folder_view_too)
413 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
414 MODEST_CONF_FOLDER_VIEW_KEY);
416 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
417 MODEST_CONF_MAIN_PANED_KEY);
419 /* We need to force a redraw here in order to get the right
420 position of the horizontal paned separator */
421 gtk_widget_show (GTK_WIDGET (self));
426 save_state (ModestWindow *window)
429 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
430 ModestMainWindowPrivate *priv;
432 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
433 conf = modest_runtime_get_conf ();
435 modest_widget_memory_save (conf,G_OBJECT(self),
436 MODEST_CONF_MAIN_WINDOW_KEY);
437 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
438 MODEST_CONF_MAIN_PANED_KEY);
439 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
440 // MODEST_CONF_HEADER_VIEW_KEY);
441 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
442 MODEST_CONF_FOLDER_VIEW_KEY);
446 compare_display_names (ModestAccountData *a,
447 ModestAccountData *b)
449 return strcmp (a->display_name, b->display_name);
453 update_menus (ModestMainWindow* self)
455 GSList *account_names, *iter, *accounts;
456 ModestMainWindowPrivate *priv;
457 ModestWindowPrivate *parent_priv;
458 ModestAccountMgr *mgr;
459 gint i, num_accounts;
461 gchar *default_account;
462 GtkWidget *send_receive_button, *item;
463 GtkAction *send_receive_all = NULL;
466 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
467 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
469 /* Get enabled account IDs */
470 mgr = modest_runtime_get_account_mgr ();
471 account_names = modest_account_mgr_account_names (mgr, TRUE);
472 iter = account_names;
476 ModestAccountData *account_data =
477 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
478 accounts = g_slist_prepend (accounts, account_data);
482 modest_account_mgr_free_account_names (account_names);
483 account_names = NULL;
485 /* Order the list of accounts by its display name */
486 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
487 num_accounts = g_slist_length (accounts);
489 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
490 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
491 gtk_action_set_visible (send_receive_all, num_accounts > 1);
493 /* Delete old send&receive popup items. We can not just do a
494 menu_detach because it does not work well with
496 if (priv->accounts_popup)
497 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
498 (GtkCallback) gtk_widget_destroy, NULL);
500 /* Delete old entries in the View menu. Do not free groups, it
502 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
504 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
505 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
506 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
507 GTK_ACTION_GROUP (groups->data));
510 if (priv->merge_ids) {
511 for (i = 0; i < priv->merge_ids->len; i++)
512 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
513 g_byte_array_free (priv->merge_ids, TRUE);
515 /* We need to call this in order to ensure
516 that the new actions are added in the right
517 order (alphabetical) */
518 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
520 groups = g_list_next (groups);
522 priv->merge_ids = g_byte_array_sized_new (num_accounts);
524 /* Get send receive button */
525 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
526 "/ToolBar/ToolbarSendReceive");
528 /* Create the menu */
529 if (num_accounts > 1) {
530 if (!priv->accounts_popup)
531 priv->accounts_popup = gtk_menu_new ();
532 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
533 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
534 g_signal_connect (G_OBJECT (item),
536 G_CALLBACK (on_send_receive_csm_activated),
538 item = gtk_separator_menu_item_new ();
539 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
542 /* Create a new action group */
543 default_account = modest_account_mgr_get_default_account (mgr);
544 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
546 for (i = 0; i < num_accounts; i++) {
547 gchar *display_name = NULL;
548 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
550 if (default_account && account_data->account_name &&
551 !(strcmp (default_account, account_data->account_name) == 0)) {
552 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
553 account_data->display_name);
556 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
557 account_data->display_name);
560 /* Create action and add it to the action group. The
561 action name must be the account name, this way we
562 could know in the handlers the account to show */
563 if(account_data && account_data->account_name) {
564 gchar* item_name, *refresh_action_name;
566 GtkAction *view_account_action, *refresh_account_action;
568 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
569 display_name, NULL, NULL, 0));
570 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
571 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
572 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
574 if (default_account && account_data->account_name &&
575 (strcmp (default_account, account_data->account_name) == 0)) {
576 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
579 /* Add ui from account data. We allow 2^9-1 account
580 changes in a single execution because we're
581 downcasting the guint to a guint8 in order to use a
582 GByteArray. It should be enough. */
583 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
584 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
585 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
586 gtk_ui_manager_add_ui (parent_priv->ui_manager,
588 "/MenuBar/ViewMenu/ViewMenuAdditions",
590 account_data->account_name,
591 GTK_UI_MANAGER_MENUITEM,
594 /* Connect the action signal "activate" */
595 g_signal_connect_after (G_OBJECT (view_account_action),
597 G_CALLBACK (on_show_account_action_toggled),
600 /* Create the items for the Tools->Send&Receive submenu */
601 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
602 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
603 display_name, NULL, NULL);
604 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
606 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
607 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
608 gtk_ui_manager_add_ui (parent_priv->ui_manager,
610 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
613 GTK_UI_MANAGER_MENUITEM,
615 g_free (refresh_action_name);
617 g_signal_connect_data (G_OBJECT (refresh_account_action),
619 G_CALLBACK (on_refresh_account_action_activated),
620 g_strdup (account_data->account_name),
621 (GClosureNotify) g_free,
624 /* Create item and add it to the send&receive
625 CSM. If there is only one account then
627 if (priv->accounts_popup) {
628 GtkWidget *label = gtk_label_new(NULL);
629 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
630 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
632 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
633 gtk_label_set_markup (GTK_LABEL (label), escaped);
638 gtk_label_set_text (GTK_LABEL (label), display_name);
641 item = gtk_menu_item_new ();
642 gtk_container_add (GTK_CONTAINER (item), label);
644 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
645 g_signal_connect_data (G_OBJECT (item),
647 G_CALLBACK (on_send_receive_csm_activated),
648 g_strdup (account_data->account_name),
649 (GClosureNotify) g_free,
656 g_free (display_name);
659 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
661 /* We cannot do this in the loop above because this relies on the action
662 * group being inserted. This makes the default account appear in bold.
663 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
664 for (i = 0; i < num_accounts; i++) {
665 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
667 if(account_data->account_name && default_account &&
668 strcmp (account_data->account_name, default_account) == 0) {
669 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
671 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
672 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
676 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
677 if (GTK_IS_LABEL (child)) {
678 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
679 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
680 gtk_label_set_markup (GTK_LABEL (child), bold_name);
685 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
686 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
690 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
691 if (GTK_IS_LABEL (child)) {
692 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
693 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
694 gtk_label_set_markup (GTK_LABEL (child), bold_name);
702 modest_account_mgr_free_account_data (mgr, account_data);
705 if (priv->accounts_popup) {
706 /* Mandatory in order to view the menu contents */
707 gtk_widget_show_all (priv->accounts_popup);
709 /* Setup tap_and_hold just if was not done before*/
710 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
711 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
715 g_slist_free (accounts);
716 g_free (default_account);
719 /* Make sure that at least one account is viewed if there are any
720 * accounts, for instance when adding the first account: */
721 set_at_least_one_account_visible (self);
725 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
727 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
728 gtk_scrolled_window_add_with_viewport
729 (GTK_SCROLLED_WINDOW(win), widget);
731 gtk_container_add (GTK_CONTAINER(win),
742 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
744 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
746 GList *oerrsignals = priv->queue_err_signals;
747 while (oerrsignals) {
748 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
749 g_signal_handler_disconnect (esignal->queue, esignal->signal);
750 g_slice_free (QueueErrorSignal, esignal);
751 oerrsignals = g_list_next (oerrsignals);
753 g_list_free (priv->queue_err_signals);
754 priv->queue_err_signals = NULL;
759 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
761 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
764 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
768 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
770 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
772 /* Update visibility */
775 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
779 modest_main_window_disconnect_signals (ModestWindow *self)
781 ModestMainWindowPrivate *priv;
782 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
784 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
785 priv->sighandlers = NULL;
789 connect_signals (ModestMainWindow *self)
791 ModestWindowPrivate *parent_priv;
792 ModestMainWindowPrivate *priv;
795 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
796 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
801 modest_signal_mgr_connect (priv->sighandlers,
802 G_OBJECT(priv->folder_view), "key-press-event",
803 G_CALLBACK(on_inner_widgets_key_pressed), self);
805 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
806 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
808 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
809 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
811 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
812 G_CALLBACK (on_folder_view_focus_in), self);
814 /* Folder view CSM */
815 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
816 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
817 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
818 G_CALLBACK(_folder_view_csm_menu_activated),
822 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
823 G_CALLBACK(modest_ui_actions_on_header_selected), self);
825 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
826 G_CALLBACK(modest_ui_actions_on_header_activated), self);
828 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
829 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
831 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
832 G_CALLBACK(on_inner_widgets_key_pressed), self);
834 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
835 G_CALLBACK(on_msg_count_changed), self);
837 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
838 G_CALLBACK (on_header_view_focus_in), self);
840 /* Header view CSM */
841 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
842 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
843 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
844 G_CALLBACK(_header_view_csm_menu_activated),
848 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
849 G_CALLBACK (modest_main_window_window_state_event),
852 /* Mail Operation Queue */
854 modest_signal_mgr_connect (priv->sighandlers,
855 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
857 G_CALLBACK (on_queue_changed), self);
859 /* Track changes in the device name */
861 modest_signal_mgr_connect (priv->sighandlers,
862 G_OBJECT(modest_runtime_get_conf ()),
864 G_CALLBACK (on_configuration_key_changed),
867 /* Track account changes. We need to refresh the toolbar */
869 modest_signal_mgr_connect (priv->sighandlers,
870 G_OBJECT (modest_runtime_get_account_store ()),
872 G_CALLBACK (on_account_inserted),
875 modest_signal_mgr_connect (priv->sighandlers,
876 G_OBJECT (modest_runtime_get_account_store ()),
878 G_CALLBACK (on_account_removed),
881 /* We need to refresh the send & receive menu to change the bold
882 * account when the default account changes. */
884 modest_signal_mgr_connect (priv->sighandlers,
885 G_OBJECT (modest_runtime_get_account_mgr ()),
886 "default_account_changed",
887 G_CALLBACK (on_default_account_changed),
892 modest_signal_mgr_connect (priv->sighandlers,
893 G_OBJECT (modest_runtime_get_account_store()),
894 "password_requested",
895 G_CALLBACK (modest_ui_actions_on_password_requested),
900 /** Idle handler, to send/receive at startup .*/
902 sync_accounts_cb (ModestMainWindow *win)
904 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
905 return FALSE; /* Do not call this idle handler again. */
910 on_hildon_program_is_topmost_notify(GObject *self,
911 GParamSpec *propert_param, gpointer user_data)
913 HildonProgram *app = HILDON_PROGRAM (self);
916 ModestWindow* self = MODEST_WINDOW(user_data);
919 /* Note that use of hildon_program_set_can_hibernate()
920 * is generally referred to as "setting the killable flag",
921 * though hibernation does not seem equal to death.
924 if (hildon_program_get_is_topmost (app)) {
925 /* Prevent hibernation when the progam comes to the foreground,
926 * because hibernation should only happen when the application
927 * is in the background: */
928 hildon_program_set_can_hibernate (app, FALSE);
930 /* Allow hibernation if the program has gone to the background: */
932 /* However, prevent hibernation while the settings are being changed: */
933 const gboolean hibernation_prevented =
934 modest_window_mgr_get_hibernation_is_prevented (
935 modest_runtime_get_window_mgr ());
937 if (hibernation_prevented)
938 hildon_program_set_can_hibernate (app, FALSE);
940 /* Allow hibernation, after saving the state: */
941 modest_osso_save_state();
942 hildon_program_set_can_hibernate (app, TRUE);
949 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
951 GtkWidget *folder_win = (GtkWidget *) user_data;
952 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
954 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
955 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
956 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
958 gtk_widget_show (GTK_WIDGET (priv->folder_view));
960 /* Connect signals */
961 connect_signals ((ModestMainWindow*)self);
963 /* Set account store */
964 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
965 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
967 /* Load previous osso state, for instance if we are being restored from
969 modest_osso_load_state ();
971 /* Restore window & widget settings */
973 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
975 /* The UI spec wants us to show a connection dialog when the application is
976 * started by the user, if there is no connection.
977 * Do this before showing the account wizard,
978 * because wizard needs a connection to discover capabilities. */
979 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
981 /* Check if accounts exist and show the account wizard if not */
982 gboolean accounts_exist =
983 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
985 if (!accounts_exist) {
986 /* This is necessary to have the main window shown behind the dialog
987 It's an ugly hack... jschmid */
988 gtk_widget_show_all(GTK_WIDGET(self));
989 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
992 GtkAction *send_receive_all;
993 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
994 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
995 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
996 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
997 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
998 modest_account_mgr_free_account_names (accounts);
1003 modest_main_window_new (void)
1005 ModestMainWindow *self = NULL;
1006 ModestMainWindowPrivate *priv = NULL;
1007 ModestWindowPrivate *parent_priv = NULL;
1008 GtkWidget *folder_win = NULL;
1009 ModestDimmingRulesGroup *menu_rules_group = NULL;
1010 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1011 GtkActionGroup *action_group = NULL;
1012 GError *error = NULL;
1013 ModestConf *conf = NULL;
1014 GtkAction *action = NULL;
1015 GdkPixbuf *window_icon;
1017 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1018 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1019 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1021 parent_priv->ui_manager = gtk_ui_manager_new();
1022 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1024 action_group = gtk_action_group_new ("ModestMainWindowActions");
1025 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1027 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1028 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1030 /* Add common actions */
1031 gtk_action_group_add_actions (action_group,
1032 modest_action_entries,
1033 G_N_ELEMENTS (modest_action_entries),
1036 gtk_action_group_add_actions (action_group,
1037 modest_folder_view_action_entries,
1038 G_N_ELEMENTS (modest_folder_view_action_entries),
1041 gtk_action_group_add_actions (action_group,
1042 modest_header_view_action_entries,
1043 G_N_ELEMENTS (modest_header_view_action_entries),
1046 gtk_action_group_add_toggle_actions (action_group,
1047 modest_toggle_action_entries,
1048 G_N_ELEMENTS (modest_toggle_action_entries),
1051 gtk_action_group_add_toggle_actions (action_group,
1052 modest_main_window_toggle_action_entries,
1053 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1056 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1057 g_object_unref (action_group);
1059 /* Load the UI definition */
1060 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1061 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1062 if (error != NULL) {
1063 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1064 g_error_free (error);
1068 /* Add common dimming rules */
1069 modest_dimming_rules_group_add_rules (menu_rules_group,
1070 modest_main_window_menu_dimming_entries,
1071 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1072 MODEST_WINDOW (self));
1073 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1074 modest_main_window_toolbar_dimming_entries,
1075 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1076 MODEST_WINDOW (self));
1078 /* Insert dimming rules group for this window */
1079 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1080 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1081 g_object_unref (menu_rules_group);
1082 g_object_unref (toolbar_rules_group);
1084 /* Add accelerators */
1085 gtk_window_add_accel_group (GTK_WINDOW (self),
1086 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1088 /* Menubar. Update the state of some toggles */
1089 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1090 conf = modest_runtime_get_conf ();
1091 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1092 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1093 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1094 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1095 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1096 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1097 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1098 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1099 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1100 gtk_widget_show (parent_priv->menubar);
1102 /* Get device name */
1103 modest_maemo_utils_get_device_name ();
1107 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1108 if (!priv->header_view)
1109 g_printerr ("modest: cannot instantiate header view\n");
1110 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1111 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1112 MODEST_CONF_HEADER_VIEW_KEY);
1114 /* Other style properties of header view */
1115 g_object_set (G_OBJECT (priv->header_view),
1116 "rules-hint", FALSE,
1118 /* gtk_widget_show (priv->header_view); */
1121 priv->empty_view = create_empty_view ();
1122 gtk_widget_show (priv->empty_view);
1124 /* Create scrolled windows */
1125 folder_win = gtk_scrolled_window_new (NULL, NULL);
1126 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1127 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1129 GTK_POLICY_AUTOMATIC);
1130 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1132 GTK_POLICY_AUTOMATIC);
1133 /* gtk_widget_show (priv->contents_widget); */
1136 priv->main_paned = gtk_hpaned_new ();
1137 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1138 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1139 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1141 /* putting it all together... */
1142 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1143 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1144 gtk_widget_show (priv->main_vbox);
1146 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1148 HildonProgram *app = hildon_program_get_instance ();
1149 hildon_program_add_window (app, HILDON_WINDOW (self));
1151 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1152 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1154 g_signal_connect (G_OBJECT(self), "show",
1155 G_CALLBACK (modest_main_window_on_show), folder_win);
1157 /* Set window icon */
1158 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1160 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1161 g_object_unref (window_icon);
1164 /* Dont't restore settings here,
1165 * because it requires a gtk_widget_show(),
1166 * and we don't want to do that until later,
1167 * so that the UI is not visible for non-menu D-Bus activation.
1169 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1171 return MODEST_WINDOW(self);
1175 modest_main_window_close_all (ModestMainWindow *self)
1178 GtkResponseType response;
1180 /* Create the confirmation dialog MSG-NOT308 */
1181 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1182 _("emev_nc_close_windows"),
1183 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1184 _("mcen_bd_no"), GTK_RESPONSE_NO,
1187 response = gtk_dialog_run (GTK_DIALOG (note));
1188 gtk_widget_destroy (GTK_WIDGET (note));
1190 if (response == GTK_RESPONSE_YES)
1198 modest_main_window_set_style (ModestMainWindow *self,
1199 ModestMainWindowStyle style)
1201 ModestMainWindowPrivate *priv;
1202 ModestWindowPrivate *parent_priv;
1206 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1208 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1209 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1211 /* no change -> nothing to do */
1212 if (priv->style == style)
1215 /* Get toggle button and update the state if needed. This will
1216 happen only when the set_style is not invoked from the UI,
1217 for example when it's called from widget memory */
1218 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1219 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1220 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1221 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1222 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1223 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1224 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1227 priv->style = style;
1229 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1230 /* Remove main paned */
1231 g_object_ref (priv->main_paned);
1232 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1234 /* Reparent the contents widget to the main vbox */
1235 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1238 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1239 /* Remove header view */
1240 g_object_ref (priv->contents_widget);
1241 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1243 /* Reparent the main paned */
1244 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1245 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1249 g_return_if_reached ();
1252 /* Let header view grab the focus if it's being shown */
1253 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1254 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1256 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1259 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1262 ModestMainWindowStyle
1263 modest_main_window_get_style (ModestMainWindow *self)
1265 ModestMainWindowPrivate *priv;
1267 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1269 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1276 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1278 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1279 ModestWindowPrivate *parent_priv;
1280 ModestWindowMgr *mgr;
1281 gboolean is_fullscreen;
1282 GtkAction *fs_toggle_action;
1285 mgr = modest_runtime_get_window_mgr ();
1287 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1289 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1291 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1292 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1293 if (is_fullscreen != active) {
1294 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1303 set_homogeneous (GtkWidget *widget,
1306 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1307 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1311 modest_main_window_show_toolbar (ModestWindow *self,
1312 gboolean show_toolbar)
1314 ModestMainWindowPrivate *priv = NULL;
1315 ModestWindowPrivate *parent_priv = NULL;
1316 GtkWidget *reply_button = NULL, *menu = NULL;
1317 GtkWidget *placeholder = NULL;
1319 const gchar *action_name;
1322 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1323 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1324 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1326 /* Set optimized view status */
1327 priv->optimized_view = !show_toolbar;
1329 if (!parent_priv->toolbar) {
1330 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1332 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1334 /* Set homogeneous toolbar */
1335 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1336 set_homogeneous, NULL);
1338 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1339 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1340 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1341 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1342 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1343 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1344 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1345 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1347 /* Add ProgressBar (Transfer toolbar) */
1348 priv->progress_bar = modest_progress_bar_widget_new ();
1349 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1350 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1351 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1352 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1353 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1355 /* Connect cancel 'clicked' signal to abort progress mode */
1356 g_signal_connect(priv->cancel_toolitem, "clicked",
1357 G_CALLBACK(cancel_progressbar),
1360 /* Add it to the observers list */
1361 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1364 hildon_window_add_toolbar (HILDON_WINDOW (self),
1365 GTK_TOOLBAR (parent_priv->toolbar));
1367 /* Set reply button tap and hold menu */
1368 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1369 "/ToolBar/ToolbarMessageReply");
1370 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1371 "/ToolbarReplyCSM");
1372 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1374 /* Set send & receive button tap and hold menu */
1375 update_menus (MODEST_MAIN_WINDOW (self));
1379 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1380 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1381 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1383 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1384 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1386 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1390 /* Update also the actions (to update the toggles in the
1391 menus), we have to do it manually because some other window
1392 of the same time could have changed it (remember that the
1393 toolbar fullscreen mode is shared by all the windows of the
1395 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1396 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1398 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1400 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1401 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1406 on_account_inserted (TnyAccountStore *accoust_store,
1407 TnyAccount *account,
1410 update_menus (MODEST_MAIN_WINDOW (user_data));
1414 on_default_account_changed (ModestAccountMgr* mgr,
1417 update_menus (MODEST_MAIN_WINDOW (user_data));
1421 on_account_removed (TnyAccountStore *accoust_store,
1422 TnyAccount *account,
1425 update_menus (MODEST_MAIN_WINDOW (user_data));
1429 * This function manages the key events used to navigate between
1430 * header and folder views (when the window is in split view)
1433 * -------------------------------------------------
1434 * HeaderView GDK_Left Move focus to folder view
1435 * FolderView GDK_Right Move focus to header view
1437 * There is no need to scroll to selected row, the widgets will be the
1438 * responsibles of doing that (probably managing the focus-in event
1441 on_inner_widgets_key_pressed (GtkWidget *widget,
1445 ModestMainWindowPrivate *priv;
1447 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1449 /* Do nothing if we're in SIMPLE style */
1450 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1453 if (MODEST_IS_HEADER_VIEW (widget)) {
1454 if (event->keyval == GDK_Left)
1455 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1456 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1457 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1460 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1461 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1467 set_alignment (GtkWidget *widget,
1470 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1471 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1475 create_empty_view (void)
1477 GtkLabel *label = NULL;
1478 GtkWidget *align = NULL;
1480 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1481 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1482 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1483 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1485 return GTK_WIDGET(align);
1489 * Free the returned string
1492 get_gray_color_markup (GtkWidget *styled_widget)
1494 gchar *gray_color_markup;
1496 /* Obtain the secondary text color. We need a realized widget, that's why
1497 we get styled_widget from outside */
1498 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1500 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1501 gray_color_markup = modest_text_utils_get_color_string (&color);
1503 gray_color_markup = g_strdup ("#BBBBBB");
1505 return gray_color_markup;
1509 * Free the returned string
1512 create_device_name_visual_string (const gchar *device_name,
1513 const gchar *gray_color_markup)
1517 /* We have to use "" to fill the %s of the translation. We can
1518 not just use the device name because the device name is
1519 shown in a different color, so it could not be included
1520 into the <span> tag */
1521 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1522 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1532 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1534 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1539 gchar *gray_color_markup;
1541 vbox = gtk_vbox_new (FALSE, 0);
1543 gray_color_markup = get_gray_color_markup (styled_widget);
1545 /* Account description: */
1546 if (modest_tny_account_is_virtual_local_folders (account)
1547 || (modest_tny_account_is_memory_card_account (account))) {
1549 /* Get device name */
1550 gchar *device_name = NULL;
1551 if (modest_tny_account_is_virtual_local_folders (account))
1552 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1553 MODEST_CONF_DEVICE_NAME, NULL);
1555 device_name = g_strdup (tny_account_get_name (account));
1557 label = create_device_name_visual_string ((const gchar *) device_name,
1558 (const gchar *) gray_color_markup);
1559 label_w = gtk_label_new (NULL);
1560 gtk_label_set_markup (GTK_LABEL (label_w), label);
1561 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1562 g_free (device_name);
1565 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1566 gtk_box_pack_start (GTK_BOX (vbox),
1567 gtk_label_new (tny_account_get_name (account)),
1570 /* Other accounts, such as IMAP and POP: */
1575 /* Put proto in uppercase */
1576 proto = g_string_new (tny_account_get_proto (account));
1577 proto = g_string_ascii_up (proto);
1579 /* note: mcen_fi_localroot_description is something like "%s account"
1580 * however, we should display "%s account: %s"... therefore, ugly tmp */
1581 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1582 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1583 gray_color_markup, tmp, tny_account_get_name (account));
1586 label_w = gtk_label_new (NULL);
1587 gtk_label_set_markup (GTK_LABEL (label_w), label);
1588 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1589 g_string_free (proto, TRUE);
1595 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1596 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1597 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1598 modest_tny_folder_store_get_message_count (folder_store));
1599 label_w = gtk_label_new (NULL);
1600 gtk_label_set_markup (GTK_LABEL (label_w), label);
1601 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1605 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1607 _("mcen_fi_rootfolder_folders"),
1608 modest_tny_folder_store_get_folder_count (folder_store));
1609 label_w = gtk_label_new (NULL);
1610 gtk_label_set_markup (GTK_LABEL (label_w), label);
1611 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1615 if (modest_tny_account_is_virtual_local_folders (account)
1616 || modest_tny_account_is_memory_card_account (account)) {
1618 gchar *size = modest_text_utils_get_display_size (
1619 modest_tny_folder_store_get_local_size (folder_store));
1621 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1622 gray_color_markup, _("mcen_fi_rootfolder_size"),
1626 label_w = gtk_label_new (NULL);
1627 gtk_label_set_markup (GTK_LABEL (label_w), label);
1628 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1630 } else if (TNY_IS_ACCOUNT(folder_store)) {
1631 TnyAccount *account = TNY_ACCOUNT(folder_store);
1633 time_t last_updated;
1634 gchar *last_updated_string;
1635 /* Get last updated from configuration */
1636 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1637 tny_account_get_id (account));
1639 if (last_updated > 0)
1640 last_updated_string = modest_text_utils_get_display_date(last_updated);
1642 last_updated_string = g_strdup (_("mcen_va_never"));
1644 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1645 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1646 label_w = gtk_label_new (NULL);
1647 gtk_label_set_markup (GTK_LABEL (label_w), label);
1648 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1649 g_free (last_updated_string);
1653 g_free (gray_color_markup);
1656 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1662 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1664 ModestMainWindowPrivate *priv = NULL;
1666 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1668 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1670 return priv->send_receive_in_progress;
1674 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1676 GtkAction *action = NULL;
1677 GtkWidget *widget = NULL;
1678 ModestMainWindowPrivate *priv = NULL;
1680 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1681 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1683 priv->send_receive_in_progress = TRUE;
1685 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1686 gtk_action_set_sensitive (action, FALSE);
1687 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1688 /* gtk_action_set_sensitive (action, FALSE); */
1689 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1690 gtk_widget_set_sensitive (widget, FALSE);
1694 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1696 GtkAction *action = NULL;
1697 GtkWidget *widget = NULL;
1698 ModestMainWindowPrivate *priv = NULL;
1700 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1701 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1703 priv->send_receive_in_progress = FALSE;
1705 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1706 gtk_action_set_sensitive (action, TRUE);
1707 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1708 /* gtk_action_set_sensitive (action, TRUE); */
1709 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1710 gtk_widget_set_sensitive (widget, TRUE);
1715 on_msg_count_changed (ModestHeaderView *header_view,
1717 TnyFolderChange *change,
1718 ModestMainWindow *main_window)
1720 gboolean folder_empty = FALSE;
1721 gboolean all_marked_as_deleted = FALSE;
1722 TnyFolderChangeChanged changed;
1723 ModestMainWindowPrivate *priv;
1725 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1726 g_return_if_fail (TNY_IS_FOLDER(folder));
1727 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1728 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1730 changed = tny_folder_change_get_changed (change);
1732 /* If something changes */
1733 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1734 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1736 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1738 /* Check header removed (hide marked as DELETED headers) */
1739 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1740 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1743 /* Check if all messages are marked to be deleted */
1744 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1745 folder_empty = folder_empty || all_marked_as_deleted ;
1747 /* Set contents style of headers view */
1749 modest_main_window_set_contents_style (main_window,
1750 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1751 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1754 modest_main_window_set_contents_style (main_window,
1755 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1761 modest_main_window_set_contents_style (ModestMainWindow *self,
1762 ModestMainWindowContentsStyle style)
1764 ModestMainWindowPrivate *priv;
1766 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1768 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1770 /* We allow to set the same content style than the previously
1771 set if there are details, because it could happen when we're
1772 selecting different accounts consecutively */
1773 if ((priv->contents_style == style) &&
1774 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1777 /* Remove previous child. Delete it if it was an account
1779 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1781 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1782 g_object_ref (content);
1783 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1784 g_object_ref (priv->empty_view);
1785 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1788 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1791 priv->contents_style = style;
1793 switch (priv->contents_style) {
1794 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1795 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1796 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1799 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1801 /* if we're started without main win, there may not be a folder
1802 * view. this fixes a GLib-Critical */
1803 if (priv->folder_view) {
1804 TnyFolderStore *selected_folderstore =
1805 modest_folder_view_get_selected (priv->folder_view);
1806 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1807 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1808 TNY_ACCOUNT (selected_folderstore));
1810 wrap_in_scrolled_window (priv->contents_widget,
1811 priv->details_widget);
1813 g_object_unref (selected_folderstore);
1814 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1819 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1820 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1821 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1825 g_return_if_reached ();
1829 gtk_widget_show_all (priv->contents_widget);
1832 ModestMainWindowContentsStyle
1833 modest_main_window_get_contents_style (ModestMainWindow *self)
1835 ModestMainWindowPrivate *priv;
1837 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1839 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1840 return priv->contents_style;
1845 on_configuration_key_changed (ModestConf* conf,
1847 ModestConfEvent event,
1848 ModestConfNotificationId id,
1849 ModestMainWindow *self)
1851 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1852 TnyAccount *account = NULL;
1854 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1857 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1860 if (priv->folder_view)
1861 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1863 if (account && TNY_IS_ACCOUNT (account) &&
1864 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1867 const gchar *device_name;
1868 gchar *new_text, *gray_color_markup;
1871 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1872 label = GTK_LABEL (children->data);
1874 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1875 MODEST_CONF_DEVICE_NAME, NULL);
1877 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1878 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1880 gtk_label_set_markup (label, new_text);
1881 gtk_widget_show (GTK_WIDGET (label));
1883 g_free (gray_color_markup);
1885 g_list_free (children);
1887 g_object_unref (account);
1891 set_toolbar_transfer_mode (ModestMainWindow *self)
1893 ModestMainWindowPrivate *priv = NULL;
1895 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1897 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1899 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1901 if (priv->progress_bar_timeout > 0) {
1902 g_source_remove (priv->progress_bar_timeout);
1903 priv->progress_bar_timeout = 0;
1910 set_toolbar_mode (ModestMainWindow *self,
1911 ModestToolBarModes mode)
1913 ModestWindowPrivate *parent_priv = NULL;
1914 ModestMainWindowPrivate *priv = NULL;
1915 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1917 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1919 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1920 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1922 /* In case this was called before the toolbar exists: */
1923 if (!(parent_priv->toolbar))
1926 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1928 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1929 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1930 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1932 /* Sets current toolbar mode */
1933 priv->current_toolbar_mode = mode;
1935 /* Checks the dimming rules */
1936 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1938 /* Show and hide toolbar items */
1940 case TOOLBAR_MODE_NORMAL:
1942 gtk_action_set_visible (sort_action, TRUE);
1944 gtk_action_set_visible (refresh_action, TRUE);
1945 if (priv->progress_toolitem) {
1946 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1947 gtk_widget_hide (priv->progress_toolitem);
1949 if (priv->progress_bar)
1950 gtk_widget_hide (priv->progress_bar);
1953 gtk_action_set_visible (cancel_action, FALSE);
1955 /* Hide toolbar if optimized view is enabled */
1956 if (priv->optimized_view)
1957 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1959 case TOOLBAR_MODE_TRANSFER:
1961 gtk_action_set_visible (sort_action, FALSE);
1963 gtk_action_set_visible (refresh_action, FALSE);
1965 gtk_action_set_visible (cancel_action, TRUE);
1966 if (priv->progress_toolitem) {
1967 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1968 gtk_widget_show (priv->progress_toolitem);
1970 if (priv->progress_bar)
1971 gtk_widget_show (priv->progress_bar);
1973 /* Show toolbar if it's hiden (optimized view ) */
1974 if (priv->optimized_view)
1975 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1978 g_return_if_reached ();
1983 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1985 ModestMainWindowPrivate *priv;
1987 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1988 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1990 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1994 cancel_progressbar (GtkToolButton *toolbutton,
1995 ModestMainWindow *self)
1998 ModestMainWindowPrivate *priv;
2000 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2002 /* Get operation observers and cancel all the operations */
2003 tmp = priv->progress_widgets;
2005 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2006 tmp=g_slist_next(tmp);
2011 observers_empty (ModestMainWindow *self)
2014 ModestMainWindowPrivate *priv;
2015 gboolean is_empty = TRUE;
2016 guint pending_ops = 0;
2018 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2019 tmp = priv->progress_widgets;
2021 /* Check all observers */
2022 while (tmp && is_empty) {
2023 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2024 is_empty = pending_ops == 0;
2026 tmp = g_slist_next(tmp);
2034 * Gets the toolbar mode needed for each mail operation. It stores in
2035 * @mode_changed if the toolbar mode has changed or not
2037 static ModestToolBarModes
2038 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2039 ModestMailOperation *mail_op,
2040 gboolean *mode_changed)
2042 ModestToolBarModes mode;
2043 ModestMainWindowPrivate *priv;
2045 *mode_changed = FALSE;
2046 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2048 /* Get toolbar mode from operation id*/
2049 switch (modest_mail_operation_get_type_operation (mail_op)) {
2050 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2051 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2052 mode = TOOLBAR_MODE_TRANSFER;
2053 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2054 *mode_changed = TRUE;
2057 mode = TOOLBAR_MODE_NORMAL;
2063 on_mail_operation_started (ModestMailOperation *mail_op,
2066 ModestMainWindow *self;
2067 ModestMailOperationTypeOperation op_type;
2068 ModestMainWindowPrivate *priv;
2069 ModestToolBarModes mode;
2071 gboolean mode_changed = FALSE;
2072 TnyAccount *account;
2074 self = MODEST_MAIN_WINDOW (user_data);
2075 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2077 /* Do not show progress for receiving operations if the
2078 account is the local account or the MMC one */
2079 op_type = modest_mail_operation_get_type_operation (mail_op);
2080 account = modest_mail_operation_get_account (mail_op);
2081 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2084 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2085 modest_tny_account_is_memory_card_account (account));
2086 g_object_unref (account);
2091 /* Get toolbar mode from operation id*/
2092 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2094 /* Add operation observers and change toolbar if neccessary*/
2095 tmp = priv->progress_widgets;
2096 if (mode == TOOLBAR_MODE_TRANSFER) {
2098 set_toolbar_transfer_mode(self);
2101 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2103 tmp = g_slist_next (tmp);
2109 on_mail_operation_finished (ModestMailOperation *mail_op,
2112 ModestToolBarModes mode;
2113 ModestMailOperationTypeOperation op_type;
2115 ModestMainWindow *self;
2116 gboolean mode_changed;
2117 TnyAccount *account;
2118 ModestMainWindowPrivate *priv;
2120 self = MODEST_MAIN_WINDOW (user_data);
2121 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2123 /* The mail operation was not added to the progress objects if
2124 the account was the local account or the MMC one */
2125 op_type = modest_mail_operation_get_type_operation (mail_op);
2126 account = modest_mail_operation_get_account (mail_op);
2127 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2130 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2131 modest_tny_account_is_memory_card_account (account));
2132 g_object_unref (account);
2137 /* Get toolbar mode from operation id*/
2138 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2140 /* Change toolbar mode */
2141 tmp = priv->progress_widgets;
2142 if (mode == TOOLBAR_MODE_TRANSFER) {
2144 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2146 tmp = g_slist_next (tmp);
2149 /* If no more operations are being observed, NORMAL mode is enabled again */
2150 if (observers_empty (self)) {
2151 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2157 on_queue_changed (ModestMailOperationQueue *queue,
2158 ModestMailOperation *mail_op,
2159 ModestMailOperationQueueNotification type,
2160 ModestMainWindow *self)
2162 ModestMainWindowPrivate *priv;
2164 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2166 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2167 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2169 "operation-started",
2170 G_CALLBACK (on_mail_operation_started),
2172 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2174 "operation-finished",
2175 G_CALLBACK (on_mail_operation_finished),
2177 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2178 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2180 "operation-started");
2181 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2183 "operation-finished");
2188 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2190 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2193 /* Get account data */
2194 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2195 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2197 /* Set the new visible & active account */
2198 if (acc_data && acc_data->store_account) {
2199 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2200 acc_data->store_account->account_name);
2201 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2202 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2203 if (action != NULL) {
2204 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2205 modest_maemo_toggle_action_set_active_block_notify (
2206 GTK_TOGGLE_ACTION (action),
2212 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2217 modest_account_mgr_free_account_data (mgr, acc_data);
2220 /* Make sure that at least one account is "viewed": */
2222 set_at_least_one_account_visible(ModestMainWindow *self)
2224 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2225 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2227 if (!(priv->folder_view)) {
2228 /* It is too early to do this. */
2232 const gchar *active_server_account_name =
2233 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2234 if (!active_server_account_name ||
2235 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2237 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2238 if (first_modest_name) {
2239 set_account_visible (self, first_modest_name);
2240 g_free (first_modest_name);
2246 on_show_account_action_toggled (GtkToggleAction *action,
2249 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2251 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2252 if (gtk_toggle_action_get_active (action))
2253 set_account_visible (self, acc_name);
2257 refresh_account (const gchar *account_name)
2261 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2263 /* If account_name == NULL, we must update all (option All) */
2265 modest_ui_actions_do_send_receive_all (win);
2267 modest_ui_actions_do_send_receive (account_name, win);
2272 on_refresh_account_action_activated (GtkAction *action,
2275 refresh_account ((const gchar*) user_data);
2279 on_send_receive_csm_activated (GtkMenuItem *item,
2282 refresh_account ((const gchar*) user_data);
2286 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2288 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2290 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2296 on_folder_view_focus_in (GtkWidget *widget,
2297 GdkEventFocus *event,
2300 ModestMainWindow *main_window = NULL;
2302 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2303 main_window = MODEST_MAIN_WINDOW (userdata);
2305 /* Update toolbar dimming state */
2306 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2312 on_header_view_focus_in (GtkWidget *widget,
2313 GdkEventFocus *event,
2316 ModestMainWindow *main_window = NULL;
2317 ModestMainWindowPrivate *priv = NULL;
2319 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2320 main_window = MODEST_MAIN_WINDOW (userdata);
2321 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2323 /* Update toolbar dimming state */
2324 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2330 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2331 TnyFolderStore *folder_store,
2333 ModestMainWindow *main_window)
2335 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2336 GtkAction *action = NULL;
2337 gboolean show_reply = TRUE;
2338 gboolean show_forward = TRUE;
2339 gboolean show_cancel_send = FALSE;
2340 gboolean show_clipboard = TRUE;
2341 gboolean show_delete = TRUE;
2344 if (TNY_IS_ACCOUNT (folder_store)) {
2345 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2346 } else if (TNY_IS_FOLDER (folder_store)) {
2347 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2348 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2349 TNY_FOLDER (folder_store));
2350 switch (folder_type) {
2351 case TNY_FOLDER_TYPE_DRAFTS:
2352 show_clipboard = show_delete = TRUE;
2353 show_reply = show_forward = show_cancel_send = FALSE;
2355 case TNY_FOLDER_TYPE_SENT:
2356 show_forward = show_clipboard = show_delete = TRUE;
2357 show_reply = show_cancel_send = FALSE;
2359 case TNY_FOLDER_TYPE_OUTBOX:
2360 show_clipboard = show_delete = show_cancel_send = TRUE;
2361 show_reply = show_forward = FALSE;
2364 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2365 show_cancel_send = FALSE;
2368 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2369 show_cancel_send = FALSE;
2374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2375 gtk_action_set_visible (action, show_reply);
2376 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2377 gtk_action_set_visible (action, show_reply);
2378 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2379 gtk_action_set_visible (action, show_forward);
2380 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2381 gtk_action_set_visible (action, show_cancel_send);
2382 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2383 gtk_action_set_visible (action, show_delete);
2385 /* We finally call to the ui actions handler, after updating properly
2386 * the header view CSM */
2387 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2391 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2392 GtkTreeModel *model,
2393 GtkTreeRowReference *row_reference,
2394 ModestMainWindow *self)
2396 ModestMainWindowPrivate *priv = NULL;
2397 GtkTreeModel *header_model = NULL;
2398 GtkTreePath *path = NULL;
2400 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2401 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2402 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2404 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2405 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2407 /* Do nothing if we changed the folder in the main view */
2408 if (header_model != model)
2411 /* Select the message in the header view */
2412 path = gtk_tree_row_reference_get_path (row_reference);
2413 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2415 gtk_tree_path_free (path);