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"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-program.h>
70 #include <hildon/hildon-program.h>
71 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
73 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
80 /* 'private'/'protected' functions */
81 static void modest_main_window_class_init (ModestMainWindowClass *klass);
82 static void modest_main_window_init (ModestMainWindow *obj);
83 static void modest_main_window_finalize (GObject *obj);
84 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
85 GdkEventWindowState *event,
88 static void connect_signals (ModestMainWindow *self);
90 static void restore_settings (ModestMainWindow *self, gboolean do_folder_view_too);
91 static void save_state (ModestWindow *self);
93 static void modest_main_window_show_toolbar (ModestWindow *window,
94 gboolean show_toolbar);
96 static void cancel_progressbar (GtkToolButton *toolbutton,
97 ModestMainWindow *self);
99 static void on_queue_changed (ModestMailOperationQueue *queue,
100 ModestMailOperation *mail_op,
101 ModestMailOperationQueueNotification type,
102 ModestMainWindow *self);
104 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
106 static void on_account_update (TnyAccountStore *account_store,
107 const gchar *account_name,
110 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
114 static void on_configuration_key_changed (ModestConf* conf,
116 ModestConfEvent event,
117 ModestMainWindow *self);
119 static void set_toolbar_mode (ModestMainWindow *self,
120 ModestToolBarModes mode);
122 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
124 static void on_show_account_action_activated (GtkAction *action,
127 static void on_refresh_account_action_activated (GtkAction *action,
130 static void on_send_receive_csm_activated (GtkMenuItem *item,
134 _on_msg_count_changed (ModestHeaderView *header_view,
136 TnyFolderChange *change,
137 ModestMainWindow *main_window);
140 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
143 static GtkWidget * create_empty_view (void);
146 on_folder_view_focus_in (GtkWidget *widget,
147 GdkEventFocus *event,
150 on_header_view_focus_in (GtkWidget *widget,
151 GdkEventFocus *event,
154 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
155 TnyFolderStore *folder_store,
157 ModestMainWindow *main_window);
159 /* list my signals */
166 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
167 struct _ModestMainWindowPrivate {
168 GtkWidget *msg_paned;
169 GtkWidget *main_paned;
170 GtkWidget *main_vbox;
171 GtkWidget *contents_widget;
172 GtkWidget *empty_view;
174 /* Progress observers */
175 GtkWidget *progress_bar;
176 GSList *progress_widgets;
179 GtkWidget *progress_toolitem;
180 GtkWidget *cancel_toolitem;
181 GtkWidget *sort_toolitem;
182 GtkWidget *refresh_toolitem;
183 ModestToolBarModes current_toolbar_mode;
185 /* Merge ids used to add/remove accounts to the ViewMenu*/
186 GByteArray *merge_ids;
188 /* On-demand widgets */
189 GtkWidget *accounts_popup;
190 GtkWidget *details_widget;
192 /* Optimized view enabled */
193 gboolean optimized_view;
195 /* Optimized view enabled */
196 gboolean send_receive_in_progress;
198 ModestHeaderView *header_view;
199 ModestFolderView *folder_view;
201 ModestMainWindowStyle style;
202 ModestMainWindowContentsStyle contents_style;
204 guint progress_bar_timeout;
206 /* Signal handler UIDs */
207 gint queue_changed_handler_uid;
208 GList *queue_err_signals;
210 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
211 MODEST_TYPE_MAIN_WINDOW, \
212 ModestMainWindowPrivate))
214 typedef struct _GetMsgAsyncHelper {
215 ModestMainWindowPrivate *main_window_private;
217 ModestTnyMsgReplyType reply_type;
218 ModestTnyMsgForwardType forward_type;
225 static GtkWindowClass *parent_class = NULL;
228 /* Private actions */
229 /* This is the context sensitive menu: */
230 static const GtkActionEntry modest_folder_view_action_entries [] = {
232 /* Folder View CSM actions */
233 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
234 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
235 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
236 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
237 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
238 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
241 static const GtkActionEntry modest_header_view_action_entries [] = {
243 /* Header View CSM actions */
244 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
245 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
246 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
247 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
248 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
249 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
250 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
251 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
252 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
253 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
256 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
257 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
260 /************************************************************************/
263 modest_main_window_get_type (void)
265 static GType my_type = 0;
267 static const GTypeInfo my_info = {
268 sizeof(ModestMainWindowClass),
269 NULL, /* base init */
270 NULL, /* base finalize */
271 (GClassInitFunc) modest_main_window_class_init,
272 NULL, /* class finalize */
273 NULL, /* class data */
274 sizeof(ModestMainWindow),
276 (GInstanceInitFunc) modest_main_window_init,
279 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
287 modest_main_window_class_init (ModestMainWindowClass *klass)
289 GObjectClass *gobject_class;
290 gobject_class = (GObjectClass*) klass;
291 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
293 parent_class = g_type_class_peek_parent (klass);
294 gobject_class->finalize = modest_main_window_finalize;
296 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
298 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
299 modest_window_class->save_state_func = save_state;
300 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
301 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
305 modest_main_window_init (ModestMainWindow *obj)
307 ModestMainWindowPrivate *priv;
309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
311 priv->queue_err_signals = NULL;
312 priv->msg_paned = NULL;
313 priv->main_paned = NULL;
314 priv->main_vbox = NULL;
315 priv->header_view = NULL;
316 priv->folder_view = NULL;
317 priv->contents_widget = NULL;
318 priv->accounts_popup = NULL;
319 priv->details_widget = NULL;
320 priv->empty_view = NULL;
321 priv->progress_widgets = NULL;
322 priv->progress_bar = NULL;
323 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
324 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
325 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
326 priv->merge_ids = NULL;
327 priv->optimized_view = FALSE;
328 priv->send_receive_in_progress = FALSE;
329 priv->progress_bar_timeout = 0;
330 priv->queue_changed_handler_uid = 0;
334 modest_main_window_finalize (GObject *obj)
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
340 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
342 g_slist_free (priv->progress_widgets);
344 g_byte_array_free (priv->merge_ids, TRUE);
346 if (priv->progress_bar_timeout > 0) {
347 g_source_remove (priv->progress_bar_timeout);
348 priv->progress_bar_timeout = 0;
351 /* Disconnect signal handlers */
352 if (priv->queue_changed_handler_uid)
353 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
354 priv->queue_changed_handler_uid);
356 G_OBJECT_CLASS(parent_class)->finalize (obj);
360 modest_main_window_get_child_widget (ModestMainWindow *self,
361 ModestWidgetType widget_type)
363 ModestMainWindowPrivate *priv;
366 g_return_val_if_fail (self, NULL);
367 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
370 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
372 switch (widget_type) {
373 case MODEST_WIDGET_TYPE_HEADER_VIEW:
374 widget = (GtkWidget*)priv->header_view; break;
375 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
376 widget = (GtkWidget*)priv->folder_view; break;
381 return widget ? GTK_WIDGET(widget) : NULL;
386 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
388 printf ("DEBUGDEBUG: %s\n", __FUNCTION__);
391 ModestMainWindowPrivate *priv;
393 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
395 conf = modest_runtime_get_conf ();
397 modest_widget_memory_restore (conf, G_OBJECT(self),
398 MODEST_CONF_MAIN_WINDOW_KEY);
400 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
401 MODEST_CONF_HEADER_VIEW_KEY);
403 if (do_folder_view_too)
404 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
405 MODEST_CONF_FOLDER_VIEW_KEY);
407 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
408 MODEST_CONF_MAIN_PANED_KEY);
410 /* We need to force a redraw here in order to get the right
411 position of the horizontal paned separator */
412 gtk_widget_show (GTK_WIDGET (self));
417 save_state (ModestWindow *window)
420 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
421 ModestMainWindowPrivate *priv;
423 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
424 conf = modest_runtime_get_conf ();
426 modest_widget_memory_save (conf,G_OBJECT(self),
427 MODEST_CONF_MAIN_WINDOW_KEY);
428 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
429 MODEST_CONF_MAIN_PANED_KEY);
430 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
431 // MODEST_CONF_HEADER_VIEW_KEY);
432 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
433 MODEST_CONF_FOLDER_VIEW_KEY);
437 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
439 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
440 gtk_scrolled_window_add_with_viewport
441 (GTK_SCROLLED_WINDOW(win), widget);
443 gtk_container_add (GTK_CONTAINER(win),
448 /* static gboolean */
449 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
451 /* modest_window_save_state (MODEST_WINDOW(self)); */
456 on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data)
459 printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message);
461 if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL)
462 /* Don't show waste the user's time by showing him a dialog telling him
463 * that he has just cancelled something: */
467 /* Get the server name: */
468 const gchar* server_name = NULL;
470 TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account (
471 TNY_CAMEL_SEND_QUEUE (self));
472 if (server_account) {
473 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
475 g_object_unref (server_account);
476 server_account = NULL;
480 server_name = _("Unknown Server");
482 /* Show the appropriate message text for the GError: */
483 gchar *message = NULL;
486 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
487 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
489 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
490 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
492 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
493 /* TODO: This logical ID seems more suitable for a wrong username or password than for a
494 * wrong authentication method. The user is unlikely to guess at the real cause.
496 message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name);
498 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
499 /* TODO: Tinymail is still sending this sometimes when it should
500 * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. */
502 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
506 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
509 modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message);
512 /* TODO: Offer to remove the message, to avoid messages in future? */
514 TnyFolder *outbox = tny_send_queue_get_outbox (queue);
515 tny_folder_remove_msg (outbox, header, NULL);
516 tny_folder_sync (outbox, TRUE, NULL);
517 g_object_unref (outbox);
527 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
529 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
531 GList *oerrsignals = priv->queue_err_signals;
532 while (oerrsignals) {
533 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
534 g_signal_handler_disconnect (esignal->queue, esignal->signal);
535 g_slice_free (QueueErrorSignal, esignal);
536 oerrsignals = g_list_next (oerrsignals);
538 g_list_free (priv->queue_err_signals);
539 priv->queue_err_signals = NULL;
543 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
545 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
547 /* When going online, do the equivalent of pressing the send/receive button,
548 * as per the specification:
549 * (without the check for >0 accounts, though that is not specified): */
551 TnyDevice *device = tny_account_store_get_device (store);
553 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
555 /* Check that we are really online.
556 * This signal should not be emitted when we are not connected,
557 * but it seems to happen sometimes: */
558 if (!tny_device_is_online (device))
561 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
562 printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
564 /* Stop the existing send queues: */
565 modest_runtime_remove_all_send_queues ();
567 /* Create the send queues again, using the appropriate transport accounts
568 * for this new connection.
569 * This could be the first time that they are created if this is the first
571 /* TODO: Does this really destroy the TnySendQueues and their threads
572 * We do not want 2 TnySendQueues to exist with the same underlying
573 * outbox directory. */
575 modest_main_window_cleanup_queue_error_signals (self);
577 GSList *account_names = modest_account_mgr_account_names (
578 modest_runtime_get_account_mgr(),
579 TRUE /* enabled accounts only */);
580 GSList *iter = account_names;
582 const gchar *account_name = (const gchar*)(iter->data);
584 TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
585 modest_tny_account_store_get_transport_account_for_open_connection
586 (modest_runtime_get_account_store(), account_name));
588 /* Q: Is this the first location where the send-queues are requested? */
589 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
590 printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name,
591 tny_account_get_id(TNY_ACCOUNT(account)));
592 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
593 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
594 G_CALLBACK (on_sendqueue_error_happened), self);
595 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
599 iter = g_slist_next (iter);
602 modest_account_mgr_free_account_names (account_names);
603 account_names = NULL;
605 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
609 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
611 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
614 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
618 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
620 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
622 /* Update visibility */
625 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
629 connect_signals (ModestMainWindow *self)
631 ModestWindowPrivate *parent_priv;
632 ModestMainWindowPrivate *priv;
635 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
636 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
639 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
640 G_CALLBACK(on_inner_widgets_key_pressed), self);
641 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
642 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
643 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
644 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
645 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
646 G_CALLBACK (on_folder_view_focus_in), self);
648 /* Folder view CSM */
649 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
650 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
651 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
652 G_CALLBACK(_folder_view_csm_menu_activated),
655 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
656 G_CALLBACK(modest_ui_actions_on_header_selected), self);
657 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
658 G_CALLBACK(modest_ui_actions_on_header_activated), self);
659 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
660 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
661 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
662 G_CALLBACK(on_inner_widgets_key_pressed), self);
663 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
664 G_CALLBACK(_on_msg_count_changed), self);
665 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
666 G_CALLBACK (on_header_view_focus_in), self);
668 /* Header view CSM */
669 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
670 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
671 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
672 G_CALLBACK(_header_view_csm_menu_activated),
676 /* g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */
677 g_signal_connect (G_OBJECT (self), "window-state-event",
678 G_CALLBACK (modest_main_window_window_state_event),
681 /* Mail Operation Queue */
682 priv->queue_changed_handler_uid =
683 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
684 "queue-changed", G_CALLBACK (on_queue_changed), self);
686 /* Track changes in the device name */
687 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
688 "key_changed", G_CALLBACK (on_configuration_key_changed),
691 /* Track account changes. We need to refresh the toolbar */
692 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
693 "account_update", G_CALLBACK (on_account_update),
697 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
698 "password_requested",
699 G_CALLBACK (modest_ui_actions_on_password_requested), self);
702 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()),
703 "connecting-finished",
704 G_CALLBACK(on_account_store_connecting_finished), self);
708 /** Idle handler, to send/receive at startup .*/
710 sync_accounts_cb (ModestMainWindow *win)
712 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
713 return FALSE; /* Do not call this idle handler again. */
717 static void on_hildon_program_is_topmost_notify(GObject *self,
718 GParamSpec *propert_param, gpointer user_data)
720 HildonProgram *app = HILDON_PROGRAM (self);
723 ModestWindow* self = MODEST_WINDOW(user_data);
726 /* Note that use of hildon_program_set_can_hibernate()
727 * is generally referred to as "setting the killable flag",
728 * though hibernation does not seem equal to death.
731 if (hildon_program_get_is_topmost (app)) {
732 /* Prevent hibernation when the progam comes to the foreground,
733 * because hibernation should only happen when the application
734 * is in the background: */
735 hildon_program_set_can_hibernate (app, FALSE);
737 /* Allow hibernation if the program has gone to the background: */
739 /* However, prevent hibernation while the settings are being changed: */
740 const gboolean hibernation_prevented =
741 modest_window_mgr_get_hibernation_is_prevented (
742 modest_runtime_get_window_mgr ());
744 if (hibernation_prevented)
745 hildon_program_set_can_hibernate (app, FALSE);
747 /* Allow hibernation, after saving the state: */
748 modest_osso_save_state();
749 hildon_program_set_can_hibernate (app, TRUE);
756 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
758 GtkWidget *folder_win = (GtkWidget *) user_data;
759 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
761 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
762 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
763 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
765 gtk_widget_show (GTK_WIDGET (priv->folder_view));
767 /* Connect signals */
768 connect_signals ((ModestMainWindow*)self);
770 /* Set account store */
771 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
772 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
774 /* Load previous osso state, for instance if we are being restored from
776 modest_osso_load_state ();
778 /* Restore window & widget settings */
780 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
782 /* Check if accounts exist and show the account wizard if not */
783 gboolean accounts_exist =
784 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
786 if (!accounts_exist) {
787 /* This is necessary to have the main window shown behind the dialog
788 It's an ugly hack... jschmid */
789 gtk_widget_show_all(GTK_WIDGET(self));
790 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
793 GtkAction *send_receive_all;
794 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
795 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
796 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
797 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
798 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
799 modest_account_mgr_free_account_names (accounts);
806 modest_main_window_new (void)
808 ModestMainWindow *self = NULL;
809 ModestMainWindowPrivate *priv = NULL;
810 ModestWindowPrivate *parent_priv = NULL;
811 GtkWidget *folder_win = NULL;
812 ModestDimmingRulesGroup *menu_rules_group = NULL;
813 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
814 GtkActionGroup *action_group = NULL;
815 GError *error = NULL;
816 ModestConf *conf = NULL;
817 GtkAction *action = NULL;
818 GdkPixbuf *window_icon;
820 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
821 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
822 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
824 parent_priv->ui_manager = gtk_ui_manager_new();
825 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
827 action_group = gtk_action_group_new ("ModestMainWindowActions");
828 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
830 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
831 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
833 /* Add common actions */
834 gtk_action_group_add_actions (action_group,
835 modest_action_entries,
836 G_N_ELEMENTS (modest_action_entries),
839 gtk_action_group_add_actions (action_group,
840 modest_folder_view_action_entries,
841 G_N_ELEMENTS (modest_folder_view_action_entries),
844 gtk_action_group_add_actions (action_group,
845 modest_header_view_action_entries,
846 G_N_ELEMENTS (modest_header_view_action_entries),
849 gtk_action_group_add_toggle_actions (action_group,
850 modest_toggle_action_entries,
851 G_N_ELEMENTS (modest_toggle_action_entries),
854 gtk_action_group_add_toggle_actions (action_group,
855 modest_main_window_toggle_action_entries,
856 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
859 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
860 g_object_unref (action_group);
862 /* Load the UI definition */
863 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
864 MODEST_UIDIR "modest-main-window-ui.xml", &error);
866 g_warning ("Could not merge modest-ui.xml: %s", error->message);
867 g_error_free (error);
871 /* Add common dimming rules */
872 modest_dimming_rules_group_add_rules (menu_rules_group,
873 modest_main_window_menu_dimming_entries,
874 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
876 modest_dimming_rules_group_add_rules (toolbar_rules_group,
877 modest_main_window_toolbar_dimming_entries,
878 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
881 /* Insert dimming rules group for this window */
882 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
883 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
884 g_object_unref (menu_rules_group);
885 g_object_unref (toolbar_rules_group);
887 /* Add accelerators */
888 gtk_window_add_accel_group (GTK_WINDOW (self),
889 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
891 /* Menubar. Update the state of some toggles */
892 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
893 conf = modest_runtime_get_conf ();
894 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
895 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
896 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
897 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
898 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
899 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
900 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
901 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
902 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
903 gtk_widget_show (parent_priv->menubar);
905 /* Get device name */
906 modest_maemo_utils_get_device_name ();
910 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
911 if (!priv->header_view)
912 g_printerr ("modest: cannot instantiate header view\n");
913 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
914 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
915 MODEST_CONF_HEADER_VIEW_KEY);
917 /* Other style properties of header view */
918 g_object_set (G_OBJECT (priv->header_view),
921 /* gtk_widget_show (priv->header_view); */
924 priv->empty_view = create_empty_view ();
925 gtk_widget_show (priv->empty_view);
927 /* Create scrolled windows */
928 folder_win = gtk_scrolled_window_new (NULL, NULL);
929 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
930 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
932 GTK_POLICY_AUTOMATIC);
933 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
935 GTK_POLICY_AUTOMATIC);
936 /* gtk_widget_show (priv->contents_widget); */
939 priv->main_paned = gtk_hpaned_new ();
940 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
941 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
942 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
944 /* putting it all together... */
945 priv->main_vbox = gtk_vbox_new (FALSE, 6);
946 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
947 gtk_widget_show (priv->main_vbox);
949 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
951 HildonProgram *app = hildon_program_get_instance ();
952 hildon_program_add_window (app, HILDON_WINDOW (self));
954 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
955 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
957 g_signal_connect (G_OBJECT(self), "show",
958 G_CALLBACK (modest_main_window_on_show), folder_win);
960 /* Set window icon */
961 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
963 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
964 g_object_unref (window_icon);
967 /* Dont't restore settings here,
968 * because it requires a gtk_widget_show(),
969 * and we don't want to do that until later,
970 * so that the UI is not visible for non-menu D-Bus activation.
972 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
974 return MODEST_WINDOW(self);
978 modest_main_window_close_all (ModestMainWindow *self)
981 GtkResponseType response;
983 /* Create the confirmation dialog MSG-NOT308 */
984 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
985 _("emev_nc_close_windows"),
986 _("mcen_bd_yes"), GTK_RESPONSE_YES,
987 _("mcen_bd_no"), GTK_RESPONSE_NO,
990 response = gtk_dialog_run (GTK_DIALOG (note));
991 gtk_widget_destroy (GTK_WIDGET (note));
993 if (response == GTK_RESPONSE_YES)
1001 modest_main_window_set_style (ModestMainWindow *self,
1002 ModestMainWindowStyle style)
1004 ModestMainWindowPrivate *priv;
1005 ModestWindowPrivate *parent_priv;
1009 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1011 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1012 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1014 /* no change -> nothing to do */
1015 if (priv->style == style)
1018 /* Get toggle button and update the state if needed. This will
1019 happen only when the set_style is not invoked from the UI,
1020 for example when it's called from widget memory */
1021 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1022 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1023 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1024 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1025 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1026 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1027 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1030 priv->style = style;
1032 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1033 /* Remove main paned */
1034 g_object_ref (priv->main_paned);
1035 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1037 /* Reparent the contents widget to the main vbox */
1038 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1040 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1041 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1042 TnyIterator *iterator = tny_list_create_iterator (selection);
1044 tny_iterator_first (iterator);
1045 header = TNY_HEADER (tny_iterator_get_current (iterator));
1046 if (tny_header_get_subject (header))
1047 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1049 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1050 g_object_unref (header);
1051 g_object_unref (iterator);
1052 g_object_unref (selection);
1056 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1057 /* Remove header view */
1058 g_object_ref (priv->contents_widget);
1059 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1061 /* Reparent the main paned */
1062 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1063 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1067 g_return_if_reached ();
1070 /* Let header view grab the focus if it's being shown */
1071 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1072 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1074 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1077 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1080 ModestMainWindowStyle
1081 modest_main_window_get_style (ModestMainWindow *self)
1083 ModestMainWindowPrivate *priv;
1085 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1087 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1094 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1096 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1097 ModestWindowPrivate *parent_priv;
1098 ModestWindowMgr *mgr;
1099 gboolean is_fullscreen;
1100 GtkAction *fs_toggle_action;
1103 mgr = modest_runtime_get_window_mgr ();
1105 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1107 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1109 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1110 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1111 if (is_fullscreen != active) {
1112 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1121 set_homogeneous (GtkWidget *widget,
1124 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1125 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1129 modest_main_window_show_toolbar (ModestWindow *self,
1130 gboolean show_toolbar)
1132 ModestMainWindowPrivate *priv = NULL;
1133 ModestWindowPrivate *parent_priv = NULL;
1134 GtkWidget *reply_button = NULL, *menu = NULL;
1135 GtkWidget *placeholder = NULL;
1138 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1139 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1140 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1142 /* Set optimized view status */
1143 priv->optimized_view = !show_toolbar;
1145 if (!parent_priv->toolbar) {
1146 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1149 /* Set homogeneous toolbar */
1150 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1151 set_homogeneous, NULL);
1153 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1154 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1155 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1156 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1157 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1158 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1159 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1160 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1162 /* Add ProgressBar (Transfer toolbar) */
1163 priv->progress_bar = modest_progress_bar_widget_new ();
1164 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1165 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1166 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1167 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1168 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1170 /* Connect cancel 'clicked' signal to abort progress mode */
1171 g_signal_connect(priv->cancel_toolitem, "clicked",
1172 G_CALLBACK(cancel_progressbar),
1175 /* Add it to the observers list */
1176 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1179 hildon_window_add_toolbar (HILDON_WINDOW (self),
1180 GTK_TOOLBAR (parent_priv->toolbar));
1182 /* Set reply button tap and hold menu */
1183 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1184 "/ToolBar/ToolbarMessageReply");
1185 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1186 "/ToolbarReplyCSM");
1187 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1189 /* Set send & receive button tap and hold menu */
1190 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1195 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1196 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1197 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1199 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1200 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1202 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1207 compare_display_names (ModestAccountData *a,
1208 ModestAccountData *b)
1210 return strcmp (a->display_name, b->display_name);
1214 on_account_update (TnyAccountStore *account_store,
1215 const gchar *account_name,
1218 GSList *account_names, *iter, *accounts;
1219 ModestMainWindow *self;
1220 ModestMainWindowPrivate *priv;
1221 ModestWindowPrivate *parent_priv;
1222 ModestAccountMgr *mgr;
1223 gint i, num_accounts;
1224 GtkActionGroup *action_group;
1226 gchar *default_account;
1227 GtkWidget *send_receive_button, *item;
1228 GtkAction *send_receive_all = NULL;
1230 self = MODEST_MAIN_WINDOW (user_data);
1231 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1232 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1234 /* Get enabled account IDs */
1235 mgr = modest_runtime_get_account_mgr ();
1236 account_names = modest_account_mgr_account_names (mgr, TRUE);
1237 iter = account_names;
1241 ModestAccountData *account_data =
1242 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1243 accounts = g_slist_prepend (accounts, account_data);
1247 modest_account_mgr_free_account_names (account_names);
1248 account_names = NULL;
1250 /* Order the list of accounts by its display name */
1251 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1252 num_accounts = g_slist_length (accounts);
1254 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1255 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1256 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1258 /* Delete old send&receive popup items. We can not just do a
1259 menu_detach because it does not work well with
1261 if (priv->accounts_popup)
1262 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1263 (GtkCallback) gtk_widget_destroy, NULL);
1265 /* Delete old entries in the View menu. Do not free groups, it
1267 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1269 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1270 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1271 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1272 GTK_ACTION_GROUP (groups->data));
1275 if (priv->merge_ids) {
1276 for (i = 0; i < priv->merge_ids->len; i++)
1277 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1278 g_byte_array_free (priv->merge_ids, TRUE);
1280 /* We need to call this in order to ensure
1281 that the new actions are added in the right
1282 order (alphabetical */
1283 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1285 groups = g_list_next (groups);
1287 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1289 /* Get send receive button */
1290 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1291 "/ToolBar/ToolbarSendReceive");
1293 /* Create the menu */
1294 if (num_accounts > 1) {
1295 if (!priv->accounts_popup)
1296 priv->accounts_popup = gtk_menu_new ();
1297 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1298 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1299 g_signal_connect (G_OBJECT (item),
1301 G_CALLBACK (on_send_receive_csm_activated),
1303 item = gtk_separator_menu_item_new ();
1304 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1307 /* Create a new action group */
1308 default_account = modest_account_mgr_get_default_account (mgr);
1309 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1310 for (i = 0; i < num_accounts; i++) {
1311 gchar *display_name = NULL;
1313 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1315 /* Create display name. The UI specification specifies a different format string
1316 * to use for the default account, though both seem to be "%s", so
1317 * I don't see what the point is. murrayc. */
1318 if (default_account && account_data->account_name &&
1319 !(strcmp (default_account, account_data->account_name) == 0)) {
1320 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1321 account_data->display_name);
1324 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1325 account_data->display_name);
1328 /* Create action and add it to the action group. The
1329 action name must be the account name, this way we
1330 could know in the handlers the account to show */
1331 if(account_data->account_name) {
1332 gchar* item_name, *refresh_action_name;
1334 GtkAction *view_account_action, *refresh_account_action;
1336 view_account_action = gtk_action_new (account_data->account_name,
1337 display_name, NULL, NULL);
1338 gtk_action_group_add_action (action_group, view_account_action);
1340 /* Add ui from account data. We allow 2^9-1 account
1341 changes in a single execution because we're
1342 downcasting the guint to a guint8 in order to use a
1343 GByteArray. It should be enough. */
1344 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1345 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1346 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1347 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1349 "/MenuBar/ViewMenu/ViewMenuAdditions",
1351 account_data->account_name,
1352 GTK_UI_MANAGER_MENUITEM,
1355 /* Connect the action signal "activate" */
1356 g_signal_connect (G_OBJECT (view_account_action),
1358 G_CALLBACK (on_show_account_action_activated),
1361 /* Create the items for the Tools->Send&Receive submenu */
1362 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1363 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1364 display_name, NULL, NULL);
1365 gtk_action_group_add_action (action_group, refresh_account_action);
1367 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1368 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1369 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1371 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1373 refresh_action_name,
1374 GTK_UI_MANAGER_MENUITEM,
1376 g_free (refresh_action_name);
1378 g_signal_connect_data (G_OBJECT (refresh_account_action),
1380 G_CALLBACK (on_refresh_account_action_activated),
1381 g_strdup (account_data->account_name),
1382 (GClosureNotify) g_free,
1385 /* Create item and add it to the send&receive
1386 CSM. If there is only one account then
1388 if (priv->accounts_popup) {
1389 GtkWidget *label = gtk_label_new(NULL);
1390 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1391 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1393 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1394 gtk_label_set_markup (GTK_LABEL (label), escaped);
1399 gtk_label_set_text (GTK_LABEL (label), display_name);
1402 item = gtk_menu_item_new ();
1403 gtk_container_add (GTK_CONTAINER (item), label);
1405 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1406 g_signal_connect_data (G_OBJECT (item),
1408 G_CALLBACK (on_send_receive_csm_activated),
1409 g_strdup (account_data->account_name),
1410 (GClosureNotify) g_free,
1417 g_free (display_name);
1420 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1422 /* We cannot do this in the loop above because this relies on the action
1423 * group being inserted. This makes the default account appear in bold.
1424 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1425 for (i = 0; i < num_accounts; i++) {
1426 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1428 if(account_data->account_name &&
1429 strcmp (account_data->account_name, default_account) == 0) {
1430 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1432 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1433 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1437 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1438 if (GTK_IS_LABEL (child)) {
1439 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1440 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1441 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1446 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1447 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1451 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1452 if (GTK_IS_LABEL (child)) {
1453 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1454 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1455 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1463 modest_account_mgr_free_account_data (mgr, account_data);
1466 if (priv->accounts_popup) {
1467 /* Mandatory in order to view the menu contents */
1468 gtk_widget_show_all (priv->accounts_popup);
1470 /* Setup tap_and_hold just if was not done before*/
1471 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1472 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1476 g_slist_free (accounts);
1477 g_free (default_account);
1481 * This function manages the key events used to navigate between
1482 * header and folder views (when the window is in split view)
1485 * -------------------------------------------------
1486 * HeaderView GDK_Left Move focus to folder view
1487 * FolderView GDK_Right Move focus to header view
1489 * There is no need to scroll to selected row, the widgets will be the
1490 * responsibles of doing that (probably managing the focus-in event
1493 on_inner_widgets_key_pressed (GtkWidget *widget,
1497 ModestMainWindowPrivate *priv;
1499 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1501 /* Do nothing if we're in SIMPLE style */
1502 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1505 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1506 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1507 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1508 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1514 set_alignment (GtkWidget *widget,
1517 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1518 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1522 create_empty_view (void)
1524 GtkLabel *label = NULL;
1525 GtkWidget *align = NULL;
1527 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1528 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1529 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1530 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1532 return GTK_WIDGET(align);
1536 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1538 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1543 gchar *gray_color_markup;
1545 vbox = gtk_vbox_new (FALSE, 0);
1547 /* Obtain the secondary text color. We need a realized widget, that's why
1548 we get styled_widget from outside */
1549 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1551 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1552 gray_color_markup = modest_text_utils_get_color_string (&color);
1554 // gray_color_markup is freed below
1555 gray_color_markup = g_strdup ("#BBBBBB");
1557 /* Account description: */
1559 if (modest_tny_account_is_virtual_local_folders (account)
1560 || (modest_tny_account_is_memory_card_account (account))) {
1562 /* Local folders: */
1564 /* Get device name */
1565 gchar *device_name = NULL;
1566 if (modest_tny_account_is_virtual_local_folders (account))
1567 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1568 MODEST_CONF_DEVICE_NAME, NULL);
1570 device_name = g_strdup (tny_account_get_name (account));
1572 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1573 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1574 gray_color_markup, tmp, device_name);
1576 label_w = gtk_label_new (NULL);
1577 gtk_label_set_markup (GTK_LABEL (label_w), label);
1578 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1579 g_free (device_name);
1582 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1583 gtk_box_pack_start (GTK_BOX (vbox),
1584 gtk_label_new (tny_account_get_name (account)),
1587 /* Other accounts, such as IMAP and POP: */
1592 /* Put proto in uppercase */
1593 proto = g_string_new (tny_account_get_proto (account));
1594 proto = g_string_ascii_up (proto);
1596 /* note: mcen_fi_localroot_description is something like "%s account"
1597 * however, we should display "%s account: %s"... therefore, ugly tmp */
1598 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1599 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1600 gray_color_markup, tmp, tny_account_get_name (account));
1603 label_w = gtk_label_new (NULL);
1604 gtk_label_set_markup (GTK_LABEL (label_w), label);
1605 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1606 g_string_free (proto, TRUE);
1612 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1613 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1614 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1615 modest_tny_folder_store_get_message_count (folder_store));
1616 label_w = gtk_label_new (NULL);
1617 gtk_label_set_markup (GTK_LABEL (label_w), label);
1618 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1622 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1624 _("mcen_fi_rootfolder_folders"),
1625 modest_tny_folder_store_get_folder_count (folder_store));
1626 label_w = gtk_label_new (NULL);
1627 gtk_label_set_markup (GTK_LABEL (label_w), label);
1628 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1632 if (modest_tny_account_is_virtual_local_folders (account)
1633 || modest_tny_account_is_memory_card_account (account)) {
1635 gchar *size = modest_text_utils_get_display_size (
1636 modest_tny_folder_store_get_local_size (folder_store));
1638 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1639 gray_color_markup, _("mcen_fi_rootfolder_size"),
1643 label_w = gtk_label_new (NULL);
1644 gtk_label_set_markup (GTK_LABEL (label_w), label);
1645 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1647 } else if (TNY_IS_ACCOUNT(folder_store)) {
1648 TnyAccount *account = TNY_ACCOUNT(folder_store);
1650 time_t last_updated;
1651 gchar *last_updated_string;
1652 /* Get last updated from configuration */
1653 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1654 tny_account_get_id (account),
1655 MODEST_ACCOUNT_LAST_UPDATED,
1657 if (last_updated > 0)
1658 last_updated_string = modest_text_utils_get_display_date(last_updated);
1660 last_updated_string = g_strdup (_("mcen_va_never"));
1662 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1663 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1664 label_w = gtk_label_new (NULL);
1665 gtk_label_set_markup (GTK_LABEL (label_w), label);
1666 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1667 g_free (last_updated_string);
1671 g_free (gray_color_markup);
1674 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1680 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1682 ModestMainWindowPrivate *priv = NULL;
1684 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1686 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1688 return priv->send_receive_in_progress;
1692 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1694 GtkAction *action = NULL;
1695 GtkWidget *widget = NULL;
1696 ModestMainWindowPrivate *priv = NULL;
1698 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1699 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1701 priv->send_receive_in_progress = TRUE;
1703 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1704 gtk_action_set_sensitive (action, FALSE);
1705 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1706 /* gtk_action_set_sensitive (action, FALSE); */
1707 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1708 gtk_widget_set_sensitive (widget, FALSE);
1712 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1714 GtkAction *action = NULL;
1715 GtkWidget *widget = NULL;
1716 ModestMainWindowPrivate *priv = NULL;
1718 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1719 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1721 priv->send_receive_in_progress = FALSE;
1723 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1724 gtk_action_set_sensitive (action, TRUE);
1725 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1726 /* gtk_action_set_sensitive (action, TRUE); */
1727 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1728 gtk_widget_set_sensitive (widget, TRUE);
1733 _on_msg_count_changed (ModestHeaderView *header_view,
1735 TnyFolderChange *change,
1736 ModestMainWindow *main_window)
1738 printf ("DEBUG: %s\n", __FUNCTION__);
1739 gboolean folder_empty = FALSE;
1740 TnyFolderChangeChanged changed;
1742 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1743 g_return_if_fail (TNY_IS_FOLDER(folder));
1744 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1746 changed = tny_folder_change_get_changed (change);
1748 /* If something changes */
1749 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1750 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1752 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1754 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1756 /* Set contents style of headers view */
1758 modest_main_window_set_contents_style (main_window,
1759 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1762 modest_main_window_set_contents_style (main_window,
1763 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1769 modest_main_window_set_contents_style (ModestMainWindow *self,
1770 ModestMainWindowContentsStyle style)
1772 ModestMainWindowPrivate *priv;
1774 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1776 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1778 /* We allow to set the same content style than the previously
1779 set if there are details, because it could happen when we're
1780 selecting different accounts consecutively */
1781 if ((priv->contents_style == style) &&
1782 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1785 /* Remove previous child. Delete it if it was an account
1787 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1789 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1790 g_object_ref (content);
1791 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1792 g_object_ref (priv->empty_view);
1793 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1796 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1799 priv->contents_style = style;
1801 switch (priv->contents_style) {
1802 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1803 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1804 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1807 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
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),
1825 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1826 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1827 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1831 g_return_if_reached ();
1835 gtk_widget_show_all (priv->contents_widget);
1838 ModestMainWindowContentsStyle
1839 modest_main_window_get_contents_style (ModestMainWindow *self)
1841 ModestMainWindowPrivate *priv;
1843 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1845 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1846 return priv->contents_style;
1851 on_configuration_key_changed (ModestConf* conf,
1853 ModestConfEvent event,
1854 ModestMainWindow *self)
1856 ModestMainWindowPrivate *priv;
1857 TnyAccount *account;
1859 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1862 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1864 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1867 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1868 if (TNY_IS_ACCOUNT (account) &&
1869 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1872 const gchar *device_name;
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 new_text = g_strdup_printf ("%s: %s",
1883 _("mcen_fi_localroot_description"),
1886 gtk_label_set_text (label, new_text);
1887 gtk_widget_show (GTK_WIDGET (label));
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 /* Show and hide toolbar items */
1942 case TOOLBAR_MODE_NORMAL:
1944 gtk_action_set_visible (sort_action, TRUE);
1946 gtk_action_set_visible (refresh_action, TRUE);
1947 if (priv->progress_toolitem) {
1948 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1949 gtk_widget_hide (priv->progress_toolitem);
1951 if (priv->progress_bar)
1952 gtk_widget_hide (priv->progress_bar);
1955 gtk_action_set_visible (cancel_action, FALSE);
1956 /* if (priv->sort_toolitem) */
1957 /* gtk_widget_show (priv->sort_toolitem); */
1959 /* if (priv->refresh_toolitem) */
1960 /* gtk_widget_show (priv->refresh_toolitem); */
1962 /* if (priv->progress_toolitem) */
1963 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1964 /* if (priv->progress_bar) */
1965 /* gtk_widget_hide (priv->progress_bar); */
1967 /* if (priv->cancel_toolitem) */
1968 /* gtk_widget_hide (priv->cancel_toolitem); */
1970 /* Hide toolbar if optimized view is enabled */
1971 if (priv->optimized_view)
1972 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1974 case TOOLBAR_MODE_TRANSFER:
1976 gtk_action_set_visible (sort_action, FALSE);
1978 gtk_action_set_visible (refresh_action, FALSE);
1980 gtk_action_set_visible (cancel_action, TRUE);
1981 if (priv->progress_toolitem) {
1982 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1983 gtk_widget_show (priv->progress_toolitem);
1985 if (priv->progress_bar)
1986 gtk_widget_show (priv->progress_bar);
1988 /* if (priv->sort_toolitem) */
1989 /* gtk_widget_hide (priv->sort_toolitem); */
1991 /* if (priv->refresh_toolitem) */
1992 /* gtk_widget_hide (priv->refresh_toolitem); */
1994 /* if (priv->progress_toolitem) */
1995 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
1996 /* if (priv->progress_bar) */
1997 /* gtk_widget_show (priv->progress_bar); */
1999 /* if (priv->cancel_toolitem) */
2000 /* gtk_widget_show (priv->cancel_toolitem); */
2002 /* Show toolbar if it's hiden (optimized view ) */
2003 if (priv->optimized_view)
2004 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2007 g_return_if_reached ();
2012 cancel_progressbar (GtkToolButton *toolbutton,
2013 ModestMainWindow *self)
2016 ModestMainWindowPrivate *priv;
2018 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2020 /* Get operation observers and cancel all the operations */
2021 tmp = priv->progress_widgets;
2023 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2024 tmp=g_slist_next(tmp);
2029 observers_empty (ModestMainWindow *self)
2032 ModestMainWindowPrivate *priv;
2033 gboolean is_empty = TRUE;
2034 guint pending_ops = 0;
2036 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2037 tmp = priv->progress_widgets;
2039 /* Check all observers */
2040 while (tmp && is_empty) {
2041 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2042 is_empty = pending_ops == 0;
2044 tmp = g_slist_next(tmp);
2051 on_queue_changed (ModestMailOperationQueue *queue,
2052 ModestMailOperation *mail_op,
2053 ModestMailOperationQueueNotification type,
2054 ModestMainWindow *self)
2056 ModestMainWindowPrivate *priv;
2057 ModestMailOperationTypeOperation op_type;
2058 ModestToolBarModes mode;
2060 gboolean mode_changed = FALSE;
2061 /* ModestMailOperationStatus status; */
2063 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2064 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2066 /* Get toolbar mode from operation id*/
2067 op_type = modest_mail_operation_get_type_operation (mail_op);
2069 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2070 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2071 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2072 mode = TOOLBAR_MODE_TRANSFER;
2073 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2074 mode_changed = TRUE;
2077 mode = TOOLBAR_MODE_NORMAL;
2082 /* Add operation observers and change toolbar if neccessary*/
2083 tmp = priv->progress_widgets;
2085 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2086 if (mode == TOOLBAR_MODE_TRANSFER) {
2088 set_toolbar_transfer_mode(self);
2090 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2092 tmp = g_slist_next (tmp);
2096 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2097 /* Change toolbar mode */
2098 if (mode == TOOLBAR_MODE_TRANSFER) {
2100 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2102 tmp = g_slist_next (tmp);
2105 /* If no more operations are being observed, NORMAL mode is enabled again */
2106 if (observers_empty (self)) {
2107 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2118 on_show_account_action_activated (GtkAction *action,
2121 ModestAccountData *acc_data;
2122 ModestMainWindow *self;
2123 ModestMainWindowPrivate *priv;
2124 ModestAccountMgr *mgr;
2125 const gchar *acc_name;
2127 self = MODEST_MAIN_WINDOW (user_data);
2128 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2130 /* Get account data */
2131 acc_name = gtk_action_get_name (action);
2132 mgr = modest_runtime_get_account_mgr ();
2133 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2135 /* Set the new visible & active account */
2136 if (acc_data->store_account) {
2137 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2138 acc_data->store_account->account_name);
2139 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2142 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2145 modest_account_mgr_free_account_data (mgr, acc_data);
2149 refresh_account (const gchar *account_name)
2153 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2155 /* If account_name == NULL, we must update all (option All) */
2157 modest_ui_actions_do_send_receive_all (win);
2159 modest_ui_actions_do_send_receive (account_name, win);
2164 on_refresh_account_action_activated (GtkAction *action,
2167 refresh_account ((const gchar*) user_data);
2171 on_send_receive_csm_activated (GtkMenuItem *item,
2174 refresh_account ((const gchar*) user_data);
2178 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2180 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2182 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2188 on_folder_view_focus_in (GtkWidget *widget,
2189 GdkEventFocus *event,
2192 ModestMainWindow *main_window = NULL;
2194 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2195 main_window = MODEST_MAIN_WINDOW (userdata);
2197 /* Update toolbar dimming state */
2198 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2204 on_header_view_focus_in (GtkWidget *widget,
2205 GdkEventFocus *event,
2208 ModestMainWindow *main_window = NULL;
2209 ModestMainWindowPrivate *priv = NULL;
2211 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2212 main_window = MODEST_MAIN_WINDOW (userdata);
2213 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2215 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2216 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2217 TnyIterator *iterator = tny_list_create_iterator (selection);
2220 tny_iterator_first (iterator);
2221 header = TNY_HEADER (tny_iterator_get_current (iterator));
2223 if (tny_header_get_subject (header))
2224 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2226 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2228 g_object_unref (header);
2229 g_object_unref (iterator);
2230 g_object_unref (selection);
2234 /* Update toolbar dimming state */
2235 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2241 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2242 TnyFolderStore *folder_store,
2244 ModestMainWindow *main_window)
2246 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2247 GtkAction *action = NULL;
2248 gboolean show_reply = TRUE;
2249 gboolean show_forward = TRUE;
2250 gboolean show_cancel_send = FALSE;
2251 gboolean show_clipboard = TRUE;
2252 gboolean show_delete = TRUE;
2255 if (TNY_IS_ACCOUNT (folder_store)) {
2256 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2257 } else if (TNY_IS_FOLDER (folder_store)) {
2258 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2259 TnyFolderType folder_type = modest_tny_folder_get_local_folder_type (
2260 TNY_FOLDER (folder_store));
2261 switch (folder_type) {
2262 case TNY_FOLDER_TYPE_DRAFTS:
2263 show_clipboard = show_delete = TRUE;
2264 show_reply = show_forward = show_cancel_send = FALSE;
2266 case TNY_FOLDER_TYPE_SENT:
2267 show_forward = show_clipboard = show_delete = TRUE;
2268 show_reply = show_cancel_send = FALSE;
2270 case TNY_FOLDER_TYPE_OUTBOX:
2271 show_clipboard = show_delete = show_cancel_send = TRUE;
2272 show_reply = show_forward = FALSE;
2275 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2276 show_cancel_send = FALSE;
2279 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2280 show_cancel_send = FALSE;
2285 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2286 gtk_action_set_visible (action, show_reply);
2287 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2288 gtk_action_set_visible (action, show_reply);
2289 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2290 gtk_action_set_visible (action, show_forward);
2291 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2292 gtk_action_set_visible (action, show_cancel_send);
2293 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2294 gtk_action_set_visible (action, show_clipboard);
2295 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2296 gtk_action_set_visible (action, show_clipboard);
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2298 gtk_action_set_visible (action, show_clipboard);
2299 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2300 gtk_action_set_visible (action, show_delete);
2302 /* We finally call to the ui actions handler, after updating properly
2303 * the header view CSM */
2304 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2309 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2310 GtkTreeModel *model,
2311 GtkTreeRowReference *row_reference,
2312 ModestMainWindow *self)
2314 ModestMainWindowPrivate *priv = NULL;
2315 GtkTreeModel *header_model = NULL;
2316 GtkTreePath *path = NULL;
2318 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2319 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2320 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2322 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2323 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2325 /* Do nothing if we changed the folder in the main view */
2326 if (header_model != model)
2329 /* Select the message in the header view */
2330 path = gtk_tree_row_reference_get_path (row_reference);
2331 _modest_header_view_select_from_path (MODEST_HEADER_VIEW (priv->header_view), path);
2332 gtk_tree_path_free (path);