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->updating_banner) {
391 gtk_widget_destroy (priv->updating_banner);
392 priv->updating_banner = NULL;
395 if (priv->restore_paned_timeout > 0) {
396 g_source_remove (priv->restore_paned_timeout);
397 priv->restore_paned_timeout = 0;
400 G_OBJECT_CLASS(parent_class)->finalize (obj);
404 modest_main_window_get_child_widget (ModestMainWindow *self,
405 ModestMainWindowWidgetType widget_type)
407 ModestMainWindowPrivate *priv;
410 g_return_val_if_fail (self, NULL);
411 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
414 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
416 switch (widget_type) {
417 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
418 widget = (GtkWidget*)priv->header_view; break;
419 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
420 widget = (GtkWidget*)priv->folder_view; break;
425 return widget ? GTK_WIDGET(widget) : NULL;
429 restore_paned_timeout_handler (gpointer *data)
431 ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
432 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
435 if (GTK_WIDGET_VISIBLE (main_window)) {
436 conf = modest_runtime_get_conf ();
437 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
438 MODEST_CONF_MAIN_PANED_KEY);
445 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
448 ModestMainWindowPrivate *priv;
450 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
452 conf = modest_runtime_get_conf ();
454 modest_widget_memory_restore (conf, G_OBJECT(self),
455 MODEST_CONF_MAIN_WINDOW_KEY);
457 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
458 MODEST_CONF_HEADER_VIEW_KEY);
460 if (do_folder_view_too)
461 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
462 MODEST_CONF_FOLDER_VIEW_KEY);
464 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
465 MODEST_CONF_MAIN_PANED_KEY);
467 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
469 /* We need to force a redraw here in order to get the right
470 position of the horizontal paned separator */
471 gtk_widget_show (GTK_WIDGET (self));
476 save_state (ModestWindow *window)
479 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
480 ModestMainWindowPrivate *priv;
482 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
483 conf = modest_runtime_get_conf ();
485 modest_widget_memory_save (conf,G_OBJECT(self),
486 MODEST_CONF_MAIN_WINDOW_KEY);
487 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
488 MODEST_CONF_MAIN_PANED_KEY);
489 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
490 // MODEST_CONF_HEADER_VIEW_KEY);
491 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
492 MODEST_CONF_FOLDER_VIEW_KEY);
496 compare_display_names (ModestAccountData *a,
497 ModestAccountData *b)
499 return strcmp (a->display_name, b->display_name);
503 update_menus (ModestMainWindow* self)
505 GSList *account_names, *iter, *accounts;
506 ModestMainWindowPrivate *priv;
507 ModestWindowPrivate *parent_priv;
508 ModestAccountMgr *mgr;
509 gint i, num_accounts;
511 gchar *default_account;
512 const gchar *active_account_name;
513 GtkWidget *send_receive_button, *item;
514 GtkAction *send_receive_all = NULL;
517 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
518 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
520 /* Get enabled account IDs */
521 mgr = modest_runtime_get_account_mgr ();
522 account_names = modest_account_mgr_account_names (mgr, TRUE);
523 iter = account_names;
527 ModestAccountData *account_data =
528 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
529 accounts = g_slist_prepend (accounts, account_data);
533 modest_account_mgr_free_account_names (account_names);
534 account_names = NULL;
536 /* Order the list of accounts by its display name */
537 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
538 num_accounts = g_slist_length (accounts);
540 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
541 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
542 gtk_action_set_visible (send_receive_all, num_accounts > 1);
544 /* Delete old send&receive popup items. We can not just do a
545 menu_detach because it does not work well with
547 if (priv->accounts_popup)
548 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
549 (GtkCallback) gtk_widget_destroy, NULL);
551 /* Delete old entries in the View menu. Do not free groups, it
553 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
555 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
556 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
557 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
558 GTK_ACTION_GROUP (groups->data));
561 if (priv->merge_ids) {
562 for (i = 0; i < priv->merge_ids->len; i++)
563 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
564 g_byte_array_free (priv->merge_ids, TRUE);
566 /* We need to call this in order to ensure
567 that the new actions are added in the right
568 order (alphabetical) */
569 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
571 groups = g_list_next (groups);
573 priv->merge_ids = g_byte_array_sized_new (num_accounts);
575 /* Get send receive button */
576 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
577 "/ToolBar/ToolbarSendReceive");
579 /* Create the menu */
580 if (num_accounts > 1) {
581 if (!priv->accounts_popup)
582 priv->accounts_popup = gtk_menu_new ();
583 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
584 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
585 g_signal_connect (G_OBJECT (item),
587 G_CALLBACK (on_send_receive_csm_activated),
589 item = gtk_separator_menu_item_new ();
590 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
593 /* Create a new action group */
594 default_account = modest_account_mgr_get_default_account (mgr);
595 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
597 if (active_account_name == NULL)
599 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
602 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
604 for (i = 0; i < num_accounts; i++) {
605 gchar *display_name = NULL;
606 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
608 if (default_account && account_data->account_name &&
609 !(strcmp (default_account, account_data->account_name) == 0)) {
610 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
611 account_data->display_name);
614 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
615 account_data->display_name);
618 /* Create action and add it to the action group. The
619 action name must be the account name, this way we
620 could know in the handlers the account to show */
621 if(account_data && account_data->account_name) {
622 gchar* item_name, *refresh_action_name;
624 GtkAction *view_account_action, *refresh_account_action;
626 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
627 display_name, NULL, NULL, 0));
628 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
629 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
630 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
632 if (active_account_name) {
633 if (active_account_name && account_data->account_name &&
634 (strcmp (active_account_name, account_data->account_name) == 0)) {
635 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
639 /* Add ui from account data. We allow 2^9-1 account
640 changes in a single execution because we're
641 downcasting the guint to a guint8 in order to use a
642 GByteArray. It should be enough. */
643 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
644 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
645 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
646 gtk_ui_manager_add_ui (parent_priv->ui_manager,
648 "/MenuBar/ViewMenu/ViewMenuAdditions",
650 account_data->account_name,
651 GTK_UI_MANAGER_MENUITEM,
654 /* Connect the action signal "activate" */
655 g_signal_connect_after (G_OBJECT (view_account_action),
657 G_CALLBACK (on_show_account_action_toggled),
660 /* Create the items for the Tools->Send&Receive submenu */
661 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
662 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
663 display_name, NULL, NULL);
664 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
666 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
667 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
668 gtk_ui_manager_add_ui (parent_priv->ui_manager,
670 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
673 GTK_UI_MANAGER_MENUITEM,
675 g_free (refresh_action_name);
677 g_signal_connect_data (G_OBJECT (refresh_account_action),
679 G_CALLBACK (on_refresh_account_action_activated),
680 g_strdup (account_data->account_name),
681 (GClosureNotify) g_free,
684 /* Create item and add it to the send&receive
685 CSM. If there is only one account then
687 if (priv->accounts_popup) {
688 GtkWidget *label = gtk_label_new(NULL);
689 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
690 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
692 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
693 gtk_label_set_markup (GTK_LABEL (label), escaped);
698 gtk_label_set_text (GTK_LABEL (label), display_name);
701 item = gtk_menu_item_new ();
702 gtk_container_add (GTK_CONTAINER (item), label);
704 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
705 g_signal_connect_data (G_OBJECT (item),
707 G_CALLBACK (on_send_receive_csm_activated),
708 g_strdup (account_data->account_name),
709 (GClosureNotify) g_free,
716 g_free (display_name);
719 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
721 /* We cannot do this in the loop above because this relies on the action
722 * group being inserted. This makes the default account appear in bold.
723 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
724 for (i = 0; i < num_accounts; i++) {
725 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
727 if(account_data->account_name && default_account &&
728 strcmp (account_data->account_name, default_account) == 0) {
729 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
731 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
732 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
736 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
737 if (GTK_IS_LABEL (child)) {
738 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
739 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
740 gtk_label_set_markup (GTK_LABEL (child), bold_name);
745 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
746 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
750 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
751 if (GTK_IS_LABEL (child)) {
752 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
753 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
754 gtk_label_set_markup (GTK_LABEL (child), bold_name);
762 modest_account_mgr_free_account_data (mgr, account_data);
765 if (priv->accounts_popup) {
766 /* Mandatory in order to view the menu contents */
767 gtk_widget_show_all (priv->accounts_popup);
769 /* Setup tap_and_hold just if was not done before*/
770 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
771 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
775 g_slist_free (accounts);
776 g_free (default_account);
779 /* Make sure that at least one account is viewed if there are any
780 * accounts, for instance when adding the first account: */
781 set_at_least_one_account_visible (self);
785 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
787 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
788 gtk_scrolled_window_add_with_viewport
789 (GTK_SCROLLED_WINDOW(win), widget);
791 gtk_container_add (GTK_CONTAINER(win),
802 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
804 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
806 GList *oerrsignals = priv->queue_err_signals;
807 while (oerrsignals) {
808 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
809 g_signal_handler_disconnect (esignal->queue, esignal->signal);
810 g_slice_free (QueueErrorSignal, esignal);
811 oerrsignals = g_list_next (oerrsignals);
813 g_list_free (priv->queue_err_signals);
814 priv->queue_err_signals = NULL;
819 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
821 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
824 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
828 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
830 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
832 /* Update visibility */
835 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
839 modest_main_window_disconnect_signals (ModestWindow *self)
841 ModestMainWindowPrivate *priv;
842 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
844 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
845 priv->sighandlers = NULL;
849 connect_signals (ModestMainWindow *self)
851 ModestWindowPrivate *parent_priv;
852 ModestMainWindowPrivate *priv;
855 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
856 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
861 modest_signal_mgr_connect (priv->sighandlers,
862 G_OBJECT(priv->folder_view), "key-press-event",
863 G_CALLBACK(on_inner_widgets_key_pressed), self);
865 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
866 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
868 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
869 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
871 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
872 G_CALLBACK (on_folder_view_focus_in), self);
874 /* Folder view CSM */
875 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
876 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
877 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
878 G_CALLBACK(_folder_view_csm_menu_activated),
882 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
883 G_CALLBACK(modest_ui_actions_on_header_selected), self);
885 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
886 G_CALLBACK(modest_ui_actions_on_header_activated), self);
888 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
889 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
891 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
892 G_CALLBACK(on_inner_widgets_key_pressed), self);
894 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
895 G_CALLBACK(on_msg_count_changed), self);
897 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
898 G_CALLBACK (on_header_view_focus_in), self);
900 modest_signal_mgr_connect (priv->sighandlers,
901 G_OBJECT (priv->header_view),
903 G_CALLBACK (on_updating_msg_list),
906 /* Header view CSM */
907 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
908 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
910 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
911 G_CALLBACK(_header_view_csm_menu_activated),
916 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
917 G_CALLBACK (modest_main_window_window_state_event),
920 /* Mail Operation Queue */
922 modest_signal_mgr_connect (priv->sighandlers,
923 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
925 G_CALLBACK (on_queue_changed), self);
927 /* Track changes in the device name */
929 modest_signal_mgr_connect (priv->sighandlers,
930 G_OBJECT(modest_runtime_get_conf ()),
932 G_CALLBACK (on_configuration_key_changed),
935 /* Track account changes. We need to refresh the toolbar */
937 modest_signal_mgr_connect (priv->sighandlers,
938 G_OBJECT (modest_runtime_get_account_store ()),
940 G_CALLBACK (on_account_inserted),
943 modest_signal_mgr_connect (priv->sighandlers,
944 G_OBJECT (modest_runtime_get_account_store ()),
946 G_CALLBACK (on_account_removed),
949 /* We need to refresh the send & receive menu to change the bold
950 * account when the default account changes. */
952 modest_signal_mgr_connect (priv->sighandlers,
953 G_OBJECT (modest_runtime_get_account_mgr ()),
954 "default_account_changed",
955 G_CALLBACK (on_default_account_changed),
960 modest_signal_mgr_connect (priv->sighandlers,
961 G_OBJECT (modest_runtime_get_account_store()),
962 "password_requested",
963 G_CALLBACK (modest_ui_actions_on_password_requested),
968 /** Idle handler, to send/receive at startup .*/
970 sync_accounts_cb (ModestMainWindow *win)
972 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
973 return FALSE; /* Do not call this idle handler again. */
978 on_hildon_program_is_topmost_notify(GObject *self,
979 GParamSpec *propert_param, gpointer user_data)
981 HildonProgram *app = HILDON_PROGRAM (self);
984 ModestWindow* self = MODEST_WINDOW(user_data);
987 /* Note that use of hildon_program_set_can_hibernate()
988 * is generally referred to as "setting the killable flag",
989 * though hibernation does not seem equal to death.
992 if (hildon_program_get_is_topmost (app)) {
993 /* Prevent hibernation when the progam comes to the foreground,
994 * because hibernation should only happen when the application
995 * is in the background: */
996 hildon_program_set_can_hibernate (app, FALSE);
998 /* Allow hibernation if the program has gone to the background: */
1000 /* However, prevent hibernation while the settings are being changed: */
1001 const gboolean hibernation_prevented =
1002 modest_window_mgr_get_hibernation_is_prevented (
1003 modest_runtime_get_window_mgr ());
1005 if (hibernation_prevented)
1006 hildon_program_set_can_hibernate (app, FALSE);
1008 /* Allow hibernation, after saving the state: */
1009 modest_osso_save_state();
1010 hildon_program_set_can_hibernate (app, TRUE);
1017 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1019 GtkWidget *folder_win = (GtkWidget *) user_data;
1020 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1022 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1023 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1024 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
1026 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1028 /* Connect signals */
1029 connect_signals (MODEST_MAIN_WINDOW (self));
1031 /* Set account store */
1032 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1033 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1035 /* Load previous osso state, for instance if we are being restored from
1037 modest_osso_load_state ();
1039 /* Restore window & widget settings */
1040 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1042 /* /\* The UI spec wants us to show a connection dialog when the application is */
1043 /* * started by the user, if there is no connection. */
1044 /* * Do this before showing the account wizard, */
1045 /* * because wizard needs a connection to discover capabilities. *\/ */
1046 /* modest_platform_connect_and_wait (GTK_WINDOW (self), NULL); */
1048 /* Check if accounts exist and show the account wizard if not */
1049 gboolean accounts_exist =
1050 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1052 if (!accounts_exist) {
1053 /* This is necessary to have the main window shown behind the dialog
1054 It's an ugly hack... jschmid */
1055 gtk_widget_show_all(GTK_WIDGET(self));
1056 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1059 GtkAction *send_receive_all;
1060 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1061 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1062 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1063 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1064 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1065 modest_account_mgr_free_account_names (accounts);
1066 update_menus (MODEST_MAIN_WINDOW (self));
1071 modest_main_window_new (void)
1073 ModestMainWindow *self = NULL;
1074 ModestMainWindowPrivate *priv = NULL;
1075 ModestWindowPrivate *parent_priv = NULL;
1076 GtkWidget *folder_win = NULL;
1077 ModestDimmingRulesGroup *menu_rules_group = NULL;
1078 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1079 GtkActionGroup *action_group = NULL;
1080 GError *error = NULL;
1081 ModestConf *conf = NULL;
1082 GtkAction *action = NULL;
1083 GdkPixbuf *window_icon;
1085 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1086 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1087 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1089 parent_priv->ui_manager = gtk_ui_manager_new();
1090 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1092 action_group = gtk_action_group_new ("ModestMainWindowActions");
1093 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1095 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1096 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1098 /* Add common actions */
1099 gtk_action_group_add_actions (action_group,
1100 modest_action_entries,
1101 G_N_ELEMENTS (modest_action_entries),
1104 gtk_action_group_add_actions (action_group,
1105 modest_folder_view_action_entries,
1106 G_N_ELEMENTS (modest_folder_view_action_entries),
1109 gtk_action_group_add_actions (action_group,
1110 modest_header_view_action_entries,
1111 G_N_ELEMENTS (modest_header_view_action_entries),
1114 gtk_action_group_add_toggle_actions (action_group,
1115 modest_toggle_action_entries,
1116 G_N_ELEMENTS (modest_toggle_action_entries),
1119 gtk_action_group_add_toggle_actions (action_group,
1120 modest_main_window_toggle_action_entries,
1121 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1124 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1125 g_object_unref (action_group);
1127 /* Load the UI definition */
1128 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1129 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1130 if (error != NULL) {
1131 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1132 g_error_free (error);
1136 /* Add common dimming rules */
1137 modest_dimming_rules_group_add_rules (menu_rules_group,
1138 modest_main_window_menu_dimming_entries,
1139 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1140 MODEST_WINDOW (self));
1141 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1142 modest_main_window_toolbar_dimming_entries,
1143 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1144 MODEST_WINDOW (self));
1146 /* Insert dimming rules group for this window */
1147 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1148 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1149 g_object_unref (menu_rules_group);
1150 g_object_unref (toolbar_rules_group);
1152 /* Add accelerators */
1153 gtk_window_add_accel_group (GTK_WINDOW (self),
1154 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1156 /* Menubar. Update the state of some toggles */
1157 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1158 conf = modest_runtime_get_conf ();
1159 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1160 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1161 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1162 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1163 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1164 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1165 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1166 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1167 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1168 gtk_widget_show (parent_priv->menubar);
1170 /* Get device name */
1171 modest_maemo_utils_get_device_name ();
1175 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1176 if (!priv->header_view)
1177 g_printerr ("modest: cannot instantiate header view\n");
1178 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1179 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1180 MODEST_CONF_HEADER_VIEW_KEY);
1182 /* Other style properties of header view */
1183 g_object_set (G_OBJECT (priv->header_view),
1184 "rules-hint", FALSE,
1186 /* gtk_widget_show (priv->header_view); */
1189 priv->empty_view = create_empty_view ();
1190 gtk_widget_show (priv->empty_view);
1192 /* Create scrolled windows */
1193 folder_win = gtk_scrolled_window_new (NULL, NULL);
1194 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1195 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1197 GTK_POLICY_AUTOMATIC);
1198 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1200 GTK_POLICY_AUTOMATIC);
1201 /* gtk_widget_show (priv->contents_widget); */
1204 priv->main_paned = gtk_hpaned_new ();
1205 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1206 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1207 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1209 /* putting it all together... */
1210 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1211 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1212 gtk_widget_show (priv->main_vbox);
1214 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1216 HildonProgram *app = hildon_program_get_instance ();
1217 hildon_program_add_window (app, HILDON_WINDOW (self));
1219 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1220 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1222 g_signal_connect (G_OBJECT(self), "show",
1223 G_CALLBACK (modest_main_window_on_show), folder_win);
1225 /* Set window icon */
1226 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1228 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1229 g_object_unref (window_icon);
1232 /* Dont't restore settings here,
1233 * because it requires a gtk_widget_show(),
1234 * and we don't want to do that until later,
1235 * so that the UI is not visible for non-menu D-Bus activation.
1237 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1239 return MODEST_WINDOW(self);
1243 modest_main_window_set_style (ModestMainWindow *self,
1244 ModestMainWindowStyle style)
1246 ModestMainWindowPrivate *priv;
1247 ModestWindowPrivate *parent_priv;
1251 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1253 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1254 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1256 /* no change -> nothing to do */
1257 if (priv->style == style)
1260 /* Get toggle button and update the state if needed. This will
1261 happen only when the set_style is not invoked from the UI,
1262 for example when it's called from widget memory */
1263 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1264 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1265 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1266 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1267 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1268 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1269 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1272 priv->style = style;
1274 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1275 /* Remove main paned */
1276 g_object_ref (priv->main_paned);
1277 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1279 /* Reparent the contents widget to the main vbox */
1280 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1283 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1284 /* Remove header view */
1285 g_object_ref (priv->contents_widget);
1286 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1288 /* Reparent the main paned */
1289 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1290 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1294 g_return_if_reached ();
1297 /* Let header view grab the focus if it's being shown */
1298 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1299 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1301 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1304 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1307 ModestMainWindowStyle
1308 modest_main_window_get_style (ModestMainWindow *self)
1310 ModestMainWindowPrivate *priv;
1312 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1314 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1321 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1323 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1324 ModestWindowPrivate *parent_priv;
1325 ModestWindowMgr *mgr;
1326 gboolean is_fullscreen;
1327 GtkAction *fs_toggle_action;
1330 mgr = modest_runtime_get_window_mgr ();
1332 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1334 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1336 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1337 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1338 if (is_fullscreen != active) {
1339 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1348 set_homogeneous (GtkWidget *widget,
1351 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1352 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1356 modest_main_window_show_toolbar (ModestWindow *self,
1357 gboolean show_toolbar)
1359 ModestMainWindowPrivate *priv = NULL;
1360 ModestWindowPrivate *parent_priv = NULL;
1361 GtkWidget *reply_button = NULL, *menu = NULL;
1362 GtkWidget *placeholder = NULL;
1364 const gchar *action_name;
1367 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1368 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1369 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1371 /* Set optimized view status */
1372 priv->optimized_view = !show_toolbar;
1374 if (!parent_priv->toolbar) {
1375 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1377 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1379 /* Set homogeneous toolbar */
1380 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1381 set_homogeneous, NULL);
1383 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1384 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1385 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1386 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1387 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1388 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1389 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1390 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1392 /* Add ProgressBar (Transfer toolbar) */
1393 priv->progress_bar = modest_progress_bar_widget_new ();
1394 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1395 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1396 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1397 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1398 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1400 /* Connect cancel 'clicked' signal to abort progress mode */
1401 g_signal_connect(priv->cancel_toolitem, "clicked",
1402 G_CALLBACK(cancel_progressbar),
1405 /* Add it to the observers list */
1406 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1409 hildon_window_add_toolbar (HILDON_WINDOW (self),
1410 GTK_TOOLBAR (parent_priv->toolbar));
1412 /* Set reply button tap and hold menu */
1413 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1414 "/ToolBar/ToolbarMessageReply");
1415 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1416 "/ToolbarReplyCSM");
1417 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1419 /* Set send & receive button tap and hold menu */
1420 update_menus (MODEST_MAIN_WINDOW (self));
1424 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1425 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1426 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1428 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1429 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1431 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1435 /* Update also the actions (to update the toggles in the
1436 menus), we have to do it manually because some other window
1437 of the same time could have changed it (remember that the
1438 toolbar fullscreen mode is shared by all the windows of the
1440 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1441 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1443 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1445 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1446 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1451 on_account_inserted (TnyAccountStore *accoust_store,
1452 TnyAccount *account,
1455 update_menus (MODEST_MAIN_WINDOW (user_data));
1459 on_default_account_changed (ModestAccountMgr* mgr,
1462 update_menus (MODEST_MAIN_WINDOW (user_data));
1466 on_account_removed (TnyAccountStore *accoust_store,
1467 TnyAccount *account,
1470 update_menus (MODEST_MAIN_WINDOW (user_data));
1474 * This function manages the key events used to navigate between
1475 * header and folder views (when the window is in split view)
1478 * -------------------------------------------------
1479 * HeaderView GDK_Left Move focus to folder view
1480 * FolderView GDK_Right Move focus to header view
1482 * There is no need to scroll to selected row, the widgets will be the
1483 * responsibles of doing that (probably managing the focus-in event
1486 on_inner_widgets_key_pressed (GtkWidget *widget,
1490 ModestMainWindowPrivate *priv;
1492 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1494 /* Do nothing if we're in SIMPLE style */
1495 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1498 if (MODEST_IS_HEADER_VIEW (widget)) {
1499 if (event->keyval == GDK_Left)
1500 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1501 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1502 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1503 if (selected_headers > 1) {
1504 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1508 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1509 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1515 set_alignment (GtkWidget *widget,
1518 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1519 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1523 create_empty_view (void)
1525 GtkLabel *label = NULL;
1526 GtkWidget *align = NULL;
1528 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1529 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1530 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1531 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1533 return GTK_WIDGET(align);
1537 * Free the returned string
1540 get_gray_color_markup (GtkWidget *styled_widget)
1542 gchar *gray_color_markup;
1544 /* Obtain the secondary text color. We need a realized widget, that's why
1545 we get styled_widget from outside */
1546 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1548 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1549 gray_color_markup = modest_text_utils_get_color_string (&color);
1551 gray_color_markup = g_strdup ("#BBBBBB");
1553 return gray_color_markup;
1557 * Free the returned string
1560 create_device_name_visual_string (const gchar *device_name,
1561 const gchar *gray_color_markup)
1565 /* We have to use "" to fill the %s of the translation. We can
1566 not just use the device name because the device name is
1567 shown in a different color, so it could not be included
1568 into the <span> tag */
1569 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1570 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1580 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1582 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1587 gchar *gray_color_markup;
1589 vbox = gtk_vbox_new (FALSE, 0);
1591 gray_color_markup = get_gray_color_markup (styled_widget);
1593 /* Account description: */
1594 if (modest_tny_account_is_virtual_local_folders (account)
1595 || (modest_tny_account_is_memory_card_account (account))) {
1597 /* Get device name */
1598 gchar *device_name = NULL;
1599 if (modest_tny_account_is_virtual_local_folders (account))
1600 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1601 MODEST_CONF_DEVICE_NAME, NULL);
1603 device_name = g_strdup (tny_account_get_name (account));
1605 label = create_device_name_visual_string ((const gchar *) device_name,
1606 (const gchar *) gray_color_markup);
1607 label_w = gtk_label_new (NULL);
1608 gtk_label_set_markup (GTK_LABEL (label_w), label);
1609 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1610 g_free (device_name);
1613 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1614 gtk_box_pack_start (GTK_BOX (vbox),
1615 gtk_label_new (tny_account_get_name (account)),
1618 /* Other accounts, such as IMAP and POP: */
1623 /* Put proto in uppercase */
1624 proto = g_string_new (tny_account_get_proto (account));
1625 proto = g_string_ascii_up (proto);
1627 /* note: mcen_fi_localroot_description is something like "%s account"
1628 * however, we should display "%s account: %s"... therefore, ugly tmp */
1629 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1630 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1631 gray_color_markup, tmp, tny_account_get_name (account));
1634 label_w = gtk_label_new (NULL);
1635 gtk_label_set_markup (GTK_LABEL (label_w), label);
1636 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1637 g_string_free (proto, TRUE);
1643 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1644 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1645 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1646 modest_tny_folder_store_get_message_count (folder_store));
1647 label_w = gtk_label_new (NULL);
1648 gtk_label_set_markup (GTK_LABEL (label_w), label);
1649 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1653 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1655 _("mcen_fi_rootfolder_folders"),
1656 modest_tny_folder_store_get_folder_count (folder_store));
1657 label_w = gtk_label_new (NULL);
1658 gtk_label_set_markup (GTK_LABEL (label_w), label);
1659 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1663 if (modest_tny_account_is_virtual_local_folders (account)
1664 || modest_tny_account_is_memory_card_account (account)) {
1666 gchar *size = modest_text_utils_get_display_size (
1667 modest_tny_folder_store_get_local_size (folder_store));
1669 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1670 gray_color_markup, _("mcen_fi_rootfolder_size"),
1674 label_w = gtk_label_new (NULL);
1675 gtk_label_set_markup (GTK_LABEL (label_w), label);
1676 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1678 } else if (TNY_IS_ACCOUNT(folder_store)) {
1679 TnyAccount *account = TNY_ACCOUNT(folder_store);
1681 time_t last_updated;
1682 const gchar *last_updated_string;
1683 /* Get last updated from configuration */
1684 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1685 tny_account_get_id (account));
1687 if (last_updated > 0)
1688 last_updated_string = modest_text_utils_get_display_date(last_updated);
1690 last_updated_string = g_strdup (_("mcen_va_never"));
1692 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1693 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1694 label_w = gtk_label_new (NULL);
1695 gtk_label_set_markup (GTK_LABEL (label_w), label);
1696 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1700 g_free (gray_color_markup);
1703 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1709 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1711 ModestMainWindowPrivate *priv = NULL;
1713 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1715 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1717 return priv->send_receive_in_progress;
1721 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1723 GtkAction *action = NULL;
1724 GtkWidget *widget = NULL;
1725 ModestMainWindowPrivate *priv = NULL;
1727 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1728 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1730 priv->send_receive_in_progress = TRUE;
1732 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1733 gtk_action_set_sensitive (action, FALSE);
1734 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1735 /* gtk_action_set_sensitive (action, FALSE); */
1736 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1737 gtk_widget_set_sensitive (widget, FALSE);
1741 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1743 GtkAction *action = NULL;
1744 GtkWidget *widget = NULL;
1745 ModestMainWindowPrivate *priv = NULL;
1747 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1748 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1750 priv->send_receive_in_progress = FALSE;
1752 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1753 gtk_action_set_sensitive (action, TRUE);
1754 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1755 /* gtk_action_set_sensitive (action, TRUE); */
1756 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1757 gtk_widget_set_sensitive (widget, TRUE);
1762 on_msg_count_changed (ModestHeaderView *header_view,
1764 TnyFolderChange *change,
1765 ModestMainWindow *main_window)
1767 gboolean folder_empty = FALSE;
1768 gboolean all_marked_as_deleted = FALSE;
1769 TnyFolderChangeChanged changed;
1770 ModestMainWindowPrivate *priv;
1772 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1773 g_return_if_fail (TNY_IS_FOLDER(folder));
1774 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1775 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1777 changed = tny_folder_change_get_changed (change);
1779 /* If something changes */
1780 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1781 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1783 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1785 /* Check header removed (hide marked as DELETED headers) */
1786 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1787 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1790 /* Check if all messages are marked to be deleted */
1791 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1792 folder_empty = folder_empty || all_marked_as_deleted ;
1794 /* Set contents style of headers view */
1796 modest_main_window_set_contents_style (main_window,
1797 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1798 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1801 modest_main_window_set_contents_style (main_window,
1802 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1808 modest_main_window_set_contents_style (ModestMainWindow *self,
1809 ModestMainWindowContentsStyle style)
1811 ModestMainWindowPrivate *priv;
1813 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1815 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1817 /* We allow to set the same content style than the previously
1818 set if there are details, because it could happen when we're
1819 selecting different accounts consecutively */
1820 if ((priv->contents_style == style) &&
1821 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1824 /* Remove previous child. Delete it if it was an account
1826 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1828 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1829 g_object_ref (content);
1830 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1831 g_object_ref (priv->empty_view);
1832 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1835 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1838 priv->contents_style = style;
1840 switch (priv->contents_style) {
1841 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1842 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1843 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1846 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1848 /* if we're started without main win, there may not be a folder
1849 * view. this fixes a GLib-Critical */
1850 if (priv->folder_view) {
1851 TnyFolderStore *selected_folderstore =
1852 modest_folder_view_get_selected (priv->folder_view);
1853 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1854 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1855 TNY_ACCOUNT (selected_folderstore));
1857 wrap_in_scrolled_window (priv->contents_widget,
1858 priv->details_widget);
1860 g_object_unref (selected_folderstore);
1861 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1866 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1867 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1868 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1872 g_return_if_reached ();
1876 gtk_widget_show_all (priv->contents_widget);
1879 ModestMainWindowContentsStyle
1880 modest_main_window_get_contents_style (ModestMainWindow *self)
1882 ModestMainWindowPrivate *priv;
1884 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1886 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1887 return priv->contents_style;
1892 on_configuration_key_changed (ModestConf* conf,
1894 ModestConfEvent event,
1895 ModestConfNotificationId id,
1896 ModestMainWindow *self)
1898 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1899 TnyAccount *account = NULL;
1901 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1904 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1907 if (priv->folder_view)
1908 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1910 if (account && TNY_IS_ACCOUNT (account) &&
1911 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1914 const gchar *device_name;
1915 gchar *new_text, *gray_color_markup;
1918 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1919 label = GTK_LABEL (children->data);
1921 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1922 MODEST_CONF_DEVICE_NAME, NULL);
1924 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1925 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1927 gtk_label_set_markup (label, new_text);
1928 gtk_widget_show (GTK_WIDGET (label));
1930 g_free (gray_color_markup);
1932 g_list_free (children);
1934 g_object_unref (account);
1938 set_toolbar_transfer_mode (ModestMainWindow *self)
1940 ModestMainWindowPrivate *priv = NULL;
1942 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1944 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1946 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1948 if (priv->progress_bar_timeout > 0) {
1949 g_source_remove (priv->progress_bar_timeout);
1950 priv->progress_bar_timeout = 0;
1957 set_toolbar_mode (ModestMainWindow *self,
1958 ModestToolBarModes mode)
1960 ModestWindowPrivate *parent_priv = NULL;
1961 ModestMainWindowPrivate *priv = NULL;
1962 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1964 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1966 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1967 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1969 /* In case this was called before the toolbar exists: */
1970 if (!(parent_priv->toolbar))
1973 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1975 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1976 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1977 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1979 /* Sets current toolbar mode */
1980 priv->current_toolbar_mode = mode;
1982 /* Checks the dimming rules */
1983 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1985 /* Show and hide toolbar items */
1987 case TOOLBAR_MODE_NORMAL:
1989 gtk_action_set_visible (sort_action, TRUE);
1991 gtk_action_set_visible (refresh_action, TRUE);
1992 if (priv->progress_toolitem) {
1993 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1994 gtk_widget_hide (priv->progress_toolitem);
1996 if (priv->progress_bar)
1997 gtk_widget_hide (priv->progress_bar);
2000 gtk_action_set_visible (cancel_action, FALSE);
2002 /* Hide toolbar if optimized view is enabled */
2003 if (priv->optimized_view)
2004 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2006 case TOOLBAR_MODE_TRANSFER:
2008 gtk_action_set_visible (sort_action, FALSE);
2010 gtk_action_set_visible (refresh_action, FALSE);
2012 gtk_action_set_visible (cancel_action, TRUE);
2013 if (priv->progress_toolitem) {
2014 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2015 gtk_widget_show (priv->progress_toolitem);
2017 if (priv->progress_bar)
2018 gtk_widget_show (priv->progress_bar);
2020 /* Show toolbar if it's hiden (optimized view ) */
2021 if (priv->optimized_view)
2022 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2025 g_return_if_reached ();
2030 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2032 ModestMainWindowPrivate *priv;
2034 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2035 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2037 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2041 cancel_progressbar (GtkToolButton *toolbutton,
2042 ModestMainWindow *self)
2045 ModestMainWindowPrivate *priv;
2047 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2049 /* Get operation observers and cancel all the operations */
2050 tmp = priv->progress_widgets;
2052 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2053 tmp=g_slist_next(tmp);
2058 observers_empty (ModestMainWindow *self)
2061 ModestMainWindowPrivate *priv;
2062 gboolean is_empty = TRUE;
2063 guint pending_ops = 0;
2065 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2066 tmp = priv->progress_widgets;
2068 /* Check all observers */
2069 while (tmp && is_empty) {
2070 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2071 is_empty = pending_ops == 0;
2073 tmp = g_slist_next(tmp);
2081 * Gets the toolbar mode needed for each mail operation. It stores in
2082 * @mode_changed if the toolbar mode has changed or not
2084 static ModestToolBarModes
2085 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2086 ModestMailOperation *mail_op,
2087 gboolean *mode_changed)
2089 ModestToolBarModes mode;
2090 ModestMainWindowPrivate *priv;
2092 *mode_changed = FALSE;
2093 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2095 /* Get toolbar mode from operation id*/
2096 switch (modest_mail_operation_get_type_operation (mail_op)) {
2097 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2098 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2099 mode = TOOLBAR_MODE_TRANSFER;
2100 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2101 *mode_changed = TRUE;
2104 mode = TOOLBAR_MODE_NORMAL;
2110 on_mail_operation_started (ModestMailOperation *mail_op,
2113 ModestMainWindow *self;
2114 ModestMailOperationTypeOperation op_type;
2115 ModestMainWindowPrivate *priv;
2116 ModestToolBarModes mode;
2118 gboolean mode_changed = FALSE;
2119 TnyAccount *account;
2121 self = MODEST_MAIN_WINDOW (user_data);
2122 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2124 /* Do not show progress for receiving operations if the
2125 account is the local account or the MMC one */
2126 op_type = modest_mail_operation_get_type_operation (mail_op);
2127 account = modest_mail_operation_get_account (mail_op);
2128 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2131 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2132 modest_tny_account_is_memory_card_account (account));
2133 g_object_unref (account);
2138 /* Get toolbar mode from operation id*/
2139 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2141 /* Add operation observers and change toolbar if neccessary*/
2142 tmp = priv->progress_widgets;
2143 if (mode == TOOLBAR_MODE_TRANSFER) {
2145 set_toolbar_transfer_mode(self);
2148 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2150 tmp = g_slist_next (tmp);
2156 on_mail_operation_finished (ModestMailOperation *mail_op,
2159 ModestToolBarModes mode;
2160 ModestMailOperationTypeOperation op_type;
2162 ModestMainWindow *self;
2163 gboolean mode_changed;
2164 TnyAccount *account;
2165 ModestMainWindowPrivate *priv;
2167 self = MODEST_MAIN_WINDOW (user_data);
2168 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2170 /* The mail operation was not added to the progress objects if
2171 the account was the local account or the MMC one */
2172 op_type = modest_mail_operation_get_type_operation (mail_op);
2173 account = modest_mail_operation_get_account (mail_op);
2174 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2177 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2178 modest_tny_account_is_memory_card_account (account));
2179 g_object_unref (account);
2184 /* Get toolbar mode from operation id*/
2185 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2187 /* Change toolbar mode */
2188 tmp = priv->progress_widgets;
2189 if (mode == TOOLBAR_MODE_TRANSFER) {
2191 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2193 tmp = g_slist_next (tmp);
2196 /* If no more operations are being observed, NORMAL mode is enabled again */
2197 if (observers_empty (self)) {
2198 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2204 on_queue_changed (ModestMailOperationQueue *queue,
2205 ModestMailOperation *mail_op,
2206 ModestMailOperationQueueNotification type,
2207 ModestMainWindow *self)
2209 ModestMainWindowPrivate *priv;
2211 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2213 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2214 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2216 "operation-started",
2217 G_CALLBACK (on_mail_operation_started),
2219 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2221 "operation-finished",
2222 G_CALLBACK (on_mail_operation_finished),
2224 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2225 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2227 "operation-started");
2228 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2230 "operation-finished");
2235 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2237 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2240 /* Get account data */
2241 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2242 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2244 /* Set the new visible & active account */
2245 if (acc_data && acc_data->store_account) {
2246 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2247 acc_data->store_account->account_name);
2248 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2249 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2250 if (action != NULL) {
2251 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2252 modest_maemo_toggle_action_set_active_block_notify (
2253 GTK_TOGGLE_ACTION (action),
2259 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2264 modest_account_mgr_free_account_data (mgr, acc_data);
2267 /* Make sure that at least one account is "viewed": */
2269 set_at_least_one_account_visible(ModestMainWindow *self)
2271 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2272 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2274 if (!(priv->folder_view)) {
2275 /* It is too early to do this. */
2279 const gchar *active_server_account_name =
2280 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2282 if (!active_server_account_name ||
2283 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2285 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2286 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2287 if (default_modest_name) {
2288 set_account_visible (self, default_modest_name);
2289 } else if (first_modest_name) {
2290 set_account_visible (self, first_modest_name);
2292 g_free (first_modest_name);
2293 g_free (default_modest_name);
2298 on_show_account_action_toggled (GtkToggleAction *action,
2301 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2303 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2304 if (gtk_toggle_action_get_active (action))
2305 set_account_visible (self, acc_name);
2309 refresh_account (const gchar *account_name)
2313 /* win must already exists here, obviously */
2314 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2317 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2321 /* If account_name == NULL, we must update all (option All) */
2323 modest_ui_actions_do_send_receive_all (win);
2325 modest_ui_actions_do_send_receive (account_name, win);
2330 on_refresh_account_action_activated (GtkAction *action,
2333 refresh_account ((const gchar*) user_data);
2337 on_send_receive_csm_activated (GtkMenuItem *item,
2340 refresh_account ((const gchar*) user_data);
2344 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2346 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2348 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2354 on_folder_view_focus_in (GtkWidget *widget,
2355 GdkEventFocus *event,
2358 ModestMainWindow *main_window = NULL;
2360 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2361 main_window = MODEST_MAIN_WINDOW (userdata);
2363 /* Update toolbar dimming state */
2364 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2370 on_header_view_focus_in (GtkWidget *widget,
2371 GdkEventFocus *event,
2374 ModestMainWindow *main_window = NULL;
2375 ModestMainWindowPrivate *priv = NULL;
2377 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2378 main_window = MODEST_MAIN_WINDOW (userdata);
2379 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2381 /* Update toolbar dimming state */
2382 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2388 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2389 TnyFolderStore *folder_store,
2391 ModestMainWindow *main_window)
2393 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2394 GtkAction *action = NULL;
2395 gboolean show_reply = TRUE;
2396 gboolean show_forward = TRUE;
2397 gboolean show_cancel_send = FALSE;
2398 gboolean show_clipboard = TRUE;
2399 gboolean show_delete = TRUE;
2402 if (TNY_IS_ACCOUNT (folder_store)) {
2403 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2404 } else if (TNY_IS_FOLDER (folder_store)) {
2405 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2406 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2407 TNY_FOLDER (folder_store));
2408 switch (folder_type) {
2409 case TNY_FOLDER_TYPE_DRAFTS:
2410 show_clipboard = show_delete = TRUE;
2411 show_reply = show_forward = show_cancel_send = FALSE;
2413 case TNY_FOLDER_TYPE_SENT:
2414 show_forward = show_clipboard = show_delete = TRUE;
2415 show_reply = show_cancel_send = FALSE;
2417 case TNY_FOLDER_TYPE_OUTBOX:
2418 show_clipboard = show_delete = show_cancel_send = TRUE;
2419 show_reply = show_forward = FALSE;
2421 case TNY_FOLDER_TYPE_INVALID:
2422 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2425 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2426 show_cancel_send = FALSE;
2429 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2430 show_cancel_send = FALSE;
2435 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2436 gtk_action_set_visible (action, show_reply);
2437 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2438 gtk_action_set_visible (action, show_reply);
2439 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2440 gtk_action_set_visible (action, show_forward);
2441 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2442 gtk_action_set_visible (action, show_cancel_send);
2443 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2444 gtk_action_set_visible (action, show_delete);
2446 /* We finally call to the ui actions handler, after updating properly
2447 * the header view CSM */
2448 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2452 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2453 GtkTreeModel *model,
2454 GtkTreeRowReference *row_reference,
2455 ModestMainWindow *self)
2457 ModestMainWindowPrivate *priv = NULL;
2458 GtkTreeModel *header_model = NULL;
2459 GtkTreePath *path = NULL;
2461 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2462 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2463 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2465 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2466 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2468 /* Do nothing if we changed the folder in the main view */
2469 if (header_model != model)
2472 /* Select the message in the header view */
2473 path = gtk_tree_row_reference_get_path (row_reference);
2474 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2476 gtk_tree_path_free (path);
2482 show_updating_banner (gpointer user_data)
2484 ModestMainWindowPrivate *priv = NULL;
2486 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2488 if (priv->updating_banner == NULL) {
2489 priv->updating_banner =
2490 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2491 _CS ("ckdg_pb_updating"));
2494 /* Remove timeout */
2495 priv->updating_banner_timeout = 0;
2500 * We use this function to show/hide a progress banner showing
2501 * "Updating" while the header view is being filled. We're not showing
2502 * it unless the update takes more than 2 seconds
2504 * If starting = TRUE then the refresh is starting, otherwise it means
2505 * that is has just finished
2508 on_updating_msg_list (ModestHeaderView *header_view,
2512 ModestMainWindowPrivate *priv = NULL;
2514 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2516 /* Remove old timeout */
2517 if (priv->updating_banner_timeout > 0) {
2518 g_source_remove (priv->updating_banner_timeout);
2519 priv->updating_banner_timeout = 0;
2522 /* Create a new timeout */
2524 priv->updating_banner_timeout =
2525 g_timeout_add (2000, show_updating_banner, user_data);
2527 /* Remove the banner if exists */
2528 if (priv->updating_banner) {
2529 gtk_widget_destroy (priv->updating_banner);
2530 priv->updating_banner = NULL;