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 static gboolean restore_paned_timeout_handler (gpointer *data);
182 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
183 struct _ModestMainWindowPrivate {
184 GtkWidget *msg_paned;
185 GtkWidget *main_paned;
186 GtkWidget *main_vbox;
187 GtkWidget *contents_widget;
188 GtkWidget *empty_view;
190 /* Progress observers */
191 GtkWidget *progress_bar;
192 GSList *progress_widgets;
195 GtkWidget *progress_toolitem;
196 GtkWidget *cancel_toolitem;
197 GtkWidget *sort_toolitem;
198 GtkWidget *refresh_toolitem;
199 ModestToolBarModes current_toolbar_mode;
201 /* Merge ids used to add/remove accounts to the ViewMenu*/
202 GByteArray *merge_ids;
203 GtkActionGroup *view_additions_group;
205 /* On-demand widgets */
206 GtkWidget *accounts_popup;
207 GtkWidget *details_widget;
209 /* Optimized view enabled */
210 gboolean optimized_view;
212 /* Optimized view enabled */
213 gboolean send_receive_in_progress;
215 ModestHeaderView *header_view;
216 ModestFolderView *folder_view;
218 ModestMainWindowStyle style;
219 ModestMainWindowContentsStyle contents_style;
221 guint progress_bar_timeout;
222 guint restore_paned_timeout;
224 /* Signal handler UIDs */
225 GList *queue_err_signals;
228 /* "Updating" banner for header view */
229 GtkWidget *updating_banner;
230 guint updating_banner_timeout;
232 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
233 MODEST_TYPE_MAIN_WINDOW, \
234 ModestMainWindowPrivate))
236 typedef struct _GetMsgAsyncHelper {
237 ModestMainWindowPrivate *main_window_private;
239 ModestTnyMsgReplyType reply_type;
240 ModestTnyMsgForwardType forward_type;
247 static GtkWindowClass *parent_class = NULL;
250 /* Private actions */
251 /* This is the context sensitive menu: */
252 static const GtkActionEntry modest_folder_view_action_entries [] = {
254 /* Folder View CSM actions */
255 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
256 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
257 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
258 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
259 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
260 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
263 static const GtkActionEntry modest_header_view_action_entries [] = {
265 /* Header View CSM actions */
266 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
267 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
268 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
269 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
270 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
271 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
272 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
273 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
274 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
275 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
278 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
279 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
282 /************************************************************************/
285 modest_main_window_get_type (void)
287 static GType my_type = 0;
289 static const GTypeInfo my_info = {
290 sizeof(ModestMainWindowClass),
291 NULL, /* base init */
292 NULL, /* base finalize */
293 (GClassInitFunc) modest_main_window_class_init,
294 NULL, /* class finalize */
295 NULL, /* class data */
296 sizeof(ModestMainWindow),
298 (GInstanceInitFunc) modest_main_window_init,
301 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
309 modest_main_window_class_init (ModestMainWindowClass *klass)
311 GObjectClass *gobject_class;
312 gobject_class = (GObjectClass*) klass;
313 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
315 parent_class = g_type_class_peek_parent (klass);
316 gobject_class->finalize = modest_main_window_finalize;
318 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
320 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
321 modest_window_class->save_state_func = save_state;
322 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
323 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
324 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
328 modest_main_window_init (ModestMainWindow *obj)
330 ModestMainWindowPrivate *priv;
332 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
334 priv->queue_err_signals = NULL;
335 priv->msg_paned = NULL;
336 priv->main_paned = NULL;
337 priv->main_vbox = NULL;
338 priv->header_view = NULL;
339 priv->folder_view = NULL;
340 priv->contents_widget = NULL;
341 priv->accounts_popup = NULL;
342 priv->details_widget = NULL;
343 priv->empty_view = NULL;
344 priv->progress_widgets = NULL;
345 priv->progress_bar = NULL;
346 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
347 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
348 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
349 priv->merge_ids = NULL;
350 priv->optimized_view = FALSE;
351 priv->send_receive_in_progress = FALSE;
352 priv->progress_bar_timeout = 0;
353 priv->restore_paned_timeout = 0;
354 priv->sighandlers = NULL;
355 priv->updating_banner = NULL;
356 priv->updating_banner_timeout = 0;
358 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
360 "applications_email_mainview");
364 modest_main_window_finalize (GObject *obj)
366 ModestMainWindowPrivate *priv;
368 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
370 /* Sanity check: shouldn't be needed, the window mgr should
371 call this function before */
372 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
374 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
376 g_slist_free (priv->progress_widgets);
378 g_byte_array_free (priv->merge_ids, TRUE);
380 if (priv->progress_bar_timeout > 0) {
381 g_source_remove (priv->progress_bar_timeout);
382 priv->progress_bar_timeout = 0;
385 if (priv->updating_banner_timeout > 0) {
386 g_source_remove (priv->updating_banner_timeout);
387 priv->updating_banner_timeout = 0;
390 if (priv->restore_paned_timeout > 0) {
391 g_source_remove (priv->restore_paned_timeout);
392 priv->restore_paned_timeout = 0;
395 G_OBJECT_CLASS(parent_class)->finalize (obj);
399 modest_main_window_get_child_widget (ModestMainWindow *self,
400 ModestMainWindowWidgetType widget_type)
402 ModestMainWindowPrivate *priv;
405 g_return_val_if_fail (self, NULL);
406 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
409 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
411 switch (widget_type) {
412 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
413 widget = (GtkWidget*)priv->header_view; break;
414 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
415 widget = (GtkWidget*)priv->folder_view; break;
420 return widget ? GTK_WIDGET(widget) : NULL;
424 restore_paned_timeout_handler (gpointer *data)
426 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
427 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
430 if (GTK_WIDGET_VISIBLE (main_window)) {
431 conf = modest_runtime_get_conf ();
432 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
433 MODEST_CONF_MAIN_PANED_KEY);
440 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
443 ModestMainWindowPrivate *priv;
445 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
447 conf = modest_runtime_get_conf ();
449 modest_widget_memory_restore (conf, G_OBJECT(self),
450 MODEST_CONF_MAIN_WINDOW_KEY);
452 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
453 MODEST_CONF_HEADER_VIEW_KEY);
455 if (do_folder_view_too)
456 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
457 MODEST_CONF_FOLDER_VIEW_KEY);
459 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
460 MODEST_CONF_MAIN_PANED_KEY);
462 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
464 /* We need to force a redraw here in order to get the right
465 position of the horizontal paned separator */
466 gtk_widget_show (GTK_WIDGET (self));
471 save_state (ModestWindow *window)
474 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
475 ModestMainWindowPrivate *priv;
477 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
478 conf = modest_runtime_get_conf ();
480 modest_widget_memory_save (conf,G_OBJECT(self),
481 MODEST_CONF_MAIN_WINDOW_KEY);
482 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
483 MODEST_CONF_MAIN_PANED_KEY);
484 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
485 // MODEST_CONF_HEADER_VIEW_KEY);
486 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
487 MODEST_CONF_FOLDER_VIEW_KEY);
491 compare_display_names (ModestAccountData *a,
492 ModestAccountData *b)
494 return strcmp (a->display_name, b->display_name);
498 update_menus (ModestMainWindow* self)
500 GSList *account_names, *iter, *accounts;
501 ModestMainWindowPrivate *priv;
502 ModestWindowPrivate *parent_priv;
503 ModestAccountMgr *mgr;
504 gint i, num_accounts;
506 gchar *default_account;
507 GtkWidget *send_receive_button, *item;
508 GtkAction *send_receive_all = NULL;
511 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
512 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
514 /* Get enabled account IDs */
515 mgr = modest_runtime_get_account_mgr ();
516 account_names = modest_account_mgr_account_names (mgr, TRUE);
517 iter = account_names;
521 ModestAccountData *account_data =
522 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
523 accounts = g_slist_prepend (accounts, account_data);
527 modest_account_mgr_free_account_names (account_names);
528 account_names = NULL;
530 /* Order the list of accounts by its display name */
531 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
532 num_accounts = g_slist_length (accounts);
534 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
535 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
536 gtk_action_set_visible (send_receive_all, num_accounts > 1);
538 /* Delete old send&receive popup items. We can not just do a
539 menu_detach because it does not work well with
541 if (priv->accounts_popup)
542 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
543 (GtkCallback) gtk_widget_destroy, NULL);
545 /* Delete old entries in the View menu. Do not free groups, it
547 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
549 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
550 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
551 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
552 GTK_ACTION_GROUP (groups->data));
555 if (priv->merge_ids) {
556 for (i = 0; i < priv->merge_ids->len; i++)
557 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
558 g_byte_array_free (priv->merge_ids, TRUE);
560 /* We need to call this in order to ensure
561 that the new actions are added in the right
562 order (alphabetical) */
563 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
565 groups = g_list_next (groups);
567 priv->merge_ids = g_byte_array_sized_new (num_accounts);
569 /* Get send receive button */
570 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
571 "/ToolBar/ToolbarSendReceive");
573 /* Create the menu */
574 if (num_accounts > 1) {
575 if (!priv->accounts_popup)
576 priv->accounts_popup = gtk_menu_new ();
577 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
578 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
579 g_signal_connect (G_OBJECT (item),
581 G_CALLBACK (on_send_receive_csm_activated),
583 item = gtk_separator_menu_item_new ();
584 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
587 /* Create a new action group */
588 default_account = modest_account_mgr_get_default_account (mgr);
589 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
591 for (i = 0; i < num_accounts; i++) {
592 gchar *display_name = NULL;
593 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
595 if (default_account && account_data->account_name &&
596 !(strcmp (default_account, account_data->account_name) == 0)) {
597 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
598 account_data->display_name);
601 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
602 account_data->display_name);
605 /* Create action and add it to the action group. The
606 action name must be the account name, this way we
607 could know in the handlers the account to show */
608 if(account_data && account_data->account_name) {
609 gchar* item_name, *refresh_action_name;
611 GtkAction *view_account_action, *refresh_account_action;
613 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
614 display_name, NULL, NULL, 0));
615 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
616 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
617 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
619 if (default_account && account_data->account_name &&
620 (strcmp (default_account, account_data->account_name) == 0)) {
621 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
624 /* Add ui from account data. We allow 2^9-1 account
625 changes in a single execution because we're
626 downcasting the guint to a guint8 in order to use a
627 GByteArray. It should be enough. */
628 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
629 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
630 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
631 gtk_ui_manager_add_ui (parent_priv->ui_manager,
633 "/MenuBar/ViewMenu/ViewMenuAdditions",
635 account_data->account_name,
636 GTK_UI_MANAGER_MENUITEM,
639 /* Connect the action signal "activate" */
640 g_signal_connect_after (G_OBJECT (view_account_action),
642 G_CALLBACK (on_show_account_action_toggled),
645 /* Create the items for the Tools->Send&Receive submenu */
646 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
647 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
648 display_name, NULL, NULL);
649 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
651 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
652 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
653 gtk_ui_manager_add_ui (parent_priv->ui_manager,
655 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
658 GTK_UI_MANAGER_MENUITEM,
660 g_free (refresh_action_name);
662 g_signal_connect_data (G_OBJECT (refresh_account_action),
664 G_CALLBACK (on_refresh_account_action_activated),
665 g_strdup (account_data->account_name),
666 (GClosureNotify) g_free,
669 /* Create item and add it to the send&receive
670 CSM. If there is only one account then
672 if (priv->accounts_popup) {
673 GtkWidget *label = gtk_label_new(NULL);
674 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
675 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
677 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
678 gtk_label_set_markup (GTK_LABEL (label), escaped);
683 gtk_label_set_text (GTK_LABEL (label), display_name);
686 item = gtk_menu_item_new ();
687 gtk_container_add (GTK_CONTAINER (item), label);
689 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
690 g_signal_connect_data (G_OBJECT (item),
692 G_CALLBACK (on_send_receive_csm_activated),
693 g_strdup (account_data->account_name),
694 (GClosureNotify) g_free,
701 g_free (display_name);
704 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
706 /* We cannot do this in the loop above because this relies on the action
707 * group being inserted. This makes the default account appear in bold.
708 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
709 for (i = 0; i < num_accounts; i++) {
710 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
712 if(account_data->account_name && default_account &&
713 strcmp (account_data->account_name, default_account) == 0) {
714 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
716 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
717 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
721 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
722 if (GTK_IS_LABEL (child)) {
723 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
724 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
725 gtk_label_set_markup (GTK_LABEL (child), bold_name);
730 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
731 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
735 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
736 if (GTK_IS_LABEL (child)) {
737 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
738 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
739 gtk_label_set_markup (GTK_LABEL (child), bold_name);
747 modest_account_mgr_free_account_data (mgr, account_data);
750 if (priv->accounts_popup) {
751 /* Mandatory in order to view the menu contents */
752 gtk_widget_show_all (priv->accounts_popup);
754 /* Setup tap_and_hold just if was not done before*/
755 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
756 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
760 g_slist_free (accounts);
761 g_free (default_account);
764 /* Make sure that at least one account is viewed if there are any
765 * accounts, for instance when adding the first account: */
766 set_at_least_one_account_visible (self);
770 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
772 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
773 gtk_scrolled_window_add_with_viewport
774 (GTK_SCROLLED_WINDOW(win), widget);
776 gtk_container_add (GTK_CONTAINER(win),
787 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
789 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
791 GList *oerrsignals = priv->queue_err_signals;
792 while (oerrsignals) {
793 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
794 g_signal_handler_disconnect (esignal->queue, esignal->signal);
795 g_slice_free (QueueErrorSignal, esignal);
796 oerrsignals = g_list_next (oerrsignals);
798 g_list_free (priv->queue_err_signals);
799 priv->queue_err_signals = NULL;
804 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
806 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
809 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
813 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
815 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
817 /* Update visibility */
820 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
824 modest_main_window_disconnect_signals (ModestWindow *self)
826 ModestMainWindowPrivate *priv;
827 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
829 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
830 priv->sighandlers = NULL;
834 connect_signals (ModestMainWindow *self)
836 ModestWindowPrivate *parent_priv;
837 ModestMainWindowPrivate *priv;
840 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
841 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
846 modest_signal_mgr_connect (priv->sighandlers,
847 G_OBJECT(priv->folder_view), "key-press-event",
848 G_CALLBACK(on_inner_widgets_key_pressed), self);
850 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
851 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
853 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
854 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
856 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
857 G_CALLBACK (on_folder_view_focus_in), self);
859 /* Folder view CSM */
860 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
861 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
862 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
863 G_CALLBACK(_folder_view_csm_menu_activated),
867 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
868 G_CALLBACK(modest_ui_actions_on_header_selected), self);
870 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
871 G_CALLBACK(modest_ui_actions_on_header_activated), self);
873 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
874 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
876 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
877 G_CALLBACK(on_inner_widgets_key_pressed), self);
879 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
880 G_CALLBACK(on_msg_count_changed), self);
882 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
883 G_CALLBACK (on_header_view_focus_in), self);
885 modest_signal_mgr_connect (priv->sighandlers,
886 G_OBJECT (priv->header_view),
888 G_CALLBACK (on_updating_msg_list),
891 /* Header view CSM */
892 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
893 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
895 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
896 G_CALLBACK(_header_view_csm_menu_activated),
901 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
902 G_CALLBACK (modest_main_window_window_state_event),
905 /* Mail Operation Queue */
907 modest_signal_mgr_connect (priv->sighandlers,
908 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
910 G_CALLBACK (on_queue_changed), self);
912 /* Track changes in the device name */
914 modest_signal_mgr_connect (priv->sighandlers,
915 G_OBJECT(modest_runtime_get_conf ()),
917 G_CALLBACK (on_configuration_key_changed),
920 /* Track account changes. We need to refresh the toolbar */
922 modest_signal_mgr_connect (priv->sighandlers,
923 G_OBJECT (modest_runtime_get_account_store ()),
925 G_CALLBACK (on_account_inserted),
928 modest_signal_mgr_connect (priv->sighandlers,
929 G_OBJECT (modest_runtime_get_account_store ()),
931 G_CALLBACK (on_account_removed),
934 /* We need to refresh the send & receive menu to change the bold
935 * account when the default account changes. */
937 modest_signal_mgr_connect (priv->sighandlers,
938 G_OBJECT (modest_runtime_get_account_mgr ()),
939 "default_account_changed",
940 G_CALLBACK (on_default_account_changed),
945 modest_signal_mgr_connect (priv->sighandlers,
946 G_OBJECT (modest_runtime_get_account_store()),
947 "password_requested",
948 G_CALLBACK (modest_ui_actions_on_password_requested),
953 /** Idle handler, to send/receive at startup .*/
955 sync_accounts_cb (ModestMainWindow *win)
957 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
958 return FALSE; /* Do not call this idle handler again. */
963 on_hildon_program_is_topmost_notify(GObject *self,
964 GParamSpec *propert_param, gpointer user_data)
966 HildonProgram *app = HILDON_PROGRAM (self);
969 ModestWindow* self = MODEST_WINDOW(user_data);
972 /* Note that use of hildon_program_set_can_hibernate()
973 * is generally referred to as "setting the killable flag",
974 * though hibernation does not seem equal to death.
977 if (hildon_program_get_is_topmost (app)) {
978 /* Prevent hibernation when the progam comes to the foreground,
979 * because hibernation should only happen when the application
980 * is in the background: */
981 hildon_program_set_can_hibernate (app, FALSE);
983 /* Allow hibernation if the program has gone to the background: */
985 /* However, prevent hibernation while the settings are being changed: */
986 const gboolean hibernation_prevented =
987 modest_window_mgr_get_hibernation_is_prevented (
988 modest_runtime_get_window_mgr ());
990 if (hibernation_prevented)
991 hildon_program_set_can_hibernate (app, FALSE);
993 /* Allow hibernation, after saving the state: */
994 modest_osso_save_state();
995 hildon_program_set_can_hibernate (app, TRUE);
1002 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1004 GtkWidget *folder_win = (GtkWidget *) user_data;
1005 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1007 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1008 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1009 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
1011 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1013 /* Connect signals */
1014 connect_signals (MODEST_MAIN_WINDOW (self));
1016 /* Set account store */
1017 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1018 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1020 /* Load previous osso state, for instance if we are being restored from
1022 modest_osso_load_state ();
1024 /* Restore window & widget settings */
1025 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1027 /* /\* The UI spec wants us to show a connection dialog when the application is */
1028 /* * started by the user, if there is no connection. */
1029 /* * Do this before showing the account wizard, */
1030 /* * because wizard needs a connection to discover capabilities. *\/ */
1031 /* modest_platform_connect_and_wait (GTK_WINDOW (self), NULL); */
1033 /* Check if accounts exist and show the account wizard if not */
1034 gboolean accounts_exist =
1035 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1037 if (!accounts_exist) {
1038 /* This is necessary to have the main window shown behind the dialog
1039 It's an ugly hack... jschmid */
1040 gtk_widget_show_all(GTK_WIDGET(self));
1041 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1044 GtkAction *send_receive_all;
1045 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1046 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1047 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1048 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1049 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1050 modest_account_mgr_free_account_names (accounts);
1055 modest_main_window_new (void)
1057 ModestMainWindow *self = NULL;
1058 ModestMainWindowPrivate *priv = NULL;
1059 ModestWindowPrivate *parent_priv = NULL;
1060 GtkWidget *folder_win = NULL;
1061 ModestDimmingRulesGroup *menu_rules_group = NULL;
1062 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1063 GtkActionGroup *action_group = NULL;
1064 GError *error = NULL;
1065 ModestConf *conf = NULL;
1066 GtkAction *action = NULL;
1067 GdkPixbuf *window_icon;
1069 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1070 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1071 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1073 parent_priv->ui_manager = gtk_ui_manager_new();
1074 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1076 action_group = gtk_action_group_new ("ModestMainWindowActions");
1077 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1079 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1080 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1082 /* Add common actions */
1083 gtk_action_group_add_actions (action_group,
1084 modest_action_entries,
1085 G_N_ELEMENTS (modest_action_entries),
1088 gtk_action_group_add_actions (action_group,
1089 modest_folder_view_action_entries,
1090 G_N_ELEMENTS (modest_folder_view_action_entries),
1093 gtk_action_group_add_actions (action_group,
1094 modest_header_view_action_entries,
1095 G_N_ELEMENTS (modest_header_view_action_entries),
1098 gtk_action_group_add_toggle_actions (action_group,
1099 modest_toggle_action_entries,
1100 G_N_ELEMENTS (modest_toggle_action_entries),
1103 gtk_action_group_add_toggle_actions (action_group,
1104 modest_main_window_toggle_action_entries,
1105 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1108 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1109 g_object_unref (action_group);
1111 /* Load the UI definition */
1112 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1113 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1114 if (error != NULL) {
1115 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1116 g_error_free (error);
1120 /* Add common dimming rules */
1121 modest_dimming_rules_group_add_rules (menu_rules_group,
1122 modest_main_window_menu_dimming_entries,
1123 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1124 MODEST_WINDOW (self));
1125 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1126 modest_main_window_toolbar_dimming_entries,
1127 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1128 MODEST_WINDOW (self));
1130 /* Insert dimming rules group for this window */
1131 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1132 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1133 g_object_unref (menu_rules_group);
1134 g_object_unref (toolbar_rules_group);
1136 /* Add accelerators */
1137 gtk_window_add_accel_group (GTK_WINDOW (self),
1138 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1140 /* Menubar. Update the state of some toggles */
1141 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1142 conf = modest_runtime_get_conf ();
1143 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1144 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1145 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1146 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1147 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1148 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1149 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1150 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1151 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1152 gtk_widget_show (parent_priv->menubar);
1154 /* Get device name */
1155 modest_maemo_utils_get_device_name ();
1159 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1160 if (!priv->header_view)
1161 g_printerr ("modest: cannot instantiate header view\n");
1162 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1163 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1164 MODEST_CONF_HEADER_VIEW_KEY);
1166 /* Other style properties of header view */
1167 g_object_set (G_OBJECT (priv->header_view),
1168 "rules-hint", FALSE,
1170 /* gtk_widget_show (priv->header_view); */
1173 priv->empty_view = create_empty_view ();
1174 gtk_widget_show (priv->empty_view);
1176 /* Create scrolled windows */
1177 folder_win = gtk_scrolled_window_new (NULL, NULL);
1178 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1179 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1181 GTK_POLICY_AUTOMATIC);
1182 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1184 GTK_POLICY_AUTOMATIC);
1185 /* gtk_widget_show (priv->contents_widget); */
1188 priv->main_paned = gtk_hpaned_new ();
1189 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1190 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1191 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1193 /* putting it all together... */
1194 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1195 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1196 gtk_widget_show (priv->main_vbox);
1198 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1200 HildonProgram *app = hildon_program_get_instance ();
1201 hildon_program_add_window (app, HILDON_WINDOW (self));
1203 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1204 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1206 g_signal_connect (G_OBJECT(self), "show",
1207 G_CALLBACK (modest_main_window_on_show), folder_win);
1209 /* Set window icon */
1210 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1212 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1213 g_object_unref (window_icon);
1216 /* Dont't restore settings here,
1217 * because it requires a gtk_widget_show(),
1218 * and we don't want to do that until later,
1219 * so that the UI is not visible for non-menu D-Bus activation.
1221 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1223 return MODEST_WINDOW(self);
1227 modest_main_window_set_style (ModestMainWindow *self,
1228 ModestMainWindowStyle style)
1230 ModestMainWindowPrivate *priv;
1231 ModestWindowPrivate *parent_priv;
1235 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1237 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1238 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1240 /* no change -> nothing to do */
1241 if (priv->style == style)
1244 /* Get toggle button and update the state if needed. This will
1245 happen only when the set_style is not invoked from the UI,
1246 for example when it's called from widget memory */
1247 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1248 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1249 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1250 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1251 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1252 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1253 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1256 priv->style = style;
1258 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1259 /* Remove main paned */
1260 g_object_ref (priv->main_paned);
1261 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1263 /* Reparent the contents widget to the main vbox */
1264 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1267 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1268 /* Remove header view */
1269 g_object_ref (priv->contents_widget);
1270 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1272 /* Reparent the main paned */
1273 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1274 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1278 g_return_if_reached ();
1281 /* Let header view grab the focus if it's being shown */
1282 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1283 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1285 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1288 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1291 ModestMainWindowStyle
1292 modest_main_window_get_style (ModestMainWindow *self)
1294 ModestMainWindowPrivate *priv;
1296 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1298 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1305 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1307 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1308 ModestWindowPrivate *parent_priv;
1309 ModestWindowMgr *mgr;
1310 gboolean is_fullscreen;
1311 GtkAction *fs_toggle_action;
1314 mgr = modest_runtime_get_window_mgr ();
1316 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1318 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1320 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1321 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1322 if (is_fullscreen != active) {
1323 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1332 set_homogeneous (GtkWidget *widget,
1335 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1336 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1340 modest_main_window_show_toolbar (ModestWindow *self,
1341 gboolean show_toolbar)
1343 ModestMainWindowPrivate *priv = NULL;
1344 ModestWindowPrivate *parent_priv = NULL;
1345 GtkWidget *reply_button = NULL, *menu = NULL;
1346 GtkWidget *placeholder = NULL;
1348 const gchar *action_name;
1351 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1352 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1353 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1355 /* Set optimized view status */
1356 priv->optimized_view = !show_toolbar;
1358 if (!parent_priv->toolbar) {
1359 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1361 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1363 /* Set homogeneous toolbar */
1364 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1365 set_homogeneous, NULL);
1367 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1368 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1369 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1370 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1371 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1372 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1373 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1374 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1376 /* Add ProgressBar (Transfer toolbar) */
1377 priv->progress_bar = modest_progress_bar_widget_new ();
1378 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1379 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1380 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1381 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1382 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1384 /* Connect cancel 'clicked' signal to abort progress mode */
1385 g_signal_connect(priv->cancel_toolitem, "clicked",
1386 G_CALLBACK(cancel_progressbar),
1389 /* Add it to the observers list */
1390 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1393 hildon_window_add_toolbar (HILDON_WINDOW (self),
1394 GTK_TOOLBAR (parent_priv->toolbar));
1396 /* Set reply button tap and hold menu */
1397 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1398 "/ToolBar/ToolbarMessageReply");
1399 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1400 "/ToolbarReplyCSM");
1401 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1403 /* Set send & receive button tap and hold menu */
1404 update_menus (MODEST_MAIN_WINDOW (self));
1408 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1409 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1410 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1412 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1413 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1415 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1419 /* Update also the actions (to update the toggles in the
1420 menus), we have to do it manually because some other window
1421 of the same time could have changed it (remember that the
1422 toolbar fullscreen mode is shared by all the windows of the
1424 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1425 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1427 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1429 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1430 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1435 on_account_inserted (TnyAccountStore *accoust_store,
1436 TnyAccount *account,
1439 update_menus (MODEST_MAIN_WINDOW (user_data));
1443 on_default_account_changed (ModestAccountMgr* mgr,
1446 update_menus (MODEST_MAIN_WINDOW (user_data));
1450 on_account_removed (TnyAccountStore *accoust_store,
1451 TnyAccount *account,
1454 update_menus (MODEST_MAIN_WINDOW (user_data));
1458 * This function manages the key events used to navigate between
1459 * header and folder views (when the window is in split view)
1462 * -------------------------------------------------
1463 * HeaderView GDK_Left Move focus to folder view
1464 * FolderView GDK_Right Move focus to header view
1466 * There is no need to scroll to selected row, the widgets will be the
1467 * responsibles of doing that (probably managing the focus-in event
1470 on_inner_widgets_key_pressed (GtkWidget *widget,
1474 ModestMainWindowPrivate *priv;
1476 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1478 /* Do nothing if we're in SIMPLE style */
1479 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1482 if (MODEST_IS_HEADER_VIEW (widget)) {
1483 if (event->keyval == GDK_Left)
1484 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1485 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1486 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1487 if (selected_headers > 1) {
1488 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1492 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1493 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1499 set_alignment (GtkWidget *widget,
1502 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1503 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1507 create_empty_view (void)
1509 GtkLabel *label = NULL;
1510 GtkWidget *align = NULL;
1512 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1513 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1514 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1515 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1517 return GTK_WIDGET(align);
1521 * Free the returned string
1524 get_gray_color_markup (GtkWidget *styled_widget)
1526 gchar *gray_color_markup;
1528 /* Obtain the secondary text color. We need a realized widget, that's why
1529 we get styled_widget from outside */
1530 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1532 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1533 gray_color_markup = modest_text_utils_get_color_string (&color);
1535 gray_color_markup = g_strdup ("#BBBBBB");
1537 return gray_color_markup;
1541 * Free the returned string
1544 create_device_name_visual_string (const gchar *device_name,
1545 const gchar *gray_color_markup)
1549 /* We have to use "" to fill the %s of the translation. We can
1550 not just use the device name because the device name is
1551 shown in a different color, so it could not be included
1552 into the <span> tag */
1553 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1554 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1564 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1566 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1571 gchar *gray_color_markup;
1573 vbox = gtk_vbox_new (FALSE, 0);
1575 gray_color_markup = get_gray_color_markup (styled_widget);
1577 /* Account description: */
1578 if (modest_tny_account_is_virtual_local_folders (account)
1579 || (modest_tny_account_is_memory_card_account (account))) {
1581 /* Get device name */
1582 gchar *device_name = NULL;
1583 if (modest_tny_account_is_virtual_local_folders (account))
1584 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1585 MODEST_CONF_DEVICE_NAME, NULL);
1587 device_name = g_strdup (tny_account_get_name (account));
1589 label = create_device_name_visual_string ((const gchar *) device_name,
1590 (const gchar *) gray_color_markup);
1591 label_w = gtk_label_new (NULL);
1592 gtk_label_set_markup (GTK_LABEL (label_w), label);
1593 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1594 g_free (device_name);
1597 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1598 gtk_box_pack_start (GTK_BOX (vbox),
1599 gtk_label_new (tny_account_get_name (account)),
1602 /* Other accounts, such as IMAP and POP: */
1607 /* Put proto in uppercase */
1608 proto = g_string_new (tny_account_get_proto (account));
1609 proto = g_string_ascii_up (proto);
1611 /* note: mcen_fi_localroot_description is something like "%s account"
1612 * however, we should display "%s account: %s"... therefore, ugly tmp */
1613 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1614 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1615 gray_color_markup, tmp, tny_account_get_name (account));
1618 label_w = gtk_label_new (NULL);
1619 gtk_label_set_markup (GTK_LABEL (label_w), label);
1620 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1621 g_string_free (proto, TRUE);
1627 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1628 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1629 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1630 modest_tny_folder_store_get_message_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 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1639 _("mcen_fi_rootfolder_folders"),
1640 modest_tny_folder_store_get_folder_count (folder_store));
1641 label_w = gtk_label_new (NULL);
1642 gtk_label_set_markup (GTK_LABEL (label_w), label);
1643 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1647 if (modest_tny_account_is_virtual_local_folders (account)
1648 || modest_tny_account_is_memory_card_account (account)) {
1650 gchar *size = modest_text_utils_get_display_size (
1651 modest_tny_folder_store_get_local_size (folder_store));
1653 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1654 gray_color_markup, _("mcen_fi_rootfolder_size"),
1658 label_w = gtk_label_new (NULL);
1659 gtk_label_set_markup (GTK_LABEL (label_w), label);
1660 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1662 } else if (TNY_IS_ACCOUNT(folder_store)) {
1663 TnyAccount *account = TNY_ACCOUNT(folder_store);
1665 time_t last_updated;
1666 const gchar *last_updated_string;
1667 /* Get last updated from configuration */
1668 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1669 tny_account_get_id (account));
1671 if (last_updated > 0)
1672 last_updated_string = modest_text_utils_get_display_date(last_updated);
1674 last_updated_string = g_strdup (_("mcen_va_never"));
1676 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1677 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1678 label_w = gtk_label_new (NULL);
1679 gtk_label_set_markup (GTK_LABEL (label_w), label);
1680 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1684 g_free (gray_color_markup);
1687 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1693 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1695 ModestMainWindowPrivate *priv = NULL;
1697 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1699 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1701 return priv->send_receive_in_progress;
1705 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1707 GtkAction *action = NULL;
1708 GtkWidget *widget = NULL;
1709 ModestMainWindowPrivate *priv = NULL;
1711 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1712 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1714 priv->send_receive_in_progress = TRUE;
1716 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1717 gtk_action_set_sensitive (action, FALSE);
1718 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1719 /* gtk_action_set_sensitive (action, FALSE); */
1720 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1721 gtk_widget_set_sensitive (widget, FALSE);
1725 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1727 GtkAction *action = NULL;
1728 GtkWidget *widget = NULL;
1729 ModestMainWindowPrivate *priv = NULL;
1731 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1732 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1734 priv->send_receive_in_progress = FALSE;
1736 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1737 gtk_action_set_sensitive (action, TRUE);
1738 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1739 /* gtk_action_set_sensitive (action, TRUE); */
1740 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1741 gtk_widget_set_sensitive (widget, TRUE);
1746 on_msg_count_changed (ModestHeaderView *header_view,
1748 TnyFolderChange *change,
1749 ModestMainWindow *main_window)
1751 gboolean folder_empty = FALSE;
1752 gboolean all_marked_as_deleted = FALSE;
1753 TnyFolderChangeChanged changed;
1754 ModestMainWindowPrivate *priv;
1756 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1757 g_return_if_fail (TNY_IS_FOLDER(folder));
1758 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1759 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1761 changed = tny_folder_change_get_changed (change);
1763 /* If something changes */
1764 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1765 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1767 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1769 /* Check header removed (hide marked as DELETED headers) */
1770 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1771 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1774 /* Check if all messages are marked to be deleted */
1775 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1776 folder_empty = folder_empty || all_marked_as_deleted ;
1778 /* Set contents style of headers view */
1780 modest_main_window_set_contents_style (main_window,
1781 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1782 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1785 modest_main_window_set_contents_style (main_window,
1786 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1792 modest_main_window_set_contents_style (ModestMainWindow *self,
1793 ModestMainWindowContentsStyle style)
1795 ModestMainWindowPrivate *priv;
1797 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1799 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1801 /* We allow to set the same content style than the previously
1802 set if there are details, because it could happen when we're
1803 selecting different accounts consecutively */
1804 if ((priv->contents_style == style) &&
1805 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1808 /* Remove previous child. Delete it if it was an account
1810 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1812 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1813 g_object_ref (content);
1814 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1815 g_object_ref (priv->empty_view);
1816 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1819 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1822 priv->contents_style = style;
1824 switch (priv->contents_style) {
1825 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1826 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1827 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1830 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1832 /* if we're started without main win, there may not be a folder
1833 * view. this fixes a GLib-Critical */
1834 if (priv->folder_view) {
1835 TnyFolderStore *selected_folderstore =
1836 modest_folder_view_get_selected (priv->folder_view);
1837 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1838 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1839 TNY_ACCOUNT (selected_folderstore));
1841 wrap_in_scrolled_window (priv->contents_widget,
1842 priv->details_widget);
1844 g_object_unref (selected_folderstore);
1845 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1850 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1851 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1852 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1856 g_return_if_reached ();
1860 gtk_widget_show_all (priv->contents_widget);
1863 ModestMainWindowContentsStyle
1864 modest_main_window_get_contents_style (ModestMainWindow *self)
1866 ModestMainWindowPrivate *priv;
1868 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1870 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1871 return priv->contents_style;
1876 on_configuration_key_changed (ModestConf* conf,
1878 ModestConfEvent event,
1879 ModestConfNotificationId id,
1880 ModestMainWindow *self)
1882 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1883 TnyAccount *account = NULL;
1885 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1888 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1891 if (priv->folder_view)
1892 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1894 if (account && TNY_IS_ACCOUNT (account) &&
1895 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1898 const gchar *device_name;
1899 gchar *new_text, *gray_color_markup;
1902 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1903 label = GTK_LABEL (children->data);
1905 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1906 MODEST_CONF_DEVICE_NAME, NULL);
1908 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1909 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1911 gtk_label_set_markup (label, new_text);
1912 gtk_widget_show (GTK_WIDGET (label));
1914 g_free (gray_color_markup);
1916 g_list_free (children);
1918 g_object_unref (account);
1922 set_toolbar_transfer_mode (ModestMainWindow *self)
1924 ModestMainWindowPrivate *priv = NULL;
1926 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1928 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1930 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1932 if (priv->progress_bar_timeout > 0) {
1933 g_source_remove (priv->progress_bar_timeout);
1934 priv->progress_bar_timeout = 0;
1941 set_toolbar_mode (ModestMainWindow *self,
1942 ModestToolBarModes mode)
1944 ModestWindowPrivate *parent_priv = NULL;
1945 ModestMainWindowPrivate *priv = NULL;
1946 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1948 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1950 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1951 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1953 /* In case this was called before the toolbar exists: */
1954 if (!(parent_priv->toolbar))
1957 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1959 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1960 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1961 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1963 /* Sets current toolbar mode */
1964 priv->current_toolbar_mode = mode;
1966 /* Checks the dimming rules */
1967 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1969 /* Show and hide toolbar items */
1971 case TOOLBAR_MODE_NORMAL:
1973 gtk_action_set_visible (sort_action, TRUE);
1975 gtk_action_set_visible (refresh_action, TRUE);
1976 if (priv->progress_toolitem) {
1977 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1978 gtk_widget_hide (priv->progress_toolitem);
1980 if (priv->progress_bar)
1981 gtk_widget_hide (priv->progress_bar);
1984 gtk_action_set_visible (cancel_action, FALSE);
1986 /* Hide toolbar if optimized view is enabled */
1987 if (priv->optimized_view)
1988 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1990 case TOOLBAR_MODE_TRANSFER:
1992 gtk_action_set_visible (sort_action, FALSE);
1994 gtk_action_set_visible (refresh_action, FALSE);
1996 gtk_action_set_visible (cancel_action, TRUE);
1997 if (priv->progress_toolitem) {
1998 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1999 gtk_widget_show (priv->progress_toolitem);
2001 if (priv->progress_bar)
2002 gtk_widget_show (priv->progress_bar);
2004 /* Show toolbar if it's hiden (optimized view ) */
2005 if (priv->optimized_view)
2006 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2009 g_return_if_reached ();
2014 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2016 ModestMainWindowPrivate *priv;
2018 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2019 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2021 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2025 cancel_progressbar (GtkToolButton *toolbutton,
2026 ModestMainWindow *self)
2029 ModestMainWindowPrivate *priv;
2031 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2033 /* Get operation observers and cancel all the operations */
2034 tmp = priv->progress_widgets;
2036 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2037 tmp=g_slist_next(tmp);
2042 observers_empty (ModestMainWindow *self)
2045 ModestMainWindowPrivate *priv;
2046 gboolean is_empty = TRUE;
2047 guint pending_ops = 0;
2049 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2050 tmp = priv->progress_widgets;
2052 /* Check all observers */
2053 while (tmp && is_empty) {
2054 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2055 is_empty = pending_ops == 0;
2057 tmp = g_slist_next(tmp);
2065 * Gets the toolbar mode needed for each mail operation. It stores in
2066 * @mode_changed if the toolbar mode has changed or not
2068 static ModestToolBarModes
2069 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2070 ModestMailOperation *mail_op,
2071 gboolean *mode_changed)
2073 ModestToolBarModes mode;
2074 ModestMainWindowPrivate *priv;
2076 *mode_changed = FALSE;
2077 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2079 /* Get toolbar mode from operation id*/
2080 switch (modest_mail_operation_get_type_operation (mail_op)) {
2081 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2082 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2083 mode = TOOLBAR_MODE_TRANSFER;
2084 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2085 *mode_changed = TRUE;
2088 mode = TOOLBAR_MODE_NORMAL;
2094 on_mail_operation_started (ModestMailOperation *mail_op,
2097 ModestMainWindow *self;
2098 ModestMailOperationTypeOperation op_type;
2099 ModestMainWindowPrivate *priv;
2100 ModestToolBarModes mode;
2102 gboolean mode_changed = FALSE;
2103 TnyAccount *account;
2105 self = MODEST_MAIN_WINDOW (user_data);
2106 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2108 /* Do not show progress for receiving operations if the
2109 account is the local account or the MMC one */
2110 op_type = modest_mail_operation_get_type_operation (mail_op);
2111 account = modest_mail_operation_get_account (mail_op);
2112 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2115 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2116 modest_tny_account_is_memory_card_account (account));
2117 g_object_unref (account);
2122 /* Get toolbar mode from operation id*/
2123 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2125 /* Add operation observers and change toolbar if neccessary*/
2126 tmp = priv->progress_widgets;
2127 if (mode == TOOLBAR_MODE_TRANSFER) {
2129 set_toolbar_transfer_mode(self);
2132 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2134 tmp = g_slist_next (tmp);
2140 on_mail_operation_finished (ModestMailOperation *mail_op,
2143 ModestToolBarModes mode;
2144 ModestMailOperationTypeOperation op_type;
2146 ModestMainWindow *self;
2147 gboolean mode_changed;
2148 TnyAccount *account;
2149 ModestMainWindowPrivate *priv;
2151 self = MODEST_MAIN_WINDOW (user_data);
2152 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2154 /* The mail operation was not added to the progress objects if
2155 the account was the local account or the MMC one */
2156 op_type = modest_mail_operation_get_type_operation (mail_op);
2157 account = modest_mail_operation_get_account (mail_op);
2158 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2161 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2162 modest_tny_account_is_memory_card_account (account));
2163 g_object_unref (account);
2168 /* Get toolbar mode from operation id*/
2169 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2171 /* Change toolbar mode */
2172 tmp = priv->progress_widgets;
2173 if (mode == TOOLBAR_MODE_TRANSFER) {
2175 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2177 tmp = g_slist_next (tmp);
2180 /* If no more operations are being observed, NORMAL mode is enabled again */
2181 if (observers_empty (self)) {
2182 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2188 on_queue_changed (ModestMailOperationQueue *queue,
2189 ModestMailOperation *mail_op,
2190 ModestMailOperationQueueNotification type,
2191 ModestMainWindow *self)
2193 ModestMainWindowPrivate *priv;
2195 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2197 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2198 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2200 "operation-started",
2201 G_CALLBACK (on_mail_operation_started),
2203 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2205 "operation-finished",
2206 G_CALLBACK (on_mail_operation_finished),
2208 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2209 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2211 "operation-started");
2212 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2214 "operation-finished");
2219 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2221 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2224 /* Get account data */
2225 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2226 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2228 /* Set the new visible & active account */
2229 if (acc_data && acc_data->store_account) {
2230 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2231 acc_data->store_account->account_name);
2232 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2233 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2234 if (action != NULL) {
2235 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2236 modest_maemo_toggle_action_set_active_block_notify (
2237 GTK_TOGGLE_ACTION (action),
2243 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2248 modest_account_mgr_free_account_data (mgr, acc_data);
2251 /* Make sure that at least one account is "viewed": */
2253 set_at_least_one_account_visible(ModestMainWindow *self)
2255 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2256 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2258 if (!(priv->folder_view)) {
2259 /* It is too early to do this. */
2263 const gchar *active_server_account_name =
2264 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2265 if (!active_server_account_name ||
2266 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2268 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2269 if (first_modest_name) {
2270 set_account_visible (self, first_modest_name);
2271 g_free (first_modest_name);
2277 on_show_account_action_toggled (GtkToggleAction *action,
2280 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2282 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2283 if (gtk_toggle_action_get_active (action))
2284 set_account_visible (self, acc_name);
2288 refresh_account (const gchar *account_name)
2292 /* win must already exists here, obviously */
2293 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2296 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2300 /* If account_name == NULL, we must update all (option All) */
2302 modest_ui_actions_do_send_receive_all (win);
2304 modest_ui_actions_do_send_receive (account_name, win);
2309 on_refresh_account_action_activated (GtkAction *action,
2312 refresh_account ((const gchar*) user_data);
2316 on_send_receive_csm_activated (GtkMenuItem *item,
2319 refresh_account ((const gchar*) user_data);
2323 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2325 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2327 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2333 on_folder_view_focus_in (GtkWidget *widget,
2334 GdkEventFocus *event,
2337 ModestMainWindow *main_window = NULL;
2339 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2340 main_window = MODEST_MAIN_WINDOW (userdata);
2342 /* Update toolbar dimming state */
2343 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2349 on_header_view_focus_in (GtkWidget *widget,
2350 GdkEventFocus *event,
2353 ModestMainWindow *main_window = NULL;
2354 ModestMainWindowPrivate *priv = NULL;
2356 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2357 main_window = MODEST_MAIN_WINDOW (userdata);
2358 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2360 /* Update toolbar dimming state */
2361 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2367 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2368 TnyFolderStore *folder_store,
2370 ModestMainWindow *main_window)
2372 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2373 GtkAction *action = NULL;
2374 gboolean show_reply = TRUE;
2375 gboolean show_forward = TRUE;
2376 gboolean show_cancel_send = FALSE;
2377 gboolean show_clipboard = TRUE;
2378 gboolean show_delete = TRUE;
2381 if (TNY_IS_ACCOUNT (folder_store)) {
2382 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2383 } else if (TNY_IS_FOLDER (folder_store)) {
2384 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2385 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2386 TNY_FOLDER (folder_store));
2387 switch (folder_type) {
2388 case TNY_FOLDER_TYPE_DRAFTS:
2389 show_clipboard = show_delete = TRUE;
2390 show_reply = show_forward = show_cancel_send = FALSE;
2392 case TNY_FOLDER_TYPE_SENT:
2393 show_forward = show_clipboard = show_delete = TRUE;
2394 show_reply = show_cancel_send = FALSE;
2396 case TNY_FOLDER_TYPE_OUTBOX:
2397 show_clipboard = show_delete = show_cancel_send = TRUE;
2398 show_reply = show_forward = FALSE;
2400 case TNY_FOLDER_TYPE_INVALID:
2401 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2404 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2405 show_cancel_send = FALSE;
2408 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2409 show_cancel_send = FALSE;
2414 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2415 gtk_action_set_visible (action, show_reply);
2416 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2417 gtk_action_set_visible (action, show_reply);
2418 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2419 gtk_action_set_visible (action, show_forward);
2420 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2421 gtk_action_set_visible (action, show_cancel_send);
2422 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2423 gtk_action_set_visible (action, show_delete);
2425 /* We finally call to the ui actions handler, after updating properly
2426 * the header view CSM */
2427 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2431 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2432 GtkTreeModel *model,
2433 GtkTreeRowReference *row_reference,
2434 ModestMainWindow *self)
2436 ModestMainWindowPrivate *priv = NULL;
2437 GtkTreeModel *header_model = NULL;
2438 GtkTreePath *path = NULL;
2440 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2441 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2442 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2444 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2445 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2447 /* Do nothing if we changed the folder in the main view */
2448 if (header_model != model)
2451 /* Select the message in the header view */
2452 path = gtk_tree_row_reference_get_path (row_reference);
2453 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2455 gtk_tree_path_free (path);
2461 show_updating_banner (gpointer user_data)
2463 ModestMainWindowPrivate *priv = NULL;
2465 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2467 priv->updating_banner =
2468 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2469 _CS ("ckdg_pb_updating"));
2471 /* Remove timeout */
2472 priv->updating_banner_timeout = 0;
2477 * We use this function to show/hide a progress banner showing
2478 * "Updating" while the header view is being filled. We're not showing
2479 * it unless the update takes more than 2 seconds
2481 * If starting = TRUE then the refresh is starting, otherwise it means
2482 * that is has just finished
2485 on_updating_msg_list (ModestHeaderView *header_view,
2489 ModestMainWindowPrivate *priv = NULL;
2491 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2493 /* Remove old timeout */
2494 if (priv->updating_banner_timeout > 0) {
2495 g_source_remove (priv->updating_banner_timeout);
2496 priv->updating_banner_timeout = 0;
2499 /* Create a new timeout */
2501 priv->updating_banner_timeout =
2502 g_timeout_add (2000, show_updating_banner, user_data);
2504 /* Remove the banner if exists */
2505 if (priv->updating_banner) {
2506 gtk_widget_destroy (priv->updating_banner);
2507 priv->updating_banner = NULL;