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 */
858 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_mail_operation_queue ()),
859 "queue-changed", G_CALLBACK (on_queue_changed), self);
861 /* Track changes in the device name */
862 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(modest_runtime_get_conf ()),
863 "key_changed", G_CALLBACK (on_configuration_key_changed),
866 /* Track account changes. We need to refresh the toolbar */
867 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
868 "account_inserted", G_CALLBACK (on_account_inserted),
870 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
871 "account_removed", G_CALLBACK (on_account_removed),
874 /* We need to refresh the send & receive menu to change the bold
875 * account when the default account changes. */
876 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
877 G_OBJECT (modest_runtime_get_account_mgr ()),
878 "default_account_changed",
879 G_CALLBACK (on_default_account_changed),
883 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store()),
884 "password_requested",
885 G_CALLBACK (modest_ui_actions_on_password_requested), self);
889 /** Idle handler, to send/receive at startup .*/
891 sync_accounts_cb (ModestMainWindow *win)
893 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
894 return FALSE; /* Do not call this idle handler again. */
899 on_hildon_program_is_topmost_notify(GObject *self,
900 GParamSpec *propert_param, gpointer user_data)
902 HildonProgram *app = HILDON_PROGRAM (self);
905 ModestWindow* self = MODEST_WINDOW(user_data);
908 /* Note that use of hildon_program_set_can_hibernate()
909 * is generally referred to as "setting the killable flag",
910 * though hibernation does not seem equal to death.
913 if (hildon_program_get_is_topmost (app)) {
914 /* Prevent hibernation when the progam comes to the foreground,
915 * because hibernation should only happen when the application
916 * is in the background: */
917 hildon_program_set_can_hibernate (app, FALSE);
919 /* Allow hibernation if the program has gone to the background: */
921 /* However, prevent hibernation while the settings are being changed: */
922 const gboolean hibernation_prevented =
923 modest_window_mgr_get_hibernation_is_prevented (
924 modest_runtime_get_window_mgr ());
926 if (hibernation_prevented)
927 hildon_program_set_can_hibernate (app, FALSE);
929 /* Allow hibernation, after saving the state: */
930 modest_osso_save_state();
931 hildon_program_set_can_hibernate (app, TRUE);
938 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
940 GtkWidget *folder_win = (GtkWidget *) user_data;
941 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
943 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
944 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
945 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
947 gtk_widget_show (GTK_WIDGET (priv->folder_view));
949 /* Connect signals */
950 connect_signals ((ModestMainWindow*)self);
952 /* Set account store */
953 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
954 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
956 /* Load previous osso state, for instance if we are being restored from
958 modest_osso_load_state ();
960 /* Restore window & widget settings */
962 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
964 /* The UI spec wants us to show a connection dialog when the application is
965 * started by the user, if there is no connection.
966 * Do this before showing the account wizard,
967 * because wizard needs a connection to discover capabilities. */
968 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
970 /* Check if accounts exist and show the account wizard if not */
971 gboolean accounts_exist =
972 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
974 if (!accounts_exist) {
975 /* This is necessary to have the main window shown behind the dialog
976 It's an ugly hack... jschmid */
977 gtk_widget_show_all(GTK_WIDGET(self));
978 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
981 GtkAction *send_receive_all;
982 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
983 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
984 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
985 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
986 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
987 modest_account_mgr_free_account_names (accounts);
992 modest_main_window_new (void)
994 ModestMainWindow *self = NULL;
995 ModestMainWindowPrivate *priv = NULL;
996 ModestWindowPrivate *parent_priv = NULL;
997 GtkWidget *folder_win = NULL;
998 ModestDimmingRulesGroup *menu_rules_group = NULL;
999 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1000 GtkActionGroup *action_group = NULL;
1001 GError *error = NULL;
1002 ModestConf *conf = NULL;
1003 GtkAction *action = NULL;
1004 GdkPixbuf *window_icon;
1006 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1007 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1008 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1010 parent_priv->ui_manager = gtk_ui_manager_new();
1011 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1013 action_group = gtk_action_group_new ("ModestMainWindowActions");
1014 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1016 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1017 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1019 /* Add common actions */
1020 gtk_action_group_add_actions (action_group,
1021 modest_action_entries,
1022 G_N_ELEMENTS (modest_action_entries),
1025 gtk_action_group_add_actions (action_group,
1026 modest_folder_view_action_entries,
1027 G_N_ELEMENTS (modest_folder_view_action_entries),
1030 gtk_action_group_add_actions (action_group,
1031 modest_header_view_action_entries,
1032 G_N_ELEMENTS (modest_header_view_action_entries),
1035 gtk_action_group_add_toggle_actions (action_group,
1036 modest_toggle_action_entries,
1037 G_N_ELEMENTS (modest_toggle_action_entries),
1040 gtk_action_group_add_toggle_actions (action_group,
1041 modest_main_window_toggle_action_entries,
1042 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1045 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1046 g_object_unref (action_group);
1048 /* Load the UI definition */
1049 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1050 MODEST_UIDIR "modest-main-window-ui.xml", &error);
1051 if (error != NULL) {
1052 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1053 g_error_free (error);
1057 /* Add common dimming rules */
1058 modest_dimming_rules_group_add_rules (menu_rules_group,
1059 modest_main_window_menu_dimming_entries,
1060 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1061 MODEST_WINDOW (self));
1062 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1063 modest_main_window_toolbar_dimming_entries,
1064 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1065 MODEST_WINDOW (self));
1067 /* Insert dimming rules group for this window */
1068 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1069 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1070 g_object_unref (menu_rules_group);
1071 g_object_unref (toolbar_rules_group);
1073 /* Add accelerators */
1074 gtk_window_add_accel_group (GTK_WINDOW (self),
1075 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1077 /* Menubar. Update the state of some toggles */
1078 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1079 conf = modest_runtime_get_conf ();
1080 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1081 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1082 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1083 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1084 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
1085 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1086 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1087 modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1088 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1089 gtk_widget_show (parent_priv->menubar);
1091 /* Get device name */
1092 modest_maemo_utils_get_device_name ();
1096 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1097 if (!priv->header_view)
1098 g_printerr ("modest: cannot instantiate header view\n");
1099 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1100 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1101 MODEST_CONF_HEADER_VIEW_KEY);
1103 /* Other style properties of header view */
1104 g_object_set (G_OBJECT (priv->header_view),
1105 "rules-hint", FALSE,
1107 /* gtk_widget_show (priv->header_view); */
1110 priv->empty_view = create_empty_view ();
1111 gtk_widget_show (priv->empty_view);
1113 /* Create scrolled windows */
1114 folder_win = gtk_scrolled_window_new (NULL, NULL);
1115 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1116 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1118 GTK_POLICY_AUTOMATIC);
1119 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1121 GTK_POLICY_AUTOMATIC);
1122 /* gtk_widget_show (priv->contents_widget); */
1125 priv->main_paned = gtk_hpaned_new ();
1126 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1127 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1128 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1130 /* putting it all together... */
1131 priv->main_vbox = gtk_vbox_new (FALSE, 6);
1132 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1133 gtk_widget_show (priv->main_vbox);
1135 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1137 HildonProgram *app = hildon_program_get_instance ();
1138 hildon_program_add_window (app, HILDON_WINDOW (self));
1140 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1141 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1143 g_signal_connect (G_OBJECT(self), "show",
1144 G_CALLBACK (modest_main_window_on_show), folder_win);
1146 /* Set window icon */
1147 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1149 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1150 g_object_unref (window_icon);
1153 /* Dont't restore settings here,
1154 * because it requires a gtk_widget_show(),
1155 * and we don't want to do that until later,
1156 * so that the UI is not visible for non-menu D-Bus activation.
1158 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1160 return MODEST_WINDOW(self);
1164 modest_main_window_close_all (ModestMainWindow *self)
1167 GtkResponseType response;
1169 /* Create the confirmation dialog MSG-NOT308 */
1170 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1171 _("emev_nc_close_windows"),
1172 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1173 _("mcen_bd_no"), GTK_RESPONSE_NO,
1176 response = gtk_dialog_run (GTK_DIALOG (note));
1177 gtk_widget_destroy (GTK_WIDGET (note));
1179 if (response == GTK_RESPONSE_YES)
1187 modest_main_window_set_style (ModestMainWindow *self,
1188 ModestMainWindowStyle style)
1190 ModestMainWindowPrivate *priv;
1191 ModestWindowPrivate *parent_priv;
1195 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1197 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1198 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1200 /* no change -> nothing to do */
1201 if (priv->style == style)
1204 /* Get toggle button and update the state if needed. This will
1205 happen only when the set_style is not invoked from the UI,
1206 for example when it's called from widget memory */
1207 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1208 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1209 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1210 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1211 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1212 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1213 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1216 priv->style = style;
1218 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1219 /* Remove main paned */
1220 g_object_ref (priv->main_paned);
1221 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1223 /* Reparent the contents widget to the main vbox */
1224 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1227 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1228 /* Remove header view */
1229 g_object_ref (priv->contents_widget);
1230 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1232 /* Reparent the main paned */
1233 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1234 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1238 g_return_if_reached ();
1241 /* Let header view grab the focus if it's being shown */
1242 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1243 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1245 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1248 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1251 ModestMainWindowStyle
1252 modest_main_window_get_style (ModestMainWindow *self)
1254 ModestMainWindowPrivate *priv;
1256 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1258 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1265 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1267 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1268 ModestWindowPrivate *parent_priv;
1269 ModestWindowMgr *mgr;
1270 gboolean is_fullscreen;
1271 GtkAction *fs_toggle_action;
1274 mgr = modest_runtime_get_window_mgr ();
1276 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1278 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1280 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1281 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1282 if (is_fullscreen != active) {
1283 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1292 set_homogeneous (GtkWidget *widget,
1295 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1296 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1300 modest_main_window_show_toolbar (ModestWindow *self,
1301 gboolean show_toolbar)
1303 ModestMainWindowPrivate *priv = NULL;
1304 ModestWindowPrivate *parent_priv = NULL;
1305 GtkWidget *reply_button = NULL, *menu = NULL;
1306 GtkWidget *placeholder = NULL;
1308 const gchar *action_name;
1311 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1312 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1313 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1315 /* Set optimized view status */
1316 priv->optimized_view = !show_toolbar;
1318 if (!parent_priv->toolbar) {
1319 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1321 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1323 /* Set homogeneous toolbar */
1324 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1325 set_homogeneous, NULL);
1327 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1328 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1329 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1330 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1331 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1332 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1333 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1334 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1336 /* Add ProgressBar (Transfer toolbar) */
1337 priv->progress_bar = modest_progress_bar_widget_new ();
1338 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1339 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1340 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1341 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1342 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1344 /* Connect cancel 'clicked' signal to abort progress mode */
1345 g_signal_connect(priv->cancel_toolitem, "clicked",
1346 G_CALLBACK(cancel_progressbar),
1349 /* Add it to the observers list */
1350 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1353 hildon_window_add_toolbar (HILDON_WINDOW (self),
1354 GTK_TOOLBAR (parent_priv->toolbar));
1356 /* Set reply button tap and hold menu */
1357 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1358 "/ToolBar/ToolbarMessageReply");
1359 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1360 "/ToolbarReplyCSM");
1361 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1363 /* Set send & receive button tap and hold menu */
1364 update_menus (MODEST_MAIN_WINDOW (self));
1368 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1369 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1370 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1372 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1373 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1375 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1379 /* Update also the actions (to update the toggles in the
1380 menus), we have to do it manually because some other window
1381 of the same time could have changed it (remember that the
1382 toolbar fullscreen mode is shared by all the windows of the
1384 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1385 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1387 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1389 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1390 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1395 on_account_inserted (TnyAccountStore *accoust_store,
1396 TnyAccount *account,
1399 update_menus (MODEST_MAIN_WINDOW (user_data));
1403 on_default_account_changed (ModestAccountMgr* mgr,
1406 update_menus (MODEST_MAIN_WINDOW (user_data));
1410 on_account_removed (TnyAccountStore *accoust_store,
1411 TnyAccount *account,
1414 update_menus (MODEST_MAIN_WINDOW (user_data));
1418 * This function manages the key events used to navigate between
1419 * header and folder views (when the window is in split view)
1422 * -------------------------------------------------
1423 * HeaderView GDK_Left Move focus to folder view
1424 * FolderView GDK_Right Move focus to header view
1426 * There is no need to scroll to selected row, the widgets will be the
1427 * responsibles of doing that (probably managing the focus-in event
1430 on_inner_widgets_key_pressed (GtkWidget *widget,
1434 ModestMainWindowPrivate *priv;
1436 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1438 /* Do nothing if we're in SIMPLE style */
1439 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1442 if (MODEST_IS_HEADER_VIEW (widget)) {
1443 if (event->keyval == GDK_Left)
1444 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1445 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1446 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1449 } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1450 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1456 set_alignment (GtkWidget *widget,
1459 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1460 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1464 create_empty_view (void)
1466 GtkLabel *label = NULL;
1467 GtkWidget *align = NULL;
1469 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1470 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1471 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1472 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1474 return GTK_WIDGET(align);
1478 * Free the returned string
1481 get_gray_color_markup (GtkWidget *styled_widget)
1483 gchar *gray_color_markup;
1485 /* Obtain the secondary text color. We need a realized widget, that's why
1486 we get styled_widget from outside */
1487 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1489 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1490 gray_color_markup = modest_text_utils_get_color_string (&color);
1492 gray_color_markup = g_strdup ("#BBBBBB");
1494 return gray_color_markup;
1498 * Free the returned string
1501 create_device_name_visual_string (const gchar *device_name,
1502 const gchar *gray_color_markup)
1506 /* We have to use "" to fill the %s of the translation. We can
1507 not just use the device name because the device name is
1508 shown in a different color, so it could not be included
1509 into the <span> tag */
1510 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1511 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1521 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1523 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1528 gchar *gray_color_markup;
1530 vbox = gtk_vbox_new (FALSE, 0);
1532 gray_color_markup = get_gray_color_markup (styled_widget);
1534 /* Account description: */
1535 if (modest_tny_account_is_virtual_local_folders (account)
1536 || (modest_tny_account_is_memory_card_account (account))) {
1538 /* Get device name */
1539 gchar *device_name = NULL;
1540 if (modest_tny_account_is_virtual_local_folders (account))
1541 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1542 MODEST_CONF_DEVICE_NAME, NULL);
1544 device_name = g_strdup (tny_account_get_name (account));
1546 label = create_device_name_visual_string ((const gchar *) device_name,
1547 (const gchar *) gray_color_markup);
1548 label_w = gtk_label_new (NULL);
1549 gtk_label_set_markup (GTK_LABEL (label_w), label);
1550 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1551 g_free (device_name);
1554 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1555 gtk_box_pack_start (GTK_BOX (vbox),
1556 gtk_label_new (tny_account_get_name (account)),
1559 /* Other accounts, such as IMAP and POP: */
1564 /* Put proto in uppercase */
1565 proto = g_string_new (tny_account_get_proto (account));
1566 proto = g_string_ascii_up (proto);
1568 /* note: mcen_fi_localroot_description is something like "%s account"
1569 * however, we should display "%s account: %s"... therefore, ugly tmp */
1570 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1571 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1572 gray_color_markup, tmp, tny_account_get_name (account));
1575 label_w = gtk_label_new (NULL);
1576 gtk_label_set_markup (GTK_LABEL (label_w), label);
1577 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1578 g_string_free (proto, TRUE);
1584 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1585 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1586 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1587 modest_tny_folder_store_get_message_count (folder_store));
1588 label_w = gtk_label_new (NULL);
1589 gtk_label_set_markup (GTK_LABEL (label_w), label);
1590 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1594 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1596 _("mcen_fi_rootfolder_folders"),
1597 modest_tny_folder_store_get_folder_count (folder_store));
1598 label_w = gtk_label_new (NULL);
1599 gtk_label_set_markup (GTK_LABEL (label_w), label);
1600 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1604 if (modest_tny_account_is_virtual_local_folders (account)
1605 || modest_tny_account_is_memory_card_account (account)) {
1607 gchar *size = modest_text_utils_get_display_size (
1608 modest_tny_folder_store_get_local_size (folder_store));
1610 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1611 gray_color_markup, _("mcen_fi_rootfolder_size"),
1615 label_w = gtk_label_new (NULL);
1616 gtk_label_set_markup (GTK_LABEL (label_w), label);
1617 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1619 } else if (TNY_IS_ACCOUNT(folder_store)) {
1620 TnyAccount *account = TNY_ACCOUNT(folder_store);
1622 time_t last_updated;
1623 gchar *last_updated_string;
1624 /* Get last updated from configuration */
1625 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1626 tny_account_get_id (account),
1627 MODEST_ACCOUNT_LAST_UPDATED,
1629 if (last_updated > 0)
1630 last_updated_string = modest_text_utils_get_display_date(last_updated);
1632 last_updated_string = g_strdup (_("mcen_va_never"));
1634 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1635 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1636 label_w = gtk_label_new (NULL);
1637 gtk_label_set_markup (GTK_LABEL (label_w), label);
1638 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1639 g_free (last_updated_string);
1643 g_free (gray_color_markup);
1646 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1652 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1654 ModestMainWindowPrivate *priv = NULL;
1656 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1658 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1660 return priv->send_receive_in_progress;
1664 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1666 GtkAction *action = NULL;
1667 GtkWidget *widget = NULL;
1668 ModestMainWindowPrivate *priv = NULL;
1670 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1671 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1673 priv->send_receive_in_progress = TRUE;
1675 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1676 gtk_action_set_sensitive (action, FALSE);
1677 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1678 /* gtk_action_set_sensitive (action, FALSE); */
1679 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1680 gtk_widget_set_sensitive (widget, FALSE);
1684 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1686 GtkAction *action = NULL;
1687 GtkWidget *widget = NULL;
1688 ModestMainWindowPrivate *priv = NULL;
1690 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1691 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1693 priv->send_receive_in_progress = FALSE;
1695 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1696 gtk_action_set_sensitive (action, TRUE);
1697 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1698 /* gtk_action_set_sensitive (action, TRUE); */
1699 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1700 gtk_widget_set_sensitive (widget, TRUE);
1705 on_msg_count_changed (ModestHeaderView *header_view,
1707 TnyFolderChange *change,
1708 ModestMainWindow *main_window)
1710 gboolean folder_empty = FALSE;
1711 gboolean all_marked_as_deleted = FALSE;
1712 TnyFolderChangeChanged changed;
1713 ModestMainWindowPrivate *priv;
1715 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1716 g_return_if_fail (TNY_IS_FOLDER(folder));
1717 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1718 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1720 changed = tny_folder_change_get_changed (change);
1722 /* If something changes */
1723 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1724 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1726 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1728 /* Check header removed (hide marked as DELETED headers) */
1729 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1730 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1733 /* Check if all messages are marked to be deleted */
1734 all_marked_as_deleted = modest_header_view_is_empty (header_view);
1735 folder_empty = folder_empty || all_marked_as_deleted ;
1737 /* Set contents style of headers view */
1739 modest_main_window_set_contents_style (main_window,
1740 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1741 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1744 modest_main_window_set_contents_style (main_window,
1745 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1751 modest_main_window_set_contents_style (ModestMainWindow *self,
1752 ModestMainWindowContentsStyle style)
1754 ModestMainWindowPrivate *priv;
1756 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1758 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1760 /* We allow to set the same content style than the previously
1761 set if there are details, because it could happen when we're
1762 selecting different accounts consecutively */
1763 if ((priv->contents_style == style) &&
1764 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1767 /* Remove previous child. Delete it if it was an account
1769 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1771 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1772 g_object_ref (content);
1773 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1774 g_object_ref (priv->empty_view);
1775 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1778 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1781 priv->contents_style = style;
1783 switch (priv->contents_style) {
1784 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1785 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1786 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1789 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1791 /* if we're started without main win, there may not be a folder
1792 * view. this fixes a GLib-Critical */
1793 if (priv->folder_view) {
1794 TnyFolderStore *selected_folderstore =
1795 modest_folder_view_get_selected (priv->folder_view);
1796 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1797 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1798 TNY_ACCOUNT (selected_folderstore));
1800 wrap_in_scrolled_window (priv->contents_widget,
1801 priv->details_widget);
1803 g_object_unref (selected_folderstore);
1804 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1809 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1810 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1811 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1815 g_return_if_reached ();
1819 gtk_widget_show_all (priv->contents_widget);
1822 ModestMainWindowContentsStyle
1823 modest_main_window_get_contents_style (ModestMainWindow *self)
1825 ModestMainWindowPrivate *priv;
1827 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1829 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1830 return priv->contents_style;
1835 on_configuration_key_changed (ModestConf* conf,
1837 ModestConfEvent event,
1838 ModestConfNotificationId id,
1839 ModestMainWindow *self)
1841 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1842 TnyAccount *account = NULL;
1844 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1847 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1850 if (priv->folder_view)
1851 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1853 if (account && TNY_IS_ACCOUNT (account) &&
1854 strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1857 const gchar *device_name;
1858 gchar *new_text, *gray_color_markup;
1861 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1862 label = GTK_LABEL (children->data);
1864 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1865 MODEST_CONF_DEVICE_NAME, NULL);
1867 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));
1868 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1870 gtk_label_set_markup (label, new_text);
1871 gtk_widget_show (GTK_WIDGET (label));
1873 g_free (gray_color_markup);
1875 g_list_free (children);
1877 g_object_unref (account);
1881 set_toolbar_transfer_mode (ModestMainWindow *self)
1883 ModestMainWindowPrivate *priv = NULL;
1885 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1887 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1889 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1891 if (priv->progress_bar_timeout > 0) {
1892 g_source_remove (priv->progress_bar_timeout);
1893 priv->progress_bar_timeout = 0;
1900 set_toolbar_mode (ModestMainWindow *self,
1901 ModestToolBarModes mode)
1903 ModestWindowPrivate *parent_priv = NULL;
1904 ModestMainWindowPrivate *priv = NULL;
1905 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1907 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1909 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1910 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1912 /* In case this was called before the toolbar exists: */
1913 if (!(parent_priv->toolbar))
1916 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1918 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1919 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1920 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1922 /* Sets current toolbar mode */
1923 priv->current_toolbar_mode = mode;
1925 /* Checks the dimming rules */
1926 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1928 /* Show and hide toolbar items */
1930 case TOOLBAR_MODE_NORMAL:
1932 gtk_action_set_visible (sort_action, TRUE);
1934 gtk_action_set_visible (refresh_action, TRUE);
1935 if (priv->progress_toolitem) {
1936 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1937 gtk_widget_hide (priv->progress_toolitem);
1939 if (priv->progress_bar)
1940 gtk_widget_hide (priv->progress_bar);
1943 gtk_action_set_visible (cancel_action, FALSE);
1945 /* Hide toolbar if optimized view is enabled */
1946 if (priv->optimized_view)
1947 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1949 case TOOLBAR_MODE_TRANSFER:
1951 gtk_action_set_visible (sort_action, FALSE);
1953 gtk_action_set_visible (refresh_action, FALSE);
1955 gtk_action_set_visible (cancel_action, TRUE);
1956 if (priv->progress_toolitem) {
1957 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1958 gtk_widget_show (priv->progress_toolitem);
1960 if (priv->progress_bar)
1961 gtk_widget_show (priv->progress_bar);
1963 /* Show toolbar if it's hiden (optimized view ) */
1964 if (priv->optimized_view)
1965 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1968 g_return_if_reached ();
1973 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1975 ModestMainWindowPrivate *priv;
1977 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1978 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1980 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1984 cancel_progressbar (GtkToolButton *toolbutton,
1985 ModestMainWindow *self)
1988 ModestMainWindowPrivate *priv;
1990 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1992 /* Get operation observers and cancel all the operations */
1993 tmp = priv->progress_widgets;
1995 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1996 tmp=g_slist_next(tmp);
2001 observers_empty (ModestMainWindow *self)
2004 ModestMainWindowPrivate *priv;
2005 gboolean is_empty = TRUE;
2006 guint pending_ops = 0;
2008 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2009 tmp = priv->progress_widgets;
2011 /* Check all observers */
2012 while (tmp && is_empty) {
2013 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2014 is_empty = pending_ops == 0;
2016 tmp = g_slist_next(tmp);
2023 on_queue_changed (ModestMailOperationQueue *queue,
2024 ModestMailOperation *mail_op,
2025 ModestMailOperationQueueNotification type,
2026 ModestMainWindow *self)
2028 ModestMainWindowPrivate *priv;
2029 ModestMailOperationTypeOperation op_type;
2030 ModestToolBarModes mode;
2032 gboolean mode_changed = FALSE;
2034 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2035 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2037 /* Get toolbar mode from operation id*/
2038 op_type = modest_mail_operation_get_type_operation (mail_op);
2040 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2041 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2042 mode = TOOLBAR_MODE_TRANSFER;
2043 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2044 mode_changed = TRUE;
2047 mode = TOOLBAR_MODE_NORMAL;
2052 /* Add operation observers and change toolbar if neccessary*/
2053 tmp = priv->progress_widgets;
2055 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2056 if (mode == TOOLBAR_MODE_TRANSFER) {
2058 set_toolbar_transfer_mode(self);
2061 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2063 tmp = g_slist_next (tmp);
2067 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2068 /* Change toolbar mode */
2069 if (mode == TOOLBAR_MODE_TRANSFER) {
2071 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2073 tmp = g_slist_next (tmp);
2076 /* If no more operations are being observed, NORMAL mode is enabled again */
2077 if (observers_empty (self)) {
2078 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2088 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2090 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2093 /* Get account data */
2094 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2095 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2097 /* Set the new visible & active account */
2098 if (acc_data && acc_data->store_account) {
2099 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2100 acc_data->store_account->account_name);
2101 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2102 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2103 if (action != NULL) {
2104 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2105 modest_maemo_toggle_action_set_active_block_notify (
2106 GTK_TOGGLE_ACTION (action),
2112 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2117 modest_account_mgr_free_account_data (mgr, acc_data);
2120 /* Make sure that at least one account is "viewed": */
2122 set_at_least_one_account_visible(ModestMainWindow *self)
2124 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2125 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2127 if (!(priv->folder_view)) {
2128 /* It is too early to do this. */
2132 const gchar *active_server_account_name =
2133 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2134 if (!active_server_account_name ||
2135 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2137 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2138 if (first_modest_name) {
2139 set_account_visible (self, first_modest_name);
2140 g_free (first_modest_name);
2146 on_show_account_action_toggled (GtkToggleAction *action,
2149 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2151 const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2152 if (gtk_toggle_action_get_active (action))
2153 set_account_visible (self, acc_name);
2157 refresh_account (const gchar *account_name)
2161 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2163 /* If account_name == NULL, we must update all (option All) */
2165 modest_ui_actions_do_send_receive_all (win);
2167 modest_ui_actions_do_send_receive (account_name, win);
2172 on_refresh_account_action_activated (GtkAction *action,
2175 refresh_account ((const gchar*) user_data);
2179 on_send_receive_csm_activated (GtkMenuItem *item,
2182 refresh_account ((const gchar*) user_data);
2186 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2188 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2190 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2196 on_folder_view_focus_in (GtkWidget *widget,
2197 GdkEventFocus *event,
2200 ModestMainWindow *main_window = NULL;
2202 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2203 main_window = MODEST_MAIN_WINDOW (userdata);
2205 /* Update toolbar dimming state */
2206 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2212 on_header_view_focus_in (GtkWidget *widget,
2213 GdkEventFocus *event,
2216 ModestMainWindow *main_window = NULL;
2217 ModestMainWindowPrivate *priv = NULL;
2219 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2220 main_window = MODEST_MAIN_WINDOW (userdata);
2221 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2223 /* Update toolbar dimming state */
2224 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2230 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2231 TnyFolderStore *folder_store,
2233 ModestMainWindow *main_window)
2235 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2236 GtkAction *action = NULL;
2237 gboolean show_reply = TRUE;
2238 gboolean show_forward = TRUE;
2239 gboolean show_cancel_send = FALSE;
2240 gboolean show_clipboard = TRUE;
2241 gboolean show_delete = TRUE;
2244 if (TNY_IS_ACCOUNT (folder_store)) {
2245 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2246 } else if (TNY_IS_FOLDER (folder_store)) {
2247 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2248 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2249 TNY_FOLDER (folder_store));
2250 switch (folder_type) {
2251 case TNY_FOLDER_TYPE_DRAFTS:
2252 show_clipboard = show_delete = TRUE;
2253 show_reply = show_forward = show_cancel_send = FALSE;
2255 case TNY_FOLDER_TYPE_SENT:
2256 show_forward = show_clipboard = show_delete = TRUE;
2257 show_reply = show_cancel_send = FALSE;
2259 case TNY_FOLDER_TYPE_OUTBOX:
2260 show_clipboard = show_delete = show_cancel_send = TRUE;
2261 show_reply = show_forward = FALSE;
2264 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2265 show_cancel_send = FALSE;
2268 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2269 show_cancel_send = FALSE;
2274 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2275 gtk_action_set_visible (action, show_reply);
2276 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2277 gtk_action_set_visible (action, show_reply);
2278 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2279 gtk_action_set_visible (action, show_forward);
2280 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2281 gtk_action_set_visible (action, show_cancel_send);
2282 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2283 gtk_action_set_visible (action, show_delete);
2285 /* We finally call to the ui actions handler, after updating properly
2286 * the header view CSM */
2287 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2291 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2292 GtkTreeModel *model,
2293 GtkTreeRowReference *row_reference,
2294 ModestMainWindow *self)
2296 ModestMainWindowPrivate *priv = NULL;
2297 GtkTreeModel *header_model = NULL;
2298 GtkTreePath *path = NULL;
2300 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2301 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2302 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2304 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2305 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2307 /* Do nothing if we changed the folder in the main view */
2308 if (header_model != model)
2311 /* Select the message in the header view */
2312 path = gtk_tree_row_reference_get_path (row_reference);
2313 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2315 gtk_tree_path_free (path);