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 account_number_changed (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; */
479 /* if (!server_name) */
480 /* server_name = _("Unknown Server"); */
482 /* /\* Show the appropriate message text for the GError: *\/ */
483 /* gchar *message = NULL; */
485 /* switch (err->code) { */
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); */
510 /* g_free (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 */
570 /* * connection. *\/ */
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); */
583 /* if (account_name) { */
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_inserted", G_CALLBACK (account_number_changed),
695 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
696 "account_removed", G_CALLBACK (account_number_changed),
700 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
701 "password_requested",
702 G_CALLBACK (modest_ui_actions_on_password_requested), self);
705 /* g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), */
706 /* "connecting-finished", */
707 /* G_CALLBACK(on_account_store_connecting_finished), self); */
711 /** Idle handler, to send/receive at startup .*/
713 sync_accounts_cb (ModestMainWindow *win)
715 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
716 return FALSE; /* Do not call this idle handler again. */
720 static void on_hildon_program_is_topmost_notify(GObject *self,
721 GParamSpec *propert_param, gpointer user_data)
723 HildonProgram *app = HILDON_PROGRAM (self);
726 ModestWindow* self = MODEST_WINDOW(user_data);
729 /* Note that use of hildon_program_set_can_hibernate()
730 * is generally referred to as "setting the killable flag",
731 * though hibernation does not seem equal to death.
734 if (hildon_program_get_is_topmost (app)) {
735 /* Prevent hibernation when the progam comes to the foreground,
736 * because hibernation should only happen when the application
737 * is in the background: */
738 hildon_program_set_can_hibernate (app, FALSE);
740 /* Allow hibernation if the program has gone to the background: */
742 /* However, prevent hibernation while the settings are being changed: */
743 const gboolean hibernation_prevented =
744 modest_window_mgr_get_hibernation_is_prevented (
745 modest_runtime_get_window_mgr ());
747 if (hibernation_prevented)
748 hildon_program_set_can_hibernate (app, FALSE);
750 /* Allow hibernation, after saving the state: */
751 modest_osso_save_state();
752 hildon_program_set_can_hibernate (app, TRUE);
759 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
761 GtkWidget *folder_win = (GtkWidget *) user_data;
762 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
764 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
765 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
766 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
768 gtk_widget_show (GTK_WIDGET (priv->folder_view));
770 /* Connect signals */
771 connect_signals ((ModestMainWindow*)self);
773 /* Set account store */
774 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
775 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
777 /* Load previous osso state, for instance if we are being restored from
779 modest_osso_load_state ();
781 /* Restore window & widget settings */
783 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
785 /* The UI spec wants us to show a connection dialog when the application is
786 * started by the user, if there is no connection.
787 * Do this before showing the account wizard,
788 * because wizard needs a connection to discover capabilities. */
789 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
791 /* Check if accounts exist and show the account wizard if not */
792 gboolean accounts_exist =
793 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
795 if (!accounts_exist) {
796 /* This is necessary to have the main window shown behind the dialog
797 It's an ugly hack... jschmid */
798 gtk_widget_show_all(GTK_WIDGET(self));
799 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
802 GtkAction *send_receive_all;
803 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
804 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
805 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
806 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
807 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
808 modest_account_mgr_free_account_names (accounts);
813 modest_main_window_new (void)
815 ModestMainWindow *self = NULL;
816 ModestMainWindowPrivate *priv = NULL;
817 ModestWindowPrivate *parent_priv = NULL;
818 GtkWidget *folder_win = NULL;
819 ModestDimmingRulesGroup *menu_rules_group = NULL;
820 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
821 GtkActionGroup *action_group = NULL;
822 GError *error = NULL;
823 ModestConf *conf = NULL;
824 GtkAction *action = NULL;
825 GdkPixbuf *window_icon;
827 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
828 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
829 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
831 parent_priv->ui_manager = gtk_ui_manager_new();
832 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
834 action_group = gtk_action_group_new ("ModestMainWindowActions");
835 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
837 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
838 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
840 /* Add common actions */
841 gtk_action_group_add_actions (action_group,
842 modest_action_entries,
843 G_N_ELEMENTS (modest_action_entries),
846 gtk_action_group_add_actions (action_group,
847 modest_folder_view_action_entries,
848 G_N_ELEMENTS (modest_folder_view_action_entries),
851 gtk_action_group_add_actions (action_group,
852 modest_header_view_action_entries,
853 G_N_ELEMENTS (modest_header_view_action_entries),
856 gtk_action_group_add_toggle_actions (action_group,
857 modest_toggle_action_entries,
858 G_N_ELEMENTS (modest_toggle_action_entries),
861 gtk_action_group_add_toggle_actions (action_group,
862 modest_main_window_toggle_action_entries,
863 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
866 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
867 g_object_unref (action_group);
869 /* Load the UI definition */
870 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
871 MODEST_UIDIR "modest-main-window-ui.xml", &error);
873 g_warning ("Could not merge modest-ui.xml: %s", error->message);
874 g_error_free (error);
878 /* Add common dimming rules */
879 modest_dimming_rules_group_add_rules (menu_rules_group,
880 modest_main_window_menu_dimming_entries,
881 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
883 modest_dimming_rules_group_add_rules (toolbar_rules_group,
884 modest_main_window_toolbar_dimming_entries,
885 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
888 /* Insert dimming rules group for this window */
889 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
890 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
891 g_object_unref (menu_rules_group);
892 g_object_unref (toolbar_rules_group);
894 /* Add accelerators */
895 gtk_window_add_accel_group (GTK_WINDOW (self),
896 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
898 /* Menubar. Update the state of some toggles */
899 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
900 conf = modest_runtime_get_conf ();
901 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
902 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
903 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
904 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
905 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
906 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
907 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
908 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
909 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
910 gtk_widget_show (parent_priv->menubar);
912 /* Get device name */
913 modest_maemo_utils_get_device_name ();
917 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
918 if (!priv->header_view)
919 g_printerr ("modest: cannot instantiate header view\n");
920 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
921 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
922 MODEST_CONF_HEADER_VIEW_KEY);
924 /* Other style properties of header view */
925 g_object_set (G_OBJECT (priv->header_view),
928 /* gtk_widget_show (priv->header_view); */
931 priv->empty_view = create_empty_view ();
932 gtk_widget_show (priv->empty_view);
934 /* Create scrolled windows */
935 folder_win = gtk_scrolled_window_new (NULL, NULL);
936 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
937 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
939 GTK_POLICY_AUTOMATIC);
940 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
942 GTK_POLICY_AUTOMATIC);
943 /* gtk_widget_show (priv->contents_widget); */
946 priv->main_paned = gtk_hpaned_new ();
947 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
948 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
949 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
951 /* putting it all together... */
952 priv->main_vbox = gtk_vbox_new (FALSE, 6);
953 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
954 gtk_widget_show (priv->main_vbox);
956 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
958 HildonProgram *app = hildon_program_get_instance ();
959 hildon_program_add_window (app, HILDON_WINDOW (self));
961 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
962 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
964 g_signal_connect (G_OBJECT(self), "show",
965 G_CALLBACK (modest_main_window_on_show), folder_win);
967 /* Set window icon */
968 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
970 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
971 g_object_unref (window_icon);
974 /* Dont't restore settings here,
975 * because it requires a gtk_widget_show(),
976 * and we don't want to do that until later,
977 * so that the UI is not visible for non-menu D-Bus activation.
979 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
981 return MODEST_WINDOW(self);
985 modest_main_window_close_all (ModestMainWindow *self)
988 GtkResponseType response;
990 /* Create the confirmation dialog MSG-NOT308 */
991 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
992 _("emev_nc_close_windows"),
993 _("mcen_bd_yes"), GTK_RESPONSE_YES,
994 _("mcen_bd_no"), GTK_RESPONSE_NO,
997 response = gtk_dialog_run (GTK_DIALOG (note));
998 gtk_widget_destroy (GTK_WIDGET (note));
1000 if (response == GTK_RESPONSE_YES)
1008 modest_main_window_set_style (ModestMainWindow *self,
1009 ModestMainWindowStyle style)
1011 ModestMainWindowPrivate *priv;
1012 ModestWindowPrivate *parent_priv;
1016 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1018 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1019 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1021 /* no change -> nothing to do */
1022 if (priv->style == style)
1025 /* Get toggle button and update the state if needed. This will
1026 happen only when the set_style is not invoked from the UI,
1027 for example when it's called from widget memory */
1028 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1029 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1030 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1031 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1032 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1033 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1034 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1037 priv->style = style;
1039 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1040 /* Remove main paned */
1041 g_object_ref (priv->main_paned);
1042 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1044 /* Reparent the contents widget to the main vbox */
1045 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1047 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1048 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1049 TnyIterator *iterator = tny_list_create_iterator (selection);
1051 tny_iterator_first (iterator);
1052 header = TNY_HEADER (tny_iterator_get_current (iterator));
1053 if (tny_header_get_subject (header))
1054 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1056 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1059 g_object_unref (header);
1061 g_object_unref (iterator);
1062 g_object_unref (selection);
1066 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1067 /* Remove header view */
1068 g_object_ref (priv->contents_widget);
1069 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1071 /* Reparent the main paned */
1072 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1073 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1077 g_return_if_reached ();
1080 /* Let header view grab the focus if it's being shown */
1081 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1082 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1084 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1087 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1090 ModestMainWindowStyle
1091 modest_main_window_get_style (ModestMainWindow *self)
1093 ModestMainWindowPrivate *priv;
1095 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1097 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1104 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1106 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1107 ModestWindowPrivate *parent_priv;
1108 ModestWindowMgr *mgr;
1109 gboolean is_fullscreen;
1110 GtkAction *fs_toggle_action;
1113 mgr = modest_runtime_get_window_mgr ();
1115 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1117 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1119 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1120 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1121 if (is_fullscreen != active) {
1122 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1131 set_homogeneous (GtkWidget *widget,
1134 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1135 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1139 modest_main_window_show_toolbar (ModestWindow *self,
1140 gboolean show_toolbar)
1142 ModestMainWindowPrivate *priv = NULL;
1143 ModestWindowPrivate *parent_priv = NULL;
1144 GtkWidget *reply_button = NULL, *menu = NULL;
1145 GtkWidget *placeholder = NULL;
1148 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1149 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1150 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1152 /* Set optimized view status */
1153 priv->optimized_view = !show_toolbar;
1155 if (!parent_priv->toolbar) {
1156 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1159 /* Set homogeneous toolbar */
1160 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1161 set_homogeneous, NULL);
1163 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1164 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1165 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1166 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1167 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1168 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1169 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1170 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1172 /* Add ProgressBar (Transfer toolbar) */
1173 priv->progress_bar = modest_progress_bar_widget_new ();
1174 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1175 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1176 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1177 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1178 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1180 /* Connect cancel 'clicked' signal to abort progress mode */
1181 g_signal_connect(priv->cancel_toolitem, "clicked",
1182 G_CALLBACK(cancel_progressbar),
1185 /* Add it to the observers list */
1186 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1189 hildon_window_add_toolbar (HILDON_WINDOW (self),
1190 GTK_TOOLBAR (parent_priv->toolbar));
1192 /* Set reply button tap and hold menu */
1193 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1194 "/ToolBar/ToolbarMessageReply");
1195 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1196 "/ToolbarReplyCSM");
1197 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1199 /* Set send & receive button tap and hold menu */
1200 account_number_changed (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1205 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1206 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1207 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1209 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1210 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1212 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1217 compare_display_names (ModestAccountData *a,
1218 ModestAccountData *b)
1220 return strcmp (a->display_name, b->display_name);
1224 account_number_changed (TnyAccountStore *account_store,
1225 const gchar *account_name,
1228 GSList *account_names, *iter, *accounts;
1229 ModestMainWindow *self;
1230 ModestMainWindowPrivate *priv;
1231 ModestWindowPrivate *parent_priv;
1232 ModestAccountMgr *mgr;
1233 gint i, num_accounts;
1234 GtkActionGroup *action_group;
1236 gchar *default_account;
1237 GtkWidget *send_receive_button, *item;
1238 GtkAction *send_receive_all = NULL;
1240 self = MODEST_MAIN_WINDOW (user_data);
1241 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1242 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1244 /* Get enabled account IDs */
1245 mgr = modest_runtime_get_account_mgr ();
1246 account_names = modest_account_mgr_account_names (mgr, TRUE);
1247 iter = account_names;
1251 ModestAccountData *account_data =
1252 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1253 accounts = g_slist_prepend (accounts, account_data);
1257 modest_account_mgr_free_account_names (account_names);
1258 account_names = NULL;
1260 /* Order the list of accounts by its display name */
1261 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1262 num_accounts = g_slist_length (accounts);
1264 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1265 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1266 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1268 /* Delete old send&receive popup items. We can not just do a
1269 menu_detach because it does not work well with
1271 if (priv->accounts_popup)
1272 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1273 (GtkCallback) gtk_widget_destroy, NULL);
1275 /* Delete old entries in the View menu. Do not free groups, it
1277 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1279 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1280 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1281 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1282 GTK_ACTION_GROUP (groups->data));
1285 if (priv->merge_ids) {
1286 for (i = 0; i < priv->merge_ids->len; i++)
1287 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1288 g_byte_array_free (priv->merge_ids, TRUE);
1290 /* We need to call this in order to ensure
1291 that the new actions are added in the right
1292 order (alphabetical */
1293 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1295 groups = g_list_next (groups);
1297 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1299 /* Get send receive button */
1300 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1301 "/ToolBar/ToolbarSendReceive");
1303 /* Create the menu */
1304 if (num_accounts > 1) {
1305 if (!priv->accounts_popup)
1306 priv->accounts_popup = gtk_menu_new ();
1307 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1308 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1309 g_signal_connect (G_OBJECT (item),
1311 G_CALLBACK (on_send_receive_csm_activated),
1313 item = gtk_separator_menu_item_new ();
1314 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1317 /* Create a new action group */
1318 default_account = modest_account_mgr_get_default_account (mgr);
1319 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1320 for (i = 0; i < num_accounts; i++) {
1321 gchar *display_name = NULL;
1323 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1325 /* Create display name. The UI specification specifies a different format string
1326 * to use for the default account, though both seem to be "%s", so
1327 * I don't see what the point is. murrayc. */
1328 if (default_account && account_data->account_name &&
1329 !(strcmp (default_account, account_data->account_name) == 0)) {
1330 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1331 account_data->display_name);
1334 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1335 account_data->display_name);
1338 /* Create action and add it to the action group. The
1339 action name must be the account name, this way we
1340 could know in the handlers the account to show */
1341 if(account_data->account_name) {
1342 gchar* item_name, *refresh_action_name;
1344 GtkAction *view_account_action, *refresh_account_action;
1346 view_account_action = gtk_action_new (account_data->account_name,
1347 display_name, NULL, NULL);
1348 gtk_action_group_add_action (action_group, view_account_action);
1350 /* Add ui from account data. We allow 2^9-1 account
1351 changes in a single execution because we're
1352 downcasting the guint to a guint8 in order to use a
1353 GByteArray. It should be enough. */
1354 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1355 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1356 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1357 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1359 "/MenuBar/ViewMenu/ViewMenuAdditions",
1361 account_data->account_name,
1362 GTK_UI_MANAGER_MENUITEM,
1365 /* Connect the action signal "activate" */
1366 g_signal_connect (G_OBJECT (view_account_action),
1368 G_CALLBACK (on_show_account_action_activated),
1371 /* Create the items for the Tools->Send&Receive submenu */
1372 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1373 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1374 display_name, NULL, NULL);
1375 gtk_action_group_add_action (action_group, refresh_account_action);
1377 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1378 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1379 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1381 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1383 refresh_action_name,
1384 GTK_UI_MANAGER_MENUITEM,
1386 g_free (refresh_action_name);
1388 g_signal_connect_data (G_OBJECT (refresh_account_action),
1390 G_CALLBACK (on_refresh_account_action_activated),
1391 g_strdup (account_data->account_name),
1392 (GClosureNotify) g_free,
1395 /* Create item and add it to the send&receive
1396 CSM. If there is only one account then
1398 if (priv->accounts_popup) {
1399 GtkWidget *label = gtk_label_new(NULL);
1400 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1401 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1403 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1404 gtk_label_set_markup (GTK_LABEL (label), escaped);
1409 gtk_label_set_text (GTK_LABEL (label), display_name);
1412 item = gtk_menu_item_new ();
1413 gtk_container_add (GTK_CONTAINER (item), label);
1415 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1416 g_signal_connect_data (G_OBJECT (item),
1418 G_CALLBACK (on_send_receive_csm_activated),
1419 g_strdup (account_data->account_name),
1420 (GClosureNotify) g_free,
1427 g_free (display_name);
1430 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1432 /* We cannot do this in the loop above because this relies on the action
1433 * group being inserted. This makes the default account appear in bold.
1434 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1435 for (i = 0; i < num_accounts; i++) {
1436 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1438 if(account_data->account_name && default_account &&
1439 strcmp (account_data->account_name, default_account) == 0) {
1440 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1442 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1443 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1447 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1448 if (GTK_IS_LABEL (child)) {
1449 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1450 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1451 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1456 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1457 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1461 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1462 if (GTK_IS_LABEL (child)) {
1463 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1464 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1465 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1473 modest_account_mgr_free_account_data (mgr, account_data);
1476 if (priv->accounts_popup) {
1477 /* Mandatory in order to view the menu contents */
1478 gtk_widget_show_all (priv->accounts_popup);
1480 /* Setup tap_and_hold just if was not done before*/
1481 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1482 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1486 g_slist_free (accounts);
1487 g_free (default_account);
1491 * This function manages the key events used to navigate between
1492 * header and folder views (when the window is in split view)
1495 * -------------------------------------------------
1496 * HeaderView GDK_Left Move focus to folder view
1497 * FolderView GDK_Right Move focus to header view
1499 * There is no need to scroll to selected row, the widgets will be the
1500 * responsibles of doing that (probably managing the focus-in event
1503 on_inner_widgets_key_pressed (GtkWidget *widget,
1507 ModestMainWindowPrivate *priv;
1509 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1511 /* Do nothing if we're in SIMPLE style */
1512 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1515 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1516 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1517 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1518 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1524 set_alignment (GtkWidget *widget,
1527 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1528 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1532 create_empty_view (void)
1534 GtkLabel *label = NULL;
1535 GtkWidget *align = NULL;
1537 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1538 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1539 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1540 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1542 return GTK_WIDGET(align);
1546 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1548 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1553 gchar *gray_color_markup;
1555 vbox = gtk_vbox_new (FALSE, 0);
1557 /* Obtain the secondary text color. We need a realized widget, that's why
1558 we get styled_widget from outside */
1559 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1561 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1562 gray_color_markup = modest_text_utils_get_color_string (&color);
1564 // gray_color_markup is freed below
1565 gray_color_markup = g_strdup ("#BBBBBB");
1567 /* Account description: */
1569 if (modest_tny_account_is_virtual_local_folders (account)
1570 || (modest_tny_account_is_memory_card_account (account))) {
1572 /* Local folders: */
1574 /* Get device name */
1575 gchar *device_name = NULL;
1576 if (modest_tny_account_is_virtual_local_folders (account))
1577 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1578 MODEST_CONF_DEVICE_NAME, NULL);
1580 device_name = g_strdup (tny_account_get_name (account));
1582 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1583 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1584 gray_color_markup, tmp, device_name);
1586 label_w = gtk_label_new (NULL);
1587 gtk_label_set_markup (GTK_LABEL (label_w), label);
1588 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1589 g_free (device_name);
1592 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1593 gtk_box_pack_start (GTK_BOX (vbox),
1594 gtk_label_new (tny_account_get_name (account)),
1597 /* Other accounts, such as IMAP and POP: */
1602 /* Put proto in uppercase */
1603 proto = g_string_new (tny_account_get_proto (account));
1604 proto = g_string_ascii_up (proto);
1606 /* note: mcen_fi_localroot_description is something like "%s account"
1607 * however, we should display "%s account: %s"... therefore, ugly tmp */
1608 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1609 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1610 gray_color_markup, tmp, tny_account_get_name (account));
1613 label_w = gtk_label_new (NULL);
1614 gtk_label_set_markup (GTK_LABEL (label_w), label);
1615 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1616 g_string_free (proto, TRUE);
1622 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1623 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1624 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1625 modest_tny_folder_store_get_message_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 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1634 _("mcen_fi_rootfolder_folders"),
1635 modest_tny_folder_store_get_folder_count (folder_store));
1636 label_w = gtk_label_new (NULL);
1637 gtk_label_set_markup (GTK_LABEL (label_w), label);
1638 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1642 if (modest_tny_account_is_virtual_local_folders (account)
1643 || modest_tny_account_is_memory_card_account (account)) {
1645 gchar *size = modest_text_utils_get_display_size (
1646 modest_tny_folder_store_get_local_size (folder_store));
1648 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1649 gray_color_markup, _("mcen_fi_rootfolder_size"),
1653 label_w = gtk_label_new (NULL);
1654 gtk_label_set_markup (GTK_LABEL (label_w), label);
1655 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1657 } else if (TNY_IS_ACCOUNT(folder_store)) {
1658 TnyAccount *account = TNY_ACCOUNT(folder_store);
1660 time_t last_updated;
1661 gchar *last_updated_string;
1662 /* Get last updated from configuration */
1663 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1664 tny_account_get_id (account),
1665 MODEST_ACCOUNT_LAST_UPDATED,
1667 if (last_updated > 0)
1668 last_updated_string = modest_text_utils_get_display_date(last_updated);
1670 last_updated_string = g_strdup (_("mcen_va_never"));
1672 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1673 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1674 label_w = gtk_label_new (NULL);
1675 gtk_label_set_markup (GTK_LABEL (label_w), label);
1676 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1677 g_free (last_updated_string);
1681 g_free (gray_color_markup);
1684 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1690 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1692 ModestMainWindowPrivate *priv = NULL;
1694 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1696 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1698 return priv->send_receive_in_progress;
1702 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1704 GtkAction *action = NULL;
1705 GtkWidget *widget = NULL;
1706 ModestMainWindowPrivate *priv = NULL;
1708 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1709 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1711 priv->send_receive_in_progress = TRUE;
1713 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1714 gtk_action_set_sensitive (action, FALSE);
1715 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1716 /* gtk_action_set_sensitive (action, FALSE); */
1717 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1718 gtk_widget_set_sensitive (widget, FALSE);
1722 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1724 GtkAction *action = NULL;
1725 GtkWidget *widget = NULL;
1726 ModestMainWindowPrivate *priv = NULL;
1728 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1729 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1731 priv->send_receive_in_progress = FALSE;
1733 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1734 gtk_action_set_sensitive (action, TRUE);
1735 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1736 /* gtk_action_set_sensitive (action, TRUE); */
1737 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1738 gtk_widget_set_sensitive (widget, TRUE);
1743 _on_msg_count_changed (ModestHeaderView *header_view,
1745 TnyFolderChange *change,
1746 ModestMainWindow *main_window)
1748 printf ("DEBUG: %s\n", __FUNCTION__);
1749 gboolean folder_empty = FALSE;
1750 TnyFolderChangeChanged changed;
1752 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1753 g_return_if_fail (TNY_IS_FOLDER(folder));
1754 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1756 changed = tny_folder_change_get_changed (change);
1758 /* If something changes */
1759 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1760 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1762 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1764 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1766 /* Set contents style of headers view */
1768 modest_main_window_set_contents_style (main_window,
1769 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1772 modest_main_window_set_contents_style (main_window,
1773 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1779 modest_main_window_set_contents_style (ModestMainWindow *self,
1780 ModestMainWindowContentsStyle style)
1782 ModestMainWindowPrivate *priv;
1784 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1786 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1788 /* We allow to set the same content style than the previously
1789 set if there are details, because it could happen when we're
1790 selecting different accounts consecutively */
1791 if ((priv->contents_style == style) &&
1792 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1795 /* Remove previous child. Delete it if it was an account
1797 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1799 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1800 g_object_ref (content);
1801 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1802 g_object_ref (priv->empty_view);
1803 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1806 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1809 priv->contents_style = style;
1811 switch (priv->contents_style) {
1812 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1813 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1814 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1817 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1819 TnyFolderStore *selected_folderstore =
1820 modest_folder_view_get_selected (priv->folder_view);
1821 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1822 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1823 TNY_ACCOUNT (selected_folderstore));
1825 wrap_in_scrolled_window (priv->contents_widget,
1826 priv->details_widget);
1828 g_object_unref (selected_folderstore);
1829 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1835 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1836 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1837 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1841 g_return_if_reached ();
1845 gtk_widget_show_all (priv->contents_widget);
1848 ModestMainWindowContentsStyle
1849 modest_main_window_get_contents_style (ModestMainWindow *self)
1851 ModestMainWindowPrivate *priv;
1853 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1855 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1856 return priv->contents_style;
1861 on_configuration_key_changed (ModestConf* conf,
1863 ModestConfEvent event,
1864 ModestMainWindow *self)
1866 ModestMainWindowPrivate *priv;
1867 TnyAccount *account;
1869 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1872 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1874 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1877 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1878 if (TNY_IS_ACCOUNT (account) &&
1879 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1882 const gchar *device_name;
1886 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1887 label = GTK_LABEL (children->data);
1889 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1890 MODEST_CONF_DEVICE_NAME, NULL);
1892 new_text = g_strdup_printf ("%s: %s",
1893 _("mcen_fi_localroot_description"),
1896 gtk_label_set_text (label, new_text);
1897 gtk_widget_show (GTK_WIDGET (label));
1900 g_list_free (children);
1902 g_object_unref (account);
1906 set_toolbar_transfer_mode (ModestMainWindow *self)
1908 ModestMainWindowPrivate *priv = NULL;
1910 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1912 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1914 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1916 if (priv->progress_bar_timeout > 0) {
1917 g_source_remove (priv->progress_bar_timeout);
1918 priv->progress_bar_timeout = 0;
1925 set_toolbar_mode (ModestMainWindow *self,
1926 ModestToolBarModes mode)
1928 ModestWindowPrivate *parent_priv = NULL;
1929 ModestMainWindowPrivate *priv = NULL;
1930 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1932 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1934 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1935 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1937 /* In case this was called before the toolbar exists: */
1938 if (!(parent_priv->toolbar))
1941 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1943 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1944 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1945 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1947 /* Sets current toolbar mode */
1948 priv->current_toolbar_mode = mode;
1950 /* Show and hide toolbar items */
1952 case TOOLBAR_MODE_NORMAL:
1954 gtk_action_set_visible (sort_action, TRUE);
1956 gtk_action_set_visible (refresh_action, TRUE);
1957 if (priv->progress_toolitem) {
1958 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1959 gtk_widget_hide (priv->progress_toolitem);
1961 if (priv->progress_bar)
1962 gtk_widget_hide (priv->progress_bar);
1965 gtk_action_set_visible (cancel_action, FALSE);
1966 /* if (priv->sort_toolitem) */
1967 /* gtk_widget_show (priv->sort_toolitem); */
1969 /* if (priv->refresh_toolitem) */
1970 /* gtk_widget_show (priv->refresh_toolitem); */
1972 /* if (priv->progress_toolitem) */
1973 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1974 /* if (priv->progress_bar) */
1975 /* gtk_widget_hide (priv->progress_bar); */
1977 /* if (priv->cancel_toolitem) */
1978 /* gtk_widget_hide (priv->cancel_toolitem); */
1980 /* Hide toolbar if optimized view is enabled */
1981 if (priv->optimized_view)
1982 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1984 case TOOLBAR_MODE_TRANSFER:
1986 gtk_action_set_visible (sort_action, FALSE);
1988 gtk_action_set_visible (refresh_action, FALSE);
1990 gtk_action_set_visible (cancel_action, TRUE);
1991 if (priv->progress_toolitem) {
1992 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1993 gtk_widget_show (priv->progress_toolitem);
1995 if (priv->progress_bar)
1996 gtk_widget_show (priv->progress_bar);
1998 /* if (priv->sort_toolitem) */
1999 /* gtk_widget_hide (priv->sort_toolitem); */
2001 /* if (priv->refresh_toolitem) */
2002 /* gtk_widget_hide (priv->refresh_toolitem); */
2004 /* if (priv->progress_toolitem) */
2005 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2006 /* if (priv->progress_bar) */
2007 /* gtk_widget_show (priv->progress_bar); */
2009 /* if (priv->cancel_toolitem) */
2010 /* gtk_widget_show (priv->cancel_toolitem); */
2012 /* Show toolbar if it's hiden (optimized view ) */
2013 if (priv->optimized_view)
2014 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2017 g_return_if_reached ();
2022 cancel_progressbar (GtkToolButton *toolbutton,
2023 ModestMainWindow *self)
2026 ModestMainWindowPrivate *priv;
2028 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2030 /* Get operation observers and cancel all the operations */
2031 tmp = priv->progress_widgets;
2033 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2034 tmp=g_slist_next(tmp);
2039 observers_empty (ModestMainWindow *self)
2042 ModestMainWindowPrivate *priv;
2043 gboolean is_empty = TRUE;
2044 guint pending_ops = 0;
2046 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2047 tmp = priv->progress_widgets;
2049 /* Check all observers */
2050 while (tmp && is_empty) {
2051 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2052 is_empty = pending_ops == 0;
2054 tmp = g_slist_next(tmp);
2061 on_queue_changed (ModestMailOperationQueue *queue,
2062 ModestMailOperation *mail_op,
2063 ModestMailOperationQueueNotification type,
2064 ModestMainWindow *self)
2066 ModestMainWindowPrivate *priv;
2067 ModestMailOperationTypeOperation op_type;
2068 ModestToolBarModes mode;
2070 gboolean mode_changed = FALSE;
2071 /* ModestMailOperationStatus status; */
2073 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2074 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2076 /* Get toolbar mode from operation id*/
2077 op_type = modest_mail_operation_get_type_operation (mail_op);
2079 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2080 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2081 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2082 mode = TOOLBAR_MODE_TRANSFER;
2083 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2084 mode_changed = TRUE;
2087 mode = TOOLBAR_MODE_NORMAL;
2092 /* Add operation observers and change toolbar if neccessary*/
2093 tmp = priv->progress_widgets;
2095 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2096 if (mode == TOOLBAR_MODE_TRANSFER) {
2098 set_toolbar_transfer_mode(self);
2100 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2102 tmp = g_slist_next (tmp);
2106 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2107 /* Change toolbar mode */
2108 if (mode == TOOLBAR_MODE_TRANSFER) {
2110 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2112 tmp = g_slist_next (tmp);
2115 /* If no more operations are being observed, NORMAL mode is enabled again */
2116 if (observers_empty (self)) {
2117 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2128 on_show_account_action_activated (GtkAction *action,
2131 ModestAccountData *acc_data;
2132 ModestMainWindow *self;
2133 ModestMainWindowPrivate *priv;
2134 ModestAccountMgr *mgr;
2135 const gchar *acc_name;
2137 self = MODEST_MAIN_WINDOW (user_data);
2138 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2140 /* Get account data */
2141 acc_name = gtk_action_get_name (action);
2142 mgr = modest_runtime_get_account_mgr ();
2143 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2145 /* Set the new visible & active account */
2146 if (acc_data->store_account) {
2147 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2148 acc_data->store_account->account_name);
2149 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2152 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2155 modest_account_mgr_free_account_data (mgr, acc_data);
2159 refresh_account (const gchar *account_name)
2163 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2165 /* If account_name == NULL, we must update all (option All) */
2167 modest_ui_actions_do_send_receive_all (win);
2169 modest_ui_actions_do_send_receive (account_name, win);
2174 on_refresh_account_action_activated (GtkAction *action,
2177 refresh_account ((const gchar*) user_data);
2181 on_send_receive_csm_activated (GtkMenuItem *item,
2184 refresh_account ((const gchar*) user_data);
2188 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2190 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2192 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2198 on_folder_view_focus_in (GtkWidget *widget,
2199 GdkEventFocus *event,
2202 ModestMainWindow *main_window = NULL;
2204 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2205 main_window = MODEST_MAIN_WINDOW (userdata);
2207 /* Update toolbar dimming state */
2208 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2214 on_header_view_focus_in (GtkWidget *widget,
2215 GdkEventFocus *event,
2218 ModestMainWindow *main_window = NULL;
2219 ModestMainWindowPrivate *priv = NULL;
2221 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2222 main_window = MODEST_MAIN_WINDOW (userdata);
2223 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2225 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2226 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2227 TnyIterator *iterator = tny_list_create_iterator (selection);
2230 tny_iterator_first (iterator);
2231 header = TNY_HEADER (tny_iterator_get_current (iterator));
2233 if (tny_header_get_subject (header))
2234 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2236 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2239 g_object_unref (header);
2241 g_object_unref (iterator);
2242 g_object_unref (selection);
2246 /* Update toolbar dimming state */
2247 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2253 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2254 TnyFolderStore *folder_store,
2256 ModestMainWindow *main_window)
2258 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2259 GtkAction *action = NULL;
2260 gboolean show_reply = TRUE;
2261 gboolean show_forward = TRUE;
2262 gboolean show_cancel_send = FALSE;
2263 gboolean show_clipboard = TRUE;
2264 gboolean show_delete = TRUE;
2267 if (TNY_IS_ACCOUNT (folder_store)) {
2268 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2269 } else if (TNY_IS_FOLDER (folder_store)) {
2270 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2271 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2272 TNY_FOLDER (folder_store));
2273 switch (folder_type) {
2274 case TNY_FOLDER_TYPE_DRAFTS:
2275 show_clipboard = show_delete = TRUE;
2276 show_reply = show_forward = show_cancel_send = FALSE;
2278 case TNY_FOLDER_TYPE_SENT:
2279 show_forward = show_clipboard = show_delete = TRUE;
2280 show_reply = show_cancel_send = FALSE;
2282 case TNY_FOLDER_TYPE_OUTBOX:
2283 show_clipboard = show_delete = show_cancel_send = TRUE;
2284 show_reply = show_forward = FALSE;
2287 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2288 show_cancel_send = FALSE;
2291 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2292 show_cancel_send = FALSE;
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2298 gtk_action_set_visible (action, show_reply);
2299 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2300 gtk_action_set_visible (action, show_reply);
2301 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2302 gtk_action_set_visible (action, show_forward);
2303 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2304 gtk_action_set_visible (action, show_cancel_send);
2305 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2306 gtk_action_set_visible (action, show_clipboard);
2307 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2308 gtk_action_set_visible (action, show_clipboard);
2309 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2310 gtk_action_set_visible (action, show_clipboard);
2311 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2312 gtk_action_set_visible (action, show_delete);
2314 /* We finally call to the ui actions handler, after updating properly
2315 * the header view CSM */
2316 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2321 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2322 GtkTreeModel *model,
2323 GtkTreeRowReference *row_reference,
2324 ModestMainWindow *self)
2326 ModestMainWindowPrivate *priv = NULL;
2327 GtkTreeModel *header_model = NULL;
2328 GtkTreePath *path = NULL;
2330 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2331 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2332 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2334 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2335 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2337 /* Do nothing if we changed the folder in the main view */
2338 if (header_model != model)
2341 /* Select the message in the header view */
2342 path = gtk_tree_row_reference_get_path (row_reference);
2343 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2345 gtk_tree_path_free (path);