1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar-widget.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "maemo/modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-program.h>
70 #include <hildon/hildon-program.h>
71 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
73 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
80 /* 'private'/'protected' functions */
81 static void modest_main_window_class_init (ModestMainWindowClass *klass);
82 static void modest_main_window_init (ModestMainWindow *obj);
83 static void modest_main_window_finalize (GObject *obj);
84 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
85 GdkEventWindowState *event,
88 static void connect_signals (ModestMainWindow *self);
90 static void restore_settings (ModestMainWindow *self, gboolean do_folder_view_too);
91 static void save_state (ModestWindow *self);
93 static void modest_main_window_show_toolbar (ModestWindow *window,
94 gboolean show_toolbar);
96 static void cancel_progressbar (GtkToolButton *toolbutton,
97 ModestMainWindow *self);
99 static void on_queue_changed (ModestMailOperationQueue *queue,
100 ModestMailOperation *mail_op,
101 ModestMailOperationQueueNotification type,
102 ModestMainWindow *self);
104 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
106 static void on_account_update (TnyAccountStore *account_store,
107 const gchar *account_name,
110 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
114 static void on_configuration_key_changed (ModestConf* conf,
116 ModestConfEvent event,
117 ModestMainWindow *self);
119 static void set_toolbar_mode (ModestMainWindow *self,
120 ModestToolBarModes mode);
122 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
124 static void on_show_account_action_activated (GtkAction *action,
127 static void on_refresh_account_action_activated (GtkAction *action,
130 static void on_send_receive_csm_activated (GtkMenuItem *item,
134 _on_msg_count_changed (ModestHeaderView *header_view,
136 TnyFolderChange *change,
137 ModestMainWindow *main_window);
140 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
143 static GtkWidget * create_empty_view (void);
146 on_folder_view_focus_in (GtkWidget *widget,
147 GdkEventFocus *event,
150 on_header_view_focus_in (GtkWidget *widget,
151 GdkEventFocus *event,
154 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
155 TnyFolderStore *folder_store,
157 ModestMainWindow *main_window);
159 /* list my signals */
166 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
167 struct _ModestMainWindowPrivate {
168 GtkWidget *msg_paned;
169 GtkWidget *main_paned;
170 GtkWidget *main_vbox;
171 GtkWidget *contents_widget;
172 GtkWidget *empty_view;
174 /* Progress observers */
175 GtkWidget *progress_bar;
176 GSList *progress_widgets;
179 GtkWidget *progress_toolitem;
180 GtkWidget *cancel_toolitem;
181 GtkWidget *sort_toolitem;
182 GtkWidget *refresh_toolitem;
183 ModestToolBarModes current_toolbar_mode;
185 /* Merge ids used to add/remove accounts to the ViewMenu*/
186 GByteArray *merge_ids;
188 /* On-demand widgets */
189 GtkWidget *accounts_popup;
190 GtkWidget *details_widget;
192 /* Optimized view enabled */
193 gboolean optimized_view;
195 /* Optimized view enabled */
196 gboolean send_receive_in_progress;
198 ModestHeaderView *header_view;
199 ModestFolderView *folder_view;
201 ModestMainWindowStyle style;
202 ModestMainWindowContentsStyle contents_style;
204 guint progress_bar_timeout;
206 /* Signal handler UIDs */
207 gint queue_changed_handler_uid;
208 GList *queue_err_signals;
210 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
211 MODEST_TYPE_MAIN_WINDOW, \
212 ModestMainWindowPrivate))
214 typedef struct _GetMsgAsyncHelper {
215 ModestMainWindowPrivate *main_window_private;
217 ModestTnyMsgReplyType reply_type;
218 ModestTnyMsgForwardType forward_type;
225 static GtkWindowClass *parent_class = NULL;
228 /* Private actions */
229 /* This is the context sensitive menu: */
230 static const GtkActionEntry modest_folder_view_action_entries [] = {
232 /* Folder View CSM actions */
233 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
234 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
235 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
236 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
237 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
238 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
241 static const GtkActionEntry modest_header_view_action_entries [] = {
243 /* Header View CSM actions */
244 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
245 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
246 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
247 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
248 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
249 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
250 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
251 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
252 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
253 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
256 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
257 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
260 /************************************************************************/
263 modest_main_window_get_type (void)
265 static GType my_type = 0;
267 static const GTypeInfo my_info = {
268 sizeof(ModestMainWindowClass),
269 NULL, /* base init */
270 NULL, /* base finalize */
271 (GClassInitFunc) modest_main_window_class_init,
272 NULL, /* class finalize */
273 NULL, /* class data */
274 sizeof(ModestMainWindow),
276 (GInstanceInitFunc) modest_main_window_init,
279 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
287 modest_main_window_class_init (ModestMainWindowClass *klass)
289 GObjectClass *gobject_class;
290 gobject_class = (GObjectClass*) klass;
291 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
293 parent_class = g_type_class_peek_parent (klass);
294 gobject_class->finalize = modest_main_window_finalize;
296 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
298 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
299 modest_window_class->save_state_func = save_state;
300 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
301 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
305 modest_main_window_init (ModestMainWindow *obj)
307 ModestMainWindowPrivate *priv;
309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
311 priv->queue_err_signals = NULL;
312 priv->msg_paned = NULL;
313 priv->main_paned = NULL;
314 priv->main_vbox = NULL;
315 priv->header_view = NULL;
316 priv->folder_view = NULL;
317 priv->contents_widget = NULL;
318 priv->accounts_popup = NULL;
319 priv->details_widget = NULL;
320 priv->empty_view = NULL;
321 priv->progress_widgets = NULL;
322 priv->progress_bar = NULL;
323 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
324 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
325 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
326 priv->merge_ids = NULL;
327 priv->optimized_view = FALSE;
328 priv->send_receive_in_progress = FALSE;
329 priv->progress_bar_timeout = 0;
330 priv->queue_changed_handler_uid = 0;
334 modest_main_window_finalize (GObject *obj)
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
340 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
342 g_slist_free (priv->progress_widgets);
344 g_byte_array_free (priv->merge_ids, TRUE);
346 if (priv->progress_bar_timeout > 0) {
347 g_source_remove (priv->progress_bar_timeout);
348 priv->progress_bar_timeout = 0;
351 /* Disconnect signal handlers */
352 if (priv->queue_changed_handler_uid)
353 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
354 priv->queue_changed_handler_uid);
356 G_OBJECT_CLASS(parent_class)->finalize (obj);
360 modest_main_window_get_child_widget (ModestMainWindow *self,
361 ModestWidgetType widget_type)
363 ModestMainWindowPrivate *priv;
366 g_return_val_if_fail (self, NULL);
367 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
370 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
372 switch (widget_type) {
373 case MODEST_WIDGET_TYPE_HEADER_VIEW:
374 widget = (GtkWidget*)priv->header_view; break;
375 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
376 widget = (GtkWidget*)priv->folder_view; break;
381 return widget ? GTK_WIDGET(widget) : NULL;
386 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
388 printf ("DEBUGDEBUG: %s\n", __FUNCTION__);
391 ModestMainWindowPrivate *priv;
393 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
395 conf = modest_runtime_get_conf ();
397 modest_widget_memory_restore (conf, G_OBJECT(self),
398 MODEST_CONF_MAIN_WINDOW_KEY);
400 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
401 MODEST_CONF_HEADER_VIEW_KEY);
403 if (do_folder_view_too)
404 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
405 MODEST_CONF_FOLDER_VIEW_KEY);
407 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
408 MODEST_CONF_MAIN_PANED_KEY);
410 /* We need to force a redraw here in order to get the right
411 position of the horizontal paned separator */
412 gtk_widget_show (GTK_WIDGET (self));
417 save_state (ModestWindow *window)
420 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
421 ModestMainWindowPrivate *priv;
423 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
424 conf = modest_runtime_get_conf ();
426 modest_widget_memory_save (conf,G_OBJECT(self),
427 MODEST_CONF_MAIN_WINDOW_KEY);
428 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
429 MODEST_CONF_MAIN_PANED_KEY);
430 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
431 // MODEST_CONF_HEADER_VIEW_KEY);
432 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
433 MODEST_CONF_FOLDER_VIEW_KEY);
437 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
439 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
440 gtk_scrolled_window_add_with_viewport
441 (GTK_SCROLLED_WINDOW(win), widget);
443 gtk_container_add (GTK_CONTAINER(win),
448 /* static gboolean */
449 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
451 /* modest_window_save_state (MODEST_WINDOW(self)); */
456 on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data)
459 printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message);
461 if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL)
462 /* Don't show waste the user's time by showing him a dialog telling him
463 * that he has just cancelled something: */
467 /* Get the server name: */
468 const gchar* server_name = NULL;
470 TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account (
471 TNY_CAMEL_SEND_QUEUE (self));
472 if (server_account) {
473 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
475 g_object_unref (server_account);
476 server_account = NULL;
480 server_name = _("Unknown Server");
482 /* Show the appropriate message text for the GError: */
483 gchar *message = NULL;
486 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
487 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
489 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
490 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
492 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
493 /* TODO: This logical ID seems more suitable for a wrong username or password than for a
494 * wrong authentication method. The user is unlikely to guess at the real cause.
496 message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name);
498 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
499 /* TODO: Tinymail is still sending this sometimes when it should
500 * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. */
502 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
506 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
509 modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message);
512 /* TODO: Offer to remove the message, to avoid messages in future? */
514 TnyFolder *outbox = tny_send_queue_get_outbox (queue);
515 tny_folder_remove_msg (outbox, header, NULL);
516 tny_folder_sync (outbox, TRUE, NULL);
517 g_object_unref (outbox);
527 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
529 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
531 GList *oerrsignals = priv->queue_err_signals;
532 while (oerrsignals) {
533 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
534 g_signal_handler_disconnect (esignal->queue, esignal->signal);
535 g_slice_free (QueueErrorSignal, esignal);
536 oerrsignals = g_list_next (oerrsignals);
538 g_list_free (priv->queue_err_signals);
539 priv->queue_err_signals = NULL;
543 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
545 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
547 /* When going online, do the equivalent of pressing the send/receive button,
548 * as per the specification:
549 * (without the check for >0 accounts, though that is not specified): */
551 TnyDevice *device = tny_account_store_get_device (store);
553 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
555 /* Check that we are really online.
556 * This signal should not be emitted when we are not connected,
557 * but it seems to happen sometimes: */
558 if (!tny_device_is_online (device))
561 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
562 printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
564 /* Stop the existing send queues: */
565 modest_runtime_remove_all_send_queues ();
567 /* Create the send queues again, using the appropriate transport accounts
568 * for this new connection.
569 * This could be the first time that they are created if this is the first
571 /* TODO: Does this really destroy the TnySendQueues and their threads
572 * We do not want 2 TnySendQueues to exist with the same underlying
573 * outbox directory. */
575 modest_main_window_cleanup_queue_error_signals (self);
577 GSList *account_names = modest_account_mgr_account_names (
578 modest_runtime_get_account_mgr(),
579 TRUE /* enabled accounts only */);
580 GSList *iter = account_names;
582 const gchar *account_name = (const gchar*)(iter->data);
584 TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
585 modest_tny_account_store_get_transport_account_for_open_connection
586 (modest_runtime_get_account_store(), account_name));
588 /* Q: Is this the first location where the send-queues are requested? */
589 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
590 printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name,
591 tny_account_get_id(TNY_ACCOUNT(account)));
592 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
593 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
594 G_CALLBACK (on_sendqueue_error_happened), self);
595 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
599 iter = g_slist_next (iter);
602 modest_account_mgr_free_account_names (account_names);
603 account_names = NULL;
605 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
609 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
611 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
614 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
618 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
620 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
622 /* Update visibility */
625 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
629 connect_signals (ModestMainWindow *self)
631 ModestWindowPrivate *parent_priv;
632 ModestMainWindowPrivate *priv;
635 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
636 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
639 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
640 G_CALLBACK(on_inner_widgets_key_pressed), self);
641 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
642 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
643 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
644 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
645 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
646 G_CALLBACK (on_folder_view_focus_in), self);
648 /* Folder view CSM */
649 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
650 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
651 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
652 G_CALLBACK(_folder_view_csm_menu_activated),
655 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
656 G_CALLBACK(modest_ui_actions_on_header_selected), self);
657 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
658 G_CALLBACK(modest_ui_actions_on_header_activated), self);
659 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
660 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
661 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
662 G_CALLBACK(on_inner_widgets_key_pressed), self);
663 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
664 G_CALLBACK(_on_msg_count_changed), self);
665 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
666 G_CALLBACK (on_header_view_focus_in), self);
668 /* Header view CSM */
669 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
670 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
671 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
672 G_CALLBACK(_header_view_csm_menu_activated),
676 /* g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */
677 g_signal_connect (G_OBJECT (self), "window-state-event",
678 G_CALLBACK (modest_main_window_window_state_event),
681 /* Mail Operation Queue */
682 priv->queue_changed_handler_uid =
683 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
684 "queue-changed", G_CALLBACK (on_queue_changed), self);
686 /* Track changes in the device name */
687 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
688 "key_changed", G_CALLBACK (on_configuration_key_changed),
691 /* Track account changes. We need to refresh the toolbar */
692 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
693 "account_update", G_CALLBACK (on_account_update),
697 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
698 "password_requested",
699 G_CALLBACK (modest_ui_actions_on_password_requested), self);
702 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()),
703 "connecting-finished",
704 G_CALLBACK(on_account_store_connecting_finished), self);
708 /** Idle handler, to send/receive at startup .*/
710 sync_accounts_cb (ModestMainWindow *win)
712 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
713 return FALSE; /* Do not call this idle handler again. */
717 static void on_hildon_program_is_topmost_notify(GObject *self,
718 GParamSpec *propert_param, gpointer user_data)
720 HildonProgram *app = HILDON_PROGRAM (self);
723 ModestWindow* self = MODEST_WINDOW(user_data);
726 /* Note that use of hildon_program_set_can_hibernate()
727 * is generally referred to as "setting the killable flag",
728 * though hibernation does not seem equal to death.
731 if (hildon_program_get_is_topmost (app)) {
732 /* Prevent hibernation when the progam comes to the foreground,
733 * because hibernation should only happen when the application
734 * is in the background: */
735 hildon_program_set_can_hibernate (app, FALSE);
737 /* Allow hibernation if the program has gone to the background: */
739 /* However, prevent hibernation while the settings are being changed: */
740 const gboolean hibernation_prevented =
741 modest_window_mgr_get_hibernation_is_prevented (
742 modest_runtime_get_window_mgr ());
744 if (hibernation_prevented)
745 hildon_program_set_can_hibernate (app, FALSE);
747 /* Allow hibernation, after saving the state: */
748 modest_osso_save_state();
749 hildon_program_set_can_hibernate (app, TRUE);
756 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
758 GtkWidget *folder_win = (GtkWidget *) user_data;
759 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
761 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
762 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
763 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
765 gtk_widget_show (GTK_WIDGET (priv->folder_view));
767 /* Connect signals */
768 connect_signals ((ModestMainWindow*)self);
770 /* Set account store */
771 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
772 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
774 /* Load previous osso state, for instance if we are being restored from
776 modest_osso_load_state ();
778 /* Restore window & widget settings */
780 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
782 /* The UI spec wants us to show a connection dialog when the application is
783 * started by the user, if there is no connection.
784 * Do this before showing the account wizard,
785 * because wizard needs a connection to discover capabilities. */
786 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
788 /* Check if accounts exist and show the account wizard if not */
789 gboolean accounts_exist =
790 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
792 if (!accounts_exist) {
793 /* This is necessary to have the main window shown behind the dialog
794 It's an ugly hack... jschmid */
795 gtk_widget_show_all(GTK_WIDGET(self));
796 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
799 GtkAction *send_receive_all;
800 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
801 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
802 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
803 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
804 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
805 modest_account_mgr_free_account_names (accounts);
810 modest_main_window_new (void)
812 ModestMainWindow *self = NULL;
813 ModestMainWindowPrivate *priv = NULL;
814 ModestWindowPrivate *parent_priv = NULL;
815 GtkWidget *folder_win = NULL;
816 ModestDimmingRulesGroup *menu_rules_group = NULL;
817 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
818 GtkActionGroup *action_group = NULL;
819 GError *error = NULL;
820 ModestConf *conf = NULL;
821 GtkAction *action = NULL;
822 GdkPixbuf *window_icon;
824 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
825 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
826 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
828 parent_priv->ui_manager = gtk_ui_manager_new();
829 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
831 action_group = gtk_action_group_new ("ModestMainWindowActions");
832 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
834 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
835 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
837 /* Add common actions */
838 gtk_action_group_add_actions (action_group,
839 modest_action_entries,
840 G_N_ELEMENTS (modest_action_entries),
843 gtk_action_group_add_actions (action_group,
844 modest_folder_view_action_entries,
845 G_N_ELEMENTS (modest_folder_view_action_entries),
848 gtk_action_group_add_actions (action_group,
849 modest_header_view_action_entries,
850 G_N_ELEMENTS (modest_header_view_action_entries),
853 gtk_action_group_add_toggle_actions (action_group,
854 modest_toggle_action_entries,
855 G_N_ELEMENTS (modest_toggle_action_entries),
858 gtk_action_group_add_toggle_actions (action_group,
859 modest_main_window_toggle_action_entries,
860 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
863 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
864 g_object_unref (action_group);
866 /* Load the UI definition */
867 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
868 MODEST_UIDIR "modest-main-window-ui.xml", &error);
870 g_warning ("Could not merge modest-ui.xml: %s", error->message);
871 g_error_free (error);
875 /* Add common dimming rules */
876 modest_dimming_rules_group_add_rules (menu_rules_group,
877 modest_main_window_menu_dimming_entries,
878 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
880 modest_dimming_rules_group_add_rules (toolbar_rules_group,
881 modest_main_window_toolbar_dimming_entries,
882 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
885 /* Insert dimming rules group for this window */
886 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
887 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
888 g_object_unref (menu_rules_group);
889 g_object_unref (toolbar_rules_group);
891 /* Add accelerators */
892 gtk_window_add_accel_group (GTK_WINDOW (self),
893 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
895 /* Menubar. Update the state of some toggles */
896 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
897 conf = modest_runtime_get_conf ();
898 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
899 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
900 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
901 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
902 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
903 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
904 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
905 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
906 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
907 gtk_widget_show (parent_priv->menubar);
909 /* Get device name */
910 modest_maemo_utils_get_device_name ();
914 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
915 if (!priv->header_view)
916 g_printerr ("modest: cannot instantiate header view\n");
917 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
918 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
919 MODEST_CONF_HEADER_VIEW_KEY);
921 /* Other style properties of header view */
922 g_object_set (G_OBJECT (priv->header_view),
925 /* gtk_widget_show (priv->header_view); */
928 priv->empty_view = create_empty_view ();
929 gtk_widget_show (priv->empty_view);
931 /* Create scrolled windows */
932 folder_win = gtk_scrolled_window_new (NULL, NULL);
933 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
934 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
936 GTK_POLICY_AUTOMATIC);
937 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
939 GTK_POLICY_AUTOMATIC);
940 /* gtk_widget_show (priv->contents_widget); */
943 priv->main_paned = gtk_hpaned_new ();
944 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
945 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
946 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
948 /* putting it all together... */
949 priv->main_vbox = gtk_vbox_new (FALSE, 6);
950 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
951 gtk_widget_show (priv->main_vbox);
953 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
955 HildonProgram *app = hildon_program_get_instance ();
956 hildon_program_add_window (app, HILDON_WINDOW (self));
958 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
959 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
961 g_signal_connect (G_OBJECT(self), "show",
962 G_CALLBACK (modest_main_window_on_show), folder_win);
964 /* Set window icon */
965 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
967 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
968 g_object_unref (window_icon);
971 /* Dont't restore settings here,
972 * because it requires a gtk_widget_show(),
973 * and we don't want to do that until later,
974 * so that the UI is not visible for non-menu D-Bus activation.
976 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
978 return MODEST_WINDOW(self);
982 modest_main_window_close_all (ModestMainWindow *self)
985 GtkResponseType response;
987 /* Create the confirmation dialog MSG-NOT308 */
988 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
989 _("emev_nc_close_windows"),
990 _("mcen_bd_yes"), GTK_RESPONSE_YES,
991 _("mcen_bd_no"), GTK_RESPONSE_NO,
994 response = gtk_dialog_run (GTK_DIALOG (note));
995 gtk_widget_destroy (GTK_WIDGET (note));
997 if (response == GTK_RESPONSE_YES)
1005 modest_main_window_set_style (ModestMainWindow *self,
1006 ModestMainWindowStyle style)
1008 ModestMainWindowPrivate *priv;
1009 ModestWindowPrivate *parent_priv;
1013 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1015 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1016 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1018 /* no change -> nothing to do */
1019 if (priv->style == style)
1022 /* Get toggle button and update the state if needed. This will
1023 happen only when the set_style is not invoked from the UI,
1024 for example when it's called from widget memory */
1025 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1026 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1027 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1028 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1029 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1030 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1031 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1034 priv->style = style;
1036 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1037 /* Remove main paned */
1038 g_object_ref (priv->main_paned);
1039 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1041 /* Reparent the contents widget to the main vbox */
1042 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1044 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1045 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1046 TnyIterator *iterator = tny_list_create_iterator (selection);
1048 tny_iterator_first (iterator);
1049 header = TNY_HEADER (tny_iterator_get_current (iterator));
1050 if (tny_header_get_subject (header))
1051 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1053 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1056 g_object_unref (header);
1058 g_object_unref (iterator);
1059 g_object_unref (selection);
1063 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1064 /* Remove header view */
1065 g_object_ref (priv->contents_widget);
1066 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1068 /* Reparent the main paned */
1069 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1070 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1074 g_return_if_reached ();
1077 /* Let header view grab the focus if it's being shown */
1078 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1079 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1081 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1084 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1087 ModestMainWindowStyle
1088 modest_main_window_get_style (ModestMainWindow *self)
1090 ModestMainWindowPrivate *priv;
1092 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1094 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1101 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1103 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1104 ModestWindowPrivate *parent_priv;
1105 ModestWindowMgr *mgr;
1106 gboolean is_fullscreen;
1107 GtkAction *fs_toggle_action;
1110 mgr = modest_runtime_get_window_mgr ();
1112 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1114 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1116 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1117 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1118 if (is_fullscreen != active) {
1119 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1128 set_homogeneous (GtkWidget *widget,
1131 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1132 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1136 modest_main_window_show_toolbar (ModestWindow *self,
1137 gboolean show_toolbar)
1139 ModestMainWindowPrivate *priv = NULL;
1140 ModestWindowPrivate *parent_priv = NULL;
1141 GtkWidget *reply_button = NULL, *menu = NULL;
1142 GtkWidget *placeholder = NULL;
1145 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1146 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1147 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1149 /* Set optimized view status */
1150 priv->optimized_view = !show_toolbar;
1152 if (!parent_priv->toolbar) {
1153 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1156 /* Set homogeneous toolbar */
1157 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1158 set_homogeneous, NULL);
1160 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1161 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1162 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1163 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1164 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1165 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1166 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1167 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1169 /* Add ProgressBar (Transfer toolbar) */
1170 priv->progress_bar = modest_progress_bar_widget_new ();
1171 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1172 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1173 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1174 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1175 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1177 /* Connect cancel 'clicked' signal to abort progress mode */
1178 g_signal_connect(priv->cancel_toolitem, "clicked",
1179 G_CALLBACK(cancel_progressbar),
1182 /* Add it to the observers list */
1183 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1186 hildon_window_add_toolbar (HILDON_WINDOW (self),
1187 GTK_TOOLBAR (parent_priv->toolbar));
1189 /* Set reply button tap and hold menu */
1190 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1191 "/ToolBar/ToolbarMessageReply");
1192 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1193 "/ToolbarReplyCSM");
1194 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1196 /* Set send & receive button tap and hold menu */
1197 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1202 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1203 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1204 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1206 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1207 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1209 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1214 compare_display_names (ModestAccountData *a,
1215 ModestAccountData *b)
1217 return strcmp (a->display_name, b->display_name);
1221 on_account_update (TnyAccountStore *account_store,
1222 const gchar *account_name,
1225 GSList *account_names, *iter, *accounts;
1226 ModestMainWindow *self;
1227 ModestMainWindowPrivate *priv;
1228 ModestWindowPrivate *parent_priv;
1229 ModestAccountMgr *mgr;
1230 gint i, num_accounts;
1231 GtkActionGroup *action_group;
1233 gchar *default_account;
1234 GtkWidget *send_receive_button, *item;
1235 GtkAction *send_receive_all = NULL;
1237 self = MODEST_MAIN_WINDOW (user_data);
1238 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1239 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1241 /* Get enabled account IDs */
1242 mgr = modest_runtime_get_account_mgr ();
1243 account_names = modest_account_mgr_account_names (mgr, TRUE);
1244 iter = account_names;
1248 ModestAccountData *account_data =
1249 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1250 accounts = g_slist_prepend (accounts, account_data);
1254 modest_account_mgr_free_account_names (account_names);
1255 account_names = NULL;
1257 /* Order the list of accounts by its display name */
1258 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1259 num_accounts = g_slist_length (accounts);
1261 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1262 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1263 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1265 /* Delete old send&receive popup items. We can not just do a
1266 menu_detach because it does not work well with
1268 if (priv->accounts_popup)
1269 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1270 (GtkCallback) gtk_widget_destroy, NULL);
1272 /* Delete old entries in the View menu. Do not free groups, it
1274 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1276 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1277 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1278 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1279 GTK_ACTION_GROUP (groups->data));
1282 if (priv->merge_ids) {
1283 for (i = 0; i < priv->merge_ids->len; i++)
1284 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1285 g_byte_array_free (priv->merge_ids, TRUE);
1287 /* We need to call this in order to ensure
1288 that the new actions are added in the right
1289 order (alphabetical */
1290 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1292 groups = g_list_next (groups);
1294 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1296 /* Get send receive button */
1297 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1298 "/ToolBar/ToolbarSendReceive");
1300 /* Create the menu */
1301 if (num_accounts > 1) {
1302 if (!priv->accounts_popup)
1303 priv->accounts_popup = gtk_menu_new ();
1304 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1305 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1306 g_signal_connect (G_OBJECT (item),
1308 G_CALLBACK (on_send_receive_csm_activated),
1310 item = gtk_separator_menu_item_new ();
1311 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1314 /* Create a new action group */
1315 default_account = modest_account_mgr_get_default_account (mgr);
1316 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1317 for (i = 0; i < num_accounts; i++) {
1318 gchar *display_name = NULL;
1320 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1322 /* Create display name. The UI specification specifies a different format string
1323 * to use for the default account, though both seem to be "%s", so
1324 * I don't see what the point is. murrayc. */
1325 if (default_account && account_data->account_name &&
1326 !(strcmp (default_account, account_data->account_name) == 0)) {
1327 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1328 account_data->display_name);
1331 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1332 account_data->display_name);
1335 /* Create action and add it to the action group. The
1336 action name must be the account name, this way we
1337 could know in the handlers the account to show */
1338 if(account_data && account_data->account_name) {
1339 gchar* item_name, *refresh_action_name;
1340 guint8 merge_id = 0;
1341 GtkAction *view_account_action, *refresh_account_action;
1343 view_account_action = gtk_action_new (account_data->account_name,
1344 display_name, NULL, NULL);
1345 gtk_action_group_add_action (action_group, view_account_action);
1347 /* Add ui from account data. We allow 2^9-1 account
1348 changes in a single execution because we're
1349 downcasting the guint to a guint8 in order to use a
1350 GByteArray. It should be enough. */
1351 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1352 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1353 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1354 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1356 "/MenuBar/ViewMenu/ViewMenuAdditions",
1358 account_data->account_name,
1359 GTK_UI_MANAGER_MENUITEM,
1362 /* Connect the action signal "activate" */
1363 g_signal_connect (G_OBJECT (view_account_action),
1365 G_CALLBACK (on_show_account_action_activated),
1368 /* Create the items for the Tools->Send&Receive submenu */
1369 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1370 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1371 display_name, NULL, NULL);
1372 printf("DEBUG: %s: menu display_name=%s\n", __FUNCTION__, display_name);
1373 gtk_action_group_add_action (action_group, refresh_account_action);
1375 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1376 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1377 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1379 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1381 refresh_action_name,
1382 GTK_UI_MANAGER_MENUITEM,
1384 g_free (refresh_action_name);
1386 g_signal_connect_data (G_OBJECT (refresh_account_action),
1388 G_CALLBACK (on_refresh_account_action_activated),
1389 g_strdup (account_data->account_name),
1390 (GClosureNotify) g_free,
1393 /* Create item and add it to the send&receive
1394 CSM. If there is only one account then
1396 if (priv->accounts_popup) {
1397 GtkWidget *label = gtk_label_new(NULL);
1398 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1399 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1401 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1402 gtk_label_set_markup (GTK_LABEL (label), escaped);
1407 gtk_label_set_text (GTK_LABEL (label), display_name);
1410 item = gtk_menu_item_new ();
1411 gtk_container_add (GTK_CONTAINER (item), label);
1413 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1414 g_signal_connect_data (G_OBJECT (item),
1416 G_CALLBACK (on_send_receive_csm_activated),
1417 g_strdup (account_data->account_name),
1418 (GClosureNotify) g_free,
1425 g_free (display_name);
1428 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1430 /* We cannot do this in the loop above because this relies on the action
1431 * group being inserted. This makes the default account appear in bold.
1432 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1433 for (i = 0; i < num_accounts; i++) {
1434 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1436 if(account_data->account_name &&
1437 strcmp (account_data->account_name, default_account) == 0) {
1438 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1440 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1441 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1445 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1446 if (GTK_IS_LABEL (child)) {
1447 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1448 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1449 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1454 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1455 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1459 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1460 if (GTK_IS_LABEL (child)) {
1461 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1462 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1463 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1471 modest_account_mgr_free_account_data (mgr, account_data);
1474 if (priv->accounts_popup) {
1475 /* Mandatory in order to view the menu contents */
1476 gtk_widget_show_all (priv->accounts_popup);
1478 /* Setup tap_and_hold just if was not done before*/
1479 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1480 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1484 g_slist_free (accounts);
1485 g_free (default_account);
1489 * This function manages the key events used to navigate between
1490 * header and folder views (when the window is in split view)
1493 * -------------------------------------------------
1494 * HeaderView GDK_Left Move focus to folder view
1495 * FolderView GDK_Right Move focus to header view
1497 * There is no need to scroll to selected row, the widgets will be the
1498 * responsibles of doing that (probably managing the focus-in event
1501 on_inner_widgets_key_pressed (GtkWidget *widget,
1505 ModestMainWindowPrivate *priv;
1507 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1509 /* Do nothing if we're in SIMPLE style */
1510 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1513 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1514 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1515 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1516 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1522 set_alignment (GtkWidget *widget,
1525 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1526 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1530 create_empty_view (void)
1532 GtkLabel *label = NULL;
1533 GtkWidget *align = NULL;
1535 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1536 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1537 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1538 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1540 return GTK_WIDGET(align);
1544 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1546 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1551 gchar *gray_color_markup;
1553 vbox = gtk_vbox_new (FALSE, 0);
1555 /* Obtain the secondary text color. We need a realized widget, that's why
1556 we get styled_widget from outside */
1557 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1559 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1560 gray_color_markup = modest_text_utils_get_color_string (&color);
1562 // gray_color_markup is freed below
1563 gray_color_markup = g_strdup ("#BBBBBB");
1565 /* Account description: */
1567 if (modest_tny_account_is_virtual_local_folders (account)
1568 || (modest_tny_account_is_memory_card_account (account))) {
1570 /* Local folders: */
1572 /* Get device name */
1573 gchar *device_name = NULL;
1574 if (modest_tny_account_is_virtual_local_folders (account))
1575 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1576 MODEST_CONF_DEVICE_NAME, NULL);
1578 device_name = g_strdup (tny_account_get_name (account));
1580 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1581 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1582 gray_color_markup, tmp, device_name);
1584 label_w = gtk_label_new (NULL);
1585 gtk_label_set_markup (GTK_LABEL (label_w), label);
1586 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1587 g_free (device_name);
1590 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1591 gtk_box_pack_start (GTK_BOX (vbox),
1592 gtk_label_new (tny_account_get_name (account)),
1595 /* Other accounts, such as IMAP and POP: */
1600 /* Put proto in uppercase */
1601 proto = g_string_new (tny_account_get_proto (account));
1602 proto = g_string_ascii_up (proto);
1604 /* note: mcen_fi_localroot_description is something like "%s account"
1605 * however, we should display "%s account: %s"... therefore, ugly tmp */
1606 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1607 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1608 gray_color_markup, tmp, tny_account_get_name (account));
1611 label_w = gtk_label_new (NULL);
1612 gtk_label_set_markup (GTK_LABEL (label_w), label);
1613 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1614 g_string_free (proto, TRUE);
1620 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1621 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1622 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1623 modest_tny_folder_store_get_message_count (folder_store));
1624 label_w = gtk_label_new (NULL);
1625 gtk_label_set_markup (GTK_LABEL (label_w), label);
1626 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1630 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1632 _("mcen_fi_rootfolder_folders"),
1633 modest_tny_folder_store_get_folder_count (folder_store));
1634 label_w = gtk_label_new (NULL);
1635 gtk_label_set_markup (GTK_LABEL (label_w), label);
1636 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1640 if (modest_tny_account_is_virtual_local_folders (account)
1641 || modest_tny_account_is_memory_card_account (account)) {
1643 gchar *size = modest_text_utils_get_display_size (
1644 modest_tny_folder_store_get_local_size (folder_store));
1646 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1647 gray_color_markup, _("mcen_fi_rootfolder_size"),
1651 label_w = gtk_label_new (NULL);
1652 gtk_label_set_markup (GTK_LABEL (label_w), label);
1653 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1655 } else if (TNY_IS_ACCOUNT(folder_store)) {
1656 TnyAccount *account = TNY_ACCOUNT(folder_store);
1658 time_t last_updated;
1659 gchar *last_updated_string;
1660 /* Get last updated from configuration */
1661 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1662 tny_account_get_id (account),
1663 MODEST_ACCOUNT_LAST_UPDATED,
1665 if (last_updated > 0)
1666 last_updated_string = modest_text_utils_get_display_date(last_updated);
1668 last_updated_string = g_strdup (_("mcen_va_never"));
1670 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1671 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1672 label_w = gtk_label_new (NULL);
1673 gtk_label_set_markup (GTK_LABEL (label_w), label);
1674 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1675 g_free (last_updated_string);
1679 g_free (gray_color_markup);
1682 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1688 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1690 ModestMainWindowPrivate *priv = NULL;
1692 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1694 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1696 return priv->send_receive_in_progress;
1700 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1702 GtkAction *action = NULL;
1703 GtkWidget *widget = NULL;
1704 ModestMainWindowPrivate *priv = NULL;
1706 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1707 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1709 priv->send_receive_in_progress = TRUE;
1711 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1712 gtk_action_set_sensitive (action, FALSE);
1713 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1714 /* gtk_action_set_sensitive (action, FALSE); */
1715 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1716 gtk_widget_set_sensitive (widget, FALSE);
1720 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1722 GtkAction *action = NULL;
1723 GtkWidget *widget = NULL;
1724 ModestMainWindowPrivate *priv = NULL;
1726 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1727 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1729 priv->send_receive_in_progress = FALSE;
1731 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1732 gtk_action_set_sensitive (action, TRUE);
1733 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1734 /* gtk_action_set_sensitive (action, TRUE); */
1735 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1736 gtk_widget_set_sensitive (widget, TRUE);
1741 _on_msg_count_changed (ModestHeaderView *header_view,
1743 TnyFolderChange *change,
1744 ModestMainWindow *main_window)
1746 printf ("DEBUG: %s\n", __FUNCTION__);
1747 gboolean folder_empty = FALSE;
1748 TnyFolderChangeChanged changed;
1749 ModestMainWindowPrivate *priv;
1751 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1752 g_return_if_fail (TNY_IS_FOLDER(folder));
1753 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1754 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
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);
1770 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1773 modest_main_window_set_contents_style (main_window,
1774 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1780 modest_main_window_set_contents_style (ModestMainWindow *self,
1781 ModestMainWindowContentsStyle style)
1783 ModestMainWindowPrivate *priv;
1785 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1787 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1789 /* We allow to set the same content style than the previously
1790 set if there are details, because it could happen when we're
1791 selecting different accounts consecutively */
1792 if ((priv->contents_style == style) &&
1793 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1796 /* Remove previous child. Delete it if it was an account
1798 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1800 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1801 g_object_ref (content);
1802 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1803 g_object_ref (priv->empty_view);
1804 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1807 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1810 priv->contents_style = style;
1812 switch (priv->contents_style) {
1813 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1814 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1815 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1818 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1820 TnyFolderStore *selected_folderstore =
1821 modest_folder_view_get_selected (priv->folder_view);
1822 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1823 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1824 TNY_ACCOUNT (selected_folderstore));
1826 wrap_in_scrolled_window (priv->contents_widget,
1827 priv->details_widget);
1829 g_object_unref (selected_folderstore);
1830 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1836 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1837 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1838 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1842 g_return_if_reached ();
1846 gtk_widget_show_all (priv->contents_widget);
1849 ModestMainWindowContentsStyle
1850 modest_main_window_get_contents_style (ModestMainWindow *self)
1852 ModestMainWindowPrivate *priv;
1854 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1856 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1857 return priv->contents_style;
1862 on_configuration_key_changed (ModestConf* conf,
1864 ModestConfEvent event,
1865 ModestMainWindow *self)
1867 ModestMainWindowPrivate *priv;
1868 TnyAccount *account;
1870 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1873 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1875 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1878 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1879 if (TNY_IS_ACCOUNT (account) &&
1880 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1883 const gchar *device_name;
1887 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1888 label = GTK_LABEL (children->data);
1890 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1891 MODEST_CONF_DEVICE_NAME, NULL);
1893 new_text = g_strdup_printf ("%s: %s",
1894 _("mcen_fi_localroot_description"),
1897 gtk_label_set_text (label, new_text);
1898 gtk_widget_show (GTK_WIDGET (label));
1901 g_list_free (children);
1903 g_object_unref (account);
1907 set_toolbar_transfer_mode (ModestMainWindow *self)
1909 ModestMainWindowPrivate *priv = NULL;
1911 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1913 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1915 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1917 if (priv->progress_bar_timeout > 0) {
1918 g_source_remove (priv->progress_bar_timeout);
1919 priv->progress_bar_timeout = 0;
1926 set_toolbar_mode (ModestMainWindow *self,
1927 ModestToolBarModes mode)
1929 ModestWindowPrivate *parent_priv = NULL;
1930 ModestMainWindowPrivate *priv = NULL;
1931 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1933 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1935 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1936 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1938 /* In case this was called before the toolbar exists: */
1939 if (!(parent_priv->toolbar))
1942 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1944 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1945 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1946 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1948 /* Sets current toolbar mode */
1949 priv->current_toolbar_mode = mode;
1951 /* Show and hide toolbar items */
1953 case TOOLBAR_MODE_NORMAL:
1955 gtk_action_set_visible (sort_action, TRUE);
1957 gtk_action_set_visible (refresh_action, TRUE);
1958 if (priv->progress_toolitem) {
1959 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1960 gtk_widget_hide (priv->progress_toolitem);
1962 if (priv->progress_bar)
1963 gtk_widget_hide (priv->progress_bar);
1966 gtk_action_set_visible (cancel_action, FALSE);
1967 /* if (priv->sort_toolitem) */
1968 /* gtk_widget_show (priv->sort_toolitem); */
1970 /* if (priv->refresh_toolitem) */
1971 /* gtk_widget_show (priv->refresh_toolitem); */
1973 /* if (priv->progress_toolitem) */
1974 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1975 /* if (priv->progress_bar) */
1976 /* gtk_widget_hide (priv->progress_bar); */
1978 /* if (priv->cancel_toolitem) */
1979 /* gtk_widget_hide (priv->cancel_toolitem); */
1981 /* Hide toolbar if optimized view is enabled */
1982 if (priv->optimized_view)
1983 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1985 case TOOLBAR_MODE_TRANSFER:
1987 gtk_action_set_visible (sort_action, FALSE);
1989 gtk_action_set_visible (refresh_action, FALSE);
1991 gtk_action_set_visible (cancel_action, TRUE);
1992 if (priv->progress_toolitem) {
1993 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1994 gtk_widget_show (priv->progress_toolitem);
1996 if (priv->progress_bar)
1997 gtk_widget_show (priv->progress_bar);
1999 /* if (priv->sort_toolitem) */
2000 /* gtk_widget_hide (priv->sort_toolitem); */
2002 /* if (priv->refresh_toolitem) */
2003 /* gtk_widget_hide (priv->refresh_toolitem); */
2005 /* if (priv->progress_toolitem) */
2006 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2007 /* if (priv->progress_bar) */
2008 /* gtk_widget_show (priv->progress_bar); */
2010 /* if (priv->cancel_toolitem) */
2011 /* gtk_widget_show (priv->cancel_toolitem); */
2013 /* Show toolbar if it's hiden (optimized view ) */
2014 if (priv->optimized_view)
2015 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2018 g_return_if_reached ();
2023 cancel_progressbar (GtkToolButton *toolbutton,
2024 ModestMainWindow *self)
2027 ModestMainWindowPrivate *priv;
2029 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2031 /* Get operation observers and cancel all the operations */
2032 tmp = priv->progress_widgets;
2034 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2035 tmp=g_slist_next(tmp);
2040 observers_empty (ModestMainWindow *self)
2043 ModestMainWindowPrivate *priv;
2044 gboolean is_empty = TRUE;
2045 guint pending_ops = 0;
2047 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2048 tmp = priv->progress_widgets;
2050 /* Check all observers */
2051 while (tmp && is_empty) {
2052 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2053 is_empty = pending_ops == 0;
2055 tmp = g_slist_next(tmp);
2062 on_queue_changed (ModestMailOperationQueue *queue,
2063 ModestMailOperation *mail_op,
2064 ModestMailOperationQueueNotification type,
2065 ModestMainWindow *self)
2067 ModestMainWindowPrivate *priv;
2068 ModestMailOperationTypeOperation op_type;
2069 ModestToolBarModes mode;
2071 gboolean mode_changed = FALSE;
2072 /* ModestMailOperationStatus status; */
2074 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2075 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2077 /* Get toolbar mode from operation id*/
2078 op_type = modest_mail_operation_get_type_operation (mail_op);
2080 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2081 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2082 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2083 mode = TOOLBAR_MODE_TRANSFER;
2084 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2085 mode_changed = TRUE;
2088 mode = TOOLBAR_MODE_NORMAL;
2093 /* Add operation observers and change toolbar if neccessary*/
2094 tmp = priv->progress_widgets;
2096 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2097 if (mode == TOOLBAR_MODE_TRANSFER) {
2099 set_toolbar_transfer_mode(self);
2101 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2103 tmp = g_slist_next (tmp);
2107 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2108 /* Change toolbar mode */
2109 if (mode == TOOLBAR_MODE_TRANSFER) {
2111 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2113 tmp = g_slist_next (tmp);
2116 /* If no more operations are being observed, NORMAL mode is enabled again */
2117 if (observers_empty (self)) {
2118 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2129 on_show_account_action_activated (GtkAction *action,
2132 ModestAccountData *acc_data;
2133 ModestMainWindow *self;
2134 ModestMainWindowPrivate *priv;
2135 ModestAccountMgr *mgr;
2136 const gchar *acc_name;
2138 self = MODEST_MAIN_WINDOW (user_data);
2139 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2141 /* Get account data */
2142 acc_name = gtk_action_get_name (action);
2143 mgr = modest_runtime_get_account_mgr ();
2144 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2146 /* Set the new visible & active account */
2147 if (acc_data && acc_data->store_account) {
2148 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2149 acc_data->store_account->account_name);
2150 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2153 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2157 modest_account_mgr_free_account_data (mgr, acc_data);
2161 refresh_account (const gchar *account_name)
2165 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2167 /* If account_name == NULL, we must update all (option All) */
2169 modest_ui_actions_do_send_receive_all (win);
2171 modest_ui_actions_do_send_receive (account_name, win);
2176 on_refresh_account_action_activated (GtkAction *action,
2179 refresh_account ((const gchar*) user_data);
2183 on_send_receive_csm_activated (GtkMenuItem *item,
2186 refresh_account ((const gchar*) user_data);
2190 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2192 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2194 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2200 on_folder_view_focus_in (GtkWidget *widget,
2201 GdkEventFocus *event,
2204 ModestMainWindow *main_window = NULL;
2206 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2207 main_window = MODEST_MAIN_WINDOW (userdata);
2209 /* Update toolbar dimming state */
2210 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2216 on_header_view_focus_in (GtkWidget *widget,
2217 GdkEventFocus *event,
2220 ModestMainWindow *main_window = NULL;
2221 ModestMainWindowPrivate *priv = NULL;
2223 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2224 main_window = MODEST_MAIN_WINDOW (userdata);
2225 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2227 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2228 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2229 TnyIterator *iterator = tny_list_create_iterator (selection);
2232 tny_iterator_first (iterator);
2233 header = TNY_HEADER (tny_iterator_get_current (iterator));
2235 if (tny_header_get_subject (header))
2236 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2238 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2241 g_object_unref (header);
2243 g_object_unref (iterator);
2244 g_object_unref (selection);
2248 /* Update toolbar dimming state */
2249 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2255 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2256 TnyFolderStore *folder_store,
2258 ModestMainWindow *main_window)
2260 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2261 GtkAction *action = NULL;
2262 gboolean show_reply = TRUE;
2263 gboolean show_forward = TRUE;
2264 gboolean show_cancel_send = FALSE;
2265 gboolean show_clipboard = TRUE;
2266 gboolean show_delete = TRUE;
2269 if (TNY_IS_ACCOUNT (folder_store)) {
2270 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2271 } else if (TNY_IS_FOLDER (folder_store)) {
2272 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2273 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2274 TNY_FOLDER (folder_store));
2275 switch (folder_type) {
2276 case TNY_FOLDER_TYPE_DRAFTS:
2277 show_clipboard = show_delete = TRUE;
2278 show_reply = show_forward = show_cancel_send = FALSE;
2280 case TNY_FOLDER_TYPE_SENT:
2281 show_forward = show_clipboard = show_delete = TRUE;
2282 show_reply = show_cancel_send = FALSE;
2284 case TNY_FOLDER_TYPE_OUTBOX:
2285 show_clipboard = show_delete = show_cancel_send = TRUE;
2286 show_reply = show_forward = FALSE;
2289 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2290 show_cancel_send = FALSE;
2293 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2294 show_cancel_send = FALSE;
2299 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2300 gtk_action_set_visible (action, show_reply);
2301 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2302 gtk_action_set_visible (action, show_reply);
2303 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2304 gtk_action_set_visible (action, show_forward);
2305 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2306 gtk_action_set_visible (action, show_cancel_send);
2307 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2308 gtk_action_set_visible (action, show_clipboard);
2309 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2310 gtk_action_set_visible (action, show_clipboard);
2311 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2312 gtk_action_set_visible (action, show_clipboard);
2313 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2314 gtk_action_set_visible (action, show_delete);
2316 /* We finally call to the ui actions handler, after updating properly
2317 * the header view CSM */
2318 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2323 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2324 GtkTreeModel *model,
2325 GtkTreeRowReference *row_reference,
2326 ModestMainWindow *self)
2328 ModestMainWindowPrivate *priv = NULL;
2329 GtkTreeModel *header_model = NULL;
2330 GtkTreePath *path = NULL;
2332 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2333 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2334 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2336 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2337 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2339 /* Do nothing if we changed the folder in the main view */
2340 if (header_model != model)
2343 /* Select the message in the header view */
2344 path = gtk_tree_row_reference_get_path (row_reference);
2345 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2347 gtk_tree_path_free (path);