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);
85 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
86 GdkEventWindowState *event,
89 static void connect_signals (ModestMainWindow *self);
91 static void modest_main_window_disconnect_signals (ModestWindow *self);
93 static void restore_settings (ModestMainWindow *self,
94 gboolean do_folder_view_too);
96 static void save_state (ModestWindow *self);
98 static void modest_main_window_show_toolbar (ModestWindow *window,
99 gboolean show_toolbar);
101 static void cancel_progressbar (GtkToolButton *toolbutton,
102 ModestMainWindow *self);
104 static void on_queue_changed (ModestMailOperationQueue *queue,
105 ModestMailOperation *mail_op,
106 ModestMailOperationQueueNotification type,
107 ModestMainWindow *self);
109 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
111 static void account_number_changed (TnyAccountStore *account_store,
112 const gchar *account_name,
115 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
119 static void on_configuration_key_changed (ModestConf* conf,
121 ModestConfEvent event,
122 ModestConfNotificationId id,
123 ModestMainWindow *self);
125 static void set_toolbar_mode (ModestMainWindow *self,
126 ModestToolBarModes mode);
128 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
130 static void on_show_account_action_activated (GtkAction *action,
133 static void on_refresh_account_action_activated (GtkAction *action,
136 static void on_send_receive_csm_activated (GtkMenuItem *item,
140 _on_msg_count_changed (ModestHeaderView *header_view,
142 TnyFolderChange *change,
143 ModestMainWindow *main_window);
146 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
149 static GtkWidget * create_empty_view (void);
152 on_folder_view_focus_in (GtkWidget *widget,
153 GdkEventFocus *event,
156 on_header_view_focus_in (GtkWidget *widget,
157 GdkEventFocus *event,
160 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
161 TnyFolderStore *folder_store,
163 ModestMainWindow *main_window);
165 /* list my signals */
172 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
173 struct _ModestMainWindowPrivate {
174 GtkWidget *msg_paned;
175 GtkWidget *main_paned;
176 GtkWidget *main_vbox;
177 GtkWidget *contents_widget;
178 GtkWidget *empty_view;
180 /* Progress observers */
181 GtkWidget *progress_bar;
182 GSList *progress_widgets;
185 GtkWidget *progress_toolitem;
186 GtkWidget *cancel_toolitem;
187 GtkWidget *sort_toolitem;
188 GtkWidget *refresh_toolitem;
189 ModestToolBarModes current_toolbar_mode;
191 /* Merge ids used to add/remove accounts to the ViewMenu*/
192 GByteArray *merge_ids;
194 /* On-demand widgets */
195 GtkWidget *accounts_popup;
196 GtkWidget *details_widget;
198 /* Optimized view enabled */
199 gboolean optimized_view;
201 /* Optimized view enabled */
202 gboolean send_receive_in_progress;
204 ModestHeaderView *header_view;
205 ModestFolderView *folder_view;
207 ModestMainWindowStyle style;
208 ModestMainWindowContentsStyle contents_style;
210 guint progress_bar_timeout;
212 /* Signal handler UIDs */
213 gint queue_changed_handler_uid;
214 GList *queue_err_signals;
216 ModestConfNotificationId notification_id;
218 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
219 MODEST_TYPE_MAIN_WINDOW, \
220 ModestMainWindowPrivate))
222 typedef struct _GetMsgAsyncHelper {
223 ModestMainWindowPrivate *main_window_private;
225 ModestTnyMsgReplyType reply_type;
226 ModestTnyMsgForwardType forward_type;
233 static GtkWindowClass *parent_class = NULL;
236 /* Private actions */
237 /* This is the context sensitive menu: */
238 static const GtkActionEntry modest_folder_view_action_entries [] = {
240 /* Folder View CSM actions */
241 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
242 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
243 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
244 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
245 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
246 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
249 static const GtkActionEntry modest_header_view_action_entries [] = {
251 /* Header View CSM actions */
252 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
253 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
254 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
255 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
256 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
257 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
258 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
259 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
260 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
261 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
264 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
265 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
268 /************************************************************************/
271 modest_main_window_get_type (void)
273 static GType my_type = 0;
275 static const GTypeInfo my_info = {
276 sizeof(ModestMainWindowClass),
277 NULL, /* base init */
278 NULL, /* base finalize */
279 (GClassInitFunc) modest_main_window_class_init,
280 NULL, /* class finalize */
281 NULL, /* class data */
282 sizeof(ModestMainWindow),
284 (GInstanceInitFunc) modest_main_window_init,
287 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
295 modest_main_window_class_init (ModestMainWindowClass *klass)
297 GObjectClass *gobject_class;
298 gobject_class = (GObjectClass*) klass;
299 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
301 parent_class = g_type_class_peek_parent (klass);
302 gobject_class->finalize = modest_main_window_finalize;
304 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
306 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
307 modest_window_class->save_state_func = save_state;
308 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
309 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
310 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
314 modest_main_window_init (ModestMainWindow *obj)
316 ModestMainWindowPrivate *priv;
318 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
320 priv->queue_err_signals = NULL;
321 priv->msg_paned = NULL;
322 priv->main_paned = NULL;
323 priv->main_vbox = NULL;
324 priv->header_view = NULL;
325 priv->folder_view = NULL;
326 priv->contents_widget = NULL;
327 priv->accounts_popup = NULL;
328 priv->details_widget = NULL;
329 priv->empty_view = NULL;
330 priv->progress_widgets = NULL;
331 priv->progress_bar = NULL;
332 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
333 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
334 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
335 priv->merge_ids = NULL;
336 priv->optimized_view = FALSE;
337 priv->send_receive_in_progress = FALSE;
338 priv->progress_bar_timeout = 0;
339 priv->queue_changed_handler_uid = 0;
343 modest_main_window_finalize (GObject *obj)
345 ModestMainWindowPrivate *priv;
347 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
349 /* Sanity check: shouldn't be needed, the window mgr should
350 call this function before */
351 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
353 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
355 g_slist_free (priv->progress_widgets);
357 g_byte_array_free (priv->merge_ids, TRUE);
359 if (priv->progress_bar_timeout > 0) {
360 g_source_remove (priv->progress_bar_timeout);
361 priv->progress_bar_timeout = 0;
364 if (priv->notification_id) {
365 modest_conf_forget_namespace (modest_runtime_get_conf (),
366 MODEST_CONF_NAMESPACE,
367 priv->notification_id);
370 G_OBJECT_CLASS(parent_class)->finalize (obj);
374 modest_main_window_get_child_widget (ModestMainWindow *self,
375 ModestWidgetType widget_type)
377 ModestMainWindowPrivate *priv;
380 g_return_val_if_fail (self, NULL);
381 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
384 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
386 switch (widget_type) {
387 case MODEST_WIDGET_TYPE_HEADER_VIEW:
388 widget = (GtkWidget*)priv->header_view; break;
389 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
390 widget = (GtkWidget*)priv->folder_view; break;
395 return widget ? GTK_WIDGET(widget) : NULL;
400 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
402 printf ("DEBUGDEBUG: %s\n", __FUNCTION__);
405 ModestMainWindowPrivate *priv;
407 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
409 conf = modest_runtime_get_conf ();
411 modest_widget_memory_restore (conf, G_OBJECT(self),
412 MODEST_CONF_MAIN_WINDOW_KEY);
414 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
415 MODEST_CONF_HEADER_VIEW_KEY);
417 if (do_folder_view_too)
418 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
419 MODEST_CONF_FOLDER_VIEW_KEY);
421 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
422 MODEST_CONF_MAIN_PANED_KEY);
424 /* We need to force a redraw here in order to get the right
425 position of the horizontal paned separator */
426 gtk_widget_show (GTK_WIDGET (self));
431 save_state (ModestWindow *window)
434 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
435 ModestMainWindowPrivate *priv;
437 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
438 conf = modest_runtime_get_conf ();
440 modest_widget_memory_save (conf,G_OBJECT(self),
441 MODEST_CONF_MAIN_WINDOW_KEY);
442 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
443 MODEST_CONF_MAIN_PANED_KEY);
444 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
445 // MODEST_CONF_HEADER_VIEW_KEY);
446 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
447 MODEST_CONF_FOLDER_VIEW_KEY);
451 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
453 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
454 gtk_scrolled_window_add_with_viewport
455 (GTK_SCROLLED_WINDOW(win), widget);
457 gtk_container_add (GTK_CONTAINER(win),
462 /* static gboolean */
463 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
465 /* modest_window_save_state (MODEST_WINDOW(self)); */
470 /* on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data) */
473 /* printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message); */
475 /* if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL) */
476 /* /\* Don't show waste the user's time by showing him a dialog telling him */
477 /* * that he has just cancelled something: *\/ */
481 /* /\* Get the server name: *\/ */
482 /* const gchar* server_name = NULL; */
484 /* TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account ( */
485 /* TNY_CAMEL_SEND_QUEUE (self)); */
486 /* if (server_account) { */
487 /* server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account)); */
489 /* g_object_unref (server_account); */
490 /* server_account = NULL; */
493 /* if (!server_name) */
494 /* server_name = _("Unknown Server"); */
496 /* /\* Show the appropriate message text for the GError: *\/ */
497 /* gchar *message = NULL; */
499 /* switch (err->code) { */
500 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED: */
501 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
503 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE: */
504 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
506 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED: */
507 /* /\* TODO: This logical ID seems more suitable for a wrong username or password than for a */
508 /* * wrong authentication method. The user is unlikely to guess at the real cause. */
510 /* message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name); */
512 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND: */
513 /* /\* TODO: Tinymail is still sending this sometimes when it should */
514 /* * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. *\/ */
516 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
520 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
523 /* modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message); */
524 /* g_free (message); */
526 /* /\* TODO: Offer to remove the message, to avoid messages in future? *\/ */
528 /* TnyFolder *outbox = tny_send_queue_get_outbox (queue); */
529 /* tny_folder_remove_msg (outbox, header, NULL); */
530 /* tny_folder_sync (outbox, TRUE, NULL); */
531 /* g_object_unref (outbox); */
541 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
543 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
545 GList *oerrsignals = priv->queue_err_signals;
546 while (oerrsignals) {
547 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
548 g_signal_handler_disconnect (esignal->queue, esignal->signal);
549 g_slice_free (QueueErrorSignal, esignal);
550 oerrsignals = g_list_next (oerrsignals);
552 g_list_free (priv->queue_err_signals);
553 priv->queue_err_signals = NULL;
557 /* on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self) */
559 /* ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); */
561 /* /\* When going online, do the equivalent of pressing the send/receive button, */
562 /* * as per the specification: */
563 /* * (without the check for >0 accounts, though that is not specified): *\/ */
565 /* TnyDevice *device = tny_account_store_get_device (store); */
567 /* /\* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); *\/ */
569 /* /\* Check that we are really online. */
570 /* * This signal should not be emitted when we are not connected, */
571 /* * but it seems to happen sometimes: *\/ */
572 /* if (!tny_device_is_online (device)) */
575 /* const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device)); */
576 /* printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id); */
578 /* /\* Stop the existing send queues: *\/ */
579 /* modest_runtime_remove_all_send_queues (); */
581 /* /\* Create the send queues again, using the appropriate transport accounts */
582 /* * for this new connection. */
583 /* * This could be the first time that they are created if this is the first */
584 /* * connection. *\/ */
585 /* /\* TODO: Does this really destroy the TnySendQueues and their threads */
586 /* * We do not want 2 TnySendQueues to exist with the same underlying */
587 /* * outbox directory. *\/ */
589 /* modest_main_window_cleanup_queue_error_signals (self); */
591 /* GSList *account_names = modest_account_mgr_account_names ( */
592 /* modest_runtime_get_account_mgr(), */
593 /* TRUE /\* enabled accounts only *\/); */
594 /* GSList *iter = account_names; */
596 /* const gchar *account_name = (const gchar*)(iter->data); */
597 /* if (account_name) { */
598 /* TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT ( */
599 /* modest_tny_account_store_get_transport_account_for_open_connection */
600 /* (modest_runtime_get_account_store(), account_name)); */
602 /* /\* Q: Is this the first location where the send-queues are requested? *\/ */
603 /* QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal); */
604 /* printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name, */
605 /* tny_account_get_id(TNY_ACCOUNT(account))); */
606 /* esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account)); */
607 /* esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened", */
608 /* G_CALLBACK (on_sendqueue_error_happened), self); */
609 /* priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal); */
613 /* iter = g_slist_next (iter); */
616 /* modest_account_mgr_free_account_names (account_names); */
617 /* account_names = NULL; */
619 /* modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self)); */
623 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
625 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
628 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
632 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
634 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
636 /* Update visibility */
639 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
643 modest_main_window_disconnect_signals (ModestWindow *self)
645 ModestMainWindowPrivate *priv;
647 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
649 /* Disconnect signal handlers */
650 if (g_signal_handler_is_connected (modest_runtime_get_mail_operation_queue (),
651 priv->queue_changed_handler_uid))
652 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
653 priv->queue_changed_handler_uid);
657 connect_signals (ModestMainWindow *self)
659 ModestWindowPrivate *parent_priv;
660 ModestMainWindowPrivate *priv;
663 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
664 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
667 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
668 G_CALLBACK(on_inner_widgets_key_pressed), self);
669 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
670 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
671 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
672 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
673 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
674 G_CALLBACK (on_folder_view_focus_in), self);
676 /* Folder view CSM */
677 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
678 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
679 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
680 G_CALLBACK(_folder_view_csm_menu_activated),
683 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
684 G_CALLBACK(modest_ui_actions_on_header_selected), self);
685 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
686 G_CALLBACK(modest_ui_actions_on_header_activated), self);
687 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
688 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
689 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
690 G_CALLBACK(on_inner_widgets_key_pressed), self);
691 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
692 G_CALLBACK(_on_msg_count_changed), self);
693 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
694 G_CALLBACK (on_header_view_focus_in), self);
696 /* Header view CSM */
697 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
698 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
699 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
700 G_CALLBACK(_header_view_csm_menu_activated),
704 g_signal_connect (G_OBJECT (self), "window-state-event",
705 G_CALLBACK (modest_main_window_window_state_event),
708 /* Mail Operation Queue */
709 priv->queue_changed_handler_uid =
710 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
711 "queue-changed", G_CALLBACK (on_queue_changed), self);
713 /* Track changes in the device name */
714 priv->notification_id = modest_conf_listen_to_namespace (modest_runtime_get_conf (),
715 MODEST_CONF_NAMESPACE);
716 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
717 "key_changed", G_CALLBACK (on_configuration_key_changed),
720 /* Track account changes. We need to refresh the toolbar */
721 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
722 "account_inserted", G_CALLBACK (account_number_changed),
724 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
725 "account_removed", G_CALLBACK (account_number_changed),
729 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
730 "password_requested",
731 G_CALLBACK (modest_ui_actions_on_password_requested), self);
734 /* g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), */
735 /* "connecting-finished", */
736 /* G_CALLBACK(on_account_store_connecting_finished), self); */
740 /** Idle handler, to send/receive at startup .*/
742 sync_accounts_cb (ModestMainWindow *win)
744 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
745 return FALSE; /* Do not call this idle handler again. */
749 static void on_hildon_program_is_topmost_notify(GObject *self,
750 GParamSpec *propert_param, gpointer user_data)
752 HildonProgram *app = HILDON_PROGRAM (self);
755 ModestWindow* self = MODEST_WINDOW(user_data);
758 /* Note that use of hildon_program_set_can_hibernate()
759 * is generally referred to as "setting the killable flag",
760 * though hibernation does not seem equal to death.
763 if (hildon_program_get_is_topmost (app)) {
764 /* Prevent hibernation when the progam comes to the foreground,
765 * because hibernation should only happen when the application
766 * is in the background: */
767 hildon_program_set_can_hibernate (app, FALSE);
769 /* Allow hibernation if the program has gone to the background: */
771 /* However, prevent hibernation while the settings are being changed: */
772 const gboolean hibernation_prevented =
773 modest_window_mgr_get_hibernation_is_prevented (
774 modest_runtime_get_window_mgr ());
776 if (hibernation_prevented)
777 hildon_program_set_can_hibernate (app, FALSE);
779 /* Allow hibernation, after saving the state: */
780 modest_osso_save_state();
781 hildon_program_set_can_hibernate (app, TRUE);
788 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
790 GtkWidget *folder_win = (GtkWidget *) user_data;
791 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
793 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
794 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
795 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
797 gtk_widget_show (GTK_WIDGET (priv->folder_view));
799 /* Connect signals */
800 connect_signals ((ModestMainWindow*)self);
802 /* Set account store */
803 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
804 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
806 /* Load previous osso state, for instance if we are being restored from
808 modest_osso_load_state ();
810 /* Restore window & widget settings */
812 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
814 /* The UI spec wants us to show a connection dialog when the application is
815 * started by the user, if there is no connection.
816 * Do this before showing the account wizard,
817 * because wizard needs a connection to discover capabilities. */
818 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
820 /* Check if accounts exist and show the account wizard if not */
821 gboolean accounts_exist =
822 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
824 if (!accounts_exist) {
825 /* This is necessary to have the main window shown behind the dialog
826 It's an ugly hack... jschmid */
827 gtk_widget_show_all(GTK_WIDGET(self));
828 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
831 GtkAction *send_receive_all;
832 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
833 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
834 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
835 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
836 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
837 modest_account_mgr_free_account_names (accounts);
842 modest_main_window_new (void)
844 ModestMainWindow *self = NULL;
845 ModestMainWindowPrivate *priv = NULL;
846 ModestWindowPrivate *parent_priv = NULL;
847 GtkWidget *folder_win = NULL;
848 ModestDimmingRulesGroup *menu_rules_group = NULL;
849 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
850 GtkActionGroup *action_group = NULL;
851 GError *error = NULL;
852 ModestConf *conf = NULL;
853 GtkAction *action = NULL;
854 GdkPixbuf *window_icon;
856 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
857 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
858 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
860 parent_priv->ui_manager = gtk_ui_manager_new();
861 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
863 action_group = gtk_action_group_new ("ModestMainWindowActions");
864 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
866 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
867 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
869 /* Add common actions */
870 gtk_action_group_add_actions (action_group,
871 modest_action_entries,
872 G_N_ELEMENTS (modest_action_entries),
875 gtk_action_group_add_actions (action_group,
876 modest_folder_view_action_entries,
877 G_N_ELEMENTS (modest_folder_view_action_entries),
880 gtk_action_group_add_actions (action_group,
881 modest_header_view_action_entries,
882 G_N_ELEMENTS (modest_header_view_action_entries),
885 gtk_action_group_add_toggle_actions (action_group,
886 modest_toggle_action_entries,
887 G_N_ELEMENTS (modest_toggle_action_entries),
890 gtk_action_group_add_toggle_actions (action_group,
891 modest_main_window_toggle_action_entries,
892 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
895 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
896 g_object_unref (action_group);
898 /* Load the UI definition */
899 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
900 MODEST_UIDIR "modest-main-window-ui.xml", &error);
902 g_warning ("Could not merge modest-ui.xml: %s", error->message);
903 g_error_free (error);
907 /* Add common dimming rules */
908 modest_dimming_rules_group_add_rules (menu_rules_group,
909 modest_main_window_menu_dimming_entries,
910 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
912 modest_dimming_rules_group_add_rules (toolbar_rules_group,
913 modest_main_window_toolbar_dimming_entries,
914 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
917 /* Insert dimming rules group for this window */
918 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
919 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
920 g_object_unref (menu_rules_group);
921 g_object_unref (toolbar_rules_group);
923 /* Add accelerators */
924 gtk_window_add_accel_group (GTK_WINDOW (self),
925 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
927 /* Menubar. Update the state of some toggles */
928 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
929 conf = modest_runtime_get_conf ();
930 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
931 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
932 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
933 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
934 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
935 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
936 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
937 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
938 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
939 gtk_widget_show (parent_priv->menubar);
941 /* Get device name */
942 modest_maemo_utils_get_device_name ();
946 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
947 if (!priv->header_view)
948 g_printerr ("modest: cannot instantiate header view\n");
949 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
950 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
951 MODEST_CONF_HEADER_VIEW_KEY);
953 /* Other style properties of header view */
954 g_object_set (G_OBJECT (priv->header_view),
957 /* gtk_widget_show (priv->header_view); */
960 priv->empty_view = create_empty_view ();
961 gtk_widget_show (priv->empty_view);
963 /* Create scrolled windows */
964 folder_win = gtk_scrolled_window_new (NULL, NULL);
965 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
966 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
968 GTK_POLICY_AUTOMATIC);
969 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
971 GTK_POLICY_AUTOMATIC);
972 /* gtk_widget_show (priv->contents_widget); */
975 priv->main_paned = gtk_hpaned_new ();
976 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
977 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
978 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
980 /* putting it all together... */
981 priv->main_vbox = gtk_vbox_new (FALSE, 6);
982 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
983 gtk_widget_show (priv->main_vbox);
985 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
987 HildonProgram *app = hildon_program_get_instance ();
988 hildon_program_add_window (app, HILDON_WINDOW (self));
990 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
991 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
993 g_signal_connect (G_OBJECT(self), "show",
994 G_CALLBACK (modest_main_window_on_show), folder_win);
996 /* Set window icon */
997 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
999 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1000 g_object_unref (window_icon);
1003 /* Dont't restore settings here,
1004 * because it requires a gtk_widget_show(),
1005 * and we don't want to do that until later,
1006 * so that the UI is not visible for non-menu D-Bus activation.
1008 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1010 return MODEST_WINDOW(self);
1014 modest_main_window_close_all (ModestMainWindow *self)
1017 GtkResponseType response;
1019 /* Create the confirmation dialog MSG-NOT308 */
1020 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1021 _("emev_nc_close_windows"),
1022 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1023 _("mcen_bd_no"), GTK_RESPONSE_NO,
1026 response = gtk_dialog_run (GTK_DIALOG (note));
1027 gtk_widget_destroy (GTK_WIDGET (note));
1029 if (response == GTK_RESPONSE_YES)
1037 modest_main_window_set_style (ModestMainWindow *self,
1038 ModestMainWindowStyle style)
1040 ModestMainWindowPrivate *priv;
1041 ModestWindowPrivate *parent_priv;
1045 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1047 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1048 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1050 /* no change -> nothing to do */
1051 if (priv->style == style)
1054 /* Get toggle button and update the state if needed. This will
1055 happen only when the set_style is not invoked from the UI,
1056 for example when it's called from widget memory */
1057 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1058 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1059 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1060 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1061 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1062 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1063 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1066 priv->style = style;
1068 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1069 /* Remove main paned */
1070 g_object_ref (priv->main_paned);
1071 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1073 /* Reparent the contents widget to the main vbox */
1074 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1076 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1077 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1078 TnyIterator *iterator = tny_list_create_iterator (selection);
1080 tny_iterator_first (iterator);
1081 header = TNY_HEADER (tny_iterator_get_current (iterator));
1082 if (tny_header_get_subject (header))
1083 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1085 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1088 g_object_unref (header);
1090 g_object_unref (iterator);
1091 g_object_unref (selection);
1095 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1096 /* Remove header view */
1097 g_object_ref (priv->contents_widget);
1098 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1100 /* Reparent the main paned */
1101 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1102 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1106 g_return_if_reached ();
1109 /* Let header view grab the focus if it's being shown */
1110 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1111 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1113 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1116 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1119 ModestMainWindowStyle
1120 modest_main_window_get_style (ModestMainWindow *self)
1122 ModestMainWindowPrivate *priv;
1124 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1126 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1133 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1135 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1136 ModestWindowPrivate *parent_priv;
1137 ModestWindowMgr *mgr;
1138 gboolean is_fullscreen;
1139 GtkAction *fs_toggle_action;
1142 mgr = modest_runtime_get_window_mgr ();
1144 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1146 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1148 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1149 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1150 if (is_fullscreen != active) {
1151 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1160 set_homogeneous (GtkWidget *widget,
1163 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1164 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1168 modest_main_window_show_toolbar (ModestWindow *self,
1169 gboolean show_toolbar)
1171 ModestMainWindowPrivate *priv = NULL;
1172 ModestWindowPrivate *parent_priv = NULL;
1173 GtkWidget *reply_button = NULL, *menu = NULL;
1174 GtkWidget *placeholder = NULL;
1177 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1178 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1179 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1181 /* Set optimized view status */
1182 priv->optimized_view = !show_toolbar;
1184 if (!parent_priv->toolbar) {
1185 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1188 /* Set homogeneous toolbar */
1189 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1190 set_homogeneous, NULL);
1192 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1193 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1194 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1195 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1196 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1197 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1198 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1199 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1201 /* Add ProgressBar (Transfer toolbar) */
1202 priv->progress_bar = modest_progress_bar_widget_new ();
1203 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1204 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1205 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1206 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1207 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1209 /* Connect cancel 'clicked' signal to abort progress mode */
1210 g_signal_connect(priv->cancel_toolitem, "clicked",
1211 G_CALLBACK(cancel_progressbar),
1214 /* Add it to the observers list */
1215 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1218 hildon_window_add_toolbar (HILDON_WINDOW (self),
1219 GTK_TOOLBAR (parent_priv->toolbar));
1221 /* Set reply button tap and hold menu */
1222 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1223 "/ToolBar/ToolbarMessageReply");
1224 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1225 "/ToolbarReplyCSM");
1226 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1228 /* Set send & receive button tap and hold menu */
1229 account_number_changed (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1234 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1235 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1236 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1238 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1239 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1241 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1246 compare_display_names (ModestAccountData *a,
1247 ModestAccountData *b)
1249 return strcmp (a->display_name, b->display_name);
1253 account_number_changed (TnyAccountStore *account_store,
1254 const gchar *account_name,
1257 GSList *account_names, *iter, *accounts;
1258 ModestMainWindow *self;
1259 ModestMainWindowPrivate *priv;
1260 ModestWindowPrivate *parent_priv;
1261 ModestAccountMgr *mgr;
1262 gint i, num_accounts;
1263 GtkActionGroup *action_group;
1265 gchar *default_account;
1266 GtkWidget *send_receive_button, *item;
1267 GtkAction *send_receive_all = NULL;
1269 self = MODEST_MAIN_WINDOW (user_data);
1270 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1271 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1273 /* Get enabled account IDs */
1274 mgr = modest_runtime_get_account_mgr ();
1275 account_names = modest_account_mgr_account_names (mgr, TRUE);
1276 iter = account_names;
1280 ModestAccountData *account_data =
1281 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1282 accounts = g_slist_prepend (accounts, account_data);
1286 modest_account_mgr_free_account_names (account_names);
1287 account_names = NULL;
1289 /* Order the list of accounts by its display name */
1290 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1291 num_accounts = g_slist_length (accounts);
1293 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1294 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1295 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1297 /* Delete old send&receive popup items. We can not just do a
1298 menu_detach because it does not work well with
1300 if (priv->accounts_popup)
1301 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1302 (GtkCallback) gtk_widget_destroy, NULL);
1304 /* Delete old entries in the View menu. Do not free groups, it
1306 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1308 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1309 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1310 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1311 GTK_ACTION_GROUP (groups->data));
1314 if (priv->merge_ids) {
1315 for (i = 0; i < priv->merge_ids->len; i++)
1316 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1317 g_byte_array_free (priv->merge_ids, TRUE);
1319 /* We need to call this in order to ensure
1320 that the new actions are added in the right
1321 order (alphabetical */
1322 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1324 groups = g_list_next (groups);
1326 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1328 /* Get send receive button */
1329 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1330 "/ToolBar/ToolbarSendReceive");
1332 /* Create the menu */
1333 if (num_accounts > 1) {
1334 if (!priv->accounts_popup)
1335 priv->accounts_popup = gtk_menu_new ();
1336 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1337 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1338 g_signal_connect (G_OBJECT (item),
1340 G_CALLBACK (on_send_receive_csm_activated),
1342 item = gtk_separator_menu_item_new ();
1343 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1346 /* Create a new action group */
1347 default_account = modest_account_mgr_get_default_account (mgr);
1348 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1349 for (i = 0; i < num_accounts; i++) {
1350 gchar *display_name = NULL;
1352 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1354 /* Create display name. The UI specification specifies a different format string
1355 * to use for the default account, though both seem to be "%s", so
1356 * I don't see what the point is. murrayc. */
1357 if (default_account && account_data->account_name &&
1358 !(strcmp (default_account, account_data->account_name) == 0)) {
1359 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1360 account_data->display_name);
1363 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1364 account_data->display_name);
1367 /* Create action and add it to the action group. The
1368 action name must be the account name, this way we
1369 could know in the handlers the account to show */
1370 if(account_data && account_data->account_name) {
1371 gchar* item_name, *refresh_action_name;
1372 guint8 merge_id = 0;
1373 GtkAction *view_account_action, *refresh_account_action;
1375 view_account_action = gtk_action_new (account_data->account_name,
1376 display_name, NULL, NULL);
1377 gtk_action_group_add_action (action_group, view_account_action);
1379 /* Add ui from account data. We allow 2^9-1 account
1380 changes in a single execution because we're
1381 downcasting the guint to a guint8 in order to use a
1382 GByteArray. It should be enough. */
1383 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1384 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1385 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1386 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1388 "/MenuBar/ViewMenu/ViewMenuAdditions",
1390 account_data->account_name,
1391 GTK_UI_MANAGER_MENUITEM,
1394 /* Connect the action signal "activate" */
1395 g_signal_connect (G_OBJECT (view_account_action),
1397 G_CALLBACK (on_show_account_action_activated),
1400 /* Create the items for the Tools->Send&Receive submenu */
1401 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1402 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1403 display_name, NULL, NULL);
1404 printf("DEBUG: %s: menu display_name=%s\n", __FUNCTION__, display_name);
1405 gtk_action_group_add_action (action_group, refresh_account_action);
1407 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1408 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1409 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1411 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1413 refresh_action_name,
1414 GTK_UI_MANAGER_MENUITEM,
1416 g_free (refresh_action_name);
1418 g_signal_connect_data (G_OBJECT (refresh_account_action),
1420 G_CALLBACK (on_refresh_account_action_activated),
1421 g_strdup (account_data->account_name),
1422 (GClosureNotify) g_free,
1425 /* Create item and add it to the send&receive
1426 CSM. If there is only one account then
1428 if (priv->accounts_popup) {
1429 GtkWidget *label = gtk_label_new(NULL);
1430 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1431 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1433 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1434 gtk_label_set_markup (GTK_LABEL (label), escaped);
1439 gtk_label_set_text (GTK_LABEL (label), display_name);
1442 item = gtk_menu_item_new ();
1443 gtk_container_add (GTK_CONTAINER (item), label);
1445 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1446 g_signal_connect_data (G_OBJECT (item),
1448 G_CALLBACK (on_send_receive_csm_activated),
1449 g_strdup (account_data->account_name),
1450 (GClosureNotify) g_free,
1457 g_free (display_name);
1460 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1462 /* We cannot do this in the loop above because this relies on the action
1463 * group being inserted. This makes the default account appear in bold.
1464 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1465 for (i = 0; i < num_accounts; i++) {
1466 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1468 if(account_data->account_name && default_account &&
1469 strcmp (account_data->account_name, default_account) == 0) {
1470 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1472 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1473 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1477 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1478 if (GTK_IS_LABEL (child)) {
1479 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1480 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1481 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1486 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1487 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1491 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1492 if (GTK_IS_LABEL (child)) {
1493 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1494 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1495 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1503 modest_account_mgr_free_account_data (mgr, account_data);
1506 if (priv->accounts_popup) {
1507 /* Mandatory in order to view the menu contents */
1508 gtk_widget_show_all (priv->accounts_popup);
1510 /* Setup tap_and_hold just if was not done before*/
1511 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1512 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1516 g_slist_free (accounts);
1517 g_free (default_account);
1521 * This function manages the key events used to navigate between
1522 * header and folder views (when the window is in split view)
1525 * -------------------------------------------------
1526 * HeaderView GDK_Left Move focus to folder view
1527 * FolderView GDK_Right Move focus to header view
1529 * There is no need to scroll to selected row, the widgets will be the
1530 * responsibles of doing that (probably managing the focus-in event
1533 on_inner_widgets_key_pressed (GtkWidget *widget,
1537 ModestMainWindowPrivate *priv;
1539 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1541 /* Do nothing if we're in SIMPLE style */
1542 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1545 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1546 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1547 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1548 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1554 set_alignment (GtkWidget *widget,
1557 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1558 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1562 create_empty_view (void)
1564 GtkLabel *label = NULL;
1565 GtkWidget *align = NULL;
1567 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1568 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1569 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1570 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1572 return GTK_WIDGET(align);
1576 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1578 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1583 gchar *gray_color_markup;
1585 vbox = gtk_vbox_new (FALSE, 0);
1587 /* Obtain the secondary text color. We need a realized widget, that's why
1588 we get styled_widget from outside */
1589 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1591 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1592 gray_color_markup = modest_text_utils_get_color_string (&color);
1594 // gray_color_markup is freed below
1595 gray_color_markup = g_strdup ("#BBBBBB");
1597 /* Account description: */
1599 if (modest_tny_account_is_virtual_local_folders (account)
1600 || (modest_tny_account_is_memory_card_account (account))) {
1602 /* Local folders: */
1604 /* Get device name */
1605 gchar *device_name = NULL;
1606 if (modest_tny_account_is_virtual_local_folders (account))
1607 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1608 MODEST_CONF_DEVICE_NAME, NULL);
1610 device_name = g_strdup (tny_account_get_name (account));
1612 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1613 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1614 gray_color_markup, tmp, device_name);
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);
1619 g_free (device_name);
1622 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1623 gtk_box_pack_start (GTK_BOX (vbox),
1624 gtk_label_new (tny_account_get_name (account)),
1627 /* Other accounts, such as IMAP and POP: */
1632 /* Put proto in uppercase */
1633 proto = g_string_new (tny_account_get_proto (account));
1634 proto = g_string_ascii_up (proto);
1636 /* note: mcen_fi_localroot_description is something like "%s account"
1637 * however, we should display "%s account: %s"... therefore, ugly tmp */
1638 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1639 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1640 gray_color_markup, tmp, tny_account_get_name (account));
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);
1646 g_string_free (proto, TRUE);
1652 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1653 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1654 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1655 modest_tny_folder_store_get_message_count (folder_store));
1656 label_w = gtk_label_new (NULL);
1657 gtk_label_set_markup (GTK_LABEL (label_w), label);
1658 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1662 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1664 _("mcen_fi_rootfolder_folders"),
1665 modest_tny_folder_store_get_folder_count (folder_store));
1666 label_w = gtk_label_new (NULL);
1667 gtk_label_set_markup (GTK_LABEL (label_w), label);
1668 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1672 if (modest_tny_account_is_virtual_local_folders (account)
1673 || modest_tny_account_is_memory_card_account (account)) {
1675 gchar *size = modest_text_utils_get_display_size (
1676 modest_tny_folder_store_get_local_size (folder_store));
1678 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1679 gray_color_markup, _("mcen_fi_rootfolder_size"),
1683 label_w = gtk_label_new (NULL);
1684 gtk_label_set_markup (GTK_LABEL (label_w), label);
1685 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1687 } else if (TNY_IS_ACCOUNT(folder_store)) {
1688 TnyAccount *account = TNY_ACCOUNT(folder_store);
1690 time_t last_updated;
1691 gchar *last_updated_string;
1692 /* Get last updated from configuration */
1693 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1694 tny_account_get_id (account),
1695 MODEST_ACCOUNT_LAST_UPDATED,
1697 if (last_updated > 0)
1698 last_updated_string = modest_text_utils_get_display_date(last_updated);
1700 last_updated_string = g_strdup (_("mcen_va_never"));
1702 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1703 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1704 label_w = gtk_label_new (NULL);
1705 gtk_label_set_markup (GTK_LABEL (label_w), label);
1706 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1707 g_free (last_updated_string);
1711 g_free (gray_color_markup);
1714 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1720 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1722 ModestMainWindowPrivate *priv = NULL;
1724 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1726 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1728 return priv->send_receive_in_progress;
1732 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1734 GtkAction *action = NULL;
1735 GtkWidget *widget = NULL;
1736 ModestMainWindowPrivate *priv = NULL;
1738 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1739 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1741 priv->send_receive_in_progress = TRUE;
1743 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1744 gtk_action_set_sensitive (action, FALSE);
1745 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1746 /* gtk_action_set_sensitive (action, FALSE); */
1747 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1748 gtk_widget_set_sensitive (widget, FALSE);
1752 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1754 GtkAction *action = NULL;
1755 GtkWidget *widget = NULL;
1756 ModestMainWindowPrivate *priv = NULL;
1758 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1759 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1761 priv->send_receive_in_progress = FALSE;
1763 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1764 gtk_action_set_sensitive (action, TRUE);
1765 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1766 /* gtk_action_set_sensitive (action, TRUE); */
1767 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1768 gtk_widget_set_sensitive (widget, TRUE);
1773 _on_msg_count_changed (ModestHeaderView *header_view,
1775 TnyFolderChange *change,
1776 ModestMainWindow *main_window)
1778 printf ("DEBUG: %s\n", __FUNCTION__);
1779 gboolean folder_empty = FALSE;
1780 TnyFolderChangeChanged changed;
1781 ModestMainWindowPrivate *priv;
1783 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1784 g_return_if_fail (TNY_IS_FOLDER(folder));
1785 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1786 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1788 changed = tny_folder_change_get_changed (change);
1790 /* If something changes */
1791 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1792 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1794 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1796 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1798 /* Set contents style of headers view */
1800 modest_main_window_set_contents_style (main_window,
1801 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1802 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1805 modest_main_window_set_contents_style (main_window,
1806 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1812 modest_main_window_set_contents_style (ModestMainWindow *self,
1813 ModestMainWindowContentsStyle style)
1815 ModestMainWindowPrivate *priv;
1817 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1819 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1821 /* We allow to set the same content style than the previously
1822 set if there are details, because it could happen when we're
1823 selecting different accounts consecutively */
1824 if ((priv->contents_style == style) &&
1825 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1828 /* Remove previous child. Delete it if it was an account
1830 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1832 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1833 g_object_ref (content);
1834 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1835 g_object_ref (priv->empty_view);
1836 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1839 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1842 priv->contents_style = style;
1844 switch (priv->contents_style) {
1845 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1846 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1847 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1850 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1852 TnyFolderStore *selected_folderstore =
1853 modest_folder_view_get_selected (priv->folder_view);
1854 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1855 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1856 TNY_ACCOUNT (selected_folderstore));
1858 wrap_in_scrolled_window (priv->contents_widget,
1859 priv->details_widget);
1861 g_object_unref (selected_folderstore);
1862 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1868 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1869 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1870 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1874 g_return_if_reached ();
1878 gtk_widget_show_all (priv->contents_widget);
1881 ModestMainWindowContentsStyle
1882 modest_main_window_get_contents_style (ModestMainWindow *self)
1884 ModestMainWindowPrivate *priv;
1886 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1888 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1889 return priv->contents_style;
1894 on_configuration_key_changed (ModestConf* conf,
1896 ModestConfEvent event,
1897 ModestConfNotificationId id,
1898 ModestMainWindow *self)
1900 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1901 TnyAccount *account;
1904 priv->notification_id != id ||
1905 strcmp (key, MODEST_CONF_DEVICE_NAME))
1908 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1911 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1912 if (TNY_IS_ACCOUNT (account) &&
1913 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1916 const gchar *device_name;
1920 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1921 label = GTK_LABEL (children->data);
1923 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1924 MODEST_CONF_DEVICE_NAME, NULL);
1926 new_text = g_strdup_printf ("%s: %s",
1927 _("mcen_fi_localroot_description"),
1930 gtk_label_set_text (label, new_text);
1931 gtk_widget_show (GTK_WIDGET (label));
1934 g_list_free (children);
1936 g_object_unref (account);
1940 set_toolbar_transfer_mode (ModestMainWindow *self)
1942 ModestMainWindowPrivate *priv = NULL;
1944 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1946 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1948 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1950 if (priv->progress_bar_timeout > 0) {
1951 g_source_remove (priv->progress_bar_timeout);
1952 priv->progress_bar_timeout = 0;
1959 set_toolbar_mode (ModestMainWindow *self,
1960 ModestToolBarModes mode)
1962 ModestWindowPrivate *parent_priv = NULL;
1963 ModestMainWindowPrivate *priv = NULL;
1964 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1966 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1968 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1969 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1971 /* In case this was called before the toolbar exists: */
1972 if (!(parent_priv->toolbar))
1975 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1977 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1978 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1979 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1981 /* Sets current toolbar mode */
1982 priv->current_toolbar_mode = mode;
1984 /* Show and hide toolbar items */
1986 case TOOLBAR_MODE_NORMAL:
1988 gtk_action_set_visible (sort_action, TRUE);
1990 gtk_action_set_visible (refresh_action, TRUE);
1991 if (priv->progress_toolitem) {
1992 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1993 gtk_widget_hide (priv->progress_toolitem);
1995 if (priv->progress_bar)
1996 gtk_widget_hide (priv->progress_bar);
1999 gtk_action_set_visible (cancel_action, FALSE);
2000 /* if (priv->sort_toolitem) */
2001 /* gtk_widget_show (priv->sort_toolitem); */
2003 /* if (priv->refresh_toolitem) */
2004 /* gtk_widget_show (priv->refresh_toolitem); */
2006 /* if (priv->progress_toolitem) */
2007 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
2008 /* if (priv->progress_bar) */
2009 /* gtk_widget_hide (priv->progress_bar); */
2011 /* if (priv->cancel_toolitem) */
2012 /* gtk_widget_hide (priv->cancel_toolitem); */
2014 /* Hide toolbar if optimized view is enabled */
2015 if (priv->optimized_view)
2016 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2018 case TOOLBAR_MODE_TRANSFER:
2020 gtk_action_set_visible (sort_action, FALSE);
2022 gtk_action_set_visible (refresh_action, FALSE);
2024 gtk_action_set_visible (cancel_action, TRUE);
2025 if (priv->progress_toolitem) {
2026 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2027 gtk_widget_show (priv->progress_toolitem);
2029 if (priv->progress_bar)
2030 gtk_widget_show (priv->progress_bar);
2032 /* if (priv->sort_toolitem) */
2033 /* gtk_widget_hide (priv->sort_toolitem); */
2035 /* if (priv->refresh_toolitem) */
2036 /* gtk_widget_hide (priv->refresh_toolitem); */
2038 /* if (priv->progress_toolitem) */
2039 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2040 /* if (priv->progress_bar) */
2041 /* gtk_widget_show (priv->progress_bar); */
2043 /* if (priv->cancel_toolitem) */
2044 /* gtk_widget_show (priv->cancel_toolitem); */
2046 /* Show toolbar if it's hiden (optimized view ) */
2047 if (priv->optimized_view)
2048 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2051 g_return_if_reached ();
2056 cancel_progressbar (GtkToolButton *toolbutton,
2057 ModestMainWindow *self)
2060 ModestMainWindowPrivate *priv;
2062 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2064 /* Get operation observers and cancel all the operations */
2065 tmp = priv->progress_widgets;
2067 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2068 tmp=g_slist_next(tmp);
2073 observers_empty (ModestMainWindow *self)
2076 ModestMainWindowPrivate *priv;
2077 gboolean is_empty = TRUE;
2078 guint pending_ops = 0;
2080 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2081 tmp = priv->progress_widgets;
2083 /* Check all observers */
2084 while (tmp && is_empty) {
2085 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2086 is_empty = pending_ops == 0;
2088 tmp = g_slist_next(tmp);
2095 on_queue_changed (ModestMailOperationQueue *queue,
2096 ModestMailOperation *mail_op,
2097 ModestMailOperationQueueNotification type,
2098 ModestMainWindow *self)
2100 ModestMainWindowPrivate *priv;
2101 ModestMailOperationTypeOperation op_type;
2102 ModestToolBarModes mode;
2104 gboolean mode_changed = FALSE;
2105 /* ModestMailOperationStatus status; */
2107 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2108 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2110 /* Get toolbar mode from operation id*/
2111 op_type = modest_mail_operation_get_type_operation (mail_op);
2113 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2114 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2115 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2116 mode = TOOLBAR_MODE_TRANSFER;
2117 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2118 mode_changed = TRUE;
2121 mode = TOOLBAR_MODE_NORMAL;
2126 /* Add operation observers and change toolbar if neccessary*/
2127 tmp = priv->progress_widgets;
2129 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2130 if (mode == TOOLBAR_MODE_TRANSFER) {
2132 set_toolbar_transfer_mode(self);
2134 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2136 tmp = g_slist_next (tmp);
2140 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2141 /* Change toolbar mode */
2142 if (mode == TOOLBAR_MODE_TRANSFER) {
2144 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2146 tmp = g_slist_next (tmp);
2149 /* If no more operations are being observed, NORMAL mode is enabled again */
2150 if (observers_empty (self)) {
2151 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2162 on_show_account_action_activated (GtkAction *action,
2165 ModestAccountData *acc_data;
2166 ModestMainWindow *self;
2167 ModestMainWindowPrivate *priv;
2168 ModestAccountMgr *mgr;
2169 const gchar *acc_name;
2171 self = MODEST_MAIN_WINDOW (user_data);
2172 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2174 /* Get account data */
2175 acc_name = gtk_action_get_name (action);
2176 mgr = modest_runtime_get_account_mgr ();
2177 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2179 /* Set the new visible & active account */
2180 if (acc_data && acc_data->store_account) {
2181 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2182 acc_data->store_account->account_name);
2183 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2186 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2190 modest_account_mgr_free_account_data (mgr, acc_data);
2194 refresh_account (const gchar *account_name)
2198 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2200 /* If account_name == NULL, we must update all (option All) */
2202 modest_ui_actions_do_send_receive_all (win);
2204 modest_ui_actions_do_send_receive (account_name, win);
2209 on_refresh_account_action_activated (GtkAction *action,
2212 refresh_account ((const gchar*) user_data);
2216 on_send_receive_csm_activated (GtkMenuItem *item,
2219 refresh_account ((const gchar*) user_data);
2223 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2225 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2227 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2233 on_folder_view_focus_in (GtkWidget *widget,
2234 GdkEventFocus *event,
2237 ModestMainWindow *main_window = NULL;
2239 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2240 main_window = MODEST_MAIN_WINDOW (userdata);
2242 /* Update toolbar dimming state */
2243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2249 on_header_view_focus_in (GtkWidget *widget,
2250 GdkEventFocus *event,
2253 ModestMainWindow *main_window = NULL;
2254 ModestMainWindowPrivate *priv = NULL;
2256 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2257 main_window = MODEST_MAIN_WINDOW (userdata);
2258 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2260 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2261 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2262 TnyIterator *iterator = tny_list_create_iterator (selection);
2265 tny_iterator_first (iterator);
2266 header = TNY_HEADER (tny_iterator_get_current (iterator));
2268 if (tny_header_get_subject (header))
2269 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2271 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2274 g_object_unref (header);
2276 g_object_unref (iterator);
2277 g_object_unref (selection);
2281 /* Update toolbar dimming state */
2282 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2288 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2289 TnyFolderStore *folder_store,
2291 ModestMainWindow *main_window)
2293 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2294 GtkAction *action = NULL;
2295 gboolean show_reply = TRUE;
2296 gboolean show_forward = TRUE;
2297 gboolean show_cancel_send = FALSE;
2298 gboolean show_clipboard = TRUE;
2299 gboolean show_delete = TRUE;
2302 if (TNY_IS_ACCOUNT (folder_store)) {
2303 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2304 } else if (TNY_IS_FOLDER (folder_store)) {
2305 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2306 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2307 TNY_FOLDER (folder_store));
2308 switch (folder_type) {
2309 case TNY_FOLDER_TYPE_DRAFTS:
2310 show_clipboard = show_delete = TRUE;
2311 show_reply = show_forward = show_cancel_send = FALSE;
2313 case TNY_FOLDER_TYPE_SENT:
2314 show_forward = show_clipboard = show_delete = TRUE;
2315 show_reply = show_cancel_send = FALSE;
2317 case TNY_FOLDER_TYPE_OUTBOX:
2318 show_clipboard = show_delete = show_cancel_send = TRUE;
2319 show_reply = show_forward = FALSE;
2322 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2323 show_cancel_send = FALSE;
2326 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2327 show_cancel_send = FALSE;
2332 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2333 gtk_action_set_visible (action, show_reply);
2334 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2335 gtk_action_set_visible (action, show_reply);
2336 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2337 gtk_action_set_visible (action, show_forward);
2338 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2339 gtk_action_set_visible (action, show_cancel_send);
2340 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2341 gtk_action_set_visible (action, show_clipboard);
2342 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2343 gtk_action_set_visible (action, show_clipboard);
2344 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2345 gtk_action_set_visible (action, show_clipboard);
2346 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2347 gtk_action_set_visible (action, show_delete);
2349 /* We finally call to the ui actions handler, after updating properly
2350 * the header view CSM */
2351 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2356 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2357 GtkTreeModel *model,
2358 GtkTreeRowReference *row_reference,
2359 ModestMainWindow *self)
2361 ModestMainWindowPrivate *priv = NULL;
2362 GtkTreeModel *header_model = NULL;
2363 GtkTreePath *path = NULL;
2365 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2366 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2367 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2369 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2370 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2372 /* Do nothing if we changed the folder in the main view */
2373 if (header_model != model)
2376 /* Select the message in the header view */
2377 path = gtk_tree_row_reference_get_path (row_reference);
2378 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2380 gtk_tree_path_free (path);