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 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 /* Timeouts are outside the main lock */
436 gdk_threads_enter ();
437 if (GTK_WIDGET_VISIBLE (main_window)) {
438 conf = modest_runtime_get_conf ();
439 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
440 MODEST_CONF_MAIN_PANED_KEY);
442 gdk_threads_leave ();
449 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
452 ModestMainWindowPrivate *priv;
454 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
456 conf = modest_runtime_get_conf ();
458 modest_widget_memory_restore (conf, G_OBJECT(self),
459 MODEST_CONF_MAIN_WINDOW_KEY);
461 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
462 MODEST_CONF_HEADER_VIEW_KEY);
464 if (do_folder_view_too)
465 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
466 MODEST_CONF_FOLDER_VIEW_KEY);
468 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
469 MODEST_CONF_MAIN_PANED_KEY);
471 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
473 /* We need to force a redraw here in order to get the right
474 position of the horizontal paned separator */
475 gtk_widget_show (GTK_WIDGET (self));
480 save_state (ModestWindow *window)
483 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
484 ModestMainWindowPrivate *priv;
486 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
487 conf = modest_runtime_get_conf ();
489 modest_widget_memory_save (conf,G_OBJECT(self),
490 MODEST_CONF_MAIN_WINDOW_KEY);
491 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
492 MODEST_CONF_MAIN_PANED_KEY);
493 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
494 // MODEST_CONF_HEADER_VIEW_KEY);
495 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
496 MODEST_CONF_FOLDER_VIEW_KEY);
500 compare_display_names (ModestAccountData *a,
501 ModestAccountData *b)
503 return strcmp (a->display_name, b->display_name);
507 update_menus (ModestMainWindow* self)
509 GSList *account_names, *iter, *accounts;
510 ModestMainWindowPrivate *priv;
511 ModestWindowPrivate *parent_priv;
512 ModestAccountMgr *mgr;
513 gint i, num_accounts;
515 gchar *default_account;
516 const gchar *active_account_name;
517 GtkWidget *send_receive_button, *item;
518 GtkAction *send_receive_all = NULL;
521 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
522 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
524 /* Get enabled account IDs */
525 mgr = modest_runtime_get_account_mgr ();
526 account_names = modest_account_mgr_account_names (mgr, TRUE);
527 iter = account_names;
531 ModestAccountData *account_data =
532 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
533 accounts = g_slist_prepend (accounts, account_data);
537 modest_account_mgr_free_account_names (account_names);
538 account_names = NULL;
540 /* Order the list of accounts by its display name */
541 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
542 num_accounts = g_slist_length (accounts);
544 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
545 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
546 gtk_action_set_visible (send_receive_all, num_accounts > 0);
548 /* Delete old send&receive popup items. We can not just do a
549 menu_detach because it does not work well with
551 if (priv->accounts_popup)
552 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
553 (GtkCallback) gtk_widget_destroy, NULL);
555 /* Delete old entries in the View menu. Do not free groups, it
557 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
559 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
560 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
561 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
562 GTK_ACTION_GROUP (groups->data));
565 if (priv->merge_ids) {
566 for (i = 0; i < priv->merge_ids->len; i++)
567 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
568 g_byte_array_free (priv->merge_ids, TRUE);
570 /* We need to call this in order to ensure
571 that the new actions are added in the right
572 order (alphabetical) */
573 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
575 groups = g_list_next (groups);
577 priv->merge_ids = g_byte_array_sized_new (num_accounts);
579 /* Get send receive button */
580 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
581 "/ToolBar/ToolbarSendReceive");
583 /* Create the menu */
584 if (num_accounts > 1) {
585 if (!priv->accounts_popup)
586 priv->accounts_popup = gtk_menu_new ();
587 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
588 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
589 g_signal_connect (G_OBJECT (item),
591 G_CALLBACK (on_send_receive_csm_activated),
593 item = gtk_separator_menu_item_new ();
594 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
597 /* Create a new action group */
598 default_account = modest_account_mgr_get_default_account (mgr);
599 active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
601 if (!active_account_name)
602 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
604 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
606 for (i = 0; i < num_accounts; i++) {
607 gchar *display_name = NULL;
608 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
611 g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
615 if (default_account && account_data->account_name &&
616 !(strcmp (default_account, account_data->account_name) == 0)) {
617 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
618 account_data->display_name);
620 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
621 account_data->display_name);
624 /* Create action and add it to the action group. The
625 action name must be the account name, this way we
626 could know in the handlers the account to show */
627 if (account_data && account_data->account_name) {
628 gchar* item_name, *refresh_action_name;
630 GtkAction *view_account_action, *refresh_account_action;
632 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
633 display_name, NULL, NULL, 0));
634 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
635 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
636 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
638 if (active_account_name) {
639 if (active_account_name && account_data->account_name &&
640 (strcmp (active_account_name, account_data->account_name) == 0)) {
641 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
645 /* Add ui from account data. We allow 2^9-1 account
646 changes in a single execution because we're
647 downcasting the guint to a guint8 in order to use a
648 GByteArray. It should be enough. */
649 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
650 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
651 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
652 gtk_ui_manager_add_ui (parent_priv->ui_manager,
654 "/MenuBar/ViewMenu/ViewMenuAdditions",
656 account_data->account_name,
657 GTK_UI_MANAGER_MENUITEM,
660 /* Connect the action signal "activate" */
661 g_signal_connect_after (G_OBJECT (view_account_action),
663 G_CALLBACK (on_show_account_action_toggled),
666 /* Create the items for the Tools->Send&Receive submenu */
667 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
668 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
669 display_name, NULL, NULL);
670 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
672 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
673 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
674 gtk_ui_manager_add_ui (parent_priv->ui_manager,
676 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
679 GTK_UI_MANAGER_MENUITEM,
681 g_free (refresh_action_name);
683 g_signal_connect_data (G_OBJECT (refresh_account_action),
685 G_CALLBACK (on_refresh_account_action_activated),
686 g_strdup (account_data->account_name),
687 (GClosureNotify) g_free,
690 /* Create item and add it to the send&receive
691 CSM. If there is only one account then
693 if (priv->accounts_popup) {
694 GtkWidget *label = gtk_label_new(NULL);
695 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
696 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
698 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
699 gtk_label_set_markup (GTK_LABEL (label), escaped);
704 gtk_label_set_text (GTK_LABEL (label), display_name);
707 item = gtk_menu_item_new ();
708 gtk_container_add (GTK_CONTAINER (item), label);
710 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
711 g_signal_connect_data (G_OBJECT (item),
713 G_CALLBACK (on_send_receive_csm_activated),
714 g_strdup (account_data->account_name),
715 (GClosureNotify) g_free,
722 g_free (display_name);
725 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
727 /* We cannot do this in the loop above because this relies on the action
728 * group being inserted. This makes the default account appear in bold.
729 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
730 for (i = 0; i < num_accounts; i++) {
731 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
733 if(account_data->account_name && default_account &&
734 strcmp (account_data->account_name, default_account) == 0) {
735 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
737 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
738 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
742 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
743 if (GTK_IS_LABEL (child)) {
744 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
745 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
746 gtk_label_set_markup (GTK_LABEL (child), bold_name);
751 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
752 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
756 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
757 if (GTK_IS_LABEL (child)) {
758 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
759 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
760 gtk_label_set_markup (GTK_LABEL (child), bold_name);
768 modest_account_mgr_free_account_data (mgr, account_data);
771 if (priv->accounts_popup) {
772 /* Mandatory in order to view the menu contents */
773 gtk_widget_show_all (priv->accounts_popup);
775 /* Setup tap_and_hold just if was not done before*/
776 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
777 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
781 g_slist_free (accounts);
782 g_free (default_account);
785 /* Make sure that at least one account is viewed if there are any
786 * accounts, for instance when adding the first account: */
787 set_at_least_one_account_visible (self);
791 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
793 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
794 gtk_scrolled_window_add_with_viewport
795 (GTK_SCROLLED_WINDOW(win), widget);
797 gtk_container_add (GTK_CONTAINER(win),
808 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
810 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
812 GList *oerrsignals = priv->queue_err_signals;
813 while (oerrsignals) {
814 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
815 g_signal_handler_disconnect (esignal->queue, esignal->signal);
816 g_slice_free (QueueErrorSignal, esignal);
817 oerrsignals = g_list_next (oerrsignals);
819 g_list_free (priv->queue_err_signals);
820 priv->queue_err_signals = NULL;
825 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
827 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
830 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
834 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
836 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
838 /* Update visibility */
841 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
845 modest_main_window_disconnect_signals (ModestWindow *self)
847 ModestMainWindowPrivate *priv;
848 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
850 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
851 priv->sighandlers = NULL;
855 connect_signals (ModestMainWindow *self)
857 ModestWindowPrivate *parent_priv;
858 ModestMainWindowPrivate *priv;
861 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
862 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
867 modest_signal_mgr_connect (priv->sighandlers,
868 G_OBJECT(priv->folder_view), "key-press-event",
869 G_CALLBACK(on_inner_widgets_key_pressed), self);
871 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view),
872 "folder_selection_changed",
873 G_CALLBACK (on_folder_selection_changed),
876 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view),
877 "folder-display-name-changed",
878 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed),
881 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view),
883 G_CALLBACK (on_folder_view_focus_in),
886 /* Folder view CSM */
887 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
888 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
889 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
890 G_CALLBACK(_folder_view_csm_menu_activated),
894 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
895 G_CALLBACK(modest_ui_actions_on_header_selected), self);
897 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
898 G_CALLBACK(modest_ui_actions_on_header_activated), self);
900 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
901 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
903 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
904 G_CALLBACK(on_inner_widgets_key_pressed), self);
906 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
907 G_CALLBACK(on_msg_count_changed), self);
909 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
910 G_CALLBACK (on_header_view_focus_in), self);
912 modest_signal_mgr_connect (priv->sighandlers,
913 G_OBJECT (priv->header_view),
915 G_CALLBACK (on_updating_msg_list),
918 /* Header view CSM */
919 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
920 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
922 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
923 G_CALLBACK(_header_view_csm_menu_activated),
928 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
929 G_CALLBACK (modest_main_window_window_state_event),
932 /* Mail Operation Queue */
934 modest_signal_mgr_connect (priv->sighandlers,
935 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
937 G_CALLBACK (on_queue_changed), self);
939 /* Track changes in the device name */
941 modest_signal_mgr_connect (priv->sighandlers,
942 G_OBJECT(modest_runtime_get_conf ()),
944 G_CALLBACK (on_configuration_key_changed),
947 /* Track account changes. We need to refresh the toolbar */
949 modest_signal_mgr_connect (priv->sighandlers,
950 G_OBJECT (modest_runtime_get_account_store ()),
952 G_CALLBACK (on_account_inserted),
955 modest_signal_mgr_connect (priv->sighandlers,
956 G_OBJECT (modest_runtime_get_account_store ()),
958 G_CALLBACK (on_account_removed),
961 /* We need to refresh the send & receive menu to change the bold
962 * account when the default account changes. */
964 modest_signal_mgr_connect (priv->sighandlers,
965 G_OBJECT (modest_runtime_get_account_mgr ()),
966 "default_account_changed",
967 G_CALLBACK (on_default_account_changed),
972 modest_signal_mgr_connect (priv->sighandlers,
973 G_OBJECT (modest_runtime_get_account_store()),
974 "password_requested",
975 G_CALLBACK (modest_ui_actions_on_password_requested),
980 /** Idle handler, to send/receive at startup .*/
982 sync_accounts_cb (ModestMainWindow *win)
984 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
985 return FALSE; /* Do not call this idle handler again. */
990 on_hildon_program_is_topmost_notify(GObject *self,
991 GParamSpec *propert_param, gpointer user_data)
993 HildonProgram *app = HILDON_PROGRAM (self);
996 ModestWindow* self = MODEST_WINDOW(user_data);
999 /* Note that use of hildon_program_set_can_hibernate()
1000 * is generally referred to as "setting the killable flag",
1001 * though hibernation does not seem equal to death.
1004 if (hildon_program_get_is_topmost (app)) {
1005 /* Prevent hibernation when the progam comes to the foreground,
1006 * because hibernation should only happen when the application
1007 * is in the background: */
1008 hildon_program_set_can_hibernate (app, FALSE);
1010 /* Allow hibernation if the program has gone to the background: */
1012 /* However, prevent hibernation while the settings are being changed: */
1013 const gboolean hibernation_prevented =
1014 modest_window_mgr_get_hibernation_is_prevented (
1015 modest_runtime_get_window_mgr ());
1017 if (hibernation_prevented)
1018 hildon_program_set_can_hibernate (app, FALSE);
1020 /* Allow hibernation, after saving the state: */
1021 modest_osso_save_state();
1022 hildon_program_set_can_hibernate (app, TRUE);
1029 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1031 GtkWidget *folder_win = (GtkWidget *) user_data;
1032 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1034 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1035 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1037 gtk_widget_show (GTK_WIDGET (priv->folder_view));
1039 /* Connect signals */
1040 connect_signals (MODEST_MAIN_WINDOW (self));
1042 /* Set account store */
1043 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1044 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1046 /* Load previous osso state, for instance if we are being restored from
1048 modest_osso_load_state ();
1050 /* Restore window & widget settings */
1051 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1053 /* Check if accounts exist and show the account wizard if not */
1054 gboolean accounts_exist =
1055 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1057 if (!accounts_exist) {
1058 /* This is necessary to have the main window shown behind the dialog
1059 It's an ugly hack... jschmid */
1060 gtk_widget_show_all(GTK_WIDGET(self));
1061 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1064 GtkAction *send_receive_all;
1065 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1066 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1067 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1068 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1069 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1070 modest_account_mgr_free_account_names (accounts);
1071 update_menus (MODEST_MAIN_WINDOW (self));
1076 modest_main_window_new (void)
1078 ModestMainWindow *self = NULL;
1079 ModestMainWindowPrivate *priv = NULL;
1080 ModestWindowPrivate *parent_priv = NULL;
1081 GtkWidget *folder_win = NULL;
1082 ModestDimmingRulesGroup *menu_rules_group = NULL;
1083 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1084 GtkActionGroup *action_group = NULL;
1085 GError *error = NULL;
1086 ModestConf *conf = NULL;
1087 GtkAction *action = NULL;
1088 GdkPixbuf *window_icon;
1090 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1091 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1092 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1094 parent_priv->ui_manager = gtk_ui_manager_new();
1095 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1097 action_group = gtk_action_group_new ("ModestMainWindowActions");
1098 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1100 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1101 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1103 /* Add common actions */
1104 gtk_action_group_add_actions (action_group,
1105 modest_action_entries,
1106 G_N_ELEMENTS (modest_action_entries),
1109 gtk_action_group_add_actions (action_group,
1110 modest_folder_view_action_entries,
1111 G_N_ELEMENTS (modest_folder_view_action_entries),
1114 gtk_action_group_add_actions (action_group,
1115 modest_header_view_action_entries,
1116 G_N_ELEMENTS (modest_header_view_action_entries),
1119 gtk_action_group_add_toggle_actions (action_group,
1120 modest_toggle_action_entries,
1121 G_N_ELEMENTS (modest_toggle_action_entries),
1124 gtk_action_group_add_toggle_actions (action_group,
1125 modest_main_window_toggle_action_entries,
1126 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1129 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1130 g_object_unref (action_group);
1132 /* Load the UI definition */
1133 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1134 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1135 if (error != NULL) {
1136 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1137 g_error_free (error);
1141 /* Add common dimming rules */
1142 modest_dimming_rules_group_add_rules (menu_rules_group,
1143 modest_main_window_menu_dimming_entries,
1144 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1145 MODEST_WINDOW (self));
1146 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1147 modest_main_window_toolbar_dimming_entries,
1148 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1149 MODEST_WINDOW (self));
1151 /* Insert dimming rules group for this window */
1152 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1153 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1154 g_object_unref (menu_rules_group);
1155 g_object_unref (toolbar_rules_group);
1157 /* Add accelerators */
1158 gtk_window_add_accel_group (GTK_WINDOW (self),
1159 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1161 /* Menubar. Update the state of some toggles */
1162 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1163 conf = modest_runtime_get_conf ();
1164 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1165 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1166 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1167 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1168 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1169 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1170 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1171 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1172 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1173 gtk_widget_show (parent_priv->menubar);
1175 /* Get device name */
1176 modest_maemo_utils_get_device_name ();
1180 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1181 if (!priv->header_view)
1182 g_printerr ("modest: cannot instantiate header view\n");
1183 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1184 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1185 MODEST_CONF_HEADER_VIEW_KEY);
1187 /* Other style properties of header view */
1188 g_object_set (G_OBJECT (priv->header_view),
1189 "rules-hint", FALSE,
1191 /* gtk_widget_show (priv->header_view); */
1194 priv->empty_view = create_empty_view ();
1195 gtk_widget_show (priv->empty_view);
1197 /* Create scrolled windows */
1198 folder_win = gtk_scrolled_window_new (NULL, NULL);
1199 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1200 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1202 GTK_POLICY_AUTOMATIC);
1203 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1205 GTK_POLICY_AUTOMATIC);
1206 /* gtk_widget_show (priv->contents_widget); */
1209 priv->main_paned = gtk_hpaned_new ();
1210 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1211 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1212 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1214 /* putting it all together... */
1215 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1216 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1217 gtk_widget_show (priv->main_vbox);
1219 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1221 HildonProgram *app = hildon_program_get_instance ();
1222 hildon_program_add_window (app, HILDON_WINDOW (self));
1224 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1225 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1227 g_signal_connect (G_OBJECT(self), "show",
1228 G_CALLBACK (modest_main_window_on_show), folder_win);
1230 /* Set window icon */
1231 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1233 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1234 g_object_unref (window_icon);
1237 /* Dont't restore settings here,
1238 * because it requires a gtk_widget_show(),
1239 * and we don't want to do that until later,
1240 * so that the UI is not visible for non-menu D-Bus activation.
1242 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1244 return MODEST_WINDOW(self);
1248 modest_main_window_set_style (ModestMainWindow *self,
1249 ModestMainWindowStyle style)
1251 ModestMainWindowPrivate *priv;
1252 ModestWindowPrivate *parent_priv;
1256 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1258 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1259 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1261 /* no change -> nothing to do */
1262 if (priv->style == style)
1265 /* Get toggle button and update the state if needed. This will
1266 happen only when the set_style is not invoked from the UI,
1267 for example when it's called from widget memory */
1268 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1269 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1270 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1271 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1272 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1273 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1274 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1277 priv->style = style;
1279 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1280 /* Remove main paned */
1281 g_object_ref (priv->main_paned);
1282 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1284 /* Reparent the contents widget to the main vbox */
1285 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1288 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1289 /* Remove header view */
1290 g_object_ref (priv->contents_widget);
1291 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1293 /* Reparent the main paned */
1294 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1295 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1299 g_return_if_reached ();
1302 /* Let header view grab the focus if it's being shown */
1303 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1304 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1306 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1309 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1312 ModestMainWindowStyle
1313 modest_main_window_get_style (ModestMainWindow *self)
1315 ModestMainWindowPrivate *priv;
1317 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1319 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1326 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1328 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1329 ModestWindowPrivate *parent_priv;
1330 ModestWindowMgr *mgr;
1331 gboolean is_fullscreen;
1332 GtkAction *fs_toggle_action;
1335 mgr = modest_runtime_get_window_mgr ();
1337 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1339 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1341 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1342 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1343 if (is_fullscreen != active) {
1344 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1353 set_homogeneous (GtkWidget *widget,
1356 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1357 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1361 modest_main_window_show_toolbar (ModestWindow *self,
1362 gboolean show_toolbar)
1364 ModestMainWindowPrivate *priv = NULL;
1365 ModestWindowPrivate *parent_priv = NULL;
1366 GtkWidget *reply_button = NULL, *menu = NULL;
1367 GtkWidget *placeholder = NULL;
1369 const gchar *action_name;
1372 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1373 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1374 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1376 /* Set optimized view status */
1377 priv->optimized_view = !show_toolbar;
1379 if (!parent_priv->toolbar) {
1380 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1382 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1384 /* Set homogeneous toolbar */
1385 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1386 set_homogeneous, NULL);
1388 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1389 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1390 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1391 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1392 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1393 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1394 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1395 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1397 /* Add ProgressBar (Transfer toolbar) */
1398 priv->progress_bar = modest_progress_bar_widget_new ();
1399 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1400 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1401 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1402 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1403 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1405 /* Connect cancel 'clicked' signal to abort progress mode */
1406 g_signal_connect(priv->cancel_toolitem, "clicked",
1407 G_CALLBACK(cancel_progressbar),
1410 /* Add it to the observers list */
1411 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1414 hildon_window_add_toolbar (HILDON_WINDOW (self),
1415 GTK_TOOLBAR (parent_priv->toolbar));
1417 /* Set reply button tap and hold menu */
1418 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1419 "/ToolBar/ToolbarMessageReply");
1420 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1421 "/ToolbarReplyCSM");
1422 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1424 /* Set send & receive button tap and hold menu */
1425 update_menus (MODEST_MAIN_WINDOW (self));
1429 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1430 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1431 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1433 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1434 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1435 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1437 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1439 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1443 /* Update also the actions (to update the toggles in the
1444 menus), we have to do it manually because some other window
1445 of the same time could have changed it (remember that the
1446 toolbar fullscreen mode is shared by all the windows of the
1448 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1449 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1451 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1453 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1454 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1459 on_account_inserted (TnyAccountStore *accoust_store,
1460 TnyAccount *account,
1463 update_menus (MODEST_MAIN_WINDOW (user_data));
1467 on_default_account_changed (ModestAccountMgr* mgr,
1470 update_menus (MODEST_MAIN_WINDOW (user_data));
1474 on_account_removed (TnyAccountStore *accoust_store,
1475 TnyAccount *account,
1478 update_menus (MODEST_MAIN_WINDOW (user_data));
1482 * This function manages the key events used to navigate between
1483 * header and folder views (when the window is in split view)
1486 * -------------------------------------------------
1487 * HeaderView GDK_Left Move focus to folder view
1488 * FolderView GDK_Right Move focus to header view
1490 * There is no need to scroll to selected row, the widgets will be the
1491 * responsibles of doing that (probably managing the focus-in event
1494 on_inner_widgets_key_pressed (GtkWidget *widget,
1498 ModestMainWindowPrivate *priv;
1500 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1502 /* Do nothing if we're in SIMPLE style */
1503 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1506 if (MODEST_IS_HEADER_VIEW (widget)) {
1507 if (event->keyval == GDK_Left)
1508 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1509 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1510 guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1511 if (selected_headers > 1) {
1512 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1516 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1517 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1523 set_alignment (GtkWidget *widget,
1526 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1527 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1531 create_empty_view (void)
1533 GtkLabel *label = NULL;
1534 GtkWidget *align = NULL;
1536 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1537 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1538 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1539 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1541 return GTK_WIDGET(align);
1545 * Free the returned string
1548 get_gray_color_markup (GtkWidget *styled_widget)
1550 gchar *gray_color_markup = NULL;
1551 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1552 /* Obtain the secondary text color. We need a realized widget, that's why
1553 we get styled_widget from outside */
1555 if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color))
1556 gray_color_markup = modest_text_utils_get_color_string (&color);
1557 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1559 if (!gray_color_markup)
1560 gray_color_markup = g_strdup ("#BBBBBB");
1562 return gray_color_markup;
1566 * Free the returned string
1569 create_device_name_visual_string (const gchar *device_name,
1570 const gchar *gray_color_markup)
1574 /* We have to use "" to fill the %s of the translation. We can
1575 not just use the device name because the device name is
1576 shown in a different color, so it could not be included
1577 into the <span> tag */
1578 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1579 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1589 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1591 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1596 gchar *gray_color_markup;
1598 vbox = gtk_vbox_new (FALSE, 0);
1600 gray_color_markup = get_gray_color_markup (styled_widget);
1602 /* Account description: */
1603 if (modest_tny_account_is_virtual_local_folders (account)
1604 || (modest_tny_account_is_memory_card_account (account))) {
1606 /* Get device name */
1607 gchar *device_name = NULL;
1608 if (modest_tny_account_is_virtual_local_folders (account))
1609 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1610 MODEST_CONF_DEVICE_NAME, NULL);
1612 device_name = g_strdup (tny_account_get_name (account));
1614 label = create_device_name_visual_string ((const gchar *) device_name,
1615 (const gchar *) gray_color_markup);
1616 label_w = gtk_label_new (NULL);
1617 gtk_label_set_markup (GTK_LABEL (label_w), label);
1618 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1619 g_free (device_name);
1622 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1623 gtk_box_pack_start (GTK_BOX (vbox),
1624 gtk_label_new (tny_account_get_name (account)),
1627 /* Other accounts, such as IMAP and POP: */
1632 /* Put proto in uppercase */
1633 proto = g_string_new (tny_account_get_proto (account));
1634 proto = g_string_ascii_up (proto);
1636 /* note: mcen_fi_localroot_description is something like "%s account"
1637 * however, we should display "%s account: %s"... therefore, ugly tmp */
1638 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1639 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1640 gray_color_markup, tmp, tny_account_get_name (account));
1643 label_w = gtk_label_new (NULL);
1644 gtk_label_set_markup (GTK_LABEL (label_w), label);
1645 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1646 g_string_free (proto, TRUE);
1652 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1653 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1654 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1655 modest_tny_folder_store_get_message_count (folder_store));
1656 label_w = gtk_label_new (NULL);
1657 gtk_label_set_markup (GTK_LABEL (label_w), label);
1658 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1662 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1664 _("mcen_fi_rootfolder_folders"),
1665 modest_tny_folder_store_get_folder_count (folder_store));
1666 label_w = gtk_label_new (NULL);
1667 gtk_label_set_markup (GTK_LABEL (label_w), label);
1668 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1672 if (modest_tny_account_is_virtual_local_folders (account)
1673 || modest_tny_account_is_memory_card_account (account)) {
1675 gchar *size = modest_text_utils_get_display_size (
1676 modest_tny_folder_store_get_local_size (folder_store));
1678 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1679 gray_color_markup, _("mcen_fi_rootfolder_size"),
1683 label_w = gtk_label_new (NULL);
1684 gtk_label_set_markup (GTK_LABEL (label_w), label);
1685 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1687 } else if (TNY_IS_ACCOUNT(folder_store)) {
1688 TnyAccount *account = TNY_ACCOUNT(folder_store);
1690 time_t last_updated;
1691 const gchar *last_updated_string;
1692 /* Get last updated from configuration */
1693 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1694 tny_account_get_id (account));
1696 if (last_updated > 0)
1697 last_updated_string = modest_text_utils_get_display_date(last_updated);
1699 last_updated_string = g_strdup (_("mcen_va_never"));
1701 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1702 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1703 label_w = gtk_label_new (NULL);
1704 gtk_label_set_markup (GTK_LABEL (label_w), label);
1705 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1709 g_free (gray_color_markup);
1712 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1718 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1720 ModestMainWindowPrivate *priv = NULL;
1722 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1724 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1726 return priv->send_receive_in_progress;
1730 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1732 GtkAction *action = NULL;
1733 GtkWidget *widget = NULL;
1734 ModestMainWindowPrivate *priv = NULL;
1736 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1737 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1739 priv->send_receive_in_progress = TRUE;
1741 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1742 gtk_action_set_sensitive (action, FALSE);
1743 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1744 /* gtk_action_set_sensitive (action, FALSE); */
1745 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1746 gtk_widget_set_sensitive (widget, FALSE);
1750 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1752 GtkAction *action = NULL;
1753 GtkWidget *widget = NULL;
1754 ModestMainWindowPrivate *priv = NULL;
1756 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1757 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1759 priv->send_receive_in_progress = FALSE;
1761 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1762 gtk_action_set_sensitive (action, TRUE);
1763 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1764 /* gtk_action_set_sensitive (action, TRUE); */
1765 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1766 gtk_widget_set_sensitive (widget, TRUE);
1771 on_msg_count_changed (ModestHeaderView *header_view,
1773 TnyFolderChange *change,
1774 ModestMainWindow *main_window)
1776 gboolean folder_empty = FALSE;
1777 gboolean all_marked_as_deleted = FALSE;
1778 TnyFolderChangeChanged changed;
1779 ModestMainWindowPrivate *priv;
1781 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1782 g_return_if_fail (TNY_IS_FOLDER(folder));
1783 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1784 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1786 changed = tny_folder_change_get_changed (change);
1788 /* If something changes */
1789 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1790 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1792 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1794 /* Check header removed (hide marked as DELETED headers) */
1795 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1796 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1799 /* Check if all messages are marked to be deleted */
1800 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1801 folder_empty = folder_empty || all_marked_as_deleted ;
1803 /* Set contents style of headers view */
1805 modest_main_window_set_contents_style (main_window,
1806 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1807 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1810 modest_main_window_set_contents_style (main_window,
1811 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1817 modest_main_window_set_contents_style (ModestMainWindow *self,
1818 ModestMainWindowContentsStyle style)
1820 ModestMainWindowPrivate *priv;
1822 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1824 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1826 /* We allow to set the same content style than the previously
1827 set if there are details, because it could happen when we're
1828 selecting different accounts consecutively */
1829 if ((priv->contents_style == style) &&
1830 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1833 /* Remove previous child. Delete it if it was an account
1835 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1837 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1838 g_object_ref (content);
1839 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1840 g_object_ref (priv->empty_view);
1841 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1844 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1847 priv->contents_style = style;
1849 switch (priv->contents_style) {
1850 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1851 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1852 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1855 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1857 /* if we're started without main win, there may not be a folder
1858 * view. this fixes a GLib-Critical */
1859 if (priv->folder_view) {
1860 TnyFolderStore *selected_folderstore =
1861 modest_folder_view_get_selected (priv->folder_view);
1862 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1863 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1864 TNY_ACCOUNT (selected_folderstore));
1866 wrap_in_scrolled_window (priv->contents_widget,
1867 priv->details_widget);
1869 g_object_unref (selected_folderstore);
1870 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1875 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1876 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1877 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1881 g_return_if_reached ();
1885 gtk_widget_show_all (priv->contents_widget);
1888 ModestMainWindowContentsStyle
1889 modest_main_window_get_contents_style (ModestMainWindow *self)
1891 ModestMainWindowPrivate *priv;
1893 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1895 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1896 return priv->contents_style;
1901 on_configuration_key_changed (ModestConf* conf,
1903 ModestConfEvent event,
1904 ModestConfNotificationId id,
1905 ModestMainWindow *self)
1907 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1908 TnyAccount *account = NULL;
1910 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1913 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1916 if (priv->folder_view)
1917 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1919 if (account && TNY_IS_ACCOUNT (account) &&
1920 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1923 const gchar *device_name;
1924 gchar *new_text, *gray_color_markup;
1927 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1928 label = GTK_LABEL (children->data);
1930 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1931 MODEST_CONF_DEVICE_NAME, NULL);
1933 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1934 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1936 gtk_label_set_markup (label, new_text);
1937 gtk_widget_show (GTK_WIDGET (label));
1939 g_free (gray_color_markup);
1941 g_list_free (children);
1943 g_object_unref (account);
1947 set_toolbar_transfer_mode (ModestMainWindow *self)
1949 ModestMainWindowPrivate *priv = NULL;
1951 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1953 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1955 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1957 if (priv->progress_bar_timeout > 0) {
1958 g_source_remove (priv->progress_bar_timeout);
1959 priv->progress_bar_timeout = 0;
1966 set_toolbar_mode (ModestMainWindow *self,
1967 ModestToolBarModes mode)
1969 ModestWindowPrivate *parent_priv = NULL;
1970 ModestMainWindowPrivate *priv = NULL;
1971 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1973 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1975 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1976 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1978 /* In case this was called before the toolbar exists: */
1979 if (!(parent_priv->toolbar))
1982 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1984 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1985 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1986 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1988 /* Sets current toolbar mode */
1989 priv->current_toolbar_mode = mode;
1991 /* Checks the dimming rules */
1992 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1994 /* Show and hide toolbar items */
1996 case TOOLBAR_MODE_NORMAL:
1998 gtk_action_set_visible (sort_action, TRUE);
2000 gtk_action_set_visible (refresh_action, TRUE);
2001 if (priv->progress_toolitem) {
2002 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2003 gtk_widget_hide (priv->progress_toolitem);
2005 if (priv->progress_bar)
2006 gtk_widget_hide (priv->progress_bar);
2009 gtk_action_set_visible (cancel_action, FALSE);
2011 /* Hide toolbar if optimized view is enabled */
2012 if (priv->optimized_view)
2013 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2015 case TOOLBAR_MODE_TRANSFER:
2017 gtk_action_set_visible (sort_action, FALSE);
2019 gtk_action_set_visible (refresh_action, FALSE);
2021 gtk_action_set_visible (cancel_action, TRUE);
2022 if (priv->progress_bar)
2023 gtk_widget_show (priv->progress_bar);
2024 if (priv->progress_toolitem) {
2025 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2026 gtk_widget_show (priv->progress_toolitem);
2029 /* Show toolbar if it's hiden (optimized view ) */
2030 if (priv->optimized_view)
2031 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2034 g_return_if_reached ();
2039 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2041 ModestMainWindowPrivate *priv;
2043 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2044 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2046 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2050 cancel_progressbar (GtkToolButton *toolbutton,
2051 ModestMainWindow *self)
2054 ModestMainWindowPrivate *priv;
2056 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2058 /* Get operation observers and cancel all the operations */
2059 tmp = priv->progress_widgets;
2061 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2062 tmp=g_slist_next(tmp);
2067 observers_empty (ModestMainWindow *self)
2070 ModestMainWindowPrivate *priv;
2071 gboolean is_empty = TRUE;
2072 guint pending_ops = 0;
2074 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2075 tmp = priv->progress_widgets;
2077 /* Check all observers */
2078 while (tmp && is_empty) {
2079 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2080 is_empty = pending_ops == 0;
2082 tmp = g_slist_next(tmp);
2090 * Gets the toolbar mode needed for each mail operation. It stores in
2091 * @mode_changed if the toolbar mode has changed or not
2093 static ModestToolBarModes
2094 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2095 ModestMailOperation *mail_op,
2096 gboolean *mode_changed)
2098 ModestToolBarModes mode;
2099 ModestMainWindowPrivate *priv;
2101 *mode_changed = FALSE;
2102 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2104 /* Get toolbar mode from operation id*/
2105 switch (modest_mail_operation_get_type_operation (mail_op)) {
2106 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2107 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2108 mode = TOOLBAR_MODE_TRANSFER;
2109 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2110 *mode_changed = TRUE;
2113 mode = TOOLBAR_MODE_NORMAL;
2119 on_mail_operation_started (ModestMailOperation *mail_op,
2122 ModestMainWindow *self;
2123 ModestMailOperationTypeOperation op_type;
2124 ModestMainWindowPrivate *priv;
2125 ModestToolBarModes mode;
2127 gboolean mode_changed = FALSE;
2128 TnyAccount *account;
2130 self = MODEST_MAIN_WINDOW (user_data);
2131 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2133 /* Do not show progress for receiving operations if the
2134 account is the local account or the MMC one */
2135 op_type = modest_mail_operation_get_type_operation (mail_op);
2136 account = modest_mail_operation_get_account (mail_op);
2137 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2140 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2141 modest_tny_account_is_memory_card_account (account));
2142 g_object_unref (account);
2147 /* Get toolbar mode from operation id*/
2148 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2150 /* Add operation observers and change toolbar if neccessary*/
2151 tmp = priv->progress_widgets;
2152 if (mode == TOOLBAR_MODE_TRANSFER) {
2154 set_toolbar_transfer_mode(self);
2157 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2159 tmp = g_slist_next (tmp);
2165 on_mail_operation_finished (ModestMailOperation *mail_op,
2168 ModestToolBarModes mode;
2169 ModestMailOperationTypeOperation op_type;
2171 ModestMainWindow *self;
2172 gboolean mode_changed;
2173 TnyAccount *account;
2174 ModestMainWindowPrivate *priv;
2176 self = MODEST_MAIN_WINDOW (user_data);
2177 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2179 /* The mail operation was not added to the progress objects if
2180 the account was the local account or the MMC one */
2181 op_type = modest_mail_operation_get_type_operation (mail_op);
2182 account = modest_mail_operation_get_account (mail_op);
2183 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2186 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2187 modest_tny_account_is_memory_card_account (account));
2188 g_object_unref (account);
2193 /* Get toolbar mode from operation id*/
2194 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2196 /* Change toolbar mode */
2197 tmp = priv->progress_widgets;
2198 if (mode == TOOLBAR_MODE_TRANSFER) {
2200 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2202 tmp = g_slist_next (tmp);
2205 /* If no more operations are being observed, NORMAL mode is enabled again */
2206 if (observers_empty (self)) {
2207 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2213 on_queue_changed (ModestMailOperationQueue *queue,
2214 ModestMailOperation *mail_op,
2215 ModestMailOperationQueueNotification type,
2216 ModestMainWindow *self)
2218 ModestMainWindowPrivate *priv;
2220 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2222 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2223 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2225 "operation-started",
2226 G_CALLBACK (on_mail_operation_started),
2228 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2230 "operation-finished",
2231 G_CALLBACK (on_mail_operation_finished),
2233 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2234 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2236 "operation-started");
2237 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2239 "operation-finished");
2244 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2246 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2249 /* Get account data */
2250 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2251 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2253 /* Set the new visible & active account */
2254 if (acc_data && acc_data->store_account) {
2255 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2256 acc_data->store_account->account_name);
2257 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2258 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2259 if (action != NULL) {
2260 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2261 modest_maemo_toggle_action_set_active_block_notify (
2262 GTK_TOGGLE_ACTION (action),
2268 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2273 modest_account_mgr_free_account_data (mgr, acc_data);
2276 /* Make sure that at least one account is "viewed": */
2278 set_at_least_one_account_visible(ModestMainWindow *self)
2280 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2281 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2283 if (!(priv->folder_view)) {
2284 /* It is too early to do this. */
2288 const gchar *active_server_account_name =
2289 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2291 if (!active_server_account_name ||
2292 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2294 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2295 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2296 if (default_modest_name) {
2297 set_account_visible (self, default_modest_name);
2298 } else if (first_modest_name) {
2299 set_account_visible (self, first_modest_name);
2301 g_free (first_modest_name);
2302 g_free (default_modest_name);
2307 on_show_account_action_toggled (GtkToggleAction *action,
2310 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2312 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2313 if (gtk_toggle_action_get_active (action))
2314 set_account_visible (self, acc_name);
2318 refresh_account (const gchar *account_name)
2322 /* win must already exists here, obviously */
2323 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2326 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2330 /* If account_name == NULL, we must update all (option All) */
2332 modest_ui_actions_do_send_receive_all (win);
2334 modest_ui_actions_do_send_receive (account_name, win);
2339 on_refresh_account_action_activated (GtkAction *action,
2342 refresh_account ((const gchar*) user_data);
2346 on_send_receive_csm_activated (GtkMenuItem *item,
2349 refresh_account ((const gchar*) user_data);
2353 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2355 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2357 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2363 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2365 ModestMainWindow *main_window = NULL;
2367 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2368 main_window = MODEST_MAIN_WINDOW (userdata);
2370 /* Update toolbar dimming state */
2371 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2377 on_header_view_focus_in (GtkWidget *widget,
2378 GdkEventFocus *event,
2381 ModestMainWindow *main_window = NULL;
2383 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2385 main_window = MODEST_MAIN_WINDOW (userdata);
2387 /* Update toolbar dimming state */
2388 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2394 on_folder_selection_changed (ModestFolderView *folder_view,
2395 TnyFolderStore *folder_store,
2397 ModestMainWindow *main_window)
2399 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2400 GtkAction *action = NULL;
2401 gboolean show_reply = TRUE;
2402 gboolean show_forward = TRUE;
2403 gboolean show_cancel_send = FALSE;
2404 gboolean show_clipboard = TRUE;
2405 gboolean show_delete = TRUE;
2408 if (TNY_IS_ACCOUNT (folder_store)) {
2409 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2410 } else if (TNY_IS_FOLDER (folder_store)) {
2411 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2412 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2413 TNY_FOLDER (folder_store));
2414 switch (folder_type) {
2415 case TNY_FOLDER_TYPE_DRAFTS:
2416 show_clipboard = show_delete = TRUE;
2417 show_reply = show_forward = show_cancel_send = FALSE;
2419 case TNY_FOLDER_TYPE_SENT:
2420 show_forward = show_clipboard = show_delete = TRUE;
2421 show_reply = show_cancel_send = FALSE;
2423 case TNY_FOLDER_TYPE_OUTBOX:
2424 show_clipboard = show_delete = show_cancel_send = TRUE;
2425 show_reply = show_forward = FALSE;
2427 case TNY_FOLDER_TYPE_INVALID:
2428 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2431 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2432 show_cancel_send = FALSE;
2435 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2436 show_cancel_send = FALSE;
2441 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2442 gtk_action_set_visible (action, show_reply);
2443 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2444 gtk_action_set_visible (action, show_reply);
2445 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2446 gtk_action_set_visible (action, show_forward);
2447 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2448 gtk_action_set_visible (action, show_cancel_send);
2449 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2450 gtk_action_set_visible (action, show_delete);
2452 /* We finally call to the ui actions handler, after updating properly
2453 * the header view CSM */
2454 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2458 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2459 GtkTreeModel *model,
2460 GtkTreeRowReference *row_reference,
2461 ModestMainWindow *self)
2463 ModestMainWindowPrivate *priv = NULL;
2464 GtkTreeModel *header_model = NULL;
2465 GtkTreePath *path = NULL;
2467 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2468 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2469 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2471 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2472 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2474 /* Do nothing if we changed the folder in the main view */
2475 if (header_model != model)
2478 /* Select the message in the header view */
2479 path = gtk_tree_row_reference_get_path (row_reference);
2480 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2482 gtk_tree_path_free (path);
2488 show_updating_banner (gpointer user_data)
2490 ModestMainWindowPrivate *priv = NULL;
2492 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2494 if (priv->updating_banner == NULL) {
2496 /* We're outside the main lock */
2497 gdk_threads_enter ();
2498 priv->updating_banner =
2499 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2500 _CS ("ckdg_pb_updating"));
2501 gdk_threads_leave ();
2504 /* Remove timeout */
2505 priv->updating_banner_timeout = 0;
2510 * We use this function to show/hide a progress banner showing
2511 * "Updating" while the header view is being filled. We're not showing
2512 * it unless the update takes more than 2 seconds
2514 * If starting = TRUE then the refresh is starting, otherwise it means
2515 * that is has just finished
2518 on_updating_msg_list (ModestHeaderView *header_view,
2522 ModestMainWindowPrivate *priv = NULL;
2524 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2526 /* Remove old timeout */
2527 if (priv->updating_banner_timeout > 0) {
2528 g_source_remove (priv->updating_banner_timeout);
2529 priv->updating_banner_timeout = 0;
2532 /* Create a new timeout */
2534 priv->updating_banner_timeout =
2535 g_timeout_add (2000, show_updating_banner, user_data);
2537 /* Remove the banner if exists */
2538 if (priv->updating_banner) {
2539 gtk_widget_destroy (priv->updating_banner);
2540 priv->updating_banner = NULL;