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_default_account_changed (ModestAccountMgr* mgr,
129 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
133 static void on_configuration_key_changed (ModestConf* conf,
135 ModestConfEvent event,
136 ModestConfNotificationId id,
137 ModestMainWindow *self);
139 static void set_toolbar_mode (ModestMainWindow *self,
140 ModestToolBarModes mode);
142 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
144 static void on_show_account_action_toggled (GtkToggleAction *action,
147 static void on_refresh_account_action_activated (GtkAction *action,
150 static void on_send_receive_csm_activated (GtkMenuItem *item,
153 static void on_msg_count_changed (ModestHeaderView *header_view,
155 TnyFolderChange *change,
156 ModestMainWindow *main_window);
158 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
161 static GtkWidget * create_empty_view (void);
163 static gboolean on_folder_view_focus_in (GtkWidget *widget,
164 GdkEventFocus *event,
167 static gboolean on_header_view_focus_in (GtkWidget *widget,
168 GdkEventFocus *event,
171 static void modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
172 TnyFolderStore *folder_store,
174 ModestMainWindow *main_window);
176 static void set_at_least_one_account_visible(ModestMainWindow *self);
178 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
179 struct _ModestMainWindowPrivate {
180 GtkWidget *msg_paned;
181 GtkWidget *main_paned;
182 GtkWidget *main_vbox;
183 GtkWidget *contents_widget;
184 GtkWidget *empty_view;
186 /* Progress observers */
187 GtkWidget *progress_bar;
188 GSList *progress_widgets;
191 GtkWidget *progress_toolitem;
192 GtkWidget *cancel_toolitem;
193 GtkWidget *sort_toolitem;
194 GtkWidget *refresh_toolitem;
195 ModestToolBarModes current_toolbar_mode;
197 /* Merge ids used to add/remove accounts to the ViewMenu*/
198 GByteArray *merge_ids;
199 GtkActionGroup *view_additions_group;
201 /* On-demand widgets */
202 GtkWidget *accounts_popup;
203 GtkWidget *details_widget;
205 /* Optimized view enabled */
206 gboolean optimized_view;
208 /* Optimized view enabled */
209 gboolean send_receive_in_progress;
211 ModestHeaderView *header_view;
212 ModestFolderView *folder_view;
214 ModestMainWindowStyle style;
215 ModestMainWindowContentsStyle contents_style;
217 guint progress_bar_timeout;
219 /* Signal handler UIDs */
220 GList *queue_err_signals;
223 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
224 MODEST_TYPE_MAIN_WINDOW, \
225 ModestMainWindowPrivate))
227 typedef struct _GetMsgAsyncHelper {
228 ModestMainWindowPrivate *main_window_private;
230 ModestTnyMsgReplyType reply_type;
231 ModestTnyMsgForwardType forward_type;
238 static GtkWindowClass *parent_class = NULL;
241 /* Private actions */
242 /* This is the context sensitive menu: */
243 static const GtkActionEntry modest_folder_view_action_entries [] = {
245 /* Folder View CSM actions */
246 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
247 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
248 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
249 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
250 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
251 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
254 static const GtkActionEntry modest_header_view_action_entries [] = {
256 /* Header View CSM actions */
257 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
258 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
259 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
260 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
261 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
262 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
263 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
264 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
265 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
266 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
269 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
270 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
273 /************************************************************************/
276 modest_main_window_get_type (void)
278 static GType my_type = 0;
280 static const GTypeInfo my_info = {
281 sizeof(ModestMainWindowClass),
282 NULL, /* base init */
283 NULL, /* base finalize */
284 (GClassInitFunc) modest_main_window_class_init,
285 NULL, /* class finalize */
286 NULL, /* class data */
287 sizeof(ModestMainWindow),
289 (GInstanceInitFunc) modest_main_window_init,
292 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
300 modest_main_window_class_init (ModestMainWindowClass *klass)
302 GObjectClass *gobject_class;
303 gobject_class = (GObjectClass*) klass;
304 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
306 parent_class = g_type_class_peek_parent (klass);
307 gobject_class->finalize = modest_main_window_finalize;
309 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
311 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
312 modest_window_class->save_state_func = save_state;
313 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
314 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
315 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
319 modest_main_window_init (ModestMainWindow *obj)
321 ModestMainWindowPrivate *priv;
323 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
325 priv->queue_err_signals = NULL;
326 priv->msg_paned = NULL;
327 priv->main_paned = NULL;
328 priv->main_vbox = NULL;
329 priv->header_view = NULL;
330 priv->folder_view = NULL;
331 priv->contents_widget = NULL;
332 priv->accounts_popup = NULL;
333 priv->details_widget = NULL;
334 priv->empty_view = NULL;
335 priv->progress_widgets = NULL;
336 priv->progress_bar = NULL;
337 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
338 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
339 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
340 priv->merge_ids = NULL;
341 priv->optimized_view = FALSE;
342 priv->send_receive_in_progress = FALSE;
343 priv->progress_bar_timeout = 0;
344 priv->sighandlers = NULL;
348 modest_main_window_finalize (GObject *obj)
350 ModestMainWindowPrivate *priv;
352 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
354 /* Sanity check: shouldn't be needed, the window mgr should
355 call this function before */
356 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
358 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
360 g_slist_free (priv->progress_widgets);
362 g_byte_array_free (priv->merge_ids, TRUE);
364 if (priv->progress_bar_timeout > 0) {
365 g_source_remove (priv->progress_bar_timeout);
366 priv->progress_bar_timeout = 0;
369 G_OBJECT_CLASS(parent_class)->finalize (obj);
373 modest_main_window_get_child_widget (ModestMainWindow *self,
374 ModestMainWindowWidgetType widget_type)
376 ModestMainWindowPrivate *priv;
379 g_return_val_if_fail (self, NULL);
380 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
383 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
385 switch (widget_type) {
386 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
387 widget = (GtkWidget*)priv->header_view; break;
388 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
389 widget = (GtkWidget*)priv->folder_view; break;
394 return widget ? GTK_WIDGET(widget) : NULL;
399 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
402 ModestMainWindowPrivate *priv;
404 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
406 conf = modest_runtime_get_conf ();
408 modest_widget_memory_restore (conf, G_OBJECT(self),
409 MODEST_CONF_MAIN_WINDOW_KEY);
411 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
412 MODEST_CONF_HEADER_VIEW_KEY);
414 if (do_folder_view_too)
415 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
416 MODEST_CONF_FOLDER_VIEW_KEY);
418 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
419 MODEST_CONF_MAIN_PANED_KEY);
421 /* We need to force a redraw here in order to get the right
422 position of the horizontal paned separator */
423 gtk_widget_show (GTK_WIDGET (self));
428 save_state (ModestWindow *window)
431 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
432 ModestMainWindowPrivate *priv;
434 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
435 conf = modest_runtime_get_conf ();
437 modest_widget_memory_save (conf,G_OBJECT(self),
438 MODEST_CONF_MAIN_WINDOW_KEY);
439 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
440 MODEST_CONF_MAIN_PANED_KEY);
441 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
442 // MODEST_CONF_HEADER_VIEW_KEY);
443 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
444 MODEST_CONF_FOLDER_VIEW_KEY);
448 compare_display_names (ModestAccountData *a,
449 ModestAccountData *b)
451 return strcmp (a->display_name, b->display_name);
455 update_menus (ModestMainWindow* self)
457 GSList *account_names, *iter, *accounts;
458 ModestMainWindowPrivate *priv;
459 ModestWindowPrivate *parent_priv;
460 ModestAccountMgr *mgr;
461 gint i, num_accounts;
463 gchar *default_account;
464 GtkWidget *send_receive_button, *item;
465 GtkAction *send_receive_all = NULL;
468 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
469 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
471 /* Get enabled account IDs */
472 mgr = modest_runtime_get_account_mgr ();
473 account_names = modest_account_mgr_account_names (mgr, TRUE);
474 iter = account_names;
478 ModestAccountData *account_data =
479 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
480 accounts = g_slist_prepend (accounts, account_data);
484 modest_account_mgr_free_account_names (account_names);
485 account_names = NULL;
487 /* Order the list of accounts by its display name */
488 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
489 num_accounts = g_slist_length (accounts);
491 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
492 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
493 gtk_action_set_visible (send_receive_all, num_accounts > 1);
495 /* Delete old send&receive popup items. We can not just do a
496 menu_detach because it does not work well with
498 if (priv->accounts_popup)
499 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
500 (GtkCallback) gtk_widget_destroy, NULL);
502 /* Delete old entries in the View menu. Do not free groups, it
504 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
506 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
507 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
508 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
509 GTK_ACTION_GROUP (groups->data));
512 if (priv->merge_ids) {
513 for (i = 0; i < priv->merge_ids->len; i++)
514 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
515 g_byte_array_free (priv->merge_ids, TRUE);
517 /* We need to call this in order to ensure
518 that the new actions are added in the right
519 order (alphabetical */
520 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
522 groups = g_list_next (groups);
524 priv->merge_ids = g_byte_array_sized_new (num_accounts);
526 /* Get send receive button */
527 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
528 "/ToolBar/ToolbarSendReceive");
530 /* Create the menu */
531 if (num_accounts > 1) {
532 if (!priv->accounts_popup)
533 priv->accounts_popup = gtk_menu_new ();
534 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
535 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
536 g_signal_connect (G_OBJECT (item),
538 G_CALLBACK (on_send_receive_csm_activated),
540 item = gtk_separator_menu_item_new ();
541 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
544 /* Create a new action group */
545 default_account = modest_account_mgr_get_default_account (mgr);
546 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
548 for (i = 0; i < num_accounts; i++) {
549 gchar *display_name = NULL;
551 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
553 /* Create display name. The UI specification specifies a different format string
554 * to use for the default account, though both seem to be "%s", so
555 * I don't see what the point is. murrayc. */
556 if (default_account && account_data->account_name &&
557 !(strcmp (default_account, account_data->account_name) == 0)) {
558 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
559 account_data->display_name);
562 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
563 account_data->display_name);
566 /* Create action and add it to the action group. The
567 action name must be the account name, this way we
568 could know in the handlers the account to show */
569 if(account_data && account_data->account_name) {
570 gchar* item_name, *refresh_action_name;
572 GtkAction *view_account_action, *refresh_account_action;
574 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
575 display_name, NULL, NULL, 0));
576 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
577 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
578 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
580 if (default_account && account_data->account_name &&
581 (strcmp (default_account, account_data->account_name) == 0)) {
582 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
585 /* Add ui from account data. We allow 2^9-1 account
586 changes in a single execution because we're
587 downcasting the guint to a guint8 in order to use a
588 GByteArray. It should be enough. */
589 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
590 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
591 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
592 gtk_ui_manager_add_ui (parent_priv->ui_manager,
594 "/MenuBar/ViewMenu/ViewMenuAdditions",
596 account_data->account_name,
597 GTK_UI_MANAGER_MENUITEM,
600 /* Connect the action signal "activate" */
601 g_signal_connect_after (G_OBJECT (view_account_action),
603 G_CALLBACK (on_show_account_action_toggled),
606 /* Create the items for the Tools->Send&Receive submenu */
607 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
608 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
609 display_name, NULL, NULL);
610 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
612 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
613 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
614 gtk_ui_manager_add_ui (parent_priv->ui_manager,
616 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
619 GTK_UI_MANAGER_MENUITEM,
621 g_free (refresh_action_name);
623 g_signal_connect_data (G_OBJECT (refresh_account_action),
625 G_CALLBACK (on_refresh_account_action_activated),
626 g_strdup (account_data->account_name),
627 (GClosureNotify) g_free,
630 /* Create item and add it to the send&receive
631 CSM. If there is only one account then
633 if (priv->accounts_popup) {
634 GtkWidget *label = gtk_label_new(NULL);
635 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
636 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
638 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
639 gtk_label_set_markup (GTK_LABEL (label), escaped);
644 gtk_label_set_text (GTK_LABEL (label), display_name);
647 item = gtk_menu_item_new ();
648 gtk_container_add (GTK_CONTAINER (item), label);
650 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
651 g_signal_connect_data (G_OBJECT (item),
653 G_CALLBACK (on_send_receive_csm_activated),
654 g_strdup (account_data->account_name),
655 (GClosureNotify) g_free,
662 g_free (display_name);
665 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
667 /* We cannot do this in the loop above because this relies on the action
668 * group being inserted. This makes the default account appear in bold.
669 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
670 for (i = 0; i < num_accounts; i++) {
671 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
673 if(account_data->account_name && default_account &&
674 strcmp (account_data->account_name, default_account) == 0) {
675 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
677 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
678 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
682 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
683 if (GTK_IS_LABEL (child)) {
684 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
685 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
686 gtk_label_set_markup (GTK_LABEL (child), bold_name);
691 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
692 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
696 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
697 if (GTK_IS_LABEL (child)) {
698 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
699 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
700 gtk_label_set_markup (GTK_LABEL (child), bold_name);
708 modest_account_mgr_free_account_data (mgr, account_data);
711 if (priv->accounts_popup) {
712 /* Mandatory in order to view the menu contents */
713 gtk_widget_show_all (priv->accounts_popup);
715 /* Setup tap_and_hold just if was not done before*/
716 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
717 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
721 g_slist_free (accounts);
722 g_free (default_account);
725 /* Make sure that at least one account is viewed if there are any
726 * accounts, for instance when adding the first account: */
727 set_at_least_one_account_visible (self);
731 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
733 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
734 gtk_scrolled_window_add_with_viewport
735 (GTK_SCROLLED_WINDOW(win), widget);
737 gtk_container_add (GTK_CONTAINER(win),
748 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
750 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
752 GList *oerrsignals = priv->queue_err_signals;
753 while (oerrsignals) {
754 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
755 g_signal_handler_disconnect (esignal->queue, esignal->signal);
756 g_slice_free (QueueErrorSignal, esignal);
757 oerrsignals = g_list_next (oerrsignals);
759 g_list_free (priv->queue_err_signals);
760 priv->queue_err_signals = NULL;
765 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
767 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
770 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
774 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
776 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
778 /* Update visibility */
781 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
785 modest_main_window_disconnect_signals (ModestWindow *self)
787 ModestMainWindowPrivate *priv;
788 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
790 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
791 priv->sighandlers = NULL;
795 connect_signals (ModestMainWindow *self)
797 ModestWindowPrivate *parent_priv;
798 ModestMainWindowPrivate *priv;
801 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
802 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
806 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
807 G_OBJECT(priv->folder_view), "key-press-event",
808 G_CALLBACK(on_inner_widgets_key_pressed), self);
809 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
810 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
811 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
812 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
813 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
814 G_CALLBACK (on_folder_view_focus_in), self);
816 /* Folder view CSM */
817 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
818 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
819 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
820 G_CALLBACK(_folder_view_csm_menu_activated),
823 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
824 G_CALLBACK(modest_ui_actions_on_header_selected), self);
825 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
826 G_CALLBACK(modest_ui_actions_on_header_activated), self);
827 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
828 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
829 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
830 G_CALLBACK(on_inner_widgets_key_pressed), self);
831 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
832 G_CALLBACK(on_msg_count_changed), self);
833 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
834 G_CALLBACK (on_header_view_focus_in), self);
836 /* Header view CSM */
837 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
838 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
839 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
840 G_CALLBACK(_header_view_csm_menu_activated),
844 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
845 G_CALLBACK (modest_main_window_window_state_event),
848 /* Mail Operation Queue */
849 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_mail_operation_queue ()),
850 "queue-changed", G_CALLBACK (on_queue_changed), self);
852 /* Track changes in the device name */
853 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(modest_runtime_get_conf ()),
854 "key_changed", G_CALLBACK (on_configuration_key_changed),
857 /* Track account changes. We need to refresh the toolbar */
858 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
859 "account_inserted", G_CALLBACK (on_account_inserted),
861 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
862 "account_removed", G_CALLBACK (on_account_removed),
865 /* We need to refresh the send & receive menu to change the bold
866 * account when the default account changes. */
867 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
868 G_OBJECT (modest_runtime_get_account_mgr ()),
869 "default_account_changed",
870 G_CALLBACK (on_default_account_changed),
874 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store()),
875 "password_requested",
876 G_CALLBACK (modest_ui_actions_on_password_requested), self);
880 /** Idle handler, to send/receive at startup .*/
882 sync_accounts_cb (ModestMainWindow *win)
884 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
885 return FALSE; /* Do not call this idle handler again. */
890 on_hildon_program_is_topmost_notify(GObject *self,
891 GParamSpec *propert_param, gpointer user_data)
893 HildonProgram *app = HILDON_PROGRAM (self);
896 ModestWindow* self = MODEST_WINDOW(user_data);
899 /* Note that use of hildon_program_set_can_hibernate()
900 * is generally referred to as "setting the killable flag",
901 * though hibernation does not seem equal to death.
904 if (hildon_program_get_is_topmost (app)) {
905 /* Prevent hibernation when the progam comes to the foreground,
906 * because hibernation should only happen when the application
907 * is in the background: */
908 hildon_program_set_can_hibernate (app, FALSE);
910 /* Allow hibernation if the program has gone to the background: */
912 /* However, prevent hibernation while the settings are being changed: */
913 const gboolean hibernation_prevented =
914 modest_window_mgr_get_hibernation_is_prevented (
915 modest_runtime_get_window_mgr ());
917 if (hibernation_prevented)
918 hildon_program_set_can_hibernate (app, FALSE);
920 /* Allow hibernation, after saving the state: */
921 modest_osso_save_state();
922 hildon_program_set_can_hibernate (app, TRUE);
929 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
931 GtkWidget *folder_win = (GtkWidget *) user_data;
932 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
934 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
935 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
936 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
938 gtk_widget_show (GTK_WIDGET (priv->folder_view));
940 /* Connect signals */
941 connect_signals ((ModestMainWindow*)self);
943 /* Set account store */
944 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
945 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
947 /* Load previous osso state, for instance if we are being restored from
949 modest_osso_load_state ();
951 /* Restore window & widget settings */
953 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
955 /* The UI spec wants us to show a connection dialog when the application is
956 * started by the user, if there is no connection.
957 * Do this before showing the account wizard,
958 * because wizard needs a connection to discover capabilities. */
959 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
961 /* Check if accounts exist and show the account wizard if not */
962 gboolean accounts_exist =
963 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
965 if (!accounts_exist) {
966 /* This is necessary to have the main window shown behind the dialog
967 It's an ugly hack... jschmid */
968 gtk_widget_show_all(GTK_WIDGET(self));
969 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
972 GtkAction *send_receive_all;
973 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
974 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
975 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
976 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
977 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
978 modest_account_mgr_free_account_names (accounts);
983 modest_main_window_new (void)
985 ModestMainWindow *self = NULL;
986 ModestMainWindowPrivate *priv = NULL;
987 ModestWindowPrivate *parent_priv = NULL;
988 GtkWidget *folder_win = NULL;
989 ModestDimmingRulesGroup *menu_rules_group = NULL;
990 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
991 GtkActionGroup *action_group = NULL;
992 GError *error = NULL;
993 ModestConf *conf = NULL;
994 GtkAction *action = NULL;
995 GdkPixbuf *window_icon;
997 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
998 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
999 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1001 parent_priv->ui_manager = gtk_ui_manager_new();
1002 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1004 action_group = gtk_action_group_new ("ModestMainWindowActions");
1005 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1007 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1008 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1010 /* Add common actions */
1011 gtk_action_group_add_actions (action_group,
1012 modest_action_entries,
1013 G_N_ELEMENTS (modest_action_entries),
1016 gtk_action_group_add_actions (action_group,
1017 modest_folder_view_action_entries,
1018 G_N_ELEMENTS (modest_folder_view_action_entries),
1021 gtk_action_group_add_actions (action_group,
1022 modest_header_view_action_entries,
1023 G_N_ELEMENTS (modest_header_view_action_entries),
1026 gtk_action_group_add_toggle_actions (action_group,
1027 modest_toggle_action_entries,
1028 G_N_ELEMENTS (modest_toggle_action_entries),
1031 gtk_action_group_add_toggle_actions (action_group,
1032 modest_main_window_toggle_action_entries,
1033 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1036 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1037 g_object_unref (action_group);
1039 /* Load the UI definition */
1040 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1041 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1042 if (error != NULL) {
1043 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1044 g_error_free (error);
1048 /* Add common dimming rules */
1049 modest_dimming_rules_group_add_rules (menu_rules_group,
1050 modest_main_window_menu_dimming_entries,
1051 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1052 MODEST_WINDOW (self));
1053 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1054 modest_main_window_toolbar_dimming_entries,
1055 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1056 MODEST_WINDOW (self));
1058 /* Insert dimming rules group for this window */
1059 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1060 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1061 g_object_unref (menu_rules_group);
1062 g_object_unref (toolbar_rules_group);
1064 /* Add accelerators */
1065 gtk_window_add_accel_group (GTK_WINDOW (self),
1066 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1068 /* Menubar. Update the state of some toggles */
1069 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1070 conf = modest_runtime_get_conf ();
1071 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1072 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1073 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1074 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1075 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1076 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1077 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1078 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1079 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1080 gtk_widget_show (parent_priv->menubar);
1082 /* Get device name */
1083 modest_maemo_utils_get_device_name ();
1087 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1088 if (!priv->header_view)
1089 g_printerr ("modest: cannot instantiate header view\n");
1090 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1091 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1092 MODEST_CONF_HEADER_VIEW_KEY);
1094 /* Other style properties of header view */
1095 g_object_set (G_OBJECT (priv->header_view),
1096 "rules-hint", FALSE,
1098 /* gtk_widget_show (priv->header_view); */
1101 priv->empty_view = create_empty_view ();
1102 gtk_widget_show (priv->empty_view);
1104 /* Create scrolled windows */
1105 folder_win = gtk_scrolled_window_new (NULL, NULL);
1106 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1107 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1109 GTK_POLICY_AUTOMATIC);
1110 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1112 GTK_POLICY_AUTOMATIC);
1113 /* gtk_widget_show (priv->contents_widget); */
1116 priv->main_paned = gtk_hpaned_new ();
1117 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1118 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1119 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1121 /* putting it all together... */
1122 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1123 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1124 gtk_widget_show (priv->main_vbox);
1126 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1128 HildonProgram *app = hildon_program_get_instance ();
1129 hildon_program_add_window (app, HILDON_WINDOW (self));
1131 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1132 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1134 g_signal_connect (G_OBJECT(self), "show",
1135 G_CALLBACK (modest_main_window_on_show), folder_win);
1137 /* Set window icon */
1138 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1140 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1141 g_object_unref (window_icon);
1144 /* Dont't restore settings here,
1145 * because it requires a gtk_widget_show(),
1146 * and we don't want to do that until later,
1147 * so that the UI is not visible for non-menu D-Bus activation.
1149 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1151 return MODEST_WINDOW(self);
1155 modest_main_window_close_all (ModestMainWindow *self)
1158 GtkResponseType response;
1160 /* Create the confirmation dialog MSG-NOT308 */
1161 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1162 _("emev_nc_close_windows"),
1163 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1164 _("mcen_bd_no"), GTK_RESPONSE_NO,
1167 response = gtk_dialog_run (GTK_DIALOG (note));
1168 gtk_widget_destroy (GTK_WIDGET (note));
1170 if (response == GTK_RESPONSE_YES)
1178 modest_main_window_set_style (ModestMainWindow *self,
1179 ModestMainWindowStyle style)
1181 ModestMainWindowPrivate *priv;
1182 ModestWindowPrivate *parent_priv;
1186 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1188 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1189 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1191 /* no change -> nothing to do */
1192 if (priv->style == style)
1195 /* Get toggle button and update the state if needed. This will
1196 happen only when the set_style is not invoked from the UI,
1197 for example when it's called from widget memory */
1198 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1199 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1200 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1201 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1202 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1203 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1204 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1207 priv->style = style;
1209 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1210 /* Remove main paned */
1211 g_object_ref (priv->main_paned);
1212 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1214 /* Reparent the contents widget to the main vbox */
1215 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1218 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1219 /* Remove header view */
1220 g_object_ref (priv->contents_widget);
1221 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1223 /* Reparent the main paned */
1224 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1225 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1229 g_return_if_reached ();
1232 /* Let header view grab the focus if it's being shown */
1233 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1234 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1236 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1239 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1242 ModestMainWindowStyle
1243 modest_main_window_get_style (ModestMainWindow *self)
1245 ModestMainWindowPrivate *priv;
1247 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1249 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1256 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1258 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1259 ModestWindowPrivate *parent_priv;
1260 ModestWindowMgr *mgr;
1261 gboolean is_fullscreen;
1262 GtkAction *fs_toggle_action;
1265 mgr = modest_runtime_get_window_mgr ();
1267 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1269 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1271 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1272 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1273 if (is_fullscreen != active) {
1274 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1283 set_homogeneous (GtkWidget *widget,
1286 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1287 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1291 modest_main_window_show_toolbar (ModestWindow *self,
1292 gboolean show_toolbar)
1294 ModestMainWindowPrivate *priv = NULL;
1295 ModestWindowPrivate *parent_priv = NULL;
1296 GtkWidget *reply_button = NULL, *menu = NULL;
1297 GtkWidget *placeholder = NULL;
1299 const gchar *action_name;
1302 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1303 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1304 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1306 /* Set optimized view status */
1307 priv->optimized_view = !show_toolbar;
1309 if (!parent_priv->toolbar) {
1310 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1312 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1314 /* Set homogeneous toolbar */
1315 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1316 set_homogeneous, NULL);
1318 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1319 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1320 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1321 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1322 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1323 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1324 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1325 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1327 /* Add ProgressBar (Transfer toolbar) */
1328 priv->progress_bar = modest_progress_bar_widget_new ();
1329 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1330 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1331 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1332 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1333 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1335 /* Connect cancel 'clicked' signal to abort progress mode */
1336 g_signal_connect(priv->cancel_toolitem, "clicked",
1337 G_CALLBACK(cancel_progressbar),
1340 /* Add it to the observers list */
1341 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1344 hildon_window_add_toolbar (HILDON_WINDOW (self),
1345 GTK_TOOLBAR (parent_priv->toolbar));
1347 /* Set reply button tap and hold menu */
1348 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1349 "/ToolBar/ToolbarMessageReply");
1350 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1351 "/ToolbarReplyCSM");
1352 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1354 /* Set send & receive button tap and hold menu */
1355 update_menus (MODEST_MAIN_WINDOW (self));
1359 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1360 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1361 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1363 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1364 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1366 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1370 /* Update also the actions (to update the toggles in the
1371 menus), we have to do it manually because some other window
1372 of the same time could have changed it (remember that the
1373 toolbar fullscreen mode is shared by all the windows of the
1375 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1376 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarFullScreenMenu";
1378 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
1380 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1381 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1386 on_account_inserted (TnyAccountStore *accoust_store,
1387 TnyAccount *account,
1390 update_menus (MODEST_MAIN_WINDOW (user_data));
1394 on_default_account_changed (ModestAccountMgr* mgr,
1397 update_menus (MODEST_MAIN_WINDOW (user_data));
1401 on_account_removed (TnyAccountStore *accoust_store,
1402 TnyAccount *account,
1405 update_menus (MODEST_MAIN_WINDOW (user_data));
1409 * This function manages the key events used to navigate between
1410 * header and folder views (when the window is in split view)
1413 * -------------------------------------------------
1414 * HeaderView GDK_Left Move focus to folder view
1415 * FolderView GDK_Right Move focus to header view
1417 * There is no need to scroll to selected row, the widgets will be the
1418 * responsibles of doing that (probably managing the focus-in event
1421 on_inner_widgets_key_pressed (GtkWidget *widget,
1425 ModestMainWindowPrivate *priv;
1427 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1429 /* Do nothing if we're in SIMPLE style */
1430 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1433 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1434 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1435 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1436 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1442 set_alignment (GtkWidget *widget,
1445 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1446 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1450 create_empty_view (void)
1452 GtkLabel *label = NULL;
1453 GtkWidget *align = NULL;
1455 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1456 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1457 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1458 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1460 return GTK_WIDGET(align);
1464 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1466 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1471 gchar *gray_color_markup;
1473 vbox = gtk_vbox_new (FALSE, 0);
1475 /* Obtain the secondary text color. We need a realized widget, that's why
1476 we get styled_widget from outside */
1477 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1479 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1480 gray_color_markup = modest_text_utils_get_color_string (&color);
1482 // gray_color_markup is freed below
1483 gray_color_markup = g_strdup ("#BBBBBB");
1485 /* Account description: */
1487 if (modest_tny_account_is_virtual_local_folders (account)
1488 || (modest_tny_account_is_memory_card_account (account))) {
1490 /* Local folders: */
1492 /* Get device name */
1493 gchar *device_name = NULL;
1494 if (modest_tny_account_is_virtual_local_folders (account))
1495 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1496 MODEST_CONF_DEVICE_NAME, NULL);
1498 device_name = g_strdup (tny_account_get_name (account));
1500 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1501 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1502 gray_color_markup, tmp, device_name);
1504 label_w = gtk_label_new (NULL);
1505 gtk_label_set_markup (GTK_LABEL (label_w), label);
1506 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1507 g_free (device_name);
1510 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1511 gtk_box_pack_start (GTK_BOX (vbox),
1512 gtk_label_new (tny_account_get_name (account)),
1515 /* Other accounts, such as IMAP and POP: */
1520 /* Put proto in uppercase */
1521 proto = g_string_new (tny_account_get_proto (account));
1522 proto = g_string_ascii_up (proto);
1524 /* note: mcen_fi_localroot_description is something like "%s account"
1525 * however, we should display "%s account: %s"... therefore, ugly tmp */
1526 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1527 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1528 gray_color_markup, tmp, tny_account_get_name (account));
1531 label_w = gtk_label_new (NULL);
1532 gtk_label_set_markup (GTK_LABEL (label_w), label);
1533 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1534 g_string_free (proto, TRUE);
1540 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1541 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1542 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1543 modest_tny_folder_store_get_message_count (folder_store));
1544 label_w = gtk_label_new (NULL);
1545 gtk_label_set_markup (GTK_LABEL (label_w), label);
1546 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1550 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1552 _("mcen_fi_rootfolder_folders"),
1553 modest_tny_folder_store_get_folder_count (folder_store));
1554 label_w = gtk_label_new (NULL);
1555 gtk_label_set_markup (GTK_LABEL (label_w), label);
1556 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1560 if (modest_tny_account_is_virtual_local_folders (account)
1561 || modest_tny_account_is_memory_card_account (account)) {
1563 gchar *size = modest_text_utils_get_display_size (
1564 modest_tny_folder_store_get_local_size (folder_store));
1566 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1567 gray_color_markup, _("mcen_fi_rootfolder_size"),
1571 label_w = gtk_label_new (NULL);
1572 gtk_label_set_markup (GTK_LABEL (label_w), label);
1573 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1575 } else if (TNY_IS_ACCOUNT(folder_store)) {
1576 TnyAccount *account = TNY_ACCOUNT(folder_store);
1578 time_t last_updated;
1579 gchar *last_updated_string;
1580 /* Get last updated from configuration */
1581 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1582 tny_account_get_id (account),
1583 MODEST_ACCOUNT_LAST_UPDATED,
1585 if (last_updated > 0)
1586 last_updated_string = modest_text_utils_get_display_date(last_updated);
1588 last_updated_string = g_strdup (_("mcen_va_never"));
1590 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1591 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1592 label_w = gtk_label_new (NULL);
1593 gtk_label_set_markup (GTK_LABEL (label_w), label);
1594 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1595 g_free (last_updated_string);
1599 g_free (gray_color_markup);
1602 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1608 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1610 ModestMainWindowPrivate *priv = NULL;
1612 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1614 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1616 return priv->send_receive_in_progress;
1620 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1622 GtkAction *action = NULL;
1623 GtkWidget *widget = NULL;
1624 ModestMainWindowPrivate *priv = NULL;
1626 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1627 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1629 priv->send_receive_in_progress = TRUE;
1631 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1632 gtk_action_set_sensitive (action, FALSE);
1633 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1634 /* gtk_action_set_sensitive (action, FALSE); */
1635 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1636 gtk_widget_set_sensitive (widget, FALSE);
1640 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1642 GtkAction *action = NULL;
1643 GtkWidget *widget = NULL;
1644 ModestMainWindowPrivate *priv = NULL;
1646 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1647 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1649 priv->send_receive_in_progress = FALSE;
1651 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1652 gtk_action_set_sensitive (action, TRUE);
1653 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1654 /* gtk_action_set_sensitive (action, TRUE); */
1655 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1656 gtk_widget_set_sensitive (widget, TRUE);
1661 on_msg_count_changed (ModestHeaderView *header_view,
1663 TnyFolderChange *change,
1664 ModestMainWindow *main_window)
1666 gboolean folder_empty = FALSE;
1667 gboolean all_marked_as_deleted = FALSE;
1668 TnyFolderChangeChanged changed;
1669 ModestMainWindowPrivate *priv;
1671 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1672 g_return_if_fail (TNY_IS_FOLDER(folder));
1673 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1674 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1676 changed = tny_folder_change_get_changed (change);
1678 /* If something changes */
1679 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1680 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1682 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1684 /* Check header removed (hide marked as DELETED headers) */
1685 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1686 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1689 /* Check if all messages are marked to be deleted */
1690 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1691 folder_empty = folder_empty || all_marked_as_deleted ;
1693 /* Set contents style of headers view */
1695 modest_main_window_set_contents_style (main_window,
1696 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1697 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1700 modest_main_window_set_contents_style (main_window,
1701 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1707 modest_main_window_set_contents_style (ModestMainWindow *self,
1708 ModestMainWindowContentsStyle style)
1710 ModestMainWindowPrivate *priv;
1712 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1714 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1716 /* We allow to set the same content style than the previously
1717 set if there are details, because it could happen when we're
1718 selecting different accounts consecutively */
1719 if ((priv->contents_style == style) &&
1720 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1723 /* Remove previous child. Delete it if it was an account
1725 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1727 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1728 g_object_ref (content);
1729 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1730 g_object_ref (priv->empty_view);
1731 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1734 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1737 priv->contents_style = style;
1739 switch (priv->contents_style) {
1740 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1741 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1742 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1745 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1747 /* if we're started without main win, there may not be a folder
1748 * view. this fixes a GLib-Critical */
1749 if (priv->folder_view) {
1750 TnyFolderStore *selected_folderstore =
1751 modest_folder_view_get_selected (priv->folder_view);
1752 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1753 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1754 TNY_ACCOUNT (selected_folderstore));
1756 wrap_in_scrolled_window (priv->contents_widget,
1757 priv->details_widget);
1759 g_object_unref (selected_folderstore);
1760 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1765 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1766 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1767 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1771 g_return_if_reached ();
1775 gtk_widget_show_all (priv->contents_widget);
1778 ModestMainWindowContentsStyle
1779 modest_main_window_get_contents_style (ModestMainWindow *self)
1781 ModestMainWindowPrivate *priv;
1783 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1785 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1786 return priv->contents_style;
1791 on_configuration_key_changed (ModestConf* conf,
1793 ModestConfEvent event,
1794 ModestConfNotificationId id,
1795 ModestMainWindow *self)
1797 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1798 TnyAccount *account = NULL;
1800 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1803 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1806 if (priv->folder_view)
1807 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1809 if (account && TNY_IS_ACCOUNT (account) &&
1810 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1813 const gchar *device_name;
1817 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1818 label = GTK_LABEL (children->data);
1820 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1821 MODEST_CONF_DEVICE_NAME, NULL);
1823 new_text = g_strdup_printf ("%s: %s",
1824 _("mcen_fi_localroot_description"),
1827 gtk_label_set_text (label, new_text);
1828 gtk_widget_show (GTK_WIDGET (label));
1831 g_list_free (children);
1833 g_object_unref (account);
1837 set_toolbar_transfer_mode (ModestMainWindow *self)
1839 ModestMainWindowPrivate *priv = NULL;
1841 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1843 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1845 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1847 if (priv->progress_bar_timeout > 0) {
1848 g_source_remove (priv->progress_bar_timeout);
1849 priv->progress_bar_timeout = 0;
1856 set_toolbar_mode (ModestMainWindow *self,
1857 ModestToolBarModes mode)
1859 ModestWindowPrivate *parent_priv = NULL;
1860 ModestMainWindowPrivate *priv = NULL;
1861 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1863 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1865 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1866 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1868 /* In case this was called before the toolbar exists: */
1869 if (!(parent_priv->toolbar))
1872 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1874 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1875 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1876 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1878 /* Sets current toolbar mode */
1879 priv->current_toolbar_mode = mode;
1881 /* Checks the dimming rules */
1882 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1884 /* Show and hide toolbar items */
1886 case TOOLBAR_MODE_NORMAL:
1888 gtk_action_set_visible (sort_action, TRUE);
1890 gtk_action_set_visible (refresh_action, TRUE);
1891 if (priv->progress_toolitem) {
1892 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1893 gtk_widget_hide (priv->progress_toolitem);
1895 if (priv->progress_bar)
1896 gtk_widget_hide (priv->progress_bar);
1899 gtk_action_set_visible (cancel_action, FALSE);
1901 /* Hide toolbar if optimized view is enabled */
1902 if (priv->optimized_view)
1903 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1905 case TOOLBAR_MODE_TRANSFER:
1907 gtk_action_set_visible (sort_action, FALSE);
1909 gtk_action_set_visible (refresh_action, FALSE);
1911 gtk_action_set_visible (cancel_action, TRUE);
1912 if (priv->progress_toolitem) {
1913 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1914 gtk_widget_show (priv->progress_toolitem);
1916 if (priv->progress_bar)
1917 gtk_widget_show (priv->progress_bar);
1919 /* Show toolbar if it's hiden (optimized view ) */
1920 if (priv->optimized_view)
1921 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1924 g_return_if_reached ();
1929 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1931 ModestMainWindowPrivate *priv;
1933 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1934 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1936 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1940 cancel_progressbar (GtkToolButton *toolbutton,
1941 ModestMainWindow *self)
1944 ModestMainWindowPrivate *priv;
1946 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1948 /* Get operation observers and cancel all the operations */
1949 tmp = priv->progress_widgets;
1951 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1952 tmp=g_slist_next(tmp);
1957 observers_empty (ModestMainWindow *self)
1960 ModestMainWindowPrivate *priv;
1961 gboolean is_empty = TRUE;
1962 guint pending_ops = 0;
1964 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1965 tmp = priv->progress_widgets;
1967 /* Check all observers */
1968 while (tmp && is_empty) {
1969 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1970 is_empty = pending_ops == 0;
1972 tmp = g_slist_next(tmp);
1979 on_queue_changed (ModestMailOperationQueue *queue,
1980 ModestMailOperation *mail_op,
1981 ModestMailOperationQueueNotification type,
1982 ModestMainWindow *self)
1984 ModestMainWindowPrivate *priv;
1985 ModestMailOperationTypeOperation op_type;
1986 ModestToolBarModes mode;
1988 gboolean mode_changed = FALSE;
1990 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1991 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1993 /* Get toolbar mode from operation id*/
1994 op_type = modest_mail_operation_get_type_operation (mail_op);
1996 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1997 case MODEST_MAIL_OPERATION_TYPE_OPEN:
1998 mode = TOOLBAR_MODE_TRANSFER;
1999 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2000 mode_changed = TRUE;
2003 mode = TOOLBAR_MODE_NORMAL;
2008 /* Add operation observers and change toolbar if neccessary*/
2009 tmp = priv->progress_widgets;
2011 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2012 if (mode == TOOLBAR_MODE_TRANSFER) {
2014 set_toolbar_transfer_mode(self);
2017 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2019 tmp = g_slist_next (tmp);
2023 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2024 /* Change toolbar mode */
2025 if (mode == TOOLBAR_MODE_TRANSFER) {
2027 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2029 tmp = g_slist_next (tmp);
2032 /* If no more operations are being observed, NORMAL mode is enabled again */
2033 if (observers_empty (self)) {
2034 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2044 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2046 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2049 /* Get account data */
2050 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2051 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2053 /* Set the new visible & active account */
2054 if (acc_data && acc_data->store_account) {
2055 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2056 acc_data->store_account->account_name);
2057 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2058 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2059 if (action != NULL) {
2060 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2061 modest_maemo_toggle_action_set_active_block_notify (
2062 GTK_TOGGLE_ACTION (action),
2068 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2073 modest_account_mgr_free_account_data (mgr, acc_data);
2076 /* Make sure that at least one account is "viewed": */
2078 set_at_least_one_account_visible(ModestMainWindow *self)
2080 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2081 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2083 if (!(priv->folder_view)) {
2084 /* It is too early to do this. */
2088 const gchar *active_server_account_name =
2089 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2090 if (!active_server_account_name ||
2091 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2093 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2094 if (first_modest_name) {
2095 set_account_visible (self, first_modest_name);
2096 g_free (first_modest_name);
2102 on_show_account_action_toggled (GtkToggleAction *action,
2105 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2107 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2108 if (gtk_toggle_action_get_active (action))
2109 set_account_visible (self, acc_name);
2113 refresh_account (const gchar *account_name)
2117 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2119 /* If account_name == NULL, we must update all (option All) */
2121 modest_ui_actions_do_send_receive_all (win);
2123 modest_ui_actions_do_send_receive (account_name, win);
2128 on_refresh_account_action_activated (GtkAction *action,
2131 refresh_account ((const gchar*) user_data);
2135 on_send_receive_csm_activated (GtkMenuItem *item,
2138 refresh_account ((const gchar*) user_data);
2142 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2144 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2146 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2152 on_folder_view_focus_in (GtkWidget *widget,
2153 GdkEventFocus *event,
2156 ModestMainWindow *main_window = NULL;
2158 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2159 main_window = MODEST_MAIN_WINDOW (userdata);
2161 /* Update toolbar dimming state */
2162 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2168 on_header_view_focus_in (GtkWidget *widget,
2169 GdkEventFocus *event,
2172 ModestMainWindow *main_window = NULL;
2173 ModestMainWindowPrivate *priv = NULL;
2175 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2176 main_window = MODEST_MAIN_WINDOW (userdata);
2177 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2179 /* Update toolbar dimming state */
2180 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2186 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2187 TnyFolderStore *folder_store,
2189 ModestMainWindow *main_window)
2191 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2192 GtkAction *action = NULL;
2193 gboolean show_reply = TRUE;
2194 gboolean show_forward = TRUE;
2195 gboolean show_cancel_send = FALSE;
2196 gboolean show_clipboard = TRUE;
2197 gboolean show_delete = TRUE;
2200 if (TNY_IS_ACCOUNT (folder_store)) {
2201 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2202 } else if (TNY_IS_FOLDER (folder_store)) {
2203 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2204 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2205 TNY_FOLDER (folder_store));
2206 switch (folder_type) {
2207 case TNY_FOLDER_TYPE_DRAFTS:
2208 show_clipboard = show_delete = TRUE;
2209 show_reply = show_forward = show_cancel_send = FALSE;
2211 case TNY_FOLDER_TYPE_SENT:
2212 show_forward = show_clipboard = show_delete = TRUE;
2213 show_reply = show_cancel_send = FALSE;
2215 case TNY_FOLDER_TYPE_OUTBOX:
2216 show_clipboard = show_delete = show_cancel_send = TRUE;
2217 show_reply = show_forward = FALSE;
2220 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2221 show_cancel_send = FALSE;
2224 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2225 show_cancel_send = FALSE;
2230 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2231 gtk_action_set_visible (action, show_reply);
2232 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2233 gtk_action_set_visible (action, show_reply);
2234 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2235 gtk_action_set_visible (action, show_forward);
2236 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2237 gtk_action_set_visible (action, show_cancel_send);
2238 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2239 gtk_action_set_visible (action, show_delete);
2241 /* We finally call to the ui actions handler, after updating properly
2242 * the header view CSM */
2243 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2247 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2248 GtkTreeModel *model,
2249 GtkTreeRowReference *row_reference,
2250 ModestMainWindow *self)
2252 ModestMainWindowPrivate *priv = NULL;
2253 GtkTreeModel *header_model = NULL;
2254 GtkTreePath *path = NULL;
2256 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2257 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2258 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2260 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2261 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2263 /* Do nothing if we changed the folder in the main view */
2264 if (header_model != model)
2267 /* Select the message in the header view */
2268 path = gtk_tree_row_reference_get_path (row_reference);
2269 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2271 gtk_tree_path_free (path);