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,
125 static void on_default_account_changed (ModestAccountMgr* mgr,
128 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
132 static void on_configuration_key_changed (ModestConf* conf,
134 ModestConfEvent event,
135 ModestConfNotificationId id,
136 ModestMainWindow *self);
138 static void set_toolbar_mode (ModestMainWindow *self,
139 ModestToolBarModes mode);
141 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
143 static void on_show_account_action_toggled (GtkToggleAction *action,
146 static void on_refresh_account_action_activated (GtkAction *action,
149 static void on_send_receive_csm_activated (GtkMenuItem *item,
152 static void on_msg_count_changed (ModestHeaderView *header_view,
154 TnyFolderChange *change,
155 ModestMainWindow *main_window);
157 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
160 static GtkWidget * create_empty_view (void);
162 static gboolean on_folder_view_focus_in (GtkWidget *widget,
163 GdkEventFocus *event,
166 static gboolean on_header_view_focus_in (GtkWidget *widget,
167 GdkEventFocus *event,
170 static void modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
171 TnyFolderStore *folder_store,
173 ModestMainWindow *main_window);
175 static void set_at_least_one_account_visible(ModestMainWindow *self);
177 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
178 struct _ModestMainWindowPrivate {
179 GtkWidget *msg_paned;
180 GtkWidget *main_paned;
181 GtkWidget *main_vbox;
182 GtkWidget *contents_widget;
183 GtkWidget *empty_view;
185 /* Progress observers */
186 GtkWidget *progress_bar;
187 GSList *progress_widgets;
190 GtkWidget *progress_toolitem;
191 GtkWidget *cancel_toolitem;
192 GtkWidget *sort_toolitem;
193 GtkWidget *refresh_toolitem;
194 ModestToolBarModes current_toolbar_mode;
196 /* Merge ids used to add/remove accounts to the ViewMenu*/
197 GByteArray *merge_ids;
198 GtkActionGroup *view_additions_group;
200 /* On-demand widgets */
201 GtkWidget *accounts_popup;
202 GtkWidget *details_widget;
204 /* Optimized view enabled */
205 gboolean optimized_view;
207 /* Optimized view enabled */
208 gboolean send_receive_in_progress;
210 ModestHeaderView *header_view;
211 ModestFolderView *folder_view;
213 ModestMainWindowStyle style;
214 ModestMainWindowContentsStyle contents_style;
216 guint progress_bar_timeout;
218 /* Signal handler UIDs */
219 GList *queue_err_signals;
222 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
223 MODEST_TYPE_MAIN_WINDOW, \
224 ModestMainWindowPrivate))
226 typedef struct _GetMsgAsyncHelper {
227 ModestMainWindowPrivate *main_window_private;
229 ModestTnyMsgReplyType reply_type;
230 ModestTnyMsgForwardType forward_type;
237 static GtkWindowClass *parent_class = NULL;
240 /* Private actions */
241 /* This is the context sensitive menu: */
242 static const GtkActionEntry modest_folder_view_action_entries [] = {
244 /* Folder View CSM actions */
245 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
246 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
247 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
248 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
249 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
250 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
253 static const GtkActionEntry modest_header_view_action_entries [] = {
255 /* Header View CSM actions */
256 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
257 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
258 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
259 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
260 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
261 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
262 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
263 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
264 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
265 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
268 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
269 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
272 /************************************************************************/
275 modest_main_window_get_type (void)
277 static GType my_type = 0;
279 static const GTypeInfo my_info = {
280 sizeof(ModestMainWindowClass),
281 NULL, /* base init */
282 NULL, /* base finalize */
283 (GClassInitFunc) modest_main_window_class_init,
284 NULL, /* class finalize */
285 NULL, /* class data */
286 sizeof(ModestMainWindow),
288 (GInstanceInitFunc) modest_main_window_init,
291 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
299 modest_main_window_class_init (ModestMainWindowClass *klass)
301 GObjectClass *gobject_class;
302 gobject_class = (GObjectClass*) klass;
303 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
305 parent_class = g_type_class_peek_parent (klass);
306 gobject_class->finalize = modest_main_window_finalize;
308 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
310 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
311 modest_window_class->save_state_func = save_state;
312 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
313 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
314 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
318 modest_main_window_init (ModestMainWindow *obj)
320 ModestMainWindowPrivate *priv;
322 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
324 priv->queue_err_signals = NULL;
325 priv->msg_paned = NULL;
326 priv->main_paned = NULL;
327 priv->main_vbox = NULL;
328 priv->header_view = NULL;
329 priv->folder_view = NULL;
330 priv->contents_widget = NULL;
331 priv->accounts_popup = NULL;
332 priv->details_widget = NULL;
333 priv->empty_view = NULL;
334 priv->progress_widgets = NULL;
335 priv->progress_bar = NULL;
336 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
337 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
338 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
339 priv->merge_ids = NULL;
340 priv->optimized_view = FALSE;
341 priv->send_receive_in_progress = FALSE;
342 priv->progress_bar_timeout = 0;
343 priv->sighandlers = NULL;
347 modest_main_window_finalize (GObject *obj)
349 ModestMainWindowPrivate *priv;
351 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
353 /* Sanity check: shouldn't be needed, the window mgr should
354 call this function before */
355 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
357 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
359 g_slist_free (priv->progress_widgets);
361 g_byte_array_free (priv->merge_ids, TRUE);
363 if (priv->progress_bar_timeout > 0) {
364 g_source_remove (priv->progress_bar_timeout);
365 priv->progress_bar_timeout = 0;
368 G_OBJECT_CLASS(parent_class)->finalize (obj);
372 modest_main_window_get_child_widget (ModestMainWindow *self,
373 ModestMainWindowWidgetType widget_type)
375 ModestMainWindowPrivate *priv;
378 g_return_val_if_fail (self, NULL);
379 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
382 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
384 switch (widget_type) {
385 case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
386 widget = (GtkWidget*)priv->header_view; break;
387 case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
388 widget = (GtkWidget*)priv->folder_view; break;
393 return widget ? GTK_WIDGET(widget) : NULL;
398 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
401 ModestMainWindowPrivate *priv;
403 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
405 conf = modest_runtime_get_conf ();
407 modest_widget_memory_restore (conf, G_OBJECT(self),
408 MODEST_CONF_MAIN_WINDOW_KEY);
410 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
411 MODEST_CONF_HEADER_VIEW_KEY);
413 if (do_folder_view_too)
414 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
415 MODEST_CONF_FOLDER_VIEW_KEY);
417 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
418 MODEST_CONF_MAIN_PANED_KEY);
420 /* We need to force a redraw here in order to get the right
421 position of the horizontal paned separator */
422 gtk_widget_show (GTK_WIDGET (self));
427 save_state (ModestWindow *window)
430 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
431 ModestMainWindowPrivate *priv;
433 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
434 conf = modest_runtime_get_conf ();
436 modest_widget_memory_save (conf,G_OBJECT(self),
437 MODEST_CONF_MAIN_WINDOW_KEY);
438 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
439 MODEST_CONF_MAIN_PANED_KEY);
440 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
441 // MODEST_CONF_HEADER_VIEW_KEY);
442 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
443 MODEST_CONF_FOLDER_VIEW_KEY);
447 compare_display_names (ModestAccountData *a,
448 ModestAccountData *b)
450 return strcmp (a->display_name, b->display_name);
454 update_menus (ModestMainWindow* self)
456 GSList *account_names, *iter, *accounts;
457 ModestMainWindowPrivate *priv;
458 ModestWindowPrivate *parent_priv;
459 ModestAccountMgr *mgr;
460 gint i, num_accounts;
462 gchar *default_account;
463 GtkWidget *send_receive_button, *item;
464 GtkAction *send_receive_all = NULL;
467 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
468 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
470 /* Get enabled account IDs */
471 mgr = modest_runtime_get_account_mgr ();
472 account_names = modest_account_mgr_account_names (mgr, TRUE);
473 iter = account_names;
477 ModestAccountData *account_data =
478 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
479 accounts = g_slist_prepend (accounts, account_data);
483 modest_account_mgr_free_account_names (account_names);
484 account_names = NULL;
486 /* Order the list of accounts by its display name */
487 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
488 num_accounts = g_slist_length (accounts);
490 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
491 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
492 gtk_action_set_visible (send_receive_all, num_accounts > 1);
494 /* Delete old send&receive popup items. We can not just do a
495 menu_detach because it does not work well with
497 if (priv->accounts_popup)
498 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
499 (GtkCallback) gtk_widget_destroy, NULL);
501 /* Delete old entries in the View menu. Do not free groups, it
503 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
505 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
506 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
507 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
508 GTK_ACTION_GROUP (groups->data));
511 if (priv->merge_ids) {
512 for (i = 0; i < priv->merge_ids->len; i++)
513 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
514 g_byte_array_free (priv->merge_ids, TRUE);
516 /* We need to call this in order to ensure
517 that the new actions are added in the right
518 order (alphabetical */
519 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
521 groups = g_list_next (groups);
523 priv->merge_ids = g_byte_array_sized_new (num_accounts);
525 /* Get send receive button */
526 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
527 "/ToolBar/ToolbarSendReceive");
529 /* Create the menu */
530 if (num_accounts > 1) {
531 if (!priv->accounts_popup)
532 priv->accounts_popup = gtk_menu_new ();
533 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
534 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
535 g_signal_connect (G_OBJECT (item),
537 G_CALLBACK (on_send_receive_csm_activated),
539 item = gtk_separator_menu_item_new ();
540 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
543 /* Create a new action group */
544 default_account = modest_account_mgr_get_default_account (mgr);
545 priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
547 for (i = 0; i < num_accounts; i++) {
548 gchar *display_name = NULL;
550 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
552 /* Create display name. The UI specification specifies a different format string
553 * to use for the default account, though both seem to be "%s", so
554 * I don't see what the point is. murrayc. */
555 if (default_account && account_data->account_name &&
556 !(strcmp (default_account, account_data->account_name) == 0)) {
557 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
558 account_data->display_name);
561 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
562 account_data->display_name);
565 /* Create action and add it to the action group. The
566 action name must be the account name, this way we
567 could know in the handlers the account to show */
568 if(account_data && account_data->account_name) {
569 gchar* item_name, *refresh_action_name;
571 GtkAction *view_account_action, *refresh_account_action;
573 view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
574 display_name, NULL, NULL, 0));
575 gtk_action_group_add_action (priv->view_additions_group, view_account_action);
576 gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
577 radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
579 if (default_account && account_data->account_name &&
580 (strcmp (default_account, account_data->account_name) == 0)) {
581 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
584 /* Add ui from account data. We allow 2^9-1 account
585 changes in a single execution because we're
586 downcasting the guint to a guint8 in order to use a
587 GByteArray. It should be enough. */
588 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
589 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
590 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
591 gtk_ui_manager_add_ui (parent_priv->ui_manager,
593 "/MenuBar/ViewMenu/ViewMenuAdditions",
595 account_data->account_name,
596 GTK_UI_MANAGER_MENUITEM,
599 /* Connect the action signal "activate" */
600 g_signal_connect_after (G_OBJECT (view_account_action),
602 G_CALLBACK (on_show_account_action_toggled),
605 /* Create the items for the Tools->Send&Receive submenu */
606 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
607 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
608 display_name, NULL, NULL);
609 gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
611 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
612 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
613 gtk_ui_manager_add_ui (parent_priv->ui_manager,
615 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
618 GTK_UI_MANAGER_MENUITEM,
620 g_free (refresh_action_name);
622 g_signal_connect_data (G_OBJECT (refresh_account_action),
624 G_CALLBACK (on_refresh_account_action_activated),
625 g_strdup (account_data->account_name),
626 (GClosureNotify) g_free,
629 /* Create item and add it to the send&receive
630 CSM. If there is only one account then
632 if (priv->accounts_popup) {
633 GtkWidget *label = gtk_label_new(NULL);
634 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
635 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
637 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
638 gtk_label_set_markup (GTK_LABEL (label), escaped);
643 gtk_label_set_text (GTK_LABEL (label), display_name);
646 item = gtk_menu_item_new ();
647 gtk_container_add (GTK_CONTAINER (item), label);
649 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
650 g_signal_connect_data (G_OBJECT (item),
652 G_CALLBACK (on_send_receive_csm_activated),
653 g_strdup (account_data->account_name),
654 (GClosureNotify) g_free,
661 g_free (display_name);
664 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
666 /* We cannot do this in the loop above because this relies on the action
667 * group being inserted. This makes the default account appear in bold.
668 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
669 for (i = 0; i < num_accounts; i++) {
670 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
672 if(account_data->account_name && default_account &&
673 strcmp (account_data->account_name, default_account) == 0) {
674 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
676 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
677 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
681 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
682 if (GTK_IS_LABEL (child)) {
683 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
684 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
685 gtk_label_set_markup (GTK_LABEL (child), bold_name);
690 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
691 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
695 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
696 if (GTK_IS_LABEL (child)) {
697 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
698 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
699 gtk_label_set_markup (GTK_LABEL (child), bold_name);
707 modest_account_mgr_free_account_data (mgr, account_data);
710 if (priv->accounts_popup) {
711 /* Mandatory in order to view the menu contents */
712 gtk_widget_show_all (priv->accounts_popup);
714 /* Setup tap_and_hold just if was not done before*/
715 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
716 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
720 g_slist_free (accounts);
721 g_free (default_account);
724 /* Make sure that at least one account is viewed if there are any
725 * accounts, for instance when adding the first account: */
726 set_at_least_one_account_visible (self);
730 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
732 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
733 gtk_scrolled_window_add_with_viewport
734 (GTK_SCROLLED_WINDOW(win), widget);
736 gtk_container_add (GTK_CONTAINER(win),
747 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
749 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
751 GList *oerrsignals = priv->queue_err_signals;
752 while (oerrsignals) {
753 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
754 g_signal_handler_disconnect (esignal->queue, esignal->signal);
755 g_slice_free (QueueErrorSignal, esignal);
756 oerrsignals = g_list_next (oerrsignals);
758 g_list_free (priv->queue_err_signals);
759 priv->queue_err_signals = NULL;
764 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
766 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
769 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
773 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
775 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
777 /* Update visibility */
780 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
784 modest_main_window_disconnect_signals (ModestWindow *self)
786 ModestMainWindowPrivate *priv;
787 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
789 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
790 priv->sighandlers = NULL;
794 connect_signals (ModestMainWindow *self)
796 ModestWindowPrivate *parent_priv;
797 ModestMainWindowPrivate *priv;
800 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
801 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
806 modest_signal_mgr_connect (priv->sighandlers,
807 G_OBJECT(priv->folder_view), "key-press-event",
808 G_CALLBACK(on_inner_widgets_key_pressed), self);
810 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
811 G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
813 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
814 G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
816 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
817 G_CALLBACK (on_folder_view_focus_in), self);
819 /* Folder view CSM */
820 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
821 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
822 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
823 G_CALLBACK(_folder_view_csm_menu_activated),
827 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
828 G_CALLBACK(modest_ui_actions_on_header_selected), self);
830 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
831 G_CALLBACK(modest_ui_actions_on_header_activated), self);
833 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
834 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
836 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
837 G_CALLBACK(on_inner_widgets_key_pressed), self);
839 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
840 G_CALLBACK(on_msg_count_changed), self);
842 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 */
859 modest_signal_mgr_connect (priv->sighandlers,
860 G_OBJECT (modest_runtime_get_mail_operation_queue ()),
862 G_CALLBACK (on_queue_changed), self);
864 /* Track changes in the device name */
866 modest_signal_mgr_connect (priv->sighandlers,
867 G_OBJECT(modest_runtime_get_conf ()),
869 G_CALLBACK (on_configuration_key_changed),
872 /* Track account changes. We need to refresh the toolbar */
874 modest_signal_mgr_connect (priv->sighandlers,
875 G_OBJECT (modest_runtime_get_account_store ()),
877 G_CALLBACK (on_account_inserted),
880 modest_signal_mgr_connect (priv->sighandlers,
881 G_OBJECT (modest_runtime_get_account_store ()),
883 G_CALLBACK (on_account_removed),
886 /* We need to refresh the send & receive menu to change the bold
887 * account when the default account changes. */
889 modest_signal_mgr_connect (priv->sighandlers,
890 G_OBJECT (modest_runtime_get_account_mgr ()),
891 "default_account_changed",
892 G_CALLBACK (on_default_account_changed),
897 modest_signal_mgr_connect (priv->sighandlers,
898 G_OBJECT (modest_runtime_get_account_store()),
899 "password_requested",
900 G_CALLBACK (modest_ui_actions_on_password_requested),
905 /** Idle handler, to send/receive at startup .*/
907 sync_accounts_cb (ModestMainWindow *win)
909 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
910 return FALSE; /* Do not call this idle handler again. */
915 on_hildon_program_is_topmost_notify(GObject *self,
916 GParamSpec *propert_param, gpointer user_data)
918 HildonProgram *app = HILDON_PROGRAM (self);
921 ModestWindow* self = MODEST_WINDOW(user_data);
924 /* Note that use of hildon_program_set_can_hibernate()
925 * is generally referred to as "setting the killable flag",
926 * though hibernation does not seem equal to death.
929 if (hildon_program_get_is_topmost (app)) {
930 /* Prevent hibernation when the progam comes to the foreground,
931 * because hibernation should only happen when the application
932 * is in the background: */
933 hildon_program_set_can_hibernate (app, FALSE);
935 /* Allow hibernation if the program has gone to the background: */
937 /* However, prevent hibernation while the settings are being changed: */
938 const gboolean hibernation_prevented =
939 modest_window_mgr_get_hibernation_is_prevented (
940 modest_runtime_get_window_mgr ());
942 if (hibernation_prevented)
943 hildon_program_set_can_hibernate (app, FALSE);
945 /* Allow hibernation, after saving the state: */
946 modest_osso_save_state();
947 hildon_program_set_can_hibernate (app, TRUE);
954 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
956 GtkWidget *folder_win = (GtkWidget *) user_data;
957 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
959 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
960 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
961 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
963 gtk_widget_show (GTK_WIDGET (priv->folder_view));
965 /* Connect signals */
966 connect_signals ((ModestMainWindow*)self);
968 /* Set account store */
969 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
970 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
972 /* Load previous osso state, for instance if we are being restored from
974 modest_osso_load_state ();
976 /* Restore window & widget settings */
978 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
980 /* The UI spec wants us to show a connection dialog when the application is
981 * started by the user, if there is no connection.
982 * Do this before showing the account wizard,
983 * because wizard needs a connection to discover capabilities. */
984 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
986 /* Check if accounts exist and show the account wizard if not */
987 gboolean accounts_exist =
988 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
990 if (!accounts_exist) {
991 /* This is necessary to have the main window shown behind the dialog
992 It's an ugly hack... jschmid */
993 gtk_widget_show_all(GTK_WIDGET(self));
994 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
997 GtkAction *send_receive_all;
998 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
999 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1000 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1001 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1002 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1003 modest_account_mgr_free_account_names (accounts);
1008 modest_main_window_new (void)
1010 ModestMainWindow *self = NULL;
1011 ModestMainWindowPrivate *priv = NULL;
1012 ModestWindowPrivate *parent_priv = NULL;
1013 GtkWidget *folder_win = NULL;
1014 ModestDimmingRulesGroup *menu_rules_group = NULL;
1015 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1016 GtkActionGroup *action_group = NULL;
1017 GError *error = NULL;
1018 ModestConf *conf = NULL;
1019 GtkAction *action = NULL;
1020 GdkPixbuf *window_icon;
1022 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1023 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1024 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1026 parent_priv->ui_manager = gtk_ui_manager_new();
1027 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1029 action_group = gtk_action_group_new ("ModestMainWindowActions");
1030 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1032 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1033 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1035 /* Add common actions */
1036 gtk_action_group_add_actions (action_group,
1037 modest_action_entries,
1038 G_N_ELEMENTS (modest_action_entries),
1041 gtk_action_group_add_actions (action_group,
1042 modest_folder_view_action_entries,
1043 G_N_ELEMENTS (modest_folder_view_action_entries),
1046 gtk_action_group_add_actions (action_group,
1047 modest_header_view_action_entries,
1048 G_N_ELEMENTS (modest_header_view_action_entries),
1051 gtk_action_group_add_toggle_actions (action_group,
1052 modest_toggle_action_entries,
1053 G_N_ELEMENTS (modest_toggle_action_entries),
1056 gtk_action_group_add_toggle_actions (action_group,
1057 modest_main_window_toggle_action_entries,
1058 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1061 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1062 g_object_unref (action_group);
1064 /* Load the UI definition */
1065 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1066 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1067 if (error != NULL) {
1068 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1069 g_error_free (error);
1073 /* Add common dimming rules */
1074 modest_dimming_rules_group_add_rules (menu_rules_group,
1075 modest_main_window_menu_dimming_entries,
1076 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1077 MODEST_WINDOW (self));
1078 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1079 modest_main_window_toolbar_dimming_entries,
1080 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1081 MODEST_WINDOW (self));
1083 /* Insert dimming rules group for this window */
1084 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1085 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1086 g_object_unref (menu_rules_group);
1087 g_object_unref (toolbar_rules_group);
1089 /* Add accelerators */
1090 gtk_window_add_accel_group (GTK_WINDOW (self),
1091 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1093 /* Menubar. Update the state of some toggles */
1094 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1095 conf = modest_runtime_get_conf ();
1096 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1097 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1098 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1099 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1100 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1101 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1102 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1103 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1104 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1105 gtk_widget_show (parent_priv->menubar);
1107 /* Get device name */
1108 modest_maemo_utils_get_device_name ();
1112 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1113 if (!priv->header_view)
1114 g_printerr ("modest: cannot instantiate header view\n");
1115 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1116 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1117 MODEST_CONF_HEADER_VIEW_KEY);
1119 /* Other style properties of header view */
1120 g_object_set (G_OBJECT (priv->header_view),
1121 "rules-hint", FALSE,
1123 /* gtk_widget_show (priv->header_view); */
1126 priv->empty_view = create_empty_view ();
1127 gtk_widget_show (priv->empty_view);
1129 /* Create scrolled windows */
1130 folder_win = gtk_scrolled_window_new (NULL, NULL);
1131 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1132 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1134 GTK_POLICY_AUTOMATIC);
1135 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1137 GTK_POLICY_AUTOMATIC);
1138 /* gtk_widget_show (priv->contents_widget); */
1141 priv->main_paned = gtk_hpaned_new ();
1142 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1143 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1144 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1146 /* putting it all together... */
1147 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1148 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1149 gtk_widget_show (priv->main_vbox);
1151 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1153 HildonProgram *app = hildon_program_get_instance ();
1154 hildon_program_add_window (app, HILDON_WINDOW (self));
1156 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1157 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1159 g_signal_connect (G_OBJECT(self), "show",
1160 G_CALLBACK (modest_main_window_on_show), folder_win);
1162 /* Set window icon */
1163 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1165 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1166 g_object_unref (window_icon);
1169 /* Dont't restore settings here,
1170 * because it requires a gtk_widget_show(),
1171 * and we don't want to do that until later,
1172 * so that the UI is not visible for non-menu D-Bus activation.
1174 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1176 return MODEST_WINDOW(self);
1180 modest_main_window_close_all (ModestMainWindow *self)
1183 GtkResponseType response;
1185 /* Create the confirmation dialog MSG-NOT308 */
1186 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1187 _("emev_nc_close_windows"),
1188 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1189 _("mcen_bd_no"), GTK_RESPONSE_NO,
1192 response = gtk_dialog_run (GTK_DIALOG (note));
1193 gtk_widget_destroy (GTK_WIDGET (note));
1195 if (response == GTK_RESPONSE_YES)
1203 modest_main_window_set_style (ModestMainWindow *self,
1204 ModestMainWindowStyle style)
1206 ModestMainWindowPrivate *priv;
1207 ModestWindowPrivate *parent_priv;
1211 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1213 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1214 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1216 /* no change -> nothing to do */
1217 if (priv->style == style)
1220 /* Get toggle button and update the state if needed. This will
1221 happen only when the set_style is not invoked from the UI,
1222 for example when it's called from widget memory */
1223 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1224 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1225 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1226 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1227 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1228 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1229 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1232 priv->style = style;
1234 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1235 /* Remove main paned */
1236 g_object_ref (priv->main_paned);
1237 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1239 /* Reparent the contents widget to the main vbox */
1240 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1243 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1244 /* Remove header view */
1245 g_object_ref (priv->contents_widget);
1246 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1248 /* Reparent the main paned */
1249 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1250 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1254 g_return_if_reached ();
1257 /* Let header view grab the focus if it's being shown */
1258 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1259 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1261 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1264 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1267 ModestMainWindowStyle
1268 modest_main_window_get_style (ModestMainWindow *self)
1270 ModestMainWindowPrivate *priv;
1272 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1274 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1281 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1283 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1284 ModestWindowPrivate *parent_priv;
1285 ModestWindowMgr *mgr;
1286 gboolean is_fullscreen;
1287 GtkAction *fs_toggle_action;
1290 mgr = modest_runtime_get_window_mgr ();
1292 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1294 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1296 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1297 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1298 if (is_fullscreen != active) {
1299 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1308 set_homogeneous (GtkWidget *widget,
1311 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1312 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1316 modest_main_window_show_toolbar (ModestWindow *self,
1317 gboolean show_toolbar)
1319 ModestMainWindowPrivate *priv = NULL;
1320 ModestWindowPrivate *parent_priv = NULL;
1321 GtkWidget *reply_button = NULL, *menu = NULL;
1322 GtkWidget *placeholder = NULL;
1324 const gchar *action_name;
1327 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1328 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1329 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1331 /* Set optimized view status */
1332 priv->optimized_view = !show_toolbar;
1334 if (!parent_priv->toolbar) {
1335 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1337 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1339 /* Set homogeneous toolbar */
1340 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1341 set_homogeneous, NULL);
1343 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1344 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1345 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1346 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1347 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1348 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1349 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1350 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1352 /* Add ProgressBar (Transfer toolbar) */
1353 priv->progress_bar = modest_progress_bar_widget_new ();
1354 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1355 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1356 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1357 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1358 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1360 /* Connect cancel 'clicked' signal to abort progress mode */
1361 g_signal_connect(priv->cancel_toolitem, "clicked",
1362 G_CALLBACK(cancel_progressbar),
1365 /* Add it to the observers list */
1366 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1369 hildon_window_add_toolbar (HILDON_WINDOW (self),
1370 GTK_TOOLBAR (parent_priv->toolbar));
1372 /* Set reply button tap and hold menu */
1373 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1374 "/ToolBar/ToolbarMessageReply");
1375 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1376 "/ToolbarReplyCSM");
1377 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1379 /* Set send & receive button tap and hold menu */
1380 update_menus (MODEST_MAIN_WINDOW (self));
1384 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1385 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1386 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1388 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1389 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1391 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1395 /* Update also the actions (to update the toggles in the
1396 menus), we have to do it manually because some other window
1397 of the same time could have changed it (remember that the
1398 toolbar fullscreen mode is shared by all the windows of the
1400 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1401 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1403 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1405 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1406 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1411 on_account_inserted (TnyAccountStore *accoust_store,
1412 TnyAccount *account,
1415 update_menus (MODEST_MAIN_WINDOW (user_data));
1419 on_default_account_changed (ModestAccountMgr* mgr,
1422 update_menus (MODEST_MAIN_WINDOW (user_data));
1426 on_account_removed (TnyAccountStore *accoust_store,
1427 TnyAccount *account,
1430 update_menus (MODEST_MAIN_WINDOW (user_data));
1434 * This function manages the key events used to navigate between
1435 * header and folder views (when the window is in split view)
1438 * -------------------------------------------------
1439 * HeaderView GDK_Left Move focus to folder view
1440 * FolderView GDK_Right Move focus to header view
1442 * There is no need to scroll to selected row, the widgets will be the
1443 * responsibles of doing that (probably managing the focus-in event
1446 on_inner_widgets_key_pressed (GtkWidget *widget,
1450 ModestMainWindowPrivate *priv;
1452 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1454 /* Do nothing if we're in SIMPLE style */
1455 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1458 if (MODEST_IS_HEADER_VIEW (widget)) {
1459 if (event->keyval == GDK_Left)
1460 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1461 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1462 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1465 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1466 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1472 set_alignment (GtkWidget *widget,
1475 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1476 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1480 create_empty_view (void)
1482 GtkLabel *label = NULL;
1483 GtkWidget *align = NULL;
1485 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1486 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1487 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1488 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1490 return GTK_WIDGET(align);
1494 * Free the returned string
1497 get_gray_color_markup (GtkWidget *styled_widget)
1499 gchar *gray_color_markup;
1501 /* Obtain the secondary text color. We need a realized widget, that's why
1502 we get styled_widget from outside */
1503 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1505 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1506 gray_color_markup = modest_text_utils_get_color_string (&color);
1508 gray_color_markup = g_strdup ("#BBBBBB");
1510 return gray_color_markup;
1514 * Free the returned string
1517 create_device_name_visual_string (const gchar *device_name,
1518 const gchar *gray_color_markup)
1522 /* We have to use "" to fill the %s of the translation. We can
1523 not just use the device name because the device name is
1524 shown in a different color, so it could not be included
1525 into the <span> tag */
1526 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1527 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1537 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1539 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1544 gchar *gray_color_markup;
1546 vbox = gtk_vbox_new (FALSE, 0);
1548 gray_color_markup = get_gray_color_markup (styled_widget);
1550 /* Account description: */
1551 if (modest_tny_account_is_virtual_local_folders (account)
1552 || (modest_tny_account_is_memory_card_account (account))) {
1554 /* Get device name */
1555 gchar *device_name = NULL;
1556 if (modest_tny_account_is_virtual_local_folders (account))
1557 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1558 MODEST_CONF_DEVICE_NAME, NULL);
1560 device_name = g_strdup (tny_account_get_name (account));
1562 label = create_device_name_visual_string ((const gchar *) device_name,
1563 (const gchar *) gray_color_markup);
1564 label_w = gtk_label_new (NULL);
1565 gtk_label_set_markup (GTK_LABEL (label_w), label);
1566 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1567 g_free (device_name);
1570 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1571 gtk_box_pack_start (GTK_BOX (vbox),
1572 gtk_label_new (tny_account_get_name (account)),
1575 /* Other accounts, such as IMAP and POP: */
1580 /* Put proto in uppercase */
1581 proto = g_string_new (tny_account_get_proto (account));
1582 proto = g_string_ascii_up (proto);
1584 /* note: mcen_fi_localroot_description is something like "%s account"
1585 * however, we should display "%s account: %s"... therefore, ugly tmp */
1586 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1587 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1588 gray_color_markup, tmp, tny_account_get_name (account));
1591 label_w = gtk_label_new (NULL);
1592 gtk_label_set_markup (GTK_LABEL (label_w), label);
1593 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1594 g_string_free (proto, TRUE);
1600 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1601 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1602 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1603 modest_tny_folder_store_get_message_count (folder_store));
1604 label_w = gtk_label_new (NULL);
1605 gtk_label_set_markup (GTK_LABEL (label_w), label);
1606 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1610 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1612 _("mcen_fi_rootfolder_folders"),
1613 modest_tny_folder_store_get_folder_count (folder_store));
1614 label_w = gtk_label_new (NULL);
1615 gtk_label_set_markup (GTK_LABEL (label_w), label);
1616 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1620 if (modest_tny_account_is_virtual_local_folders (account)
1621 || modest_tny_account_is_memory_card_account (account)) {
1623 gchar *size = modest_text_utils_get_display_size (
1624 modest_tny_folder_store_get_local_size (folder_store));
1626 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1627 gray_color_markup, _("mcen_fi_rootfolder_size"),
1631 label_w = gtk_label_new (NULL);
1632 gtk_label_set_markup (GTK_LABEL (label_w), label);
1633 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1635 } else if (TNY_IS_ACCOUNT(folder_store)) {
1636 TnyAccount *account = TNY_ACCOUNT(folder_store);
1638 time_t last_updated;
1639 gchar *last_updated_string;
1640 /* Get last updated from configuration */
1641 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (),
1642 tny_account_get_id (account));
1644 if (last_updated > 0)
1645 last_updated_string = modest_text_utils_get_display_date(last_updated);
1647 last_updated_string = g_strdup (_("mcen_va_never"));
1649 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1650 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1651 label_w = gtk_label_new (NULL);
1652 gtk_label_set_markup (GTK_LABEL (label_w), label);
1653 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1654 g_free (last_updated_string);
1658 g_free (gray_color_markup);
1661 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1667 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1669 ModestMainWindowPrivate *priv = NULL;
1671 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1673 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1675 return priv->send_receive_in_progress;
1679 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1681 GtkAction *action = NULL;
1682 GtkWidget *widget = NULL;
1683 ModestMainWindowPrivate *priv = NULL;
1685 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1686 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1688 priv->send_receive_in_progress = TRUE;
1690 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1691 gtk_action_set_sensitive (action, FALSE);
1692 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1693 /* gtk_action_set_sensitive (action, FALSE); */
1694 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1695 gtk_widget_set_sensitive (widget, FALSE);
1699 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1701 GtkAction *action = NULL;
1702 GtkWidget *widget = NULL;
1703 ModestMainWindowPrivate *priv = NULL;
1705 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1706 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1708 priv->send_receive_in_progress = FALSE;
1710 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1711 gtk_action_set_sensitive (action, TRUE);
1712 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1713 /* gtk_action_set_sensitive (action, TRUE); */
1714 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1715 gtk_widget_set_sensitive (widget, TRUE);
1720 on_msg_count_changed (ModestHeaderView *header_view,
1722 TnyFolderChange *change,
1723 ModestMainWindow *main_window)
1725 gboolean folder_empty = FALSE;
1726 gboolean all_marked_as_deleted = FALSE;
1727 TnyFolderChangeChanged changed;
1728 ModestMainWindowPrivate *priv;
1730 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1731 g_return_if_fail (TNY_IS_FOLDER(folder));
1732 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1733 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1735 changed = tny_folder_change_get_changed (change);
1737 /* If something changes */
1738 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1739 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1741 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1743 /* Check header removed (hide marked as DELETED headers) */
1744 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1745 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1748 /* Check if all messages are marked to be deleted */
1749 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1750 folder_empty = folder_empty || all_marked_as_deleted ;
1752 /* Set contents style of headers view */
1754 modest_main_window_set_contents_style (main_window,
1755 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1756 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1759 modest_main_window_set_contents_style (main_window,
1760 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1766 modest_main_window_set_contents_style (ModestMainWindow *self,
1767 ModestMainWindowContentsStyle style)
1769 ModestMainWindowPrivate *priv;
1771 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1773 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1775 /* We allow to set the same content style than the previously
1776 set if there are details, because it could happen when we're
1777 selecting different accounts consecutively */
1778 if ((priv->contents_style == style) &&
1779 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1782 /* Remove previous child. Delete it if it was an account
1784 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1786 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1787 g_object_ref (content);
1788 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1789 g_object_ref (priv->empty_view);
1790 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1793 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1796 priv->contents_style = style;
1798 switch (priv->contents_style) {
1799 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1800 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1801 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1804 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1806 /* if we're started without main win, there may not be a folder
1807 * view. this fixes a GLib-Critical */
1808 if (priv->folder_view) {
1809 TnyFolderStore *selected_folderstore =
1810 modest_folder_view_get_selected (priv->folder_view);
1811 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1812 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1813 TNY_ACCOUNT (selected_folderstore));
1815 wrap_in_scrolled_window (priv->contents_widget,
1816 priv->details_widget);
1818 g_object_unref (selected_folderstore);
1819 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1824 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1825 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1826 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1830 g_return_if_reached ();
1834 gtk_widget_show_all (priv->contents_widget);
1837 ModestMainWindowContentsStyle
1838 modest_main_window_get_contents_style (ModestMainWindow *self)
1840 ModestMainWindowPrivate *priv;
1842 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1844 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1845 return priv->contents_style;
1850 on_configuration_key_changed (ModestConf* conf,
1852 ModestConfEvent event,
1853 ModestConfNotificationId id,
1854 ModestMainWindow *self)
1856 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1857 TnyAccount *account = NULL;
1859 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1862 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1865 if (priv->folder_view)
1866 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1868 if (account && TNY_IS_ACCOUNT (account) &&
1869 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1872 const gchar *device_name;
1873 gchar *new_text, *gray_color_markup;
1876 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1877 label = GTK_LABEL (children->data);
1879 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1880 MODEST_CONF_DEVICE_NAME, NULL);
1882 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1883 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1885 gtk_label_set_markup (label, new_text);
1886 gtk_widget_show (GTK_WIDGET (label));
1888 g_free (gray_color_markup);
1890 g_list_free (children);
1892 g_object_unref (account);
1896 set_toolbar_transfer_mode (ModestMainWindow *self)
1898 ModestMainWindowPrivate *priv = NULL;
1900 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1902 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1904 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1906 if (priv->progress_bar_timeout > 0) {
1907 g_source_remove (priv->progress_bar_timeout);
1908 priv->progress_bar_timeout = 0;
1915 set_toolbar_mode (ModestMainWindow *self,
1916 ModestToolBarModes mode)
1918 ModestWindowPrivate *parent_priv = NULL;
1919 ModestMainWindowPrivate *priv = NULL;
1920 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1922 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1924 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1925 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1927 /* In case this was called before the toolbar exists: */
1928 if (!(parent_priv->toolbar))
1931 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1933 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1934 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1935 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1937 /* Sets current toolbar mode */
1938 priv->current_toolbar_mode = mode;
1940 /* Checks the dimming rules */
1941 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1943 /* Show and hide toolbar items */
1945 case TOOLBAR_MODE_NORMAL:
1947 gtk_action_set_visible (sort_action, TRUE);
1949 gtk_action_set_visible (refresh_action, TRUE);
1950 if (priv->progress_toolitem) {
1951 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1952 gtk_widget_hide (priv->progress_toolitem);
1954 if (priv->progress_bar)
1955 gtk_widget_hide (priv->progress_bar);
1958 gtk_action_set_visible (cancel_action, FALSE);
1960 /* Hide toolbar if optimized view is enabled */
1961 if (priv->optimized_view)
1962 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1964 case TOOLBAR_MODE_TRANSFER:
1966 gtk_action_set_visible (sort_action, FALSE);
1968 gtk_action_set_visible (refresh_action, FALSE);
1970 gtk_action_set_visible (cancel_action, TRUE);
1971 if (priv->progress_toolitem) {
1972 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1973 gtk_widget_show (priv->progress_toolitem);
1975 if (priv->progress_bar)
1976 gtk_widget_show (priv->progress_bar);
1978 /* Show toolbar if it's hiden (optimized view ) */
1979 if (priv->optimized_view)
1980 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1983 g_return_if_reached ();
1988 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1990 ModestMainWindowPrivate *priv;
1992 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1993 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1995 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1999 cancel_progressbar (GtkToolButton *toolbutton,
2000 ModestMainWindow *self)
2003 ModestMainWindowPrivate *priv;
2005 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2007 /* Get operation observers and cancel all the operations */
2008 tmp = priv->progress_widgets;
2010 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2011 tmp=g_slist_next(tmp);
2016 observers_empty (ModestMainWindow *self)
2019 ModestMainWindowPrivate *priv;
2020 gboolean is_empty = TRUE;
2021 guint pending_ops = 0;
2023 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2024 tmp = priv->progress_widgets;
2026 /* Check all observers */
2027 while (tmp && is_empty) {
2028 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2029 is_empty = pending_ops == 0;
2031 tmp = g_slist_next(tmp);
2039 * Gets the toolbar mode needed for each mail operation. It stores in
2040 * @mode_changed if the toolbar mode has changed or not
2042 static ModestToolBarModes
2043 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2044 ModestMailOperation *mail_op,
2045 gboolean *mode_changed)
2047 ModestToolBarModes mode;
2048 ModestMainWindowPrivate *priv;
2050 *mode_changed = FALSE;
2051 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2053 /* Get toolbar mode from operation id*/
2054 switch (modest_mail_operation_get_type_operation (mail_op)) {
2055 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2056 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2057 mode = TOOLBAR_MODE_TRANSFER;
2058 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2059 *mode_changed = TRUE;
2062 mode = TOOLBAR_MODE_NORMAL;
2068 on_mail_operation_started (ModestMailOperation *mail_op,
2071 ModestMainWindow *self;
2072 ModestMailOperationTypeOperation op_type;
2073 ModestMainWindowPrivate *priv;
2074 ModestToolBarModes mode;
2076 gboolean mode_changed = FALSE;
2077 TnyAccount *account;
2079 self = MODEST_MAIN_WINDOW (user_data);
2080 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2082 /* Do not show progress for receiving operations if the
2083 account is the local account or the MMC one */
2084 op_type = modest_mail_operation_get_type_operation (mail_op);
2085 account = modest_mail_operation_get_account (mail_op);
2086 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2089 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2090 modest_tny_account_is_memory_card_account (account));
2091 g_object_unref (account);
2096 /* Get toolbar mode from operation id*/
2097 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2099 /* Add operation observers and change toolbar if neccessary*/
2100 tmp = priv->progress_widgets;
2101 if (mode == TOOLBAR_MODE_TRANSFER) {
2103 set_toolbar_transfer_mode(self);
2106 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2108 tmp = g_slist_next (tmp);
2114 on_mail_operation_finished (ModestMailOperation *mail_op,
2117 ModestToolBarModes mode;
2118 ModestMailOperationTypeOperation op_type;
2120 ModestMainWindow *self;
2121 gboolean mode_changed;
2122 TnyAccount *account;
2123 ModestMainWindowPrivate *priv;
2125 self = MODEST_MAIN_WINDOW (user_data);
2126 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2128 /* The mail operation was not added to the progress objects if
2129 the account was the local account or the MMC one */
2130 op_type = modest_mail_operation_get_type_operation (mail_op);
2131 account = modest_mail_operation_get_account (mail_op);
2132 if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2135 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2136 modest_tny_account_is_memory_card_account (account));
2137 g_object_unref (account);
2142 /* Get toolbar mode from operation id*/
2143 mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2145 /* Change toolbar mode */
2146 tmp = priv->progress_widgets;
2147 if (mode == TOOLBAR_MODE_TRANSFER) {
2149 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2151 tmp = g_slist_next (tmp);
2154 /* If no more operations are being observed, NORMAL mode is enabled again */
2155 if (observers_empty (self)) {
2156 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2162 on_queue_changed (ModestMailOperationQueue *queue,
2163 ModestMailOperation *mail_op,
2164 ModestMailOperationQueueNotification type,
2165 ModestMainWindow *self)
2167 ModestMainWindowPrivate *priv;
2169 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2171 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2172 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2174 "operation-started",
2175 G_CALLBACK (on_mail_operation_started),
2177 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2179 "operation-finished",
2180 G_CALLBACK (on_mail_operation_finished),
2182 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2183 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2185 "operation-started");
2186 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2188 "operation-finished");
2193 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2195 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2198 /* Get account data */
2199 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2200 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2202 /* Set the new visible & active account */
2203 if (acc_data && acc_data->store_account) {
2204 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2205 acc_data->store_account->account_name);
2206 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2207 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2208 if (action != NULL) {
2209 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2210 modest_maemo_toggle_action_set_active_block_notify (
2211 GTK_TOGGLE_ACTION (action),
2217 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2222 modest_account_mgr_free_account_data (mgr, acc_data);
2225 /* Make sure that at least one account is "viewed": */
2227 set_at_least_one_account_visible(ModestMainWindow *self)
2229 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2230 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2232 if (!(priv->folder_view)) {
2233 /* It is too early to do this. */
2237 const gchar *active_server_account_name =
2238 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2239 if (!active_server_account_name ||
2240 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2242 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2243 if (first_modest_name) {
2244 set_account_visible (self, first_modest_name);
2245 g_free (first_modest_name);
2251 on_show_account_action_toggled (GtkToggleAction *action,
2254 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2256 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2257 if (gtk_toggle_action_get_active (action))
2258 set_account_visible (self, acc_name);
2262 refresh_account (const gchar *account_name)
2266 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2268 /* If account_name == NULL, we must update all (option All) */
2270 modest_ui_actions_do_send_receive_all (win);
2272 modest_ui_actions_do_send_receive (account_name, win);
2277 on_refresh_account_action_activated (GtkAction *action,
2280 refresh_account ((const gchar*) user_data);
2284 on_send_receive_csm_activated (GtkMenuItem *item,
2287 refresh_account ((const gchar*) user_data);
2291 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2293 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2295 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2301 on_folder_view_focus_in (GtkWidget *widget,
2302 GdkEventFocus *event,
2305 ModestMainWindow *main_window = NULL;
2307 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2308 main_window = MODEST_MAIN_WINDOW (userdata);
2310 /* Update toolbar dimming state */
2311 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2317 on_header_view_focus_in (GtkWidget *widget,
2318 GdkEventFocus *event,
2321 ModestMainWindow *main_window = NULL;
2322 ModestMainWindowPrivate *priv = NULL;
2324 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2325 main_window = MODEST_MAIN_WINDOW (userdata);
2326 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2328 /* Update toolbar dimming state */
2329 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2335 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2336 TnyFolderStore *folder_store,
2338 ModestMainWindow *main_window)
2340 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2341 GtkAction *action = NULL;
2342 gboolean show_reply = TRUE;
2343 gboolean show_forward = TRUE;
2344 gboolean show_cancel_send = FALSE;
2345 gboolean show_clipboard = TRUE;
2346 gboolean show_delete = TRUE;
2349 if (TNY_IS_ACCOUNT (folder_store)) {
2350 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2351 } else if (TNY_IS_FOLDER (folder_store)) {
2352 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2353 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2354 TNY_FOLDER (folder_store));
2355 switch (folder_type) {
2356 case TNY_FOLDER_TYPE_DRAFTS:
2357 show_clipboard = show_delete = TRUE;
2358 show_reply = show_forward = show_cancel_send = FALSE;
2360 case TNY_FOLDER_TYPE_SENT:
2361 show_forward = show_clipboard = show_delete = TRUE;
2362 show_reply = show_cancel_send = FALSE;
2364 case TNY_FOLDER_TYPE_OUTBOX:
2365 show_clipboard = show_delete = show_cancel_send = TRUE;
2366 show_reply = show_forward = FALSE;
2369 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2370 show_cancel_send = FALSE;
2373 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2374 show_cancel_send = FALSE;
2379 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2380 gtk_action_set_visible (action, show_reply);
2381 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2382 gtk_action_set_visible (action, show_reply);
2383 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2384 gtk_action_set_visible (action, show_forward);
2385 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2386 gtk_action_set_visible (action, show_cancel_send);
2387 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2388 gtk_action_set_visible (action, show_delete);
2390 /* We finally call to the ui actions handler, after updating properly
2391 * the header view CSM */
2392 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2396 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2397 GtkTreeModel *model,
2398 GtkTreeRowReference *row_reference,
2399 ModestMainWindow *self)
2401 ModestMainWindowPrivate *priv = NULL;
2402 GtkTreeModel *header_model = NULL;
2403 GtkTreePath *path = NULL;
2405 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2406 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2407 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2409 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2410 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2412 /* Do nothing if we changed the folder in the main view */
2413 if (header_model != model)
2416 /* Select the message in the header view */
2417 path = gtk_tree_row_reference_get_path (row_reference);
2418 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2420 gtk_tree_path_free (path);