1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar-widget.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "maemo/modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-program.h>
70 #include <hildon/hildon-program.h>
71 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
73 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
80 /* 'private'/'protected' functions */
81 static void modest_main_window_class_init (ModestMainWindowClass *klass);
82 static void modest_main_window_init (ModestMainWindow *obj);
83 static void modest_main_window_finalize (GObject *obj);
84 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
85 GdkEventWindowState *event,
88 static void connect_signals (ModestMainWindow *self);
90 static void restore_settings (ModestMainWindow *self, gboolean do_folder_view_too);
91 static void save_state (ModestWindow *self);
93 static void modest_main_window_show_toolbar (ModestWindow *window,
94 gboolean show_toolbar);
96 static void cancel_progressbar (GtkToolButton *toolbutton,
97 ModestMainWindow *self);
99 static void on_queue_changed (ModestMailOperationQueue *queue,
100 ModestMailOperation *mail_op,
101 ModestMailOperationQueueNotification type,
102 ModestMainWindow *self);
104 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
106 static void on_account_update (TnyAccountStore *account_store,
107 const gchar *account_name,
110 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
114 static void on_configuration_key_changed (ModestConf* conf,
116 ModestConfEvent event,
117 ModestMainWindow *self);
119 static void set_toolbar_mode (ModestMainWindow *self,
120 ModestToolBarModes mode);
122 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
124 static void on_show_account_action_activated (GtkAction *action,
127 static void on_refresh_account_action_activated (GtkAction *action,
130 static void on_send_receive_csm_activated (GtkMenuItem *item,
134 _on_msg_count_changed (ModestHeaderView *header_view,
136 TnyFolderChange *change,
137 ModestMainWindow *main_window);
140 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
143 static GtkWidget * create_empty_view (void);
146 on_folder_view_focus_in (GtkWidget *widget,
147 GdkEventFocus *event,
150 on_header_view_focus_in (GtkWidget *widget,
151 GdkEventFocus *event,
154 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
155 TnyFolderStore *folder_store,
157 ModestMainWindow *main_window);
159 /* list my signals */
166 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
167 struct _ModestMainWindowPrivate {
168 GtkWidget *msg_paned;
169 GtkWidget *main_paned;
170 GtkWidget *main_vbox;
171 GtkWidget *contents_widget;
172 GtkWidget *empty_view;
174 /* Progress observers */
175 GtkWidget *progress_bar;
176 GSList *progress_widgets;
179 GtkWidget *progress_toolitem;
180 GtkWidget *cancel_toolitem;
181 GtkWidget *sort_toolitem;
182 GtkWidget *refresh_toolitem;
183 ModestToolBarModes current_toolbar_mode;
185 /* Merge ids used to add/remove accounts to the ViewMenu*/
186 GByteArray *merge_ids;
188 /* On-demand widgets */
189 GtkWidget *accounts_popup;
190 GtkWidget *details_widget;
192 /* Optimized view enabled */
193 gboolean optimized_view;
195 /* Optimized view enabled */
196 gboolean send_receive_in_progress;
198 ModestHeaderView *header_view;
199 ModestFolderView *folder_view;
201 ModestMainWindowStyle style;
202 ModestMainWindowContentsStyle contents_style;
204 guint progress_bar_timeout;
206 /* Signal handler UIDs */
207 gint queue_changed_handler_uid;
208 GList *queue_err_signals;
210 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
211 MODEST_TYPE_MAIN_WINDOW, \
212 ModestMainWindowPrivate))
214 typedef struct _GetMsgAsyncHelper {
215 ModestMainWindowPrivate *main_window_private;
217 ModestTnyMsgReplyType reply_type;
218 ModestTnyMsgForwardType forward_type;
225 static GtkWindowClass *parent_class = NULL;
228 /* Private actions */
229 /* This is the context sensitive menu: */
230 static const GtkActionEntry modest_folder_view_action_entries [] = {
232 /* Folder View CSM actions */
233 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
234 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
235 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
236 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
237 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
238 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
241 static const GtkActionEntry modest_header_view_action_entries [] = {
243 /* Header View CSM actions */
244 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
245 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
246 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
247 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
248 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
249 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
250 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
251 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
252 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
253 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
256 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
257 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
260 /************************************************************************/
263 modest_main_window_get_type (void)
265 static GType my_type = 0;
267 static const GTypeInfo my_info = {
268 sizeof(ModestMainWindowClass),
269 NULL, /* base init */
270 NULL, /* base finalize */
271 (GClassInitFunc) modest_main_window_class_init,
272 NULL, /* class finalize */
273 NULL, /* class data */
274 sizeof(ModestMainWindow),
276 (GInstanceInitFunc) modest_main_window_init,
279 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
287 modest_main_window_class_init (ModestMainWindowClass *klass)
289 GObjectClass *gobject_class;
290 gobject_class = (GObjectClass*) klass;
291 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
293 parent_class = g_type_class_peek_parent (klass);
294 gobject_class->finalize = modest_main_window_finalize;
296 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
298 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
299 modest_window_class->save_state_func = save_state;
300 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
301 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
305 modest_main_window_init (ModestMainWindow *obj)
307 ModestMainWindowPrivate *priv;
309 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
311 priv->queue_err_signals = NULL;
312 priv->msg_paned = NULL;
313 priv->main_paned = NULL;
314 priv->main_vbox = NULL;
315 priv->header_view = NULL;
316 priv->folder_view = NULL;
317 priv->contents_widget = NULL;
318 priv->accounts_popup = NULL;
319 priv->details_widget = NULL;
320 priv->empty_view = NULL;
321 priv->progress_widgets = NULL;
322 priv->progress_bar = NULL;
323 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
324 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
325 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
326 priv->merge_ids = NULL;
327 priv->optimized_view = FALSE;
328 priv->send_receive_in_progress = FALSE;
329 priv->progress_bar_timeout = 0;
330 priv->queue_changed_handler_uid = 0;
334 modest_main_window_finalize (GObject *obj)
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
340 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
342 g_slist_free (priv->progress_widgets);
344 g_byte_array_free (priv->merge_ids, TRUE);
346 if (priv->progress_bar_timeout > 0) {
347 g_source_remove (priv->progress_bar_timeout);
348 priv->progress_bar_timeout = 0;
351 /* Disconnect signal handlers */
352 if (priv->queue_changed_handler_uid)
353 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
354 priv->queue_changed_handler_uid);
356 G_OBJECT_CLASS(parent_class)->finalize (obj);
360 modest_main_window_get_child_widget (ModestMainWindow *self,
361 ModestWidgetType widget_type)
363 ModestMainWindowPrivate *priv;
366 g_return_val_if_fail (self, NULL);
367 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
370 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
372 switch (widget_type) {
373 case MODEST_WIDGET_TYPE_HEADER_VIEW:
374 widget = (GtkWidget*)priv->header_view; break;
375 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
376 widget = (GtkWidget*)priv->folder_view; break;
381 return widget ? GTK_WIDGET(widget) : NULL;
386 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
388 printf ("DEBUGDEBUG: %s\n", __FUNCTION__);
391 ModestMainWindowPrivate *priv;
393 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
395 conf = modest_runtime_get_conf ();
397 modest_widget_memory_restore (conf, G_OBJECT(self),
398 MODEST_CONF_MAIN_WINDOW_KEY);
400 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
401 MODEST_CONF_HEADER_VIEW_KEY);
403 if (do_folder_view_too)
404 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
405 MODEST_CONF_FOLDER_VIEW_KEY);
407 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
408 MODEST_CONF_MAIN_PANED_KEY);
410 /* We need to force a redraw here in order to get the right
411 position of the horizontal paned separator */
412 gtk_widget_show (GTK_WIDGET (self));
417 save_state (ModestWindow *window)
420 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
421 ModestMainWindowPrivate *priv;
423 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
424 conf = modest_runtime_get_conf ();
426 modest_widget_memory_save (conf,G_OBJECT(self),
427 MODEST_CONF_MAIN_WINDOW_KEY);
428 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
429 MODEST_CONF_MAIN_PANED_KEY);
430 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
431 // MODEST_CONF_HEADER_VIEW_KEY);
432 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
433 MODEST_CONF_FOLDER_VIEW_KEY);
437 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
439 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
440 gtk_scrolled_window_add_with_viewport
441 (GTK_SCROLLED_WINDOW(win), widget);
443 gtk_container_add (GTK_CONTAINER(win),
448 /* static gboolean */
449 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
451 /* modest_window_save_state (MODEST_WINDOW(self)); */
456 on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data)
459 printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message);
461 if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL)
462 /* Don't show waste the user's time by showing him a dialog telling him
463 * that he has just cancelled something: */
467 /* Get the server name: */
468 const gchar* server_name = NULL;
470 TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account (
471 TNY_CAMEL_SEND_QUEUE (self));
472 if (server_account) {
473 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
475 g_object_unref (server_account);
476 server_account = NULL;
480 server_name = _("Unknown Server");
482 /* Show the appropriate message text for the GError: */
483 gchar *message = NULL;
486 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
487 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
489 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
490 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
492 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
493 /* TODO: This logical ID seems more suitable for a wrong username or password than for a
494 * wrong authentication method. The user is unlikely to guess at the real cause.
496 message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name);
498 case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
499 /* TODO: Tinymail is still sending this sometimes when it should
500 * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. */
502 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
506 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
509 modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message);
512 /* TODO: Offer to remove the message, to avoid messages in future? */
514 TnyFolder *outbox = tny_send_queue_get_outbox (queue);
515 tny_folder_remove_msg (outbox, header, NULL);
516 tny_folder_sync (outbox, TRUE, NULL);
517 g_object_unref (outbox);
527 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
529 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
531 GList *oerrsignals = priv->queue_err_signals;
532 while (oerrsignals) {
533 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
534 g_signal_handler_disconnect (esignal->queue, esignal->signal);
535 g_slice_free (QueueErrorSignal, esignal);
536 oerrsignals = g_list_next (oerrsignals);
538 g_list_free (priv->queue_err_signals);
539 priv->queue_err_signals = NULL;
543 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
545 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
547 /* When going online, do the equivalent of pressing the send/receive button,
548 * as per the specification:
549 * (without the check for >0 accounts, though that is not specified): */
551 TnyDevice *device = tny_account_store_get_device (store);
553 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
555 /* Check that we are really online.
556 * This signal should not be emitted when we are not connected,
557 * but it seems to happen sometimes: */
558 if (!tny_device_is_online (device))
561 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
562 printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
564 /* Stop the existing send queues: */
565 modest_runtime_remove_all_send_queues ();
567 /* Create the send queues again, using the appropriate transport accounts
568 * for this new connection.
569 * This could be the first time that they are created if this is the first
571 /* TODO: Does this really destroy the TnySendQueues and their threads
572 * We do not want 2 TnySendQueues to exist with the same underlying
573 * outbox directory. */
575 modest_main_window_cleanup_queue_error_signals (self);
577 GSList *account_names = modest_account_mgr_account_names (
578 modest_runtime_get_account_mgr(),
579 TRUE /* enabled accounts only */);
580 GSList *iter = account_names;
582 const gchar *account_name = (const gchar*)(iter->data);
584 TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
585 modest_tny_account_store_get_transport_account_for_open_connection
586 (modest_runtime_get_account_store(), account_name));
588 /* Q: Is this the first location where the send-queues are requested? */
589 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
590 printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name,
591 tny_account_get_id(TNY_ACCOUNT(account)));
592 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
593 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
594 G_CALLBACK (on_sendqueue_error_happened), self);
595 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
599 iter = g_slist_next (iter);
602 modest_account_mgr_free_account_names (account_names);
603 account_names = NULL;
605 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
609 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
611 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
614 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
618 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
620 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
622 /* Update visibility */
625 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
629 connect_signals (ModestMainWindow *self)
631 ModestWindowPrivate *parent_priv;
632 ModestMainWindowPrivate *priv;
635 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
636 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
639 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
640 G_CALLBACK(on_inner_widgets_key_pressed), self);
641 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
642 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
643 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
644 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
645 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
646 G_CALLBACK (on_folder_view_focus_in), self);
648 /* Folder view CSM */
649 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
650 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
651 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
652 G_CALLBACK(_folder_view_csm_menu_activated),
655 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
656 G_CALLBACK(modest_ui_actions_on_header_selected), self);
657 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
658 G_CALLBACK(modest_ui_actions_on_header_activated), self);
659 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
660 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
661 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
662 G_CALLBACK(on_inner_widgets_key_pressed), self);
663 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
664 G_CALLBACK(_on_msg_count_changed), self);
665 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
666 G_CALLBACK (on_header_view_focus_in), self);
668 /* Header view CSM */
669 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
670 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
671 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
672 G_CALLBACK(_header_view_csm_menu_activated),
676 /* g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */
677 g_signal_connect (G_OBJECT (self), "window-state-event",
678 G_CALLBACK (modest_main_window_window_state_event),
681 /* Mail Operation Queue */
682 priv->queue_changed_handler_uid =
683 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
684 "queue-changed", G_CALLBACK (on_queue_changed), self);
686 /* Track changes in the device name */
687 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
688 "key_changed", G_CALLBACK (on_configuration_key_changed),
691 /* Track account changes. We need to refresh the toolbar */
692 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
693 "account_update", G_CALLBACK (on_account_update),
697 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
698 "password_requested",
699 G_CALLBACK (modest_ui_actions_on_password_requested), self);
702 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()),
703 "connecting-finished",
704 G_CALLBACK(on_account_store_connecting_finished), self);
708 /** Idle handler, to send/receive at startup .*/
710 sync_accounts_cb (ModestMainWindow *win)
712 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
713 return FALSE; /* Do not call this idle handler again. */
717 static void on_hildon_program_is_topmost_notify(GObject *self,
718 GParamSpec *propert_param, gpointer user_data)
720 HildonProgram *app = HILDON_PROGRAM (self);
723 ModestWindow* self = MODEST_WINDOW(user_data);
726 /* Note that use of hildon_program_set_can_hibernate()
727 * is generally referred to as "setting the killable flag",
728 * though hibernation does not seem equal to death.
731 if (hildon_program_get_is_topmost (app)) {
732 /* Prevent hibernation when the progam comes to the foreground,
733 * because hibernation should only happen when the application
734 * is in the background: */
735 hildon_program_set_can_hibernate (app, FALSE);
737 /* Allow hibernation if the program has gone to the background: */
739 /* However, prevent hibernation while the settings are being changed: */
740 const gboolean hibernation_prevented =
741 modest_window_mgr_get_hibernation_is_prevented (
742 modest_runtime_get_window_mgr ());
744 if (hibernation_prevented)
745 hildon_program_set_can_hibernate (app, FALSE);
747 /* Allow hibernation, after saving the state: */
748 modest_osso_save_state();
749 hildon_program_set_can_hibernate (app, TRUE);
756 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
758 GtkWidget *folder_win = (GtkWidget *) user_data;
759 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
761 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
762 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
763 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
765 gtk_widget_show (GTK_WIDGET (priv->folder_view));
767 /* Connect signals */
768 connect_signals ((ModestMainWindow*)self);
770 /* Set account store */
771 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
772 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
774 /* Load previous osso state, for instance if we are being restored from
776 modest_osso_load_state ();
778 /* Restore window & widget settings */
780 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
782 /* Check if accounts exist and show the account wizard if not */
783 gboolean accounts_exist =
784 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
786 if (!accounts_exist) {
787 /* This is necessary to have the main window shown behind the dialog
788 It's an ugly hack... jschmid */
789 gtk_widget_show_all(GTK_WIDGET(self));
790 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
793 GtkAction *send_receive_all;
794 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
795 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
796 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
797 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
798 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
799 modest_account_mgr_free_account_names (accounts);
806 modest_main_window_new (void)
808 ModestMainWindow *self = NULL;
809 ModestMainWindowPrivate *priv = NULL;
810 ModestWindowPrivate *parent_priv = NULL;
811 GtkWidget *folder_win = NULL;
812 ModestDimmingRulesGroup *menu_rules_group = NULL;
813 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
814 GtkActionGroup *action_group = NULL;
815 GError *error = NULL;
816 ModestConf *conf = NULL;
817 GtkAction *action = NULL;
818 GdkPixbuf *window_icon;
820 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
821 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
822 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
824 parent_priv->ui_manager = gtk_ui_manager_new();
825 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
827 action_group = gtk_action_group_new ("ModestMainWindowActions");
828 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
830 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
831 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
833 /* Add common actions */
834 gtk_action_group_add_actions (action_group,
835 modest_action_entries,
836 G_N_ELEMENTS (modest_action_entries),
839 gtk_action_group_add_actions (action_group,
840 modest_folder_view_action_entries,
841 G_N_ELEMENTS (modest_folder_view_action_entries),
844 gtk_action_group_add_actions (action_group,
845 modest_header_view_action_entries,
846 G_N_ELEMENTS (modest_header_view_action_entries),
849 gtk_action_group_add_toggle_actions (action_group,
850 modest_toggle_action_entries,
851 G_N_ELEMENTS (modest_toggle_action_entries),
854 gtk_action_group_add_toggle_actions (action_group,
855 modest_main_window_toggle_action_entries,
856 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
859 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
860 g_object_unref (action_group);
862 /* Load the UI definition */
863 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
864 MODEST_UIDIR "modest-main-window-ui.xml", &error);
866 g_warning ("Could not merge modest-ui.xml: %s", error->message);
867 g_error_free (error);
871 /* Add common dimming rules */
872 modest_dimming_rules_group_add_rules (menu_rules_group,
873 modest_main_window_menu_dimming_entries,
874 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
876 modest_dimming_rules_group_add_rules (toolbar_rules_group,
877 modest_main_window_toolbar_dimming_entries,
878 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
881 /* Insert dimming rules group for this window */
882 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
883 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
884 g_object_unref (menu_rules_group);
885 g_object_unref (toolbar_rules_group);
887 /* Add accelerators */
888 gtk_window_add_accel_group (GTK_WINDOW (self),
889 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
891 /* Menubar. Update the state of some toggles */
892 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
893 conf = modest_runtime_get_conf ();
894 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
895 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
896 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
897 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
898 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
899 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
900 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
901 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
902 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
903 gtk_widget_show (parent_priv->menubar);
905 /* Get device name */
906 modest_maemo_utils_get_device_name ();
910 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
911 if (!priv->header_view)
912 g_printerr ("modest: cannot instantiate header view\n");
913 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
914 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
915 MODEST_CONF_HEADER_VIEW_KEY);
917 /* Other style properties of header view */
918 g_object_set (G_OBJECT (priv->header_view),
921 /* gtk_widget_show (priv->header_view); */
924 priv->empty_view = create_empty_view ();
925 gtk_widget_show (priv->empty_view);
927 /* Create scrolled windows */
928 folder_win = gtk_scrolled_window_new (NULL, NULL);
929 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
930 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
932 GTK_POLICY_AUTOMATIC);
933 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
935 GTK_POLICY_AUTOMATIC);
936 /* gtk_widget_show (priv->contents_widget); */
939 priv->main_paned = gtk_hpaned_new ();
940 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
941 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
942 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
944 /* putting it all together... */
945 priv->main_vbox = gtk_vbox_new (FALSE, 6);
946 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
947 gtk_widget_show (priv->main_vbox);
949 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
951 HildonProgram *app = hildon_program_get_instance ();
952 hildon_program_add_window (app, HILDON_WINDOW (self));
954 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
955 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
957 g_signal_connect (G_OBJECT(self), "show",
958 G_CALLBACK (modest_main_window_on_show), folder_win);
960 /* Set window icon */
961 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
963 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
964 g_object_unref (window_icon);
967 /* Dont't restore settings here,
968 * because it requires a gtk_widget_show(),
969 * and we don't want to do that until later,
970 * so that the UI is not visible for non-menu D-Bus activation.
972 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
974 return MODEST_WINDOW(self);
978 modest_main_window_close_all (ModestMainWindow *self)
981 GtkResponseType response;
983 /* Create the confirmation dialog MSG-NOT308 */
984 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
985 _("emev_nc_close_windows"),
986 _("mcen_bd_yes"), GTK_RESPONSE_YES,
987 _("mcen_bd_no"), GTK_RESPONSE_NO,
990 response = gtk_dialog_run (GTK_DIALOG (note));
991 gtk_widget_destroy (GTK_WIDGET (note));
993 if (response == GTK_RESPONSE_YES)
1001 modest_main_window_set_style (ModestMainWindow *self,
1002 ModestMainWindowStyle style)
1004 ModestMainWindowPrivate *priv;
1005 ModestWindowPrivate *parent_priv;
1009 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1011 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1012 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1014 /* no change -> nothing to do */
1015 if (priv->style == style)
1018 /* Get toggle button and update the state if needed. This will
1019 happen only when the set_style is not invoked from the UI,
1020 for example when it's called from widget memory */
1021 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1022 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1023 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1024 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1025 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1026 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1027 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1030 priv->style = style;
1032 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1033 /* Remove main paned */
1034 g_object_ref (priv->main_paned);
1035 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1037 /* Reparent the contents widget to the main vbox */
1038 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1040 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1041 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1042 TnyIterator *iterator = tny_list_create_iterator (selection);
1044 tny_iterator_first (iterator);
1045 header = TNY_HEADER (tny_iterator_get_current (iterator));
1046 if (tny_header_get_subject (header))
1047 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1049 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1052 g_object_unref (header);
1054 g_object_unref (iterator);
1055 g_object_unref (selection);
1059 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1060 /* Remove header view */
1061 g_object_ref (priv->contents_widget);
1062 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1064 /* Reparent the main paned */
1065 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1066 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1070 g_return_if_reached ();
1073 /* Let header view grab the focus if it's being shown */
1074 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1075 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1077 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1080 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1083 ModestMainWindowStyle
1084 modest_main_window_get_style (ModestMainWindow *self)
1086 ModestMainWindowPrivate *priv;
1088 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1090 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1097 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1099 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1100 ModestWindowPrivate *parent_priv;
1101 ModestWindowMgr *mgr;
1102 gboolean is_fullscreen;
1103 GtkAction *fs_toggle_action;
1106 mgr = modest_runtime_get_window_mgr ();
1108 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1110 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1112 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1113 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1114 if (is_fullscreen != active) {
1115 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1124 set_homogeneous (GtkWidget *widget,
1127 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1128 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1132 modest_main_window_show_toolbar (ModestWindow *self,
1133 gboolean show_toolbar)
1135 ModestMainWindowPrivate *priv = NULL;
1136 ModestWindowPrivate *parent_priv = NULL;
1137 GtkWidget *reply_button = NULL, *menu = NULL;
1138 GtkWidget *placeholder = NULL;
1141 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1142 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1143 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1145 /* Set optimized view status */
1146 priv->optimized_view = !show_toolbar;
1148 if (!parent_priv->toolbar) {
1149 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1152 /* Set homogeneous toolbar */
1153 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1154 set_homogeneous, NULL);
1156 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1157 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1158 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1159 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1160 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1161 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1162 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1163 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1165 /* Add ProgressBar (Transfer toolbar) */
1166 priv->progress_bar = modest_progress_bar_widget_new ();
1167 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1168 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1169 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1170 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1171 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1173 /* Connect cancel 'clicked' signal to abort progress mode */
1174 g_signal_connect(priv->cancel_toolitem, "clicked",
1175 G_CALLBACK(cancel_progressbar),
1178 /* Add it to the observers list */
1179 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1182 hildon_window_add_toolbar (HILDON_WINDOW (self),
1183 GTK_TOOLBAR (parent_priv->toolbar));
1185 /* Set reply button tap and hold menu */
1186 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1187 "/ToolBar/ToolbarMessageReply");
1188 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1189 "/ToolbarReplyCSM");
1190 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1192 /* Set send & receive button tap and hold menu */
1193 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1198 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1199 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1200 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1202 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1203 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1205 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1210 compare_display_names (ModestAccountData *a,
1211 ModestAccountData *b)
1213 return strcmp (a->display_name, b->display_name);
1217 on_account_update (TnyAccountStore *account_store,
1218 const gchar *account_name,
1221 GSList *account_names, *iter, *accounts;
1222 ModestMainWindow *self;
1223 ModestMainWindowPrivate *priv;
1224 ModestWindowPrivate *parent_priv;
1225 ModestAccountMgr *mgr;
1226 gint i, num_accounts;
1227 GtkActionGroup *action_group;
1229 gchar *default_account;
1230 GtkWidget *send_receive_button, *item;
1231 GtkAction *send_receive_all = NULL;
1233 self = MODEST_MAIN_WINDOW (user_data);
1234 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1235 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1237 /* Get enabled account IDs */
1238 mgr = modest_runtime_get_account_mgr ();
1239 account_names = modest_account_mgr_account_names (mgr, TRUE);
1240 iter = account_names;
1244 ModestAccountData *account_data =
1245 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1246 accounts = g_slist_prepend (accounts, account_data);
1250 modest_account_mgr_free_account_names (account_names);
1251 account_names = NULL;
1253 /* Order the list of accounts by its display name */
1254 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1255 num_accounts = g_slist_length (accounts);
1257 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1258 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1259 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1261 /* Delete old send&receive popup items. We can not just do a
1262 menu_detach because it does not work well with
1264 if (priv->accounts_popup)
1265 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1266 (GtkCallback) gtk_widget_destroy, NULL);
1268 /* Delete old entries in the View menu. Do not free groups, it
1270 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1272 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1273 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1274 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1275 GTK_ACTION_GROUP (groups->data));
1278 if (priv->merge_ids) {
1279 for (i = 0; i < priv->merge_ids->len; i++)
1280 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1281 g_byte_array_free (priv->merge_ids, TRUE);
1283 /* We need to call this in order to ensure
1284 that the new actions are added in the right
1285 order (alphabetical */
1286 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1288 groups = g_list_next (groups);
1290 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1292 /* Get send receive button */
1293 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1294 "/ToolBar/ToolbarSendReceive");
1296 /* Create the menu */
1297 if (num_accounts > 1) {
1298 if (!priv->accounts_popup)
1299 priv->accounts_popup = gtk_menu_new ();
1300 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1301 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1302 g_signal_connect (G_OBJECT (item),
1304 G_CALLBACK (on_send_receive_csm_activated),
1306 item = gtk_separator_menu_item_new ();
1307 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1310 /* Create a new action group */
1311 default_account = modest_account_mgr_get_default_account (mgr);
1312 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1313 for (i = 0; i < num_accounts; i++) {
1314 gchar *display_name = NULL;
1316 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1318 /* Create display name. The UI specification specifies a different format string
1319 * to use for the default account, though both seem to be "%s", so
1320 * I don't see what the point is. murrayc. */
1321 if (default_account && account_data->account_name &&
1322 !(strcmp (default_account, account_data->account_name) == 0)) {
1323 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1324 account_data->display_name);
1327 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1328 account_data->display_name);
1331 /* Create action and add it to the action group. The
1332 action name must be the account name, this way we
1333 could know in the handlers the account to show */
1334 if(account_data->account_name) {
1335 gchar* item_name, *refresh_action_name;
1337 GtkAction *view_account_action, *refresh_account_action;
1339 view_account_action = gtk_action_new (account_data->account_name,
1340 display_name, NULL, NULL);
1341 gtk_action_group_add_action (action_group, view_account_action);
1343 /* Add ui from account data. We allow 2^9-1 account
1344 changes in a single execution because we're
1345 downcasting the guint to a guint8 in order to use a
1346 GByteArray. It should be enough. */
1347 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1348 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1349 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1350 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1352 "/MenuBar/ViewMenu/ViewMenuAdditions",
1354 account_data->account_name,
1355 GTK_UI_MANAGER_MENUITEM,
1358 /* Connect the action signal "activate" */
1359 g_signal_connect (G_OBJECT (view_account_action),
1361 G_CALLBACK (on_show_account_action_activated),
1364 /* Create the items for the Tools->Send&Receive submenu */
1365 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1366 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1367 display_name, NULL, NULL);
1368 gtk_action_group_add_action (action_group, refresh_account_action);
1370 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1371 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1372 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1374 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1376 refresh_action_name,
1377 GTK_UI_MANAGER_MENUITEM,
1379 g_free (refresh_action_name);
1381 g_signal_connect_data (G_OBJECT (refresh_account_action),
1383 G_CALLBACK (on_refresh_account_action_activated),
1384 g_strdup (account_data->account_name),
1385 (GClosureNotify) g_free,
1388 /* Create item and add it to the send&receive
1389 CSM. If there is only one account then
1391 if (priv->accounts_popup) {
1392 GtkWidget *label = gtk_label_new(NULL);
1393 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1394 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1396 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1397 gtk_label_set_markup (GTK_LABEL (label), escaped);
1402 gtk_label_set_text (GTK_LABEL (label), display_name);
1405 item = gtk_menu_item_new ();
1406 gtk_container_add (GTK_CONTAINER (item), label);
1408 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1409 g_signal_connect_data (G_OBJECT (item),
1411 G_CALLBACK (on_send_receive_csm_activated),
1412 g_strdup (account_data->account_name),
1413 (GClosureNotify) g_free,
1420 g_free (display_name);
1423 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1425 /* We cannot do this in the loop above because this relies on the action
1426 * group being inserted. This makes the default account appear in bold.
1427 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1428 for (i = 0; i < num_accounts; i++) {
1429 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1431 if(account_data->account_name &&
1432 strcmp (account_data->account_name, default_account) == 0) {
1433 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1435 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1436 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1440 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1441 if (GTK_IS_LABEL (child)) {
1442 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1443 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1444 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1449 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1450 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1454 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1455 if (GTK_IS_LABEL (child)) {
1456 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1457 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1458 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1466 modest_account_mgr_free_account_data (mgr, account_data);
1469 if (priv->accounts_popup) {
1470 /* Mandatory in order to view the menu contents */
1471 gtk_widget_show_all (priv->accounts_popup);
1473 /* Setup tap_and_hold just if was not done before*/
1474 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1475 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1479 g_slist_free (accounts);
1480 g_free (default_account);
1484 * This function manages the key events used to navigate between
1485 * header and folder views (when the window is in split view)
1488 * -------------------------------------------------
1489 * HeaderView GDK_Left Move focus to folder view
1490 * FolderView GDK_Right Move focus to header view
1492 * There is no need to scroll to selected row, the widgets will be the
1493 * responsibles of doing that (probably managing the focus-in event
1496 on_inner_widgets_key_pressed (GtkWidget *widget,
1500 ModestMainWindowPrivate *priv;
1502 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1504 /* Do nothing if we're in SIMPLE style */
1505 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1508 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1509 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1510 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1511 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1517 set_alignment (GtkWidget *widget,
1520 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1521 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1525 create_empty_view (void)
1527 GtkLabel *label = NULL;
1528 GtkWidget *align = NULL;
1530 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1531 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1532 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1533 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1535 return GTK_WIDGET(align);
1539 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1541 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1546 gchar *gray_color_markup;
1548 vbox = gtk_vbox_new (FALSE, 0);
1550 /* Obtain the secondary text color. We need a realized widget, that's why
1551 we get styled_widget from outside */
1552 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1554 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1555 gray_color_markup = modest_text_utils_get_color_string (&color);
1557 // gray_color_markup is freed below
1558 gray_color_markup = g_strdup ("#BBBBBB");
1560 /* Account description: */
1562 if (modest_tny_account_is_virtual_local_folders (account)
1563 || (modest_tny_account_is_memory_card_account (account))) {
1565 /* Local folders: */
1567 /* Get device name */
1568 gchar *device_name = NULL;
1569 if (modest_tny_account_is_virtual_local_folders (account))
1570 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1571 MODEST_CONF_DEVICE_NAME, NULL);
1573 device_name = g_strdup (tny_account_get_name (account));
1575 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1576 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1577 gray_color_markup, tmp, device_name);
1579 label_w = gtk_label_new (NULL);
1580 gtk_label_set_markup (GTK_LABEL (label_w), label);
1581 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1582 g_free (device_name);
1585 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1586 gtk_box_pack_start (GTK_BOX (vbox),
1587 gtk_label_new (tny_account_get_name (account)),
1590 /* Other accounts, such as IMAP and POP: */
1595 /* Put proto in uppercase */
1596 proto = g_string_new (tny_account_get_proto (account));
1597 proto = g_string_ascii_up (proto);
1599 /* note: mcen_fi_localroot_description is something like "%s account"
1600 * however, we should display "%s account: %s"... therefore, ugly tmp */
1601 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1602 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1603 gray_color_markup, tmp, tny_account_get_name (account));
1606 label_w = gtk_label_new (NULL);
1607 gtk_label_set_markup (GTK_LABEL (label_w), label);
1608 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1609 g_string_free (proto, TRUE);
1615 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1616 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1617 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1618 modest_tny_folder_store_get_message_count (folder_store));
1619 label_w = gtk_label_new (NULL);
1620 gtk_label_set_markup (GTK_LABEL (label_w), label);
1621 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1625 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1627 _("mcen_fi_rootfolder_folders"),
1628 modest_tny_folder_store_get_folder_count (folder_store));
1629 label_w = gtk_label_new (NULL);
1630 gtk_label_set_markup (GTK_LABEL (label_w), label);
1631 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1635 if (modest_tny_account_is_virtual_local_folders (account)
1636 || modest_tny_account_is_memory_card_account (account)) {
1638 gchar *size = modest_text_utils_get_display_size (
1639 modest_tny_folder_store_get_local_size (folder_store));
1641 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1642 gray_color_markup, _("mcen_fi_rootfolder_size"),
1646 label_w = gtk_label_new (NULL);
1647 gtk_label_set_markup (GTK_LABEL (label_w), label);
1648 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1650 } else if (TNY_IS_ACCOUNT(folder_store)) {
1651 TnyAccount *account = TNY_ACCOUNT(folder_store);
1653 time_t last_updated;
1654 gchar *last_updated_string;
1655 /* Get last updated from configuration */
1656 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1657 tny_account_get_id (account),
1658 MODEST_ACCOUNT_LAST_UPDATED,
1660 if (last_updated > 0)
1661 last_updated_string = modest_text_utils_get_display_date(last_updated);
1663 last_updated_string = g_strdup (_("mcen_va_never"));
1665 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1666 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1667 label_w = gtk_label_new (NULL);
1668 gtk_label_set_markup (GTK_LABEL (label_w), label);
1669 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1670 g_free (last_updated_string);
1674 g_free (gray_color_markup);
1677 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1683 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1685 ModestMainWindowPrivate *priv = NULL;
1687 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1689 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1691 return priv->send_receive_in_progress;
1695 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1697 GtkAction *action = NULL;
1698 GtkWidget *widget = NULL;
1699 ModestMainWindowPrivate *priv = NULL;
1701 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1702 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1704 priv->send_receive_in_progress = TRUE;
1706 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1707 gtk_action_set_sensitive (action, FALSE);
1708 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1709 /* gtk_action_set_sensitive (action, FALSE); */
1710 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1711 gtk_widget_set_sensitive (widget, FALSE);
1715 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1717 GtkAction *action = NULL;
1718 GtkWidget *widget = NULL;
1719 ModestMainWindowPrivate *priv = NULL;
1721 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1722 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1724 priv->send_receive_in_progress = FALSE;
1726 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1727 gtk_action_set_sensitive (action, TRUE);
1728 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1729 /* gtk_action_set_sensitive (action, TRUE); */
1730 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1731 gtk_widget_set_sensitive (widget, TRUE);
1736 _on_msg_count_changed (ModestHeaderView *header_view,
1738 TnyFolderChange *change,
1739 ModestMainWindow *main_window)
1741 printf ("DEBUG: %s\n", __FUNCTION__);
1742 gboolean folder_empty = FALSE;
1743 TnyFolderChangeChanged changed;
1745 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1746 g_return_if_fail (TNY_IS_FOLDER(folder));
1747 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1749 changed = tny_folder_change_get_changed (change);
1751 /* If something changes */
1752 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1753 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1755 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1757 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1759 /* Set contents style of headers view */
1761 modest_main_window_set_contents_style (main_window,
1762 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1765 modest_main_window_set_contents_style (main_window,
1766 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1772 modest_main_window_set_contents_style (ModestMainWindow *self,
1773 ModestMainWindowContentsStyle style)
1775 ModestMainWindowPrivate *priv;
1777 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1779 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1781 /* We allow to set the same content style than the previously
1782 set if there are details, because it could happen when we're
1783 selecting different accounts consecutively */
1784 if ((priv->contents_style == style) &&
1785 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1788 /* Remove previous child. Delete it if it was an account
1790 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1792 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1793 g_object_ref (content);
1794 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1795 g_object_ref (priv->empty_view);
1796 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1799 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1802 priv->contents_style = style;
1804 switch (priv->contents_style) {
1805 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1806 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1807 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1810 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1812 TnyFolderStore *selected_folderstore =
1813 modest_folder_view_get_selected (priv->folder_view);
1814 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1815 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1816 TNY_ACCOUNT (selected_folderstore));
1818 wrap_in_scrolled_window (priv->contents_widget,
1819 priv->details_widget);
1821 g_object_unref (selected_folderstore);
1822 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1828 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1829 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1830 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1834 g_return_if_reached ();
1838 gtk_widget_show_all (priv->contents_widget);
1841 ModestMainWindowContentsStyle
1842 modest_main_window_get_contents_style (ModestMainWindow *self)
1844 ModestMainWindowPrivate *priv;
1846 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1848 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1849 return priv->contents_style;
1854 on_configuration_key_changed (ModestConf* conf,
1856 ModestConfEvent event,
1857 ModestMainWindow *self)
1859 ModestMainWindowPrivate *priv;
1860 TnyAccount *account;
1862 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1865 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1867 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1870 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1871 if (TNY_IS_ACCOUNT (account) &&
1872 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1875 const gchar *device_name;
1879 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1880 label = GTK_LABEL (children->data);
1882 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1883 MODEST_CONF_DEVICE_NAME, NULL);
1885 new_text = g_strdup_printf ("%s: %s",
1886 _("mcen_fi_localroot_description"),
1889 gtk_label_set_text (label, new_text);
1890 gtk_widget_show (GTK_WIDGET (label));
1893 g_list_free (children);
1895 g_object_unref (account);
1899 set_toolbar_transfer_mode (ModestMainWindow *self)
1901 ModestMainWindowPrivate *priv = NULL;
1903 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1905 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1907 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1909 if (priv->progress_bar_timeout > 0) {
1910 g_source_remove (priv->progress_bar_timeout);
1911 priv->progress_bar_timeout = 0;
1918 set_toolbar_mode (ModestMainWindow *self,
1919 ModestToolBarModes mode)
1921 ModestWindowPrivate *parent_priv = NULL;
1922 ModestMainWindowPrivate *priv = NULL;
1923 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1925 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1927 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1928 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1930 /* In case this was called before the toolbar exists: */
1931 if (!(parent_priv->toolbar))
1934 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1936 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1937 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1938 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1940 /* Sets current toolbar mode */
1941 priv->current_toolbar_mode = mode;
1943 /* Show and hide toolbar items */
1945 case TOOLBAR_MODE_NORMAL:
1947 gtk_action_set_visible (sort_action, TRUE);
1949 gtk_action_set_visible (refresh_action, TRUE);
1950 if (priv->progress_toolitem) {
1951 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1952 gtk_widget_hide (priv->progress_toolitem);
1954 if (priv->progress_bar)
1955 gtk_widget_hide (priv->progress_bar);
1958 gtk_action_set_visible (cancel_action, FALSE);
1959 /* if (priv->sort_toolitem) */
1960 /* gtk_widget_show (priv->sort_toolitem); */
1962 /* if (priv->refresh_toolitem) */
1963 /* gtk_widget_show (priv->refresh_toolitem); */
1965 /* if (priv->progress_toolitem) */
1966 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1967 /* if (priv->progress_bar) */
1968 /* gtk_widget_hide (priv->progress_bar); */
1970 /* if (priv->cancel_toolitem) */
1971 /* gtk_widget_hide (priv->cancel_toolitem); */
1973 /* Hide toolbar if optimized view is enabled */
1974 if (priv->optimized_view)
1975 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1977 case TOOLBAR_MODE_TRANSFER:
1979 gtk_action_set_visible (sort_action, FALSE);
1981 gtk_action_set_visible (refresh_action, FALSE);
1983 gtk_action_set_visible (cancel_action, TRUE);
1984 if (priv->progress_toolitem) {
1985 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1986 gtk_widget_show (priv->progress_toolitem);
1988 if (priv->progress_bar)
1989 gtk_widget_show (priv->progress_bar);
1991 /* if (priv->sort_toolitem) */
1992 /* gtk_widget_hide (priv->sort_toolitem); */
1994 /* if (priv->refresh_toolitem) */
1995 /* gtk_widget_hide (priv->refresh_toolitem); */
1997 /* if (priv->progress_toolitem) */
1998 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
1999 /* if (priv->progress_bar) */
2000 /* gtk_widget_show (priv->progress_bar); */
2002 /* if (priv->cancel_toolitem) */
2003 /* gtk_widget_show (priv->cancel_toolitem); */
2005 /* Show toolbar if it's hiden (optimized view ) */
2006 if (priv->optimized_view)
2007 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2010 g_return_if_reached ();
2015 cancel_progressbar (GtkToolButton *toolbutton,
2016 ModestMainWindow *self)
2019 ModestMainWindowPrivate *priv;
2021 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2023 /* Get operation observers and cancel all the operations */
2024 tmp = priv->progress_widgets;
2026 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2027 tmp=g_slist_next(tmp);
2032 observers_empty (ModestMainWindow *self)
2035 ModestMainWindowPrivate *priv;
2036 gboolean is_empty = TRUE;
2037 guint pending_ops = 0;
2039 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2040 tmp = priv->progress_widgets;
2042 /* Check all observers */
2043 while (tmp && is_empty) {
2044 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2045 is_empty = pending_ops == 0;
2047 tmp = g_slist_next(tmp);
2054 on_queue_changed (ModestMailOperationQueue *queue,
2055 ModestMailOperation *mail_op,
2056 ModestMailOperationQueueNotification type,
2057 ModestMainWindow *self)
2059 ModestMainWindowPrivate *priv;
2060 ModestMailOperationTypeOperation op_type;
2061 ModestToolBarModes mode;
2063 gboolean mode_changed = FALSE;
2064 /* ModestMailOperationStatus status; */
2066 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2067 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2069 /* Get toolbar mode from operation id*/
2070 op_type = modest_mail_operation_get_type_operation (mail_op);
2072 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2073 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2074 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2075 mode = TOOLBAR_MODE_TRANSFER;
2076 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2077 mode_changed = TRUE;
2080 mode = TOOLBAR_MODE_NORMAL;
2085 /* Add operation observers and change toolbar if neccessary*/
2086 tmp = priv->progress_widgets;
2088 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2089 if (mode == TOOLBAR_MODE_TRANSFER) {
2091 set_toolbar_transfer_mode(self);
2093 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2095 tmp = g_slist_next (tmp);
2099 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2100 /* Change toolbar mode */
2101 if (mode == TOOLBAR_MODE_TRANSFER) {
2103 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2105 tmp = g_slist_next (tmp);
2108 /* If no more operations are being observed, NORMAL mode is enabled again */
2109 if (observers_empty (self)) {
2110 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2121 on_show_account_action_activated (GtkAction *action,
2124 ModestAccountData *acc_data;
2125 ModestMainWindow *self;
2126 ModestMainWindowPrivate *priv;
2127 ModestAccountMgr *mgr;
2128 const gchar *acc_name;
2130 self = MODEST_MAIN_WINDOW (user_data);
2131 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2133 /* Get account data */
2134 acc_name = gtk_action_get_name (action);
2135 mgr = modest_runtime_get_account_mgr ();
2136 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2138 /* Set the new visible & active account */
2139 if (acc_data->store_account) {
2140 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2141 acc_data->store_account->account_name);
2142 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2145 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2148 modest_account_mgr_free_account_data (mgr, acc_data);
2152 refresh_account (const gchar *account_name)
2156 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2158 /* If account_name == NULL, we must update all (option All) */
2160 modest_ui_actions_do_send_receive_all (win);
2162 modest_ui_actions_do_send_receive (account_name, win);
2167 on_refresh_account_action_activated (GtkAction *action,
2170 refresh_account ((const gchar*) user_data);
2174 on_send_receive_csm_activated (GtkMenuItem *item,
2177 refresh_account ((const gchar*) user_data);
2181 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2183 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2185 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2191 on_folder_view_focus_in (GtkWidget *widget,
2192 GdkEventFocus *event,
2195 ModestMainWindow *main_window = NULL;
2197 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2198 main_window = MODEST_MAIN_WINDOW (userdata);
2200 /* Update toolbar dimming state */
2201 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2207 on_header_view_focus_in (GtkWidget *widget,
2208 GdkEventFocus *event,
2211 ModestMainWindow *main_window = NULL;
2212 ModestMainWindowPrivate *priv = NULL;
2214 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2215 main_window = MODEST_MAIN_WINDOW (userdata);
2216 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2218 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2219 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2220 TnyIterator *iterator = tny_list_create_iterator (selection);
2223 tny_iterator_first (iterator);
2224 header = TNY_HEADER (tny_iterator_get_current (iterator));
2226 if (tny_header_get_subject (header))
2227 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2229 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2232 g_object_unref (header);
2234 g_object_unref (iterator);
2235 g_object_unref (selection);
2239 /* Update toolbar dimming state */
2240 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2246 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2247 TnyFolderStore *folder_store,
2249 ModestMainWindow *main_window)
2251 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2252 GtkAction *action = NULL;
2253 gboolean show_reply = TRUE;
2254 gboolean show_forward = TRUE;
2255 gboolean show_cancel_send = FALSE;
2256 gboolean show_clipboard = TRUE;
2257 gboolean show_delete = TRUE;
2260 if (TNY_IS_ACCOUNT (folder_store)) {
2261 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2262 } else if (TNY_IS_FOLDER (folder_store)) {
2263 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2264 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2265 TNY_FOLDER (folder_store));
2266 switch (folder_type) {
2267 case TNY_FOLDER_TYPE_DRAFTS:
2268 show_clipboard = show_delete = TRUE;
2269 show_reply = show_forward = show_cancel_send = FALSE;
2271 case TNY_FOLDER_TYPE_SENT:
2272 show_forward = show_clipboard = show_delete = TRUE;
2273 show_reply = show_cancel_send = FALSE;
2275 case TNY_FOLDER_TYPE_OUTBOX:
2276 show_clipboard = show_delete = show_cancel_send = TRUE;
2277 show_reply = show_forward = FALSE;
2280 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2281 show_cancel_send = FALSE;
2284 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2285 show_cancel_send = FALSE;
2290 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2291 gtk_action_set_visible (action, show_reply);
2292 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2293 gtk_action_set_visible (action, show_reply);
2294 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2295 gtk_action_set_visible (action, show_forward);
2296 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2297 gtk_action_set_visible (action, show_cancel_send);
2298 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2299 gtk_action_set_visible (action, show_clipboard);
2300 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2301 gtk_action_set_visible (action, show_clipboard);
2302 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2303 gtk_action_set_visible (action, show_clipboard);
2304 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2305 gtk_action_set_visible (action, show_delete);
2307 /* We finally call to the ui actions handler, after updating properly
2308 * the header view CSM */
2309 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2314 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2315 GtkTreeModel *model,
2316 GtkTreeRowReference *row_reference,
2317 ModestMainWindow *self)
2319 ModestMainWindowPrivate *priv = NULL;
2320 GtkTreeModel *header_model = NULL;
2321 GtkTreePath *path = NULL;
2323 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2324 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2325 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2327 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2328 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2330 /* Do nothing if we changed the folder in the main view */
2331 if (header_model != model)
2334 /* Select the message in the header view */
2335 path = gtk_tree_row_reference_get_path (row_reference);
2336 _modest_header_view_select_from_path (MODEST_HEADER_VIEW (priv->header_view), path);
2337 gtk_tree_path_free (path);