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);
100 update_menus (ModestMainWindow* self);
102 static void modest_main_window_show_toolbar (ModestWindow *window,
103 gboolean show_toolbar);
105 static void cancel_progressbar (GtkToolButton *toolbutton,
106 ModestMainWindow *self);
108 static void on_queue_changed (ModestMailOperationQueue *queue,
109 ModestMailOperation *mail_op,
110 ModestMailOperationQueueNotification type,
111 ModestMainWindow *self);
113 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
116 on_account_inserted (TnyAccountStore *accoust_store,
121 on_account_removed (TnyAccountStore *accoust_store,
126 on_account_changed (ModestAccountMgr* mgr,
127 const gchar* account,
130 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
134 static void on_configuration_key_changed (ModestConf* conf,
136 ModestConfEvent event,
137 ModestConfNotificationId id,
138 ModestMainWindow *self);
140 static void set_toolbar_mode (ModestMainWindow *self,
141 ModestToolBarModes mode);
143 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
145 static void on_show_account_action_toggled (GtkToggleAction *action,
148 static void on_refresh_account_action_activated (GtkAction *action,
151 static void on_send_receive_csm_activated (GtkMenuItem *item,
154 static void on_msg_count_changed (ModestHeaderView *header_view,
156 TnyFolderChange *change,
157 ModestMainWindow *main_window);
159 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
162 static GtkWidget * create_empty_view (void);
164 static gboolean on_folder_view_focus_in (GtkWidget *widget,
165 GdkEventFocus *event,
168 static gboolean on_header_view_focus_in (GtkWidget *widget,
169 GdkEventFocus *event,
172 static void modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
173 TnyFolderStore *folder_store,
175 ModestMainWindow *main_window);
177 static void set_at_least_one_account_visible(ModestMainWindow *self);
179 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
180 struct _ModestMainWindowPrivate {
181 GtkWidget *msg_paned;
182 GtkWidget *main_paned;
183 GtkWidget *main_vbox;
184 GtkWidget *contents_widget;
185 GtkWidget *empty_view;
187 /* Progress observers */
188 GtkWidget *progress_bar;
189 GSList *progress_widgets;
192 GtkWidget *progress_toolitem;
193 GtkWidget *cancel_toolitem;
194 GtkWidget *sort_toolitem;
195 GtkWidget *refresh_toolitem;
196 ModestToolBarModes current_toolbar_mode;
198 /* Merge ids used to add/remove accounts to the ViewMenu*/
199 GByteArray *merge_ids;
200 GtkActionGroup *view_additions_group;
202 /* On-demand widgets */
203 GtkWidget *accounts_popup;
204 GtkWidget *details_widget;
206 /* Optimized view enabled */
207 gboolean optimized_view;
209 /* Optimized view enabled */
210 gboolean send_receive_in_progress;
212 ModestHeaderView *header_view;
213 ModestFolderView *folder_view;
215 ModestMainWindowStyle style;
216 ModestMainWindowContentsStyle contents_style;
218 guint progress_bar_timeout;
220 /* Signal handler UIDs */
221 GList *queue_err_signals;
224 ModestConfNotificationId notification_id;
226 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
227 MODEST_TYPE_MAIN_WINDOW, \
228 ModestMainWindowPrivate))
230 typedef struct _GetMsgAsyncHelper {
231 ModestMainWindowPrivate *main_window_private;
233 ModestTnyMsgReplyType reply_type;
234 ModestTnyMsgForwardType forward_type;
241 static GtkWindowClass *parent_class = NULL;
244 /* Private actions */
245 /* This is the context sensitive menu: */
246 static const GtkActionEntry modest_folder_view_action_entries [] = {
248 /* Folder View CSM actions */
249 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
250 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
251 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
252 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
253 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
254 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
257 static const GtkActionEntry modest_header_view_action_entries [] = {
259 /* Header View CSM actions */
260 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
261 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
262 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
263 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
264 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
265 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
266 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
267 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
268 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
269 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
272 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
273 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
276 /************************************************************************/
279 modest_main_window_get_type (void)
281 static GType my_type = 0;
283 static const GTypeInfo my_info = {
284 sizeof(ModestMainWindowClass),
285 NULL, /* base init */
286 NULL, /* base finalize */
287 (GClassInitFunc) modest_main_window_class_init,
288 NULL, /* class finalize */
289 NULL, /* class data */
290 sizeof(ModestMainWindow),
292 (GInstanceInitFunc) modest_main_window_init,
295 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
303 modest_main_window_class_init (ModestMainWindowClass *klass)
305 GObjectClass *gobject_class;
306 gobject_class = (GObjectClass*) klass;
307 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
309 parent_class = g_type_class_peek_parent (klass);
310 gobject_class->finalize = modest_main_window_finalize;
312 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
314 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
315 modest_window_class->save_state_func = save_state;
316 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
317 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
318 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
322 modest_main_window_init (ModestMainWindow *obj)
324 ModestMainWindowPrivate *priv;
326 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
328 priv->queue_err_signals = NULL;
329 priv->msg_paned = NULL;
330 priv->main_paned = NULL;
331 priv->main_vbox = NULL;
332 priv->header_view = NULL;
333 priv->folder_view = NULL;
334 priv->contents_widget = NULL;
335 priv->accounts_popup = NULL;
336 priv->details_widget = NULL;
337 priv->empty_view = NULL;
338 priv->progress_widgets = NULL;
339 priv->progress_bar = NULL;
340 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
341 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
342 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
343 priv->merge_ids = NULL;
344 priv->optimized_view = FALSE;
345 priv->send_receive_in_progress = FALSE;
346 priv->progress_bar_timeout = 0;
347 priv->sighandlers = NULL;
351 modest_main_window_finalize (GObject *obj)
353 ModestMainWindowPrivate *priv;
355 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
357 if (priv->notification_id) {
358 modest_conf_forget_namespace (modest_runtime_get_conf (),
359 MODEST_CONF_NAMESPACE,
360 priv->notification_id);
363 /* Sanity check: shouldn't be needed, the window mgr should
364 call this function before */
365 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
367 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
369 g_slist_free (priv->progress_widgets);
371 g_byte_array_free (priv->merge_ids, TRUE);
373 if (priv->progress_bar_timeout > 0) {
374 g_source_remove (priv->progress_bar_timeout);
375 priv->progress_bar_timeout = 0;
378 G_OBJECT_CLASS(parent_class)->finalize (obj);
382 modest_main_window_get_child_widget (ModestMainWindow *self,
383 ModestMainWindowWidgetType widget_type)
385 ModestMainWindowPrivate *priv;
388 g_return_val_if_fail (self, NULL);
389 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
392 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
394 switch (widget_type) {
395 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
396 widget = (GtkWidget*)priv->header_view; break;
397 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
398 widget = (GtkWidget*)priv->folder_view; break;
403 return widget ? GTK_WIDGET(widget) : NULL;
408 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
411 ModestMainWindowPrivate *priv;
413 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
415 conf = modest_runtime_get_conf ();
417 modest_widget_memory_restore (conf, G_OBJECT(self),
418 MODEST_CONF_MAIN_WINDOW_KEY);
420 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
421 MODEST_CONF_HEADER_VIEW_KEY);
423 if (do_folder_view_too)
424 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
425 MODEST_CONF_FOLDER_VIEW_KEY);
427 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
428 MODEST_CONF_MAIN_PANED_KEY);
430 /* We need to force a redraw here in order to get the right
431 position of the horizontal paned separator */
432 gtk_widget_show (GTK_WIDGET (self));
437 save_state (ModestWindow *window)
440 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
441 ModestMainWindowPrivate *priv;
443 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
444 conf = modest_runtime_get_conf ();
446 modest_widget_memory_save (conf,G_OBJECT(self),
447 MODEST_CONF_MAIN_WINDOW_KEY);
448 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
449 MODEST_CONF_MAIN_PANED_KEY);
450 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
451 // MODEST_CONF_HEADER_VIEW_KEY);
452 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
453 MODEST_CONF_FOLDER_VIEW_KEY);
457 compare_display_names (ModestAccountData *a,
458 ModestAccountData *b)
460 return strcmp (a->display_name, b->display_name);
464 update_menus (ModestMainWindow* self)
466 GSList *account_names, *iter, *accounts;
467 ModestMainWindowPrivate *priv;
468 ModestWindowPrivate *parent_priv;
469 ModestAccountMgr *mgr;
470 gint i, num_accounts;
472 gchar *default_account;
473 GtkWidget *send_receive_button, *item;
474 GtkAction *send_receive_all = NULL;
477 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
478 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
480 /* Get enabled account IDs */
481 mgr = modest_runtime_get_account_mgr ();
482 account_names = modest_account_mgr_account_names (mgr, TRUE);
483 iter = account_names;
487 ModestAccountData *account_data =
488 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
489 accounts = g_slist_prepend (accounts, account_data);
493 modest_account_mgr_free_account_names (account_names);
494 account_names = NULL;
496 /* Order the list of accounts by its display name */
497 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
498 num_accounts = g_slist_length (accounts);
500 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
501 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
502 gtk_action_set_visible (send_receive_all, num_accounts > 1);
504 /* Delete old send&receive popup items. We can not just do a
505 menu_detach because it does not work well with
507 if (priv->accounts_popup)
508 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
509 (GtkCallback) gtk_widget_destroy, NULL);
511 /* Delete old entries in the View menu. Do not free groups, it
513 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
515 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
516 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
517 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
518 GTK_ACTION_GROUP (groups->data));
521 if (priv->merge_ids) {
522 for (i = 0; i < priv->merge_ids->len; i++)
523 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
524 g_byte_array_free (priv->merge_ids, TRUE);
526 /* We need to call this in order to ensure
527 that the new actions are added in the right
528 order (alphabetical */
529 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
531 groups = g_list_next (groups);
533 priv->merge_ids = g_byte_array_sized_new (num_accounts);
535 /* Get send receive button */
536 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
537 "/ToolBar/ToolbarSendReceive");
539 /* Create the menu */
540 if (num_accounts > 1) {
541 if (!priv->accounts_popup)
542 priv->accounts_popup = gtk_menu_new ();
543 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
544 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
545 g_signal_connect (G_OBJECT (item),
547 G_CALLBACK (on_send_receive_csm_activated),
549 item = gtk_separator_menu_item_new ();
550 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
553 /* Create a new action group */
554 default_account = modest_account_mgr_get_default_account (mgr);
555 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
557 for (i = 0; i < num_accounts; i++) {
558 gchar *display_name = NULL;
560 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
562 /* Create display name. The UI specification specifies a different format string
563 * to use for the default account, though both seem to be "%s", so
564 * I don't see what the point is. murrayc. */
565 if (default_account && account_data->account_name &&
566 !(strcmp (default_account, account_data->account_name) == 0)) {
567 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
568 account_data->display_name);
571 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
572 account_data->display_name);
575 /* Create action and add it to the action group. The
576 action name must be the account name, this way we
577 could know in the handlers the account to show */
578 if(account_data && account_data->account_name) {
579 gchar* item_name, *refresh_action_name;
581 GtkAction *view_account_action, *refresh_account_action;
583 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
584 display_name, NULL, NULL, 0));
585 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
586 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
587 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
589 if (default_account && account_data->account_name &&
590 (strcmp (default_account, account_data->account_name) == 0)) {
591 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
594 /* Add ui from account data. We allow 2^9-1 account
595 changes in a single execution because we're
596 downcasting the guint to a guint8 in order to use a
597 GByteArray. It should be enough. */
598 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
599 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
600 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
601 gtk_ui_manager_add_ui (parent_priv->ui_manager,
603 "/MenuBar/ViewMenu/ViewMenuAdditions",
605 account_data->account_name,
606 GTK_UI_MANAGER_MENUITEM,
609 /* Connect the action signal "activate" */
610 g_signal_connect_after (G_OBJECT (view_account_action),
612 G_CALLBACK (on_show_account_action_toggled),
615 /* Create the items for the Tools->Send&Receive submenu */
616 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
617 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
618 display_name, NULL, NULL);
619 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
621 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
622 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
623 gtk_ui_manager_add_ui (parent_priv->ui_manager,
625 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
628 GTK_UI_MANAGER_MENUITEM,
630 g_free (refresh_action_name);
632 g_signal_connect_data (G_OBJECT (refresh_account_action),
634 G_CALLBACK (on_refresh_account_action_activated),
635 g_strdup (account_data->account_name),
636 (GClosureNotify) g_free,
639 /* Create item and add it to the send&receive
640 CSM. If there is only one account then
642 if (priv->accounts_popup) {
643 GtkWidget *label = gtk_label_new(NULL);
644 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
645 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
647 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
648 gtk_label_set_markup (GTK_LABEL (label), escaped);
653 gtk_label_set_text (GTK_LABEL (label), display_name);
656 item = gtk_menu_item_new ();
657 gtk_container_add (GTK_CONTAINER (item), label);
659 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
660 g_signal_connect_data (G_OBJECT (item),
662 G_CALLBACK (on_send_receive_csm_activated),
663 g_strdup (account_data->account_name),
664 (GClosureNotify) g_free,
671 g_free (display_name);
674 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
676 /* We cannot do this in the loop above because this relies on the action
677 * group being inserted. This makes the default account appear in bold.
678 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
679 for (i = 0; i < num_accounts; i++) {
680 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
682 if(account_data->account_name && default_account &&
683 strcmp (account_data->account_name, default_account) == 0) {
684 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
686 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
687 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
691 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
692 if (GTK_IS_LABEL (child)) {
693 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
694 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
695 gtk_label_set_markup (GTK_LABEL (child), bold_name);
700 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
701 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
705 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
706 if (GTK_IS_LABEL (child)) {
707 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
708 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
709 gtk_label_set_markup (GTK_LABEL (child), bold_name);
717 modest_account_mgr_free_account_data (mgr, account_data);
720 if (priv->accounts_popup) {
721 /* Mandatory in order to view the menu contents */
722 gtk_widget_show_all (priv->accounts_popup);
724 /* Setup tap_and_hold just if was not done before*/
725 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
726 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
730 g_slist_free (accounts);
731 g_free (default_account);
734 /* Make sure that at least one account is viewed if there are any
735 * accounts, for instance when adding the first account: */
736 set_at_least_one_account_visible (self);
740 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
742 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
743 gtk_scrolled_window_add_with_viewport
744 (GTK_SCROLLED_WINDOW(win), widget);
746 gtk_container_add (GTK_CONTAINER(win),
757 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
759 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
761 GList *oerrsignals = priv->queue_err_signals;
762 while (oerrsignals) {
763 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
764 g_signal_handler_disconnect (esignal->queue, esignal->signal);
765 g_slice_free (QueueErrorSignal, esignal);
766 oerrsignals = g_list_next (oerrsignals);
768 g_list_free (priv->queue_err_signals);
769 priv->queue_err_signals = NULL;
774 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
776 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
779 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
783 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
785 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
787 /* Update visibility */
790 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
794 modest_main_window_disconnect_signals (ModestWindow *self)
796 ModestMainWindowPrivate *priv;
797 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
799 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
800 priv->sighandlers = NULL;
804 connect_signals (ModestMainWindow *self)
806 ModestWindowPrivate *parent_priv;
807 ModestMainWindowPrivate *priv;
810 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
811 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
815 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
816 G_OBJECT(priv->folder_view), "key-press-event",
817 G_CALLBACK(on_inner_widgets_key_pressed), self);
818 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
819 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
820 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
821 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
822 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
823 G_CALLBACK (on_folder_view_focus_in), self);
825 /* Folder view CSM */
826 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
827 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
828 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
829 G_CALLBACK(_folder_view_csm_menu_activated),
832 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
833 G_CALLBACK(modest_ui_actions_on_header_selected), self);
834 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
835 G_CALLBACK(modest_ui_actions_on_header_activated), self);
836 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
837 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
838 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
839 G_CALLBACK(on_inner_widgets_key_pressed), self);
840 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
841 G_CALLBACK(on_msg_count_changed), self);
842 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
843 G_CALLBACK (on_header_view_focus_in), self);
845 /* Header view CSM */
846 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
847 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
848 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
849 G_CALLBACK(_header_view_csm_menu_activated),
853 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
854 G_CALLBACK (modest_main_window_window_state_event),
857 /* Mail Operation Queue */
858 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_mail_operation_queue ()),
859 "queue-changed", G_CALLBACK (on_queue_changed), self);
861 /* Track changes in the device name */
862 priv->notification_id = modest_conf_listen_to_namespace (modest_runtime_get_conf (),
863 MODEST_CONF_NAMESPACE);
864 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(modest_runtime_get_conf ()),
865 "key_changed", G_CALLBACK (on_configuration_key_changed),
868 /* Track account changes. We need to refresh the toolbar */
869 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
870 "account_inserted", G_CALLBACK (on_account_inserted),
872 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
873 "account_removed", G_CALLBACK (on_account_removed),
876 /* We need to refresh the send & receive menu to change the bold
877 * account when the default account changes. */
878 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_mgr ()),
879 "account_changed", G_CALLBACK (on_account_changed),
883 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store()),
884 "password_requested",
885 G_CALLBACK (modest_ui_actions_on_password_requested), self);
889 /** Idle handler, to send/receive at startup .*/
891 sync_accounts_cb (ModestMainWindow *win)
893 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
894 return FALSE; /* Do not call this idle handler again. */
899 on_hildon_program_is_topmost_notify(GObject *self,
900 GParamSpec *propert_param, gpointer user_data)
902 HildonProgram *app = HILDON_PROGRAM (self);
905 ModestWindow* self = MODEST_WINDOW(user_data);
908 /* Note that use of hildon_program_set_can_hibernate()
909 * is generally referred to as "setting the killable flag",
910 * though hibernation does not seem equal to death.
913 if (hildon_program_get_is_topmost (app)) {
914 /* Prevent hibernation when the progam comes to the foreground,
915 * because hibernation should only happen when the application
916 * is in the background: */
917 hildon_program_set_can_hibernate (app, FALSE);
919 /* Allow hibernation if the program has gone to the background: */
921 /* However, prevent hibernation while the settings are being changed: */
922 const gboolean hibernation_prevented =
923 modest_window_mgr_get_hibernation_is_prevented (
924 modest_runtime_get_window_mgr ());
926 if (hibernation_prevented)
927 hildon_program_set_can_hibernate (app, FALSE);
929 /* Allow hibernation, after saving the state: */
930 modest_osso_save_state();
931 hildon_program_set_can_hibernate (app, TRUE);
938 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
940 GtkWidget *folder_win = (GtkWidget *) user_data;
941 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
943 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
944 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
945 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
947 gtk_widget_show (GTK_WIDGET (priv->folder_view));
949 /* Connect signals */
950 connect_signals ((ModestMainWindow*)self);
952 /* Set account store */
953 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
954 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
956 /* Load previous osso state, for instance if we are being restored from
958 modest_osso_load_state ();
960 /* Restore window & widget settings */
962 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
964 /* The UI spec wants us to show a connection dialog when the application is
965 * started by the user, if there is no connection.
966 * Do this before showing the account wizard,
967 * because wizard needs a connection to discover capabilities. */
968 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
970 /* Check if accounts exist and show the account wizard if not */
971 gboolean accounts_exist =
972 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
974 if (!accounts_exist) {
975 /* This is necessary to have the main window shown behind the dialog
976 It's an ugly hack... jschmid */
977 gtk_widget_show_all(GTK_WIDGET(self));
978 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
981 GtkAction *send_receive_all;
982 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
983 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
984 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
985 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
986 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
987 modest_account_mgr_free_account_names (accounts);
992 modest_main_window_new (void)
994 ModestMainWindow *self = NULL;
995 ModestMainWindowPrivate *priv = NULL;
996 ModestWindowPrivate *parent_priv = NULL;
997 GtkWidget *folder_win = NULL;
998 ModestDimmingRulesGroup *menu_rules_group = NULL;
999 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1000 GtkActionGroup *action_group = NULL;
1001 GError *error = NULL;
1002 ModestConf *conf = NULL;
1003 GtkAction *action = NULL;
1004 GdkPixbuf *window_icon;
1006 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1007 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1008 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1010 parent_priv->ui_manager = gtk_ui_manager_new();
1011 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1013 action_group = gtk_action_group_new ("ModestMainWindowActions");
1014 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1016 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1017 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1019 /* Add common actions */
1020 gtk_action_group_add_actions (action_group,
1021 modest_action_entries,
1022 G_N_ELEMENTS (modest_action_entries),
1025 gtk_action_group_add_actions (action_group,
1026 modest_folder_view_action_entries,
1027 G_N_ELEMENTS (modest_folder_view_action_entries),
1030 gtk_action_group_add_actions (action_group,
1031 modest_header_view_action_entries,
1032 G_N_ELEMENTS (modest_header_view_action_entries),
1035 gtk_action_group_add_toggle_actions (action_group,
1036 modest_toggle_action_entries,
1037 G_N_ELEMENTS (modest_toggle_action_entries),
1040 gtk_action_group_add_toggle_actions (action_group,
1041 modest_main_window_toggle_action_entries,
1042 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1045 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1046 g_object_unref (action_group);
1048 /* Load the UI definition */
1049 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1050 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1051 if (error != NULL) {
1052 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1053 g_error_free (error);
1057 /* Add common dimming rules */
1058 modest_dimming_rules_group_add_rules (menu_rules_group,
1059 modest_main_window_menu_dimming_entries,
1060 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1061 MODEST_WINDOW (self));
1062 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1063 modest_main_window_toolbar_dimming_entries,
1064 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1065 MODEST_WINDOW (self));
1067 /* Insert dimming rules group for this window */
1068 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1069 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1070 g_object_unref (menu_rules_group);
1071 g_object_unref (toolbar_rules_group);
1073 /* Add accelerators */
1074 gtk_window_add_accel_group (GTK_WINDOW (self),
1075 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1077 /* Menubar. Update the state of some toggles */
1078 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1079 conf = modest_runtime_get_conf ();
1080 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1081 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1082 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1083 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1084 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1085 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1086 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1087 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1088 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1089 gtk_widget_show (parent_priv->menubar);
1091 /* Get device name */
1092 modest_maemo_utils_get_device_name ();
1096 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1097 if (!priv->header_view)
1098 g_printerr ("modest: cannot instantiate header view\n");
1099 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1100 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1101 MODEST_CONF_HEADER_VIEW_KEY);
1103 /* Other style properties of header view */
1104 g_object_set (G_OBJECT (priv->header_view),
1105 "rules-hint", FALSE,
1107 /* gtk_widget_show (priv->header_view); */
1110 priv->empty_view = create_empty_view ();
1111 gtk_widget_show (priv->empty_view);
1113 /* Create scrolled windows */
1114 folder_win = gtk_scrolled_window_new (NULL, NULL);
1115 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1116 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1118 GTK_POLICY_AUTOMATIC);
1119 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1121 GTK_POLICY_AUTOMATIC);
1122 /* gtk_widget_show (priv->contents_widget); */
1125 priv->main_paned = gtk_hpaned_new ();
1126 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1127 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1128 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1130 /* putting it all together... */
1131 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1132 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1133 gtk_widget_show (priv->main_vbox);
1135 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1137 HildonProgram *app = hildon_program_get_instance ();
1138 hildon_program_add_window (app, HILDON_WINDOW (self));
1140 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1141 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1143 g_signal_connect (G_OBJECT(self), "show",
1144 G_CALLBACK (modest_main_window_on_show), folder_win);
1146 /* Set window icon */
1147 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1149 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1150 g_object_unref (window_icon);
1153 /* Dont't restore settings here,
1154 * because it requires a gtk_widget_show(),
1155 * and we don't want to do that until later,
1156 * so that the UI is not visible for non-menu D-Bus activation.
1158 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1160 return MODEST_WINDOW(self);
1164 modest_main_window_close_all (ModestMainWindow *self)
1167 GtkResponseType response;
1169 /* Create the confirmation dialog MSG-NOT308 */
1170 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1171 _("emev_nc_close_windows"),
1172 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1173 _("mcen_bd_no"), GTK_RESPONSE_NO,
1176 response = gtk_dialog_run (GTK_DIALOG (note));
1177 gtk_widget_destroy (GTK_WIDGET (note));
1179 if (response == GTK_RESPONSE_YES)
1187 modest_main_window_set_style (ModestMainWindow *self,
1188 ModestMainWindowStyle style)
1190 ModestMainWindowPrivate *priv;
1191 ModestWindowPrivate *parent_priv;
1195 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1197 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1198 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1200 /* no change -> nothing to do */
1201 if (priv->style == style)
1204 /* Get toggle button and update the state if needed. This will
1205 happen only when the set_style is not invoked from the UI,
1206 for example when it's called from widget memory */
1207 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1208 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1209 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1210 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1211 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1212 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1213 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1216 priv->style = style;
1218 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1219 /* Remove main paned */
1220 g_object_ref (priv->main_paned);
1221 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1223 /* Reparent the contents widget to the main vbox */
1224 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1227 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1228 /* Remove header view */
1229 g_object_ref (priv->contents_widget);
1230 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1232 /* Reparent the main paned */
1233 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1234 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1238 g_return_if_reached ();
1241 /* Let header view grab the focus if it's being shown */
1242 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1243 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1245 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1248 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1251 ModestMainWindowStyle
1252 modest_main_window_get_style (ModestMainWindow *self)
1254 ModestMainWindowPrivate *priv;
1256 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1258 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1265 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1267 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1268 ModestWindowPrivate *parent_priv;
1269 ModestWindowMgr *mgr;
1270 gboolean is_fullscreen;
1271 GtkAction *fs_toggle_action;
1274 mgr = modest_runtime_get_window_mgr ();
1276 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1278 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1280 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1281 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1282 if (is_fullscreen != active) {
1283 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1292 set_homogeneous (GtkWidget *widget,
1295 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1296 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1300 modest_main_window_show_toolbar (ModestWindow *self,
1301 gboolean show_toolbar)
1303 ModestMainWindowPrivate *priv = NULL;
1304 ModestWindowPrivate *parent_priv = NULL;
1305 GtkWidget *reply_button = NULL, *menu = NULL;
1306 GtkWidget *placeholder = NULL;
1308 const gchar *action_name;
1311 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1312 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1313 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1315 /* Set optimized view status */
1316 priv->optimized_view = !show_toolbar;
1318 if (!parent_priv->toolbar) {
1319 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1321 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1323 /* Set homogeneous toolbar */
1324 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1325 set_homogeneous, NULL);
1327 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1328 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1329 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1330 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1331 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1332 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1333 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1334 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1336 /* Add ProgressBar (Transfer toolbar) */
1337 priv->progress_bar = modest_progress_bar_widget_new ();
1338 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1339 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1340 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1341 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1342 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1344 /* Connect cancel 'clicked' signal to abort progress mode */
1345 g_signal_connect(priv->cancel_toolitem, "clicked",
1346 G_CALLBACK(cancel_progressbar),
1349 /* Add it to the observers list */
1350 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1353 hildon_window_add_toolbar (HILDON_WINDOW (self),
1354 GTK_TOOLBAR (parent_priv->toolbar));
1356 /* Set reply button tap and hold menu */
1357 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1358 "/ToolBar/ToolbarMessageReply");
1359 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1360 "/ToolbarReplyCSM");
1361 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1363 /* Set send & receive button tap and hold menu */
1364 update_menus (MODEST_MAIN_WINDOW (self));
1368 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1369 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1370 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1372 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1373 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1375 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1379 /* Update also the actions (to update the toggles in the
1380 menus), we have to do it manually because some other window
1381 of the same time could have changed it (remember that the
1382 toolbar fullscreen mode is shared by all the windows of the
1384 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1385 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarFullScreenMenu";
1387 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
1389 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1390 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1395 on_account_inserted (TnyAccountStore *accoust_store,
1396 TnyAccount *account,
1399 update_menus (MODEST_MAIN_WINDOW (user_data));
1403 on_account_changed (ModestAccountMgr* mgr,
1404 const gchar* account,
1407 gchar *default_account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
1409 /* Actually, we only want to know when another account has become
1410 * the default account, but there is no default_account_changed
1411 * signal in ModestAccountMgr. */
1412 if(strcmp(account, default_account) == 0)
1413 update_menus (MODEST_MAIN_WINDOW (user_data));
1415 g_free (default_account);
1419 on_account_removed (TnyAccountStore *accoust_store,
1420 TnyAccount *account,
1423 update_menus (MODEST_MAIN_WINDOW (user_data));
1427 * This function manages the key events used to navigate between
1428 * header and folder views (when the window is in split view)
1431 * -------------------------------------------------
1432 * HeaderView GDK_Left Move focus to folder view
1433 * FolderView GDK_Right Move focus to header view
1435 * There is no need to scroll to selected row, the widgets will be the
1436 * responsibles of doing that (probably managing the focus-in event
1439 on_inner_widgets_key_pressed (GtkWidget *widget,
1443 ModestMainWindowPrivate *priv;
1445 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1447 /* Do nothing if we're in SIMPLE style */
1448 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1451 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1452 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1453 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1454 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1460 set_alignment (GtkWidget *widget,
1463 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1464 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1468 create_empty_view (void)
1470 GtkLabel *label = NULL;
1471 GtkWidget *align = NULL;
1473 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1474 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1475 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1476 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1478 return GTK_WIDGET(align);
1482 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1484 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1489 gchar *gray_color_markup;
1491 vbox = gtk_vbox_new (FALSE, 0);
1493 /* Obtain the secondary text color. We need a realized widget, that's why
1494 we get styled_widget from outside */
1495 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1497 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1498 gray_color_markup = modest_text_utils_get_color_string (&color);
1500 // gray_color_markup is freed below
1501 gray_color_markup = g_strdup ("#BBBBBB");
1503 /* Account description: */
1505 if (modest_tny_account_is_virtual_local_folders (account)
1506 || (modest_tny_account_is_memory_card_account (account))) {
1508 /* Local folders: */
1510 /* Get device name */
1511 gchar *device_name = NULL;
1512 if (modest_tny_account_is_virtual_local_folders (account))
1513 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1514 MODEST_CONF_DEVICE_NAME, NULL);
1516 device_name = g_strdup (tny_account_get_name (account));
1518 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1519 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1520 gray_color_markup, tmp, device_name);
1522 label_w = gtk_label_new (NULL);
1523 gtk_label_set_markup (GTK_LABEL (label_w), label);
1524 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1525 g_free (device_name);
1528 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1529 gtk_box_pack_start (GTK_BOX (vbox),
1530 gtk_label_new (tny_account_get_name (account)),
1533 /* Other accounts, such as IMAP and POP: */
1538 /* Put proto in uppercase */
1539 proto = g_string_new (tny_account_get_proto (account));
1540 proto = g_string_ascii_up (proto);
1542 /* note: mcen_fi_localroot_description is something like "%s account"
1543 * however, we should display "%s account: %s"... therefore, ugly tmp */
1544 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1545 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1546 gray_color_markup, tmp, tny_account_get_name (account));
1549 label_w = gtk_label_new (NULL);
1550 gtk_label_set_markup (GTK_LABEL (label_w), label);
1551 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1552 g_string_free (proto, TRUE);
1558 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1559 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1560 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1561 modest_tny_folder_store_get_message_count (folder_store));
1562 label_w = gtk_label_new (NULL);
1563 gtk_label_set_markup (GTK_LABEL (label_w), label);
1564 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1568 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1570 _("mcen_fi_rootfolder_folders"),
1571 modest_tny_folder_store_get_folder_count (folder_store));
1572 label_w = gtk_label_new (NULL);
1573 gtk_label_set_markup (GTK_LABEL (label_w), label);
1574 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1578 if (modest_tny_account_is_virtual_local_folders (account)
1579 || modest_tny_account_is_memory_card_account (account)) {
1581 gchar *size = modest_text_utils_get_display_size (
1582 modest_tny_folder_store_get_local_size (folder_store));
1584 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1585 gray_color_markup, _("mcen_fi_rootfolder_size"),
1589 label_w = gtk_label_new (NULL);
1590 gtk_label_set_markup (GTK_LABEL (label_w), label);
1591 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1593 } else if (TNY_IS_ACCOUNT(folder_store)) {
1594 TnyAccount *account = TNY_ACCOUNT(folder_store);
1596 time_t last_updated;
1597 gchar *last_updated_string;
1598 /* Get last updated from configuration */
1599 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1600 tny_account_get_id (account),
1601 MODEST_ACCOUNT_LAST_UPDATED,
1603 if (last_updated > 0)
1604 last_updated_string = modest_text_utils_get_display_date(last_updated);
1606 last_updated_string = g_strdup (_("mcen_va_never"));
1608 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1609 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1610 label_w = gtk_label_new (NULL);
1611 gtk_label_set_markup (GTK_LABEL (label_w), label);
1612 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1613 g_free (last_updated_string);
1617 g_free (gray_color_markup);
1620 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1626 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1628 ModestMainWindowPrivate *priv = NULL;
1630 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1632 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1634 return priv->send_receive_in_progress;
1638 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1640 GtkAction *action = NULL;
1641 GtkWidget *widget = NULL;
1642 ModestMainWindowPrivate *priv = NULL;
1644 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1645 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1647 priv->send_receive_in_progress = TRUE;
1649 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1650 gtk_action_set_sensitive (action, FALSE);
1651 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1652 /* gtk_action_set_sensitive (action, FALSE); */
1653 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1654 gtk_widget_set_sensitive (widget, FALSE);
1658 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1660 GtkAction *action = NULL;
1661 GtkWidget *widget = NULL;
1662 ModestMainWindowPrivate *priv = NULL;
1664 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1665 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1667 priv->send_receive_in_progress = FALSE;
1669 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1670 gtk_action_set_sensitive (action, TRUE);
1671 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1672 /* gtk_action_set_sensitive (action, TRUE); */
1673 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1674 gtk_widget_set_sensitive (widget, TRUE);
1679 on_msg_count_changed (ModestHeaderView *header_view,
1681 TnyFolderChange *change,
1682 ModestMainWindow *main_window)
1684 gboolean folder_empty = FALSE;
1685 gboolean all_marked_as_deleted = FALSE;
1686 TnyFolderChangeChanged changed;
1687 ModestMainWindowPrivate *priv;
1689 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1690 g_return_if_fail (TNY_IS_FOLDER(folder));
1691 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1692 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1694 changed = tny_folder_change_get_changed (change);
1696 /* If something changes */
1697 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1698 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1700 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1702 /* Check header removed (hide marked as DELETED headers) */
1703 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1704 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1707 /* Check if all messages are marked to be deleted */
1708 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1709 folder_empty = folder_empty || all_marked_as_deleted ;
1711 /* Set contents style of headers view */
1713 modest_main_window_set_contents_style (main_window,
1714 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1715 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1718 modest_main_window_set_contents_style (main_window,
1719 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1725 modest_main_window_set_contents_style (ModestMainWindow *self,
1726 ModestMainWindowContentsStyle style)
1728 ModestMainWindowPrivate *priv;
1730 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1732 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1734 /* We allow to set the same content style than the previously
1735 set if there are details, because it could happen when we're
1736 selecting different accounts consecutively */
1737 if ((priv->contents_style == style) &&
1738 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1741 /* Remove previous child. Delete it if it was an account
1743 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1745 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1746 g_object_ref (content);
1747 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1748 g_object_ref (priv->empty_view);
1749 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1752 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1755 priv->contents_style = style;
1757 switch (priv->contents_style) {
1758 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1759 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1760 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1763 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1765 /* if we're started without main win, there may not be a folder
1766 * view. this fixes a GLib-Critical */
1767 if (priv->folder_view) {
1768 TnyFolderStore *selected_folderstore =
1769 modest_folder_view_get_selected (priv->folder_view);
1770 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1771 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1772 TNY_ACCOUNT (selected_folderstore));
1774 wrap_in_scrolled_window (priv->contents_widget,
1775 priv->details_widget);
1777 g_object_unref (selected_folderstore);
1778 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1783 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1784 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1785 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1789 g_return_if_reached ();
1793 gtk_widget_show_all (priv->contents_widget);
1796 ModestMainWindowContentsStyle
1797 modest_main_window_get_contents_style (ModestMainWindow *self)
1799 ModestMainWindowPrivate *priv;
1801 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1803 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1804 return priv->contents_style;
1809 on_configuration_key_changed (ModestConf* conf,
1811 ModestConfEvent event,
1812 ModestConfNotificationId id,
1813 ModestMainWindow *self)
1815 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1816 TnyAccount *account = NULL;
1819 priv->notification_id != id ||
1820 strcmp (key, MODEST_CONF_DEVICE_NAME))
1823 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1825 if (priv->folder_view)
1826 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1827 if (account && TNY_IS_ACCOUNT (account) &&
1828 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1831 const gchar *device_name;
1835 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1836 label = GTK_LABEL (children->data);
1838 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1839 MODEST_CONF_DEVICE_NAME, NULL);
1841 new_text = g_strdup_printf ("%s: %s",
1842 _("mcen_fi_localroot_description"),
1845 gtk_label_set_text (label, new_text);
1846 gtk_widget_show (GTK_WIDGET (label));
1849 g_list_free (children);
1851 g_object_unref (account);
1855 set_toolbar_transfer_mode (ModestMainWindow *self)
1857 ModestMainWindowPrivate *priv = NULL;
1859 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1861 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1863 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1865 if (priv->progress_bar_timeout > 0) {
1866 g_source_remove (priv->progress_bar_timeout);
1867 priv->progress_bar_timeout = 0;
1874 set_toolbar_mode (ModestMainWindow *self,
1875 ModestToolBarModes mode)
1877 ModestWindowPrivate *parent_priv = NULL;
1878 ModestMainWindowPrivate *priv = NULL;
1879 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1881 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1883 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1884 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1886 /* In case this was called before the toolbar exists: */
1887 if (!(parent_priv->toolbar))
1890 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1892 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1893 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1894 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1896 /* Sets current toolbar mode */
1897 priv->current_toolbar_mode = mode;
1899 /* Checks the dimming rules */
1900 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1902 /* Show and hide toolbar items */
1904 case TOOLBAR_MODE_NORMAL:
1906 gtk_action_set_visible (sort_action, TRUE);
1908 gtk_action_set_visible (refresh_action, TRUE);
1909 if (priv->progress_toolitem) {
1910 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1911 gtk_widget_hide (priv->progress_toolitem);
1913 if (priv->progress_bar)
1914 gtk_widget_hide (priv->progress_bar);
1917 gtk_action_set_visible (cancel_action, FALSE);
1919 /* Hide toolbar if optimized view is enabled */
1920 if (priv->optimized_view)
1921 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1923 case TOOLBAR_MODE_TRANSFER:
1925 gtk_action_set_visible (sort_action, FALSE);
1927 gtk_action_set_visible (refresh_action, FALSE);
1929 gtk_action_set_visible (cancel_action, TRUE);
1930 if (priv->progress_toolitem) {
1931 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1932 gtk_widget_show (priv->progress_toolitem);
1934 if (priv->progress_bar)
1935 gtk_widget_show (priv->progress_bar);
1937 /* Show toolbar if it's hiden (optimized view ) */
1938 if (priv->optimized_view)
1939 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1942 g_return_if_reached ();
1947 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1949 ModestMainWindowPrivate *priv;
1951 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1952 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1954 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1958 cancel_progressbar (GtkToolButton *toolbutton,
1959 ModestMainWindow *self)
1962 ModestMainWindowPrivate *priv;
1964 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1966 /* Get operation observers and cancel all the operations */
1967 tmp = priv->progress_widgets;
1969 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1970 tmp=g_slist_next(tmp);
1975 observers_empty (ModestMainWindow *self)
1978 ModestMainWindowPrivate *priv;
1979 gboolean is_empty = TRUE;
1980 guint pending_ops = 0;
1982 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1983 tmp = priv->progress_widgets;
1985 /* Check all observers */
1986 while (tmp && is_empty) {
1987 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1988 is_empty = pending_ops == 0;
1990 tmp = g_slist_next(tmp);
1997 on_queue_changed (ModestMailOperationQueue *queue,
1998 ModestMailOperation *mail_op,
1999 ModestMailOperationQueueNotification type,
2000 ModestMainWindow *self)
2002 ModestMainWindowPrivate *priv;
2003 ModestMailOperationTypeOperation op_type;
2004 ModestToolBarModes mode;
2006 gboolean mode_changed = FALSE;
2008 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2009 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2011 /* Get toolbar mode from operation id*/
2012 op_type = modest_mail_operation_get_type_operation (mail_op);
2014 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2015 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2016 mode = TOOLBAR_MODE_TRANSFER;
2017 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2018 mode_changed = TRUE;
2021 mode = TOOLBAR_MODE_NORMAL;
2026 /* Add operation observers and change toolbar if neccessary*/
2027 tmp = priv->progress_widgets;
2029 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2030 if (mode == TOOLBAR_MODE_TRANSFER) {
2032 set_toolbar_transfer_mode(self);
2035 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2037 tmp = g_slist_next (tmp);
2041 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2042 /* Change toolbar mode */
2043 if (mode == TOOLBAR_MODE_TRANSFER) {
2045 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2047 tmp = g_slist_next (tmp);
2050 /* If no more operations are being observed, NORMAL mode is enabled again */
2051 if (observers_empty (self)) {
2052 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2062 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2064 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2067 /* Get account data */
2068 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2069 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2071 /* Set the new visible & active account */
2072 if (acc_data && acc_data->store_account) {
2073 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2074 acc_data->store_account->account_name);
2075 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2076 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2077 if (action != NULL) {
2078 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2079 modest_maemo_toggle_action_set_active_block_notify (
2080 GTK_TOGGLE_ACTION (action),
2086 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2091 modest_account_mgr_free_account_data (mgr, acc_data);
2094 /* Make sure that at least one account is "viewed": */
2096 set_at_least_one_account_visible(ModestMainWindow *self)
2098 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2099 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2101 if (!(priv->folder_view)) {
2102 /* It is too early to do this. */
2106 const gchar *active_server_account_name =
2107 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2108 if (!active_server_account_name ||
2109 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2111 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2112 if (first_modest_name) {
2113 set_account_visible (self, first_modest_name);
2114 g_free (first_modest_name);
2120 on_show_account_action_toggled (GtkToggleAction *action,
2123 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2125 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2126 if (gtk_toggle_action_get_active (action))
2127 set_account_visible (self, acc_name);
2131 refresh_account (const gchar *account_name)
2135 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2137 /* If account_name == NULL, we must update all (option All) */
2139 modest_ui_actions_do_send_receive_all (win);
2141 modest_ui_actions_do_send_receive (account_name, win);
2146 on_refresh_account_action_activated (GtkAction *action,
2149 refresh_account ((const gchar*) user_data);
2153 on_send_receive_csm_activated (GtkMenuItem *item,
2156 refresh_account ((const gchar*) user_data);
2160 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2162 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2164 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2170 on_folder_view_focus_in (GtkWidget *widget,
2171 GdkEventFocus *event,
2174 ModestMainWindow *main_window = NULL;
2176 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2177 main_window = MODEST_MAIN_WINDOW (userdata);
2179 /* Update toolbar dimming state */
2180 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2186 on_header_view_focus_in (GtkWidget *widget,
2187 GdkEventFocus *event,
2190 ModestMainWindow *main_window = NULL;
2191 ModestMainWindowPrivate *priv = NULL;
2193 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2194 main_window = MODEST_MAIN_WINDOW (userdata);
2195 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2197 /* Update toolbar dimming state */
2198 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2204 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2205 TnyFolderStore *folder_store,
2207 ModestMainWindow *main_window)
2209 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2210 GtkAction *action = NULL;
2211 gboolean show_reply = TRUE;
2212 gboolean show_forward = TRUE;
2213 gboolean show_cancel_send = FALSE;
2214 gboolean show_clipboard = TRUE;
2215 gboolean show_delete = TRUE;
2218 if (TNY_IS_ACCOUNT (folder_store)) {
2219 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2220 } else if (TNY_IS_FOLDER (folder_store)) {
2221 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2222 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2223 TNY_FOLDER (folder_store));
2224 switch (folder_type) {
2225 case TNY_FOLDER_TYPE_DRAFTS:
2226 show_clipboard = show_delete = TRUE;
2227 show_reply = show_forward = show_cancel_send = FALSE;
2229 case TNY_FOLDER_TYPE_SENT:
2230 show_forward = show_clipboard = show_delete = TRUE;
2231 show_reply = show_cancel_send = FALSE;
2233 case TNY_FOLDER_TYPE_OUTBOX:
2234 show_clipboard = show_delete = show_cancel_send = TRUE;
2235 show_reply = show_forward = FALSE;
2238 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2239 show_cancel_send = FALSE;
2242 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2243 show_cancel_send = FALSE;
2248 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2249 gtk_action_set_visible (action, show_reply);
2250 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2251 gtk_action_set_visible (action, show_reply);
2252 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2253 gtk_action_set_visible (action, show_forward);
2254 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2255 gtk_action_set_visible (action, show_cancel_send);
2256 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2257 gtk_action_set_visible (action, show_delete);
2259 /* We finally call to the ui actions handler, after updating properly
2260 * the header view CSM */
2261 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2265 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2266 GtkTreeModel *model,
2267 GtkTreeRowReference *row_reference,
2268 ModestMainWindow *self)
2270 ModestMainWindowPrivate *priv = NULL;
2271 GtkTreeModel *header_model = NULL;
2272 GtkTreePath *path = NULL;
2274 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2275 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2276 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2278 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2279 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2281 /* Do nothing if we changed the folder in the main view */
2282 if (header_model != model)
2285 /* Select the message in the header view */
2286 path = gtk_tree_row_reference_get_path (row_reference);
2287 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2289 gtk_tree_path_free (path);