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:
500 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
504 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
507 modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message);
510 /* TODO: Offer to remove the message, to avoid messages in future? */
512 TnyFolder *outbox = tny_send_queue_get_outbox (queue);
513 tny_folder_remove_msg (outbox, header, NULL);
514 tny_folder_sync (outbox, TRUE, NULL);
515 g_object_unref (outbox);
525 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
527 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
529 GList *oerrsignals = priv->queue_err_signals;
530 while (oerrsignals) {
531 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
532 g_signal_handler_disconnect (esignal->queue, esignal->signal);
533 g_slice_free (QueueErrorSignal, esignal);
534 oerrsignals = g_list_next (oerrsignals);
536 g_list_free (priv->queue_err_signals);
537 priv->queue_err_signals = NULL;
541 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
543 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
545 /* When going online, do the equivalent of pressing the send/receive button,
546 * as per the specification:
547 * (without the check for >0 accounts, though that is not specified): */
549 TnyDevice *device = tny_account_store_get_device (store);
551 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
553 /* Check that we are really online.
554 * This signal should not be emitted when we are not connected,
555 * but it seems to happen sometimes: */
556 if (!tny_device_is_online (device))
559 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
560 printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
562 /* Stop the existing send queues: */
563 modest_runtime_remove_all_send_queues ();
565 /* Create the send queues again, using the appropriate transport accounts
566 * for this new connection.
567 * This could be the first time that they are created if this is the first
569 /* TODO: Does this really destroy the TnySendQueues and their threads
570 * We do not want 2 TnySendQueues to exist with the same underlying
571 * outbox directory. */
573 modest_main_window_cleanup_queue_error_signals (self);
575 GSList *account_names = modest_account_mgr_account_names (
576 modest_runtime_get_account_mgr(),
577 TRUE /* enabled accounts only */);
578 GSList *iter = account_names;
580 const gchar *account_name = (const gchar*)(iter->data);
582 TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
583 modest_tny_account_store_get_transport_account_for_open_connection
584 (modest_runtime_get_account_store(), account_name));
586 /* Q: Is this the first location where the send-queues are requested? */
587 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
588 printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name,
589 tny_account_get_id(TNY_ACCOUNT(account)));
590 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
591 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
592 G_CALLBACK (on_sendqueue_error_happened), self);
593 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
597 iter = g_slist_next (iter);
600 modest_account_mgr_free_account_names (account_names);
601 account_names = NULL;
603 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
607 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
609 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
612 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
616 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
618 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
620 /* Update visibility */
623 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
627 connect_signals (ModestMainWindow *self)
629 ModestWindowPrivate *parent_priv;
630 ModestMainWindowPrivate *priv;
633 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
634 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
637 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
638 G_CALLBACK(on_inner_widgets_key_pressed), self);
639 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
640 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
641 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
642 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
643 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
644 G_CALLBACK (on_folder_view_focus_in), self);
646 /* Folder view CSM */
647 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
648 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
649 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
650 G_CALLBACK(_folder_view_csm_menu_activated),
653 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
654 G_CALLBACK(modest_ui_actions_on_header_selected), self);
655 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
656 G_CALLBACK(modest_ui_actions_on_header_activated), self);
657 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
658 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
659 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
660 G_CALLBACK(on_inner_widgets_key_pressed), self);
661 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
662 G_CALLBACK(_on_msg_count_changed), self);
663 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
664 G_CALLBACK (on_header_view_focus_in), self);
666 /* Header view CSM */
667 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
668 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
669 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
670 G_CALLBACK(_header_view_csm_menu_activated),
674 /* g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */
675 g_signal_connect (G_OBJECT (self), "window-state-event",
676 G_CALLBACK (modest_main_window_window_state_event),
679 /* Mail Operation Queue */
680 priv->queue_changed_handler_uid =
681 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
682 "queue-changed", G_CALLBACK (on_queue_changed), self);
684 /* Track changes in the device name */
685 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
686 "key_changed", G_CALLBACK (on_configuration_key_changed),
689 /* Track account changes. We need to refresh the toolbar */
690 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
691 "account_update", G_CALLBACK (on_account_update),
695 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
696 "password_requested",
697 G_CALLBACK (modest_ui_actions_on_password_requested), self);
700 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()),
701 "connecting-finished",
702 G_CALLBACK(on_account_store_connecting_finished), self);
706 /** Idle handler, to send/receive at startup .*/
708 sync_accounts_cb (ModestMainWindow *win)
710 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
711 return FALSE; /* Do not call this idle handler again. */
715 static void on_hildon_program_is_topmost_notify(GObject *self,
716 GParamSpec *propert_param, gpointer user_data)
718 HildonProgram *app = HILDON_PROGRAM (self);
721 ModestWindow* self = MODEST_WINDOW(user_data);
724 /* Note that use of hildon_program_set_can_hibernate()
725 * is generally referred to as "setting the killable flag",
726 * though hibernation does not seem equal to death.
729 if (hildon_program_get_is_topmost (app)) {
730 /* Prevent hibernation when the progam comes to the foreground,
731 * because hibernation should only happen when the application
732 * is in the background: */
733 hildon_program_set_can_hibernate (app, FALSE);
735 /* Allow hibernation if the program has gone to the background: */
737 /* However, prevent hibernation while the settings are being changed: */
738 const gboolean hibernation_prevented =
739 modest_window_mgr_get_hibernation_is_prevented (
740 modest_runtime_get_window_mgr ());
742 if (hibernation_prevented)
743 hildon_program_set_can_hibernate (app, FALSE);
745 /* Allow hibernation, after saving the state: */
746 modest_osso_save_state();
747 hildon_program_set_can_hibernate (app, TRUE);
754 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
756 GtkWidget *folder_win = (GtkWidget *) user_data;
757 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
759 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
760 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
761 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
763 gtk_widget_show (GTK_WIDGET (priv->folder_view));
765 /* Connect signals */
766 connect_signals ((ModestMainWindow*)self);
768 /* Set account store */
769 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
770 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
772 /* Load previous osso state, for instance if we are being restored from
774 modest_osso_load_state ();
776 /* Restore window & widget settings */
778 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
780 /* Check if accounts exist and show the account wizard if not */
781 gboolean accounts_exist =
782 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
784 if (!accounts_exist) {
785 /* This is necessary to have the main window shown behind the dialog
786 It's an ugly hack... jschmid */
787 gtk_widget_show_all(GTK_WIDGET(self));
788 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
791 GtkAction *send_receive_all;
792 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
793 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
794 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
795 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
796 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
797 modest_account_mgr_free_account_names (accounts);
804 modest_main_window_new (void)
806 ModestMainWindow *self = NULL;
807 ModestMainWindowPrivate *priv = NULL;
808 ModestWindowPrivate *parent_priv = NULL;
809 GtkWidget *folder_win = NULL;
810 ModestDimmingRulesGroup *menu_rules_group = NULL;
811 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
812 GtkActionGroup *action_group = NULL;
813 GError *error = NULL;
814 ModestConf *conf = NULL;
815 GtkAction *action = NULL;
816 GdkPixbuf *window_icon;
818 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
819 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
820 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
822 parent_priv->ui_manager = gtk_ui_manager_new();
823 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
825 action_group = gtk_action_group_new ("ModestMainWindowActions");
826 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
828 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
829 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
831 /* Add common actions */
832 gtk_action_group_add_actions (action_group,
833 modest_action_entries,
834 G_N_ELEMENTS (modest_action_entries),
837 gtk_action_group_add_actions (action_group,
838 modest_folder_view_action_entries,
839 G_N_ELEMENTS (modest_folder_view_action_entries),
842 gtk_action_group_add_actions (action_group,
843 modest_header_view_action_entries,
844 G_N_ELEMENTS (modest_header_view_action_entries),
847 gtk_action_group_add_toggle_actions (action_group,
848 modest_toggle_action_entries,
849 G_N_ELEMENTS (modest_toggle_action_entries),
852 gtk_action_group_add_toggle_actions (action_group,
853 modest_main_window_toggle_action_entries,
854 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
857 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
858 g_object_unref (action_group);
860 /* Load the UI definition */
861 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
862 MODEST_UIDIR "modest-main-window-ui.xml", &error);
864 g_warning ("Could not merge modest-ui.xml: %s", error->message);
865 g_error_free (error);
869 /* Add common dimming rules */
870 modest_dimming_rules_group_add_rules (menu_rules_group,
871 modest_main_window_menu_dimming_entries,
872 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
874 modest_dimming_rules_group_add_rules (toolbar_rules_group,
875 modest_main_window_toolbar_dimming_entries,
876 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
879 /* Insert dimming rules group for this window */
880 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
881 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
882 g_object_unref (menu_rules_group);
883 g_object_unref (toolbar_rules_group);
885 /* Add accelerators */
886 gtk_window_add_accel_group (GTK_WINDOW (self),
887 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
889 /* Menubar. Update the state of some toggles */
890 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
891 conf = modest_runtime_get_conf ();
892 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
893 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
894 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
895 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
896 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
897 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
898 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
899 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
900 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
901 gtk_widget_show (parent_priv->menubar);
903 /* Get device name */
904 modest_maemo_utils_get_device_name ();
908 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
909 if (!priv->header_view)
910 g_printerr ("modest: cannot instantiate header view\n");
911 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
912 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
913 MODEST_CONF_HEADER_VIEW_KEY);
915 /* Other style properties of header view */
916 g_object_set (G_OBJECT (priv->header_view),
919 /* gtk_widget_show (priv->header_view); */
922 priv->empty_view = create_empty_view ();
923 gtk_widget_show (priv->empty_view);
925 /* Create scrolled windows */
926 folder_win = gtk_scrolled_window_new (NULL, NULL);
927 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
928 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
930 GTK_POLICY_AUTOMATIC);
931 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
933 GTK_POLICY_AUTOMATIC);
934 /* gtk_widget_show (priv->contents_widget); */
937 priv->main_paned = gtk_hpaned_new ();
938 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
939 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
940 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
942 /* putting it all together... */
943 priv->main_vbox = gtk_vbox_new (FALSE, 6);
944 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
945 gtk_widget_show (priv->main_vbox);
947 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
949 HildonProgram *app = hildon_program_get_instance ();
950 hildon_program_add_window (app, HILDON_WINDOW (self));
952 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
953 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
955 g_signal_connect (G_OBJECT(self), "show",
956 G_CALLBACK (modest_main_window_on_show), folder_win);
958 /* Set window icon */
959 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
961 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
962 g_object_unref (window_icon);
965 /* Dont't restore settings here,
966 * because it requires a gtk_widget_show(),
967 * and we don't want to do that until later,
968 * so that the UI is not visible for non-menu D-Bus activation.
970 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
972 return MODEST_WINDOW(self);
976 modest_main_window_close_all (ModestMainWindow *self)
979 GtkResponseType response;
981 /* Create the confirmation dialog MSG-NOT308 */
982 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
983 _("emev_nc_close_windows"),
984 _("mcen_bd_yes"), GTK_RESPONSE_YES,
985 _("mcen_bd_no"), GTK_RESPONSE_NO,
988 response = gtk_dialog_run (GTK_DIALOG (note));
989 gtk_widget_destroy (GTK_WIDGET (note));
991 if (response == GTK_RESPONSE_YES)
999 modest_main_window_set_style (ModestMainWindow *self,
1000 ModestMainWindowStyle style)
1002 ModestMainWindowPrivate *priv;
1003 ModestWindowPrivate *parent_priv;
1007 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1009 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1010 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1012 /* no change -> nothing to do */
1013 if (priv->style == style)
1016 /* Get toggle button and update the state if needed. This will
1017 happen only when the set_style is not invoked from the UI,
1018 for example when it's called from widget memory */
1019 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1020 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1021 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1022 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1023 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1024 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1025 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1028 priv->style = style;
1030 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1031 /* Remove main paned */
1032 g_object_ref (priv->main_paned);
1033 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1035 /* Reparent the contents widget to the main vbox */
1036 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1038 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1039 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1040 TnyIterator *iterator = tny_list_create_iterator (selection);
1042 tny_iterator_first (iterator);
1043 header = TNY_HEADER (tny_iterator_get_current (iterator));
1044 if (tny_header_get_subject (header))
1045 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1047 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1048 g_object_unref (header);
1049 g_object_unref (iterator);
1050 g_object_unref (selection);
1054 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1055 /* Remove header view */
1056 g_object_ref (priv->contents_widget);
1057 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1059 /* Reparent the main paned */
1060 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1061 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1065 g_return_if_reached ();
1068 /* Let header view grab the focus if it's being shown */
1069 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1070 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1072 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1075 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1078 ModestMainWindowStyle
1079 modest_main_window_get_style (ModestMainWindow *self)
1081 ModestMainWindowPrivate *priv;
1083 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1085 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1092 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1094 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1095 ModestWindowPrivate *parent_priv;
1096 ModestWindowMgr *mgr;
1097 gboolean is_fullscreen;
1098 GtkAction *fs_toggle_action;
1101 mgr = modest_runtime_get_window_mgr ();
1103 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1105 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1107 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1108 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1109 if (is_fullscreen != active) {
1110 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1119 set_homogeneous (GtkWidget *widget,
1122 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1123 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1127 modest_main_window_show_toolbar (ModestWindow *self,
1128 gboolean show_toolbar)
1130 ModestMainWindowPrivate *priv = NULL;
1131 ModestWindowPrivate *parent_priv = NULL;
1132 GtkWidget *reply_button = NULL, *menu = NULL;
1133 GtkWidget *placeholder = NULL;
1136 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1137 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1138 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1140 /* Set optimized view status */
1141 priv->optimized_view = !show_toolbar;
1143 if (!parent_priv->toolbar) {
1144 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1147 /* Set homogeneous toolbar */
1148 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1149 set_homogeneous, NULL);
1151 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1152 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1153 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1154 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1155 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1156 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1157 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1158 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1160 /* Add ProgressBar (Transfer toolbar) */
1161 priv->progress_bar = modest_progress_bar_widget_new ();
1162 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1163 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1164 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1165 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1166 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1168 /* Connect cancel 'clicked' signal to abort progress mode */
1169 g_signal_connect(priv->cancel_toolitem, "clicked",
1170 G_CALLBACK(cancel_progressbar),
1173 /* Add it to the observers list */
1174 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1177 hildon_window_add_toolbar (HILDON_WINDOW (self),
1178 GTK_TOOLBAR (parent_priv->toolbar));
1180 /* Set reply button tap and hold menu */
1181 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1182 "/ToolBar/ToolbarMessageReply");
1183 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1184 "/ToolbarReplyCSM");
1185 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1187 /* Set send & receive button tap and hold menu */
1188 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1193 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1194 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1195 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1197 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1198 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1200 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1205 compare_display_names (ModestAccountData *a,
1206 ModestAccountData *b)
1208 return strcmp (a->display_name, b->display_name);
1212 on_account_update (TnyAccountStore *account_store,
1213 const gchar *account_name,
1216 GSList *account_names, *iter, *accounts;
1217 ModestMainWindow *self;
1218 ModestMainWindowPrivate *priv;
1219 ModestWindowPrivate *parent_priv;
1220 ModestAccountMgr *mgr;
1221 gint i, num_accounts;
1222 GtkActionGroup *action_group;
1224 gchar *default_account;
1225 GtkWidget *send_receive_button, *item;
1226 GtkAction *send_receive_all = NULL;
1228 self = MODEST_MAIN_WINDOW (user_data);
1229 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1230 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1232 /* Get enabled account IDs */
1233 mgr = modest_runtime_get_account_mgr ();
1234 account_names = modest_account_mgr_account_names (mgr, TRUE);
1235 iter = account_names;
1239 ModestAccountData *account_data =
1240 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1241 accounts = g_slist_prepend (accounts, account_data);
1245 modest_account_mgr_free_account_names (account_names);
1246 account_names = NULL;
1248 /* Order the list of accounts by its display name */
1249 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1250 num_accounts = g_slist_length (accounts);
1252 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1253 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1254 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1256 /* Delete old send&receive popup items. We can not just do a
1257 menu_detach because it does not work well with
1259 if (priv->accounts_popup)
1260 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1261 (GtkCallback) gtk_widget_destroy, NULL);
1263 /* Delete old entries in the View menu. Do not free groups, it
1265 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1267 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1268 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1269 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1270 GTK_ACTION_GROUP (groups->data));
1273 if (priv->merge_ids) {
1274 for (i = 0; i < priv->merge_ids->len; i++)
1275 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1276 g_byte_array_free (priv->merge_ids, TRUE);
1278 /* We need to call this in order to ensure
1279 that the new actions are added in the right
1280 order (alphabetical */
1281 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1283 groups = g_list_next (groups);
1285 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1287 /* Get send receive button */
1288 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1289 "/ToolBar/ToolbarSendReceive");
1291 /* Create the menu */
1292 if (num_accounts > 1) {
1293 if (!priv->accounts_popup)
1294 priv->accounts_popup = gtk_menu_new ();
1295 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1296 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1297 g_signal_connect (G_OBJECT (item),
1299 G_CALLBACK (on_send_receive_csm_activated),
1301 item = gtk_separator_menu_item_new ();
1302 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1305 /* Create a new action group */
1306 default_account = modest_account_mgr_get_default_account (mgr);
1307 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1308 for (i = 0; i < num_accounts; i++) {
1309 gchar *display_name = NULL;
1311 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1313 /* Create display name. The UI specification specifies a different format string
1314 * to use for the default account, though both seem to be "%s", so
1315 * I don't see what the point is. murrayc. */
1316 if (default_account && account_data->account_name &&
1317 !(strcmp (default_account, account_data->account_name) == 0)) {
1318 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1319 account_data->display_name);
1322 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1323 account_data->display_name);
1326 /* Create action and add it to the action group. The
1327 action name must be the account name, this way we
1328 could know in the handlers the account to show */
1329 if(account_data->account_name) {
1330 gchar* item_name, *refresh_action_name;
1332 GtkAction *view_account_action, *refresh_account_action;
1334 view_account_action = gtk_action_new (account_data->account_name,
1335 display_name, NULL, NULL);
1336 gtk_action_group_add_action (action_group, view_account_action);
1338 /* Add ui from account data. We allow 2^9-1 account
1339 changes in a single execution because we're
1340 downcasting the guint to a guint8 in order to use a
1341 GByteArray. It should be enough. */
1342 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1343 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1344 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1345 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1347 "/MenuBar/ViewMenu/ViewMenuAdditions",
1349 account_data->account_name,
1350 GTK_UI_MANAGER_MENUITEM,
1353 /* Connect the action signal "activate" */
1354 g_signal_connect (G_OBJECT (view_account_action),
1356 G_CALLBACK (on_show_account_action_activated),
1359 /* Create the items for the Tools->Send&Receive submenu */
1360 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1361 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1362 display_name, NULL, NULL);
1363 gtk_action_group_add_action (action_group, refresh_account_action);
1365 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1366 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1367 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1369 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1371 refresh_action_name,
1372 GTK_UI_MANAGER_MENUITEM,
1374 g_free (refresh_action_name);
1376 g_signal_connect_data (G_OBJECT (refresh_account_action),
1378 G_CALLBACK (on_refresh_account_action_activated),
1379 g_strdup (account_data->account_name),
1380 (GClosureNotify) g_free,
1383 /* Create item and add it to the send&receive
1384 CSM. If there is only one account then
1386 if (priv->accounts_popup) {
1387 GtkWidget *label = gtk_label_new(NULL);
1388 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1389 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1391 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1392 gtk_label_set_markup (GTK_LABEL (label), escaped);
1397 gtk_label_set_text (GTK_LABEL (label), display_name);
1400 item = gtk_menu_item_new ();
1401 gtk_container_add (GTK_CONTAINER (item), label);
1403 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1404 g_signal_connect_data (G_OBJECT (item),
1406 G_CALLBACK (on_send_receive_csm_activated),
1407 g_strdup (account_data->account_name),
1408 (GClosureNotify) g_free,
1415 g_free (display_name);
1418 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1420 /* We cannot do this in the loop above because this relies on the action
1421 * group being inserted. This makes the default account appear in bold.
1422 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1423 for (i = 0; i < num_accounts; i++) {
1424 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1426 if(account_data->account_name &&
1427 strcmp (account_data->account_name, default_account) == 0) {
1428 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1430 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1431 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1435 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1436 if (GTK_IS_LABEL (child)) {
1437 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1438 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1439 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1444 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1445 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1449 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1450 if (GTK_IS_LABEL (child)) {
1451 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1452 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1453 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1461 modest_account_mgr_free_account_data (mgr, account_data);
1464 if (priv->accounts_popup) {
1465 /* Mandatory in order to view the menu contents */
1466 gtk_widget_show_all (priv->accounts_popup);
1468 /* Setup tap_and_hold just if was not done before*/
1469 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1470 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1474 g_slist_free (accounts);
1475 g_free (default_account);
1479 * This function manages the key events used to navigate between
1480 * header and folder views (when the window is in split view)
1483 * -------------------------------------------------
1484 * HeaderView GDK_Left Move focus to folder view
1485 * FolderView GDK_Right Move focus to header view
1487 * There is no need to scroll to selected row, the widgets will be the
1488 * responsibles of doing that (probably managing the focus-in event
1491 on_inner_widgets_key_pressed (GtkWidget *widget,
1495 ModestMainWindowPrivate *priv;
1497 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1499 /* Do nothing if we're in SIMPLE style */
1500 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1503 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1504 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1505 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1506 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1512 set_alignment (GtkWidget *widget,
1515 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1516 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1520 create_empty_view (void)
1522 GtkLabel *label = NULL;
1523 GtkWidget *align = NULL;
1525 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1526 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1527 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1528 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1530 return GTK_WIDGET(align);
1534 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1536 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1541 gchar *gray_color_markup;
1543 vbox = gtk_vbox_new (FALSE, 0);
1545 /* Obtain the secondary text color. We need a realized widget, that's why
1546 we get styled_widget from outside */
1547 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1549 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1550 gray_color_markup = modest_text_utils_get_color_string (&color);
1552 // gray_color_markup is freed below
1553 gray_color_markup = g_strdup ("#BBBBBB");
1555 /* Account description: */
1557 if (modest_tny_account_is_virtual_local_folders (account)
1558 || (modest_tny_account_is_memory_card_account (account))) {
1560 /* Local folders: */
1562 /* Get device name */
1563 gchar *device_name = NULL;
1564 if (modest_tny_account_is_virtual_local_folders (account))
1565 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1566 MODEST_CONF_DEVICE_NAME, NULL);
1568 device_name = g_strdup (tny_account_get_name (account));
1570 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1571 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1572 gray_color_markup, tmp, device_name);
1574 label_w = gtk_label_new (NULL);
1575 gtk_label_set_markup (GTK_LABEL (label_w), label);
1576 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1577 g_free (device_name);
1580 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1581 gtk_box_pack_start (GTK_BOX (vbox),
1582 gtk_label_new (tny_account_get_name (account)),
1585 /* Other accounts, such as IMAP and POP: */
1590 /* Put proto in uppercase */
1591 proto = g_string_new (tny_account_get_proto (account));
1592 proto = g_string_ascii_up (proto);
1594 /* note: mcen_fi_localroot_description is something like "%s account"
1595 * however, we should display "%s account: %s"... therefore, ugly tmp */
1596 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1597 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1598 gray_color_markup, tmp, tny_account_get_name (account));
1601 label_w = gtk_label_new (NULL);
1602 gtk_label_set_markup (GTK_LABEL (label_w), label);
1603 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1604 g_string_free (proto, TRUE);
1610 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1611 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1612 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1613 modest_tny_folder_store_get_message_count (folder_store));
1614 label_w = gtk_label_new (NULL);
1615 gtk_label_set_markup (GTK_LABEL (label_w), label);
1616 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1620 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1622 _("mcen_fi_rootfolder_folders"),
1623 modest_tny_folder_store_get_folder_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 if (modest_tny_account_is_virtual_local_folders (account)
1631 || modest_tny_account_is_memory_card_account (account)) {
1633 gchar *size = modest_text_utils_get_display_size (
1634 modest_tny_folder_store_get_local_size (folder_store));
1636 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1637 gray_color_markup, _("mcen_fi_rootfolder_size"),
1641 label_w = gtk_label_new (NULL);
1642 gtk_label_set_markup (GTK_LABEL (label_w), label);
1643 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1645 } else if (TNY_IS_ACCOUNT(folder_store)) {
1646 TnyAccount *account = TNY_ACCOUNT(folder_store);
1648 time_t last_updated;
1649 gchar *last_updated_string;
1650 /* Get last updated from configuration */
1651 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1652 tny_account_get_id (account),
1653 MODEST_ACCOUNT_LAST_UPDATED,
1655 if (last_updated > 0)
1656 last_updated_string = modest_text_utils_get_display_date(last_updated);
1658 last_updated_string = g_strdup (_("mcen_va_never"));
1660 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1661 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1662 label_w = gtk_label_new (NULL);
1663 gtk_label_set_markup (GTK_LABEL (label_w), label);
1664 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1665 g_free (last_updated_string);
1669 g_free (gray_color_markup);
1672 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1678 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1680 ModestMainWindowPrivate *priv = NULL;
1682 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1684 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1686 return priv->send_receive_in_progress;
1690 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1692 GtkAction *action = NULL;
1693 GtkWidget *widget = NULL;
1694 ModestMainWindowPrivate *priv = NULL;
1696 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1697 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1699 priv->send_receive_in_progress = TRUE;
1701 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1702 gtk_action_set_sensitive (action, FALSE);
1703 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1704 /* gtk_action_set_sensitive (action, FALSE); */
1705 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1706 gtk_widget_set_sensitive (widget, FALSE);
1710 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1712 GtkAction *action = NULL;
1713 GtkWidget *widget = NULL;
1714 ModestMainWindowPrivate *priv = NULL;
1716 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1717 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1719 priv->send_receive_in_progress = FALSE;
1721 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1722 gtk_action_set_sensitive (action, TRUE);
1723 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1724 /* gtk_action_set_sensitive (action, TRUE); */
1725 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1726 gtk_widget_set_sensitive (widget, TRUE);
1731 _on_msg_count_changed (ModestHeaderView *header_view,
1733 TnyFolderChange *change,
1734 ModestMainWindow *main_window)
1736 printf ("DEBUG: %s\n", __FUNCTION__);
1737 gboolean folder_empty = FALSE;
1738 TnyFolderChangeChanged changed;
1740 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1741 g_return_if_fail (TNY_IS_FOLDER(folder));
1742 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1744 changed = tny_folder_change_get_changed (change);
1746 /* If something changes */
1747 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1748 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1750 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1752 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1754 /* Set contents style of headers view */
1756 modest_main_window_set_contents_style (main_window,
1757 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1760 modest_main_window_set_contents_style (main_window,
1761 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1767 modest_main_window_set_contents_style (ModestMainWindow *self,
1768 ModestMainWindowContentsStyle style)
1770 ModestMainWindowPrivate *priv;
1772 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1774 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1776 /* We allow to set the same content style than the previously
1777 set if there are details, because it could happen when we're
1778 selecting different accounts consecutively */
1779 if ((priv->contents_style == style) &&
1780 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1783 /* Remove previous child. Delete it if it was an account
1785 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1787 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1788 g_object_ref (content);
1789 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1790 g_object_ref (priv->empty_view);
1791 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1794 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1797 priv->contents_style = style;
1799 switch (priv->contents_style) {
1800 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1801 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1802 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1805 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1807 TnyFolderStore *selected_folderstore =
1808 modest_folder_view_get_selected (priv->folder_view);
1809 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1810 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1811 TNY_ACCOUNT (selected_folderstore));
1813 wrap_in_scrolled_window (priv->contents_widget,
1814 priv->details_widget);
1816 g_object_unref (selected_folderstore);
1817 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1823 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1824 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1825 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1829 g_return_if_reached ();
1833 gtk_widget_show_all (priv->contents_widget);
1836 ModestMainWindowContentsStyle
1837 modest_main_window_get_contents_style (ModestMainWindow *self)
1839 ModestMainWindowPrivate *priv;
1841 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1843 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1844 return priv->contents_style;
1849 on_configuration_key_changed (ModestConf* conf,
1851 ModestConfEvent event,
1852 ModestMainWindow *self)
1854 ModestMainWindowPrivate *priv;
1855 TnyAccount *account;
1857 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1860 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1862 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1865 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1866 if (TNY_IS_ACCOUNT (account) &&
1867 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1870 const gchar *device_name;
1874 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1875 label = GTK_LABEL (children->data);
1877 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1878 MODEST_CONF_DEVICE_NAME, NULL);
1880 new_text = g_strdup_printf ("%s: %s",
1881 _("mcen_fi_localroot_description"),
1884 gtk_label_set_text (label, new_text);
1885 gtk_widget_show (GTK_WIDGET (label));
1888 g_list_free (children);
1890 g_object_unref (account);
1894 set_toolbar_transfer_mode (ModestMainWindow *self)
1896 ModestMainWindowPrivate *priv = NULL;
1898 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1900 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1902 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1904 if (priv->progress_bar_timeout > 0) {
1905 g_source_remove (priv->progress_bar_timeout);
1906 priv->progress_bar_timeout = 0;
1913 set_toolbar_mode (ModestMainWindow *self,
1914 ModestToolBarModes mode)
1916 ModestWindowPrivate *parent_priv = NULL;
1917 ModestMainWindowPrivate *priv = NULL;
1918 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1920 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1922 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1923 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1925 /* In case this was called before the toolbar exists: */
1926 if (!(parent_priv->toolbar))
1929 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1931 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1932 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1933 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1935 /* Sets current toolbar mode */
1936 priv->current_toolbar_mode = mode;
1938 /* Show and hide toolbar items */
1940 case TOOLBAR_MODE_NORMAL:
1942 gtk_action_set_visible (sort_action, TRUE);
1944 gtk_action_set_visible (refresh_action, TRUE);
1945 if (priv->progress_toolitem) {
1946 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1947 gtk_widget_hide (priv->progress_toolitem);
1949 if (priv->progress_bar)
1950 gtk_widget_hide (priv->progress_bar);
1953 gtk_action_set_visible (cancel_action, FALSE);
1954 /* if (priv->sort_toolitem) */
1955 /* gtk_widget_show (priv->sort_toolitem); */
1957 /* if (priv->refresh_toolitem) */
1958 /* gtk_widget_show (priv->refresh_toolitem); */
1960 /* if (priv->progress_toolitem) */
1961 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1962 /* if (priv->progress_bar) */
1963 /* gtk_widget_hide (priv->progress_bar); */
1965 /* if (priv->cancel_toolitem) */
1966 /* gtk_widget_hide (priv->cancel_toolitem); */
1968 /* Hide toolbar if optimized view is enabled */
1969 if (priv->optimized_view)
1970 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1972 case TOOLBAR_MODE_TRANSFER:
1974 gtk_action_set_visible (sort_action, FALSE);
1976 gtk_action_set_visible (refresh_action, FALSE);
1978 gtk_action_set_visible (cancel_action, TRUE);
1979 if (priv->progress_toolitem) {
1980 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1981 gtk_widget_show (priv->progress_toolitem);
1983 if (priv->progress_bar)
1984 gtk_widget_show (priv->progress_bar);
1986 /* if (priv->sort_toolitem) */
1987 /* gtk_widget_hide (priv->sort_toolitem); */
1989 /* if (priv->refresh_toolitem) */
1990 /* gtk_widget_hide (priv->refresh_toolitem); */
1992 /* if (priv->progress_toolitem) */
1993 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
1994 /* if (priv->progress_bar) */
1995 /* gtk_widget_show (priv->progress_bar); */
1997 /* if (priv->cancel_toolitem) */
1998 /* gtk_widget_show (priv->cancel_toolitem); */
2000 /* Show toolbar if it's hiden (optimized view ) */
2001 if (priv->optimized_view)
2002 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2005 g_return_if_reached ();
2010 cancel_progressbar (GtkToolButton *toolbutton,
2011 ModestMainWindow *self)
2014 ModestMainWindowPrivate *priv;
2016 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2018 /* Get operation observers and cancel its current operation */
2019 tmp = priv->progress_widgets;
2021 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
2022 tmp=g_slist_next(tmp);
2027 observers_empty (ModestMainWindow *self)
2030 ModestMainWindowPrivate *priv;
2031 gboolean is_empty = TRUE;
2032 guint pending_ops = 0;
2034 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2035 tmp = priv->progress_widgets;
2037 /* Check all observers */
2038 while (tmp && is_empty) {
2039 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2040 is_empty = pending_ops == 0;
2042 tmp = g_slist_next(tmp);
2049 on_queue_changed (ModestMailOperationQueue *queue,
2050 ModestMailOperation *mail_op,
2051 ModestMailOperationQueueNotification type,
2052 ModestMainWindow *self)
2054 ModestMainWindowPrivate *priv;
2055 ModestMailOperationTypeOperation op_type;
2056 ModestToolBarModes mode;
2058 gboolean mode_changed = FALSE;
2059 /* ModestMailOperationStatus status; */
2061 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2062 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2064 /* Get toolbar mode from operation id*/
2065 op_type = modest_mail_operation_get_type_operation (mail_op);
2067 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2068 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2069 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2070 mode = TOOLBAR_MODE_TRANSFER;
2071 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2072 mode_changed = TRUE;
2075 mode = TOOLBAR_MODE_NORMAL;
2080 /* Add operation observers and change toolbar if neccessary*/
2081 tmp = priv->progress_widgets;
2083 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2084 if (mode == TOOLBAR_MODE_TRANSFER) {
2086 set_toolbar_transfer_mode(self);
2088 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2090 tmp = g_slist_next (tmp);
2094 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2095 /* Change toolbar mode */
2096 if (mode == TOOLBAR_MODE_TRANSFER) {
2098 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2100 tmp = g_slist_next (tmp);
2103 /* If no more operations are being observed, NORMAL mode is enabled again */
2104 if (observers_empty (self)) {
2105 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2116 on_show_account_action_activated (GtkAction *action,
2119 ModestAccountData *acc_data;
2120 ModestMainWindow *self;
2121 ModestMainWindowPrivate *priv;
2122 ModestAccountMgr *mgr;
2123 const gchar *acc_name;
2125 self = MODEST_MAIN_WINDOW (user_data);
2126 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2128 /* Get account data */
2129 acc_name = gtk_action_get_name (action);
2130 mgr = modest_runtime_get_account_mgr ();
2131 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2133 /* Set the new visible & active account */
2134 if (acc_data->store_account) {
2135 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2136 acc_data->store_account->account_name);
2137 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2140 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2143 modest_account_mgr_free_account_data (mgr, acc_data);
2147 refresh_account (const gchar *account_name)
2151 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2153 /* If account_name == NULL, we must update all (option All) */
2155 modest_ui_actions_do_send_receive_all (win);
2157 modest_ui_actions_do_send_receive (account_name, win);
2162 on_refresh_account_action_activated (GtkAction *action,
2165 refresh_account ((const gchar*) user_data);
2169 on_send_receive_csm_activated (GtkMenuItem *item,
2172 refresh_account ((const gchar*) user_data);
2176 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2178 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2180 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2186 on_folder_view_focus_in (GtkWidget *widget,
2187 GdkEventFocus *event,
2190 ModestMainWindow *main_window = NULL;
2192 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2193 main_window = MODEST_MAIN_WINDOW (userdata);
2195 /* Update toolbar dimming state */
2196 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2202 on_header_view_focus_in (GtkWidget *widget,
2203 GdkEventFocus *event,
2206 ModestMainWindow *main_window = NULL;
2207 ModestMainWindowPrivate *priv = NULL;
2209 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2210 main_window = MODEST_MAIN_WINDOW (userdata);
2211 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2213 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2214 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2215 TnyIterator *iterator = tny_list_create_iterator (selection);
2218 tny_iterator_first (iterator);
2219 header = TNY_HEADER (tny_iterator_get_current (iterator));
2221 if (tny_header_get_subject (header))
2222 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2224 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2226 g_object_unref (header);
2227 g_object_unref (iterator);
2228 g_object_unref (selection);
2232 /* Update toolbar dimming state */
2233 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2239 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2240 TnyFolderStore *folder_store,
2242 ModestMainWindow *main_window)
2244 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2245 GtkAction *action = NULL;
2246 gboolean show_reply = TRUE;
2247 gboolean show_forward = TRUE;
2248 gboolean show_cancel_send = FALSE;
2249 gboolean show_clipboard = TRUE;
2250 gboolean show_delete = TRUE;
2253 if (TNY_IS_ACCOUNT (folder_store)) {
2254 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2255 } else if (TNY_IS_FOLDER (folder_store)) {
2256 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2257 TnyFolderType folder_type = modest_tny_folder_get_local_folder_type (
2258 TNY_FOLDER (folder_store));
2259 switch (folder_type) {
2260 case TNY_FOLDER_TYPE_DRAFTS:
2261 show_clipboard = show_delete = TRUE;
2262 show_reply = show_forward = show_cancel_send = FALSE;
2264 case TNY_FOLDER_TYPE_SENT:
2265 show_forward = show_clipboard = show_delete = TRUE;
2266 show_reply = show_cancel_send = FALSE;
2268 case TNY_FOLDER_TYPE_OUTBOX:
2269 show_clipboard = show_delete = show_cancel_send = TRUE;
2270 show_reply = show_forward = FALSE;
2273 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2274 show_cancel_send = FALSE;
2277 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2278 show_cancel_send = FALSE;
2283 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2284 gtk_action_set_visible (action, show_reply);
2285 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2286 gtk_action_set_visible (action, show_reply);
2287 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2288 gtk_action_set_visible (action, show_forward);
2289 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2290 gtk_action_set_visible (action, show_cancel_send);
2291 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2292 gtk_action_set_visible (action, show_clipboard);
2293 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2294 gtk_action_set_visible (action, show_clipboard);
2295 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2296 gtk_action_set_visible (action, show_clipboard);
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2298 gtk_action_set_visible (action, show_delete);
2300 /* We finally call to the ui actions handler, after updating properly
2301 * the header view CSM */
2302 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2307 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2308 GtkTreeModel *model,
2309 GtkTreeRowReference *row_reference,
2310 ModestMainWindow *self)
2312 ModestMainWindowPrivate *priv = NULL;
2313 GtkTreeModel *header_model = NULL;
2314 GtkTreePath *path = NULL;
2316 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2317 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2318 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2320 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2321 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2323 /* Do nothing if we changed the folder in the main view */
2324 if (header_model != model)
2327 /* Select the message in the header view */
2328 path = gtk_tree_row_reference_get_path (row_reference);
2329 _modest_header_view_select_from_path (MODEST_HEADER_VIEW (priv->header_view), path);
2330 gtk_tree_path_free (path);