1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
35 #include <tny-iterator.h>
36 #include <tny-maemo-conic-device.h>
37 #include <tny-error.h>
38 #include "modest-hildon-includes.h"
39 #include "modest-defs.h"
41 #include "widgets/modest-header-view-priv.h"
42 #include "widgets/modest-main-window.h"
43 #include "widgets/modest-msg-edit-window.h"
44 #include "widgets/modest-account-view-window.h"
45 #include "modest-runtime.h"
46 #include "modest-account-mgr-helpers.h"
47 #include "modest-platform.h"
48 #include "modest-widget-memory.h"
49 #include "modest-window-priv.h"
50 #include "modest-main-window-ui.h"
51 #include "modest-main-window-ui-dimming.h"
52 #include "modest-account-mgr.h"
53 #include "modest-tny-account.h"
54 #include "modest-tny-folder.h"
55 #include "modest-conf.h"
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar-widget.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "maemo/modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-program.h>
70 #include <hildon/hildon-program.h>
71 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
73 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
80 /* 'private'/'protected' functions */
81 static void modest_main_window_class_init (ModestMainWindowClass *klass);
82 static void modest_main_window_init (ModestMainWindow *obj);
83 static void modest_main_window_finalize (GObject *obj);
85 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
86 GdkEventWindowState *event,
89 static void connect_signals (ModestMainWindow *self);
91 static void modest_main_window_disconnect_signals (ModestWindow *self);
93 static void restore_settings (ModestMainWindow *self,
94 gboolean do_folder_view_too);
96 static void save_state (ModestWindow *self);
98 static void modest_main_window_show_toolbar (ModestWindow *window,
99 gboolean show_toolbar);
101 static void cancel_progressbar (GtkToolButton *toolbutton,
102 ModestMainWindow *self);
104 static void on_queue_changed (ModestMailOperationQueue *queue,
105 ModestMailOperation *mail_op,
106 ModestMailOperationQueueNotification type,
107 ModestMainWindow *self);
109 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
111 static void account_number_changed (TnyAccountStore *account_store,
112 const gchar *account_name,
115 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
119 static void on_configuration_key_changed (ModestConf* conf,
121 ModestConfEvent event,
122 ModestConfNotificationId id,
123 ModestMainWindow *self);
125 static void set_toolbar_mode (ModestMainWindow *self,
126 ModestToolBarModes mode);
128 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
130 static void on_show_account_action_activated (GtkAction *action,
133 static void on_refresh_account_action_activated (GtkAction *action,
136 static void on_send_receive_csm_activated (GtkMenuItem *item,
140 _on_msg_count_changed (ModestHeaderView *header_view,
142 TnyFolderChange *change,
143 ModestMainWindow *main_window);
146 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
149 static GtkWidget * create_empty_view (void);
152 on_folder_view_focus_in (GtkWidget *widget,
153 GdkEventFocus *event,
156 on_header_view_focus_in (GtkWidget *widget,
157 GdkEventFocus *event,
160 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
161 TnyFolderStore *folder_store,
163 ModestMainWindow *main_window);
166 set_at_least_one_account_visible(ModestMainWindow *self);
168 /* list my signals */
175 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
176 struct _ModestMainWindowPrivate {
177 GtkWidget *msg_paned;
178 GtkWidget *main_paned;
179 GtkWidget *main_vbox;
180 GtkWidget *contents_widget;
181 GtkWidget *empty_view;
183 /* Progress observers */
184 GtkWidget *progress_bar;
185 GSList *progress_widgets;
188 GtkWidget *progress_toolitem;
189 GtkWidget *cancel_toolitem;
190 GtkWidget *sort_toolitem;
191 GtkWidget *refresh_toolitem;
192 ModestToolBarModes current_toolbar_mode;
194 /* Merge ids used to add/remove accounts to the ViewMenu*/
195 GByteArray *merge_ids;
197 /* On-demand widgets */
198 GtkWidget *accounts_popup;
199 GtkWidget *details_widget;
201 /* Optimized view enabled */
202 gboolean optimized_view;
204 /* Optimized view enabled */
205 gboolean send_receive_in_progress;
207 ModestHeaderView *header_view;
208 ModestFolderView *folder_view;
210 ModestMainWindowStyle style;
211 ModestMainWindowContentsStyle contents_style;
213 guint progress_bar_timeout;
215 /* Signal handler UIDs */
216 gint queue_changed_handler_uid;
217 GList *queue_err_signals;
219 ModestConfNotificationId notification_id;
221 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
222 MODEST_TYPE_MAIN_WINDOW, \
223 ModestMainWindowPrivate))
225 typedef struct _GetMsgAsyncHelper {
226 ModestMainWindowPrivate *main_window_private;
228 ModestTnyMsgReplyType reply_type;
229 ModestTnyMsgForwardType forward_type;
236 static GtkWindowClass *parent_class = NULL;
239 /* Private actions */
240 /* This is the context sensitive menu: */
241 static const GtkActionEntry modest_folder_view_action_entries [] = {
243 /* Folder View CSM actions */
244 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
245 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
246 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
247 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
248 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
249 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
252 static const GtkActionEntry modest_header_view_action_entries [] = {
254 /* Header View CSM actions */
255 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
256 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
257 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
258 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
259 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
260 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
261 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
262 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
263 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
264 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
267 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
268 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
271 /************************************************************************/
274 modest_main_window_get_type (void)
276 static GType my_type = 0;
278 static const GTypeInfo my_info = {
279 sizeof(ModestMainWindowClass),
280 NULL, /* base init */
281 NULL, /* base finalize */
282 (GClassInitFunc) modest_main_window_class_init,
283 NULL, /* class finalize */
284 NULL, /* class data */
285 sizeof(ModestMainWindow),
287 (GInstanceInitFunc) modest_main_window_init,
290 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
298 modest_main_window_class_init (ModestMainWindowClass *klass)
300 GObjectClass *gobject_class;
301 gobject_class = (GObjectClass*) klass;
302 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
304 parent_class = g_type_class_peek_parent (klass);
305 gobject_class->finalize = modest_main_window_finalize;
307 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
309 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
310 modest_window_class->save_state_func = save_state;
311 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
312 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
313 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
317 modest_main_window_init (ModestMainWindow *obj)
319 ModestMainWindowPrivate *priv;
321 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
323 priv->queue_err_signals = NULL;
324 priv->msg_paned = NULL;
325 priv->main_paned = NULL;
326 priv->main_vbox = NULL;
327 priv->header_view = NULL;
328 priv->folder_view = NULL;
329 priv->contents_widget = NULL;
330 priv->accounts_popup = NULL;
331 priv->details_widget = NULL;
332 priv->empty_view = NULL;
333 priv->progress_widgets = NULL;
334 priv->progress_bar = NULL;
335 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
336 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
337 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
338 priv->merge_ids = NULL;
339 priv->optimized_view = FALSE;
340 priv->send_receive_in_progress = FALSE;
341 priv->progress_bar_timeout = 0;
342 priv->queue_changed_handler_uid = 0;
346 modest_main_window_finalize (GObject *obj)
348 ModestMainWindowPrivate *priv;
350 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
352 /* Sanity check: shouldn't be needed, the window mgr should
353 call this function before */
354 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
356 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
358 g_slist_free (priv->progress_widgets);
360 g_byte_array_free (priv->merge_ids, TRUE);
362 if (priv->progress_bar_timeout > 0) {
363 g_source_remove (priv->progress_bar_timeout);
364 priv->progress_bar_timeout = 0;
367 if (priv->notification_id) {
368 modest_conf_forget_namespace (modest_runtime_get_conf (),
369 MODEST_CONF_NAMESPACE,
370 priv->notification_id);
373 G_OBJECT_CLASS(parent_class)->finalize (obj);
377 modest_main_window_get_child_widget (ModestMainWindow *self,
378 ModestWidgetType widget_type)
380 ModestMainWindowPrivate *priv;
383 g_return_val_if_fail (self, NULL);
384 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
387 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
389 switch (widget_type) {
390 case MODEST_WIDGET_TYPE_HEADER_VIEW:
391 widget = (GtkWidget*)priv->header_view; break;
392 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
393 widget = (GtkWidget*)priv->folder_view; break;
398 return widget ? GTK_WIDGET(widget) : NULL;
403 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
406 ModestMainWindowPrivate *priv;
408 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
410 conf = modest_runtime_get_conf ();
412 modest_widget_memory_restore (conf, G_OBJECT(self),
413 MODEST_CONF_MAIN_WINDOW_KEY);
415 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
416 MODEST_CONF_HEADER_VIEW_KEY);
418 if (do_folder_view_too)
419 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
420 MODEST_CONF_FOLDER_VIEW_KEY);
422 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
423 MODEST_CONF_MAIN_PANED_KEY);
425 /* We need to force a redraw here in order to get the right
426 position of the horizontal paned separator */
427 gtk_widget_show (GTK_WIDGET (self));
432 save_state (ModestWindow *window)
435 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
436 ModestMainWindowPrivate *priv;
438 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
439 conf = modest_runtime_get_conf ();
441 modest_widget_memory_save (conf,G_OBJECT(self),
442 MODEST_CONF_MAIN_WINDOW_KEY);
443 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
444 MODEST_CONF_MAIN_PANED_KEY);
445 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
446 // MODEST_CONF_HEADER_VIEW_KEY);
447 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
448 MODEST_CONF_FOLDER_VIEW_KEY);
452 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
454 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
455 gtk_scrolled_window_add_with_viewport
456 (GTK_SCROLLED_WINDOW(win), widget);
458 gtk_container_add (GTK_CONTAINER(win),
463 /* static gboolean */
464 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
466 /* modest_window_save_state (MODEST_WINDOW(self)); */
471 /* on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data) */
474 /* printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message); */
476 /* if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL) */
477 /* /\* Don't show waste the user's time by showing him a dialog telling him */
478 /* * that he has just cancelled something: *\/ */
482 /* /\* Get the server name: *\/ */
483 /* const gchar* server_name = NULL; */
485 /* TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account ( */
486 /* TNY_CAMEL_SEND_QUEUE (self)); */
487 /* if (server_account) { */
488 /* server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account)); */
490 /* g_object_unref (server_account); */
491 /* server_account = NULL; */
494 /* if (!server_name) */
495 /* server_name = _("Unknown Server"); */
497 /* /\* Show the appropriate message text for the GError: *\/ */
498 /* gchar *message = NULL; */
500 /* switch (err->code) { */
501 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED: */
502 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
504 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE: */
505 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
507 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED: */
508 /* /\* TODO: This logical ID seems more suitable for a wrong username or password than for a */
509 /* * wrong authentication method. The user is unlikely to guess at the real cause. */
511 /* message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name); */
513 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND: */
514 /* /\* TODO: Tinymail is still sending this sometimes when it should */
515 /* * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. *\/ */
517 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
521 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
524 /* modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message); */
525 /* g_free (message); */
527 /* /\* TODO: Offer to remove the message, to avoid messages in future? *\/ */
529 /* TnyFolder *outbox = tny_send_queue_get_outbox (queue); */
530 /* tny_folder_remove_msg (outbox, header, NULL); */
531 /* tny_folder_sync (outbox, TRUE, NULL); */
532 /* g_object_unref (outbox); */
542 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
544 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
546 GList *oerrsignals = priv->queue_err_signals;
547 while (oerrsignals) {
548 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
549 g_signal_handler_disconnect (esignal->queue, esignal->signal);
550 g_slice_free (QueueErrorSignal, esignal);
551 oerrsignals = g_list_next (oerrsignals);
553 g_list_free (priv->queue_err_signals);
554 priv->queue_err_signals = NULL;
558 /* on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self) */
560 /* ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); */
562 /* /\* When going online, do the equivalent of pressing the send/receive button, */
563 /* * as per the specification: */
564 /* * (without the check for >0 accounts, though that is not specified): *\/ */
566 /* TnyDevice *device = tny_account_store_get_device (store); */
568 /* /\* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); *\/ */
570 /* /\* Check that we are really online. */
571 /* * This signal should not be emitted when we are not connected, */
572 /* * but it seems to happen sometimes: *\/ */
573 /* if (!tny_device_is_online (device)) */
576 /* const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device)); */
577 /* printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id); */
579 /* /\* Stop the existing send queues: *\/ */
580 /* modest_runtime_remove_all_send_queues (); */
582 /* /\* Create the send queues again, using the appropriate transport accounts */
583 /* * for this new connection. */
584 /* * This could be the first time that they are created if this is the first */
585 /* * connection. *\/ */
586 /* /\* TODO: Does this really destroy the TnySendQueues and their threads */
587 /* * We do not want 2 TnySendQueues to exist with the same underlying */
588 /* * outbox directory. *\/ */
590 /* modest_main_window_cleanup_queue_error_signals (self); */
592 /* GSList *account_names = modest_account_mgr_account_names ( */
593 /* modest_runtime_get_account_mgr(), */
594 /* TRUE /\* enabled accounts only *\/); */
595 /* GSList *iter = account_names; */
597 /* const gchar *account_name = (const gchar*)(iter->data); */
598 /* if (account_name) { */
599 /* TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT ( */
600 /* modest_tny_account_store_get_transport_account_for_open_connection */
601 /* (modest_runtime_get_account_store(), account_name)); */
603 /* /\* Q: Is this the first location where the send-queues are requested? *\/ */
604 /* QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal); */
605 /* printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name, */
606 /* tny_account_get_id(TNY_ACCOUNT(account))); */
607 /* esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account)); */
608 /* esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened", */
609 /* G_CALLBACK (on_sendqueue_error_happened), self); */
610 /* priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal); */
614 /* iter = g_slist_next (iter); */
617 /* modest_account_mgr_free_account_names (account_names); */
618 /* account_names = NULL; */
620 /* modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self)); */
624 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
626 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
629 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
633 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
635 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
637 /* Update visibility */
640 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
644 modest_main_window_disconnect_signals (ModestWindow *self)
646 ModestMainWindowPrivate *priv;
648 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
650 /* Disconnect signal handlers */
651 if (g_signal_handler_is_connected (modest_runtime_get_mail_operation_queue (),
652 priv->queue_changed_handler_uid))
653 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
654 priv->queue_changed_handler_uid);
658 connect_signals (ModestMainWindow *self)
660 ModestWindowPrivate *parent_priv;
661 ModestMainWindowPrivate *priv;
664 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
665 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
668 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
669 G_CALLBACK(on_inner_widgets_key_pressed), self);
670 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
671 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
672 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
673 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
674 g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event",
675 G_CALLBACK (on_folder_view_focus_in), self);
677 /* Folder view CSM */
678 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
679 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
680 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
681 G_CALLBACK(_folder_view_csm_menu_activated),
684 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
685 G_CALLBACK(modest_ui_actions_on_header_selected), self);
686 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
687 G_CALLBACK(modest_ui_actions_on_header_activated), self);
688 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
689 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
690 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
691 G_CALLBACK(on_inner_widgets_key_pressed), self);
692 g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
693 G_CALLBACK(_on_msg_count_changed), self);
694 g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
695 G_CALLBACK (on_header_view_focus_in), self);
697 /* Header view CSM */
698 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
699 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
700 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
701 G_CALLBACK(_header_view_csm_menu_activated),
705 g_signal_connect (G_OBJECT (self), "window-state-event",
706 G_CALLBACK (modest_main_window_window_state_event),
709 /* Mail Operation Queue */
710 priv->queue_changed_handler_uid =
711 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
712 "queue-changed", G_CALLBACK (on_queue_changed), self);
714 /* Track changes in the device name */
715 priv->notification_id = modest_conf_listen_to_namespace (modest_runtime_get_conf (),
716 MODEST_CONF_NAMESPACE);
717 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
718 "key_changed", G_CALLBACK (on_configuration_key_changed),
721 /* Track account changes. We need to refresh the toolbar */
722 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
723 "account_inserted", G_CALLBACK (account_number_changed),
725 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
726 "account_removed", G_CALLBACK (account_number_changed),
730 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()),
731 "password_requested",
732 G_CALLBACK (modest_ui_actions_on_password_requested), self);
735 /* g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), */
736 /* "connecting-finished", */
737 /* G_CALLBACK(on_account_store_connecting_finished), self); */
741 /** Idle handler, to send/receive at startup .*/
743 sync_accounts_cb (ModestMainWindow *win)
745 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
746 return FALSE; /* Do not call this idle handler again. */
750 static void on_hildon_program_is_topmost_notify(GObject *self,
751 GParamSpec *propert_param, gpointer user_data)
753 HildonProgram *app = HILDON_PROGRAM (self);
756 ModestWindow* self = MODEST_WINDOW(user_data);
759 /* Note that use of hildon_program_set_can_hibernate()
760 * is generally referred to as "setting the killable flag",
761 * though hibernation does not seem equal to death.
764 if (hildon_program_get_is_topmost (app)) {
765 /* Prevent hibernation when the progam comes to the foreground,
766 * because hibernation should only happen when the application
767 * is in the background: */
768 hildon_program_set_can_hibernate (app, FALSE);
770 /* Allow hibernation if the program has gone to the background: */
772 /* However, prevent hibernation while the settings are being changed: */
773 const gboolean hibernation_prevented =
774 modest_window_mgr_get_hibernation_is_prevented (
775 modest_runtime_get_window_mgr ());
777 if (hibernation_prevented)
778 hildon_program_set_can_hibernate (app, FALSE);
780 /* Allow hibernation, after saving the state: */
781 modest_osso_save_state();
782 hildon_program_set_can_hibernate (app, TRUE);
789 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
791 GtkWidget *folder_win = (GtkWidget *) user_data;
792 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
794 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
795 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
796 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
798 gtk_widget_show (GTK_WIDGET (priv->folder_view));
800 /* Connect signals */
801 connect_signals ((ModestMainWindow*)self);
803 /* Set account store */
804 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
805 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
807 /* Load previous osso state, for instance if we are being restored from
809 modest_osso_load_state ();
811 /* Restore window & widget settings */
813 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
815 /* The UI spec wants us to show a connection dialog when the application is
816 * started by the user, if there is no connection.
817 * Do this before showing the account wizard,
818 * because wizard needs a connection to discover capabilities. */
819 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
821 /* Check if accounts exist and show the account wizard if not */
822 gboolean accounts_exist =
823 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
825 if (!accounts_exist) {
826 /* This is necessary to have the main window shown behind the dialog
827 It's an ugly hack... jschmid */
828 gtk_widget_show_all(GTK_WIDGET(self));
829 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
832 GtkAction *send_receive_all;
833 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
834 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
835 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
836 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
837 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
838 modest_account_mgr_free_account_names (accounts);
843 modest_main_window_new (void)
845 ModestMainWindow *self = NULL;
846 ModestMainWindowPrivate *priv = NULL;
847 ModestWindowPrivate *parent_priv = NULL;
848 GtkWidget *folder_win = NULL;
849 ModestDimmingRulesGroup *menu_rules_group = NULL;
850 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
851 GtkActionGroup *action_group = NULL;
852 GError *error = NULL;
853 ModestConf *conf = NULL;
854 GtkAction *action = NULL;
855 GdkPixbuf *window_icon;
857 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
858 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
859 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
861 parent_priv->ui_manager = gtk_ui_manager_new();
862 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
864 action_group = gtk_action_group_new ("ModestMainWindowActions");
865 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
867 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
868 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
870 /* Add common actions */
871 gtk_action_group_add_actions (action_group,
872 modest_action_entries,
873 G_N_ELEMENTS (modest_action_entries),
876 gtk_action_group_add_actions (action_group,
877 modest_folder_view_action_entries,
878 G_N_ELEMENTS (modest_folder_view_action_entries),
881 gtk_action_group_add_actions (action_group,
882 modest_header_view_action_entries,
883 G_N_ELEMENTS (modest_header_view_action_entries),
886 gtk_action_group_add_toggle_actions (action_group,
887 modest_toggle_action_entries,
888 G_N_ELEMENTS (modest_toggle_action_entries),
891 gtk_action_group_add_toggle_actions (action_group,
892 modest_main_window_toggle_action_entries,
893 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
896 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
897 g_object_unref (action_group);
899 /* Load the UI definition */
900 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
901 MODEST_UIDIR "modest-main-window-ui.xml", &error);
903 g_warning ("Could not merge modest-ui.xml: %s", error->message);
904 g_error_free (error);
908 /* Add common dimming rules */
909 modest_dimming_rules_group_add_rules (menu_rules_group,
910 modest_main_window_menu_dimming_entries,
911 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
913 modest_dimming_rules_group_add_rules (toolbar_rules_group,
914 modest_main_window_toolbar_dimming_entries,
915 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
918 /* Insert dimming rules group for this window */
919 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
920 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
921 g_object_unref (menu_rules_group);
922 g_object_unref (toolbar_rules_group);
924 /* Add accelerators */
925 gtk_window_add_accel_group (GTK_WINDOW (self),
926 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
928 /* Menubar. Update the state of some toggles */
929 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
930 conf = modest_runtime_get_conf ();
931 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
932 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
933 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
934 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
935 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
936 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
937 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
938 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
939 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
940 gtk_widget_show (parent_priv->menubar);
942 /* Get device name */
943 modest_maemo_utils_get_device_name ();
947 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
948 if (!priv->header_view)
949 g_printerr ("modest: cannot instantiate header view\n");
950 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
951 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
952 MODEST_CONF_HEADER_VIEW_KEY);
954 /* Other style properties of header view */
955 g_object_set (G_OBJECT (priv->header_view),
958 /* gtk_widget_show (priv->header_view); */
961 priv->empty_view = create_empty_view ();
962 gtk_widget_show (priv->empty_view);
964 /* Create scrolled windows */
965 folder_win = gtk_scrolled_window_new (NULL, NULL);
966 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
967 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
969 GTK_POLICY_AUTOMATIC);
970 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
972 GTK_POLICY_AUTOMATIC);
973 /* gtk_widget_show (priv->contents_widget); */
976 priv->main_paned = gtk_hpaned_new ();
977 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
978 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
979 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
981 /* putting it all together... */
982 priv->main_vbox = gtk_vbox_new (FALSE, 6);
983 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
984 gtk_widget_show (priv->main_vbox);
986 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
988 HildonProgram *app = hildon_program_get_instance ();
989 hildon_program_add_window (app, HILDON_WINDOW (self));
991 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
992 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
994 g_signal_connect (G_OBJECT(self), "show",
995 G_CALLBACK (modest_main_window_on_show), folder_win);
997 /* Set window icon */
998 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1000 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1001 g_object_unref (window_icon);
1004 /* Dont't restore settings here,
1005 * because it requires a gtk_widget_show(),
1006 * and we don't want to do that until later,
1007 * so that the UI is not visible for non-menu D-Bus activation.
1009 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1011 return MODEST_WINDOW(self);
1015 modest_main_window_close_all (ModestMainWindow *self)
1018 GtkResponseType response;
1020 /* Create the confirmation dialog MSG-NOT308 */
1021 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1022 _("emev_nc_close_windows"),
1023 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1024 _("mcen_bd_no"), GTK_RESPONSE_NO,
1027 response = gtk_dialog_run (GTK_DIALOG (note));
1028 gtk_widget_destroy (GTK_WIDGET (note));
1030 if (response == GTK_RESPONSE_YES)
1038 modest_main_window_set_style (ModestMainWindow *self,
1039 ModestMainWindowStyle style)
1041 ModestMainWindowPrivate *priv;
1042 ModestWindowPrivate *parent_priv;
1046 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1048 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1049 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1051 /* no change -> nothing to do */
1052 if (priv->style == style)
1055 /* Get toggle button and update the state if needed. This will
1056 happen only when the set_style is not invoked from the UI,
1057 for example when it's called from widget memory */
1058 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1059 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1060 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1061 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1062 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1063 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1064 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1067 priv->style = style;
1069 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1070 /* Remove main paned */
1071 g_object_ref (priv->main_paned);
1072 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1074 /* Reparent the contents widget to the main vbox */
1075 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1077 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1078 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1079 TnyIterator *iterator = tny_list_create_iterator (selection);
1081 tny_iterator_first (iterator);
1082 header = TNY_HEADER (tny_iterator_get_current (iterator));
1083 if (tny_header_get_subject (header))
1084 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1086 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1089 g_object_unref (header);
1091 g_object_unref (iterator);
1092 g_object_unref (selection);
1096 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1097 /* Remove header view */
1098 g_object_ref (priv->contents_widget);
1099 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1101 /* Reparent the main paned */
1102 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1103 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1107 g_return_if_reached ();
1110 /* Let header view grab the focus if it's being shown */
1111 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1112 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1114 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1117 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1120 ModestMainWindowStyle
1121 modest_main_window_get_style (ModestMainWindow *self)
1123 ModestMainWindowPrivate *priv;
1125 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1127 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1134 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1136 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1137 ModestWindowPrivate *parent_priv;
1138 ModestWindowMgr *mgr;
1139 gboolean is_fullscreen;
1140 GtkAction *fs_toggle_action;
1143 mgr = modest_runtime_get_window_mgr ();
1145 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1147 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1149 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1150 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1151 if (is_fullscreen != active) {
1152 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1161 set_homogeneous (GtkWidget *widget,
1164 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1165 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1169 modest_main_window_show_toolbar (ModestWindow *self,
1170 gboolean show_toolbar)
1172 ModestMainWindowPrivate *priv = NULL;
1173 ModestWindowPrivate *parent_priv = NULL;
1174 GtkWidget *reply_button = NULL, *menu = NULL;
1175 GtkWidget *placeholder = NULL;
1178 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1179 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1180 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1182 /* Set optimized view status */
1183 priv->optimized_view = !show_toolbar;
1185 if (!parent_priv->toolbar) {
1186 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1189 /* Set homogeneous toolbar */
1190 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1191 set_homogeneous, NULL);
1193 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1194 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1195 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1196 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1197 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1198 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1199 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1200 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1202 /* Add ProgressBar (Transfer toolbar) */
1203 priv->progress_bar = modest_progress_bar_widget_new ();
1204 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1205 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1206 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1207 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1208 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1210 /* Connect cancel 'clicked' signal to abort progress mode */
1211 g_signal_connect(priv->cancel_toolitem, "clicked",
1212 G_CALLBACK(cancel_progressbar),
1215 /* Add it to the observers list */
1216 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1219 hildon_window_add_toolbar (HILDON_WINDOW (self),
1220 GTK_TOOLBAR (parent_priv->toolbar));
1222 /* Set reply button tap and hold menu */
1223 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1224 "/ToolBar/ToolbarMessageReply");
1225 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1226 "/ToolbarReplyCSM");
1227 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1229 /* Set send & receive button tap and hold menu */
1230 account_number_changed (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1235 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1236 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1237 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1239 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1240 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1242 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1247 compare_display_names (ModestAccountData *a,
1248 ModestAccountData *b)
1250 return strcmp (a->display_name, b->display_name);
1254 account_number_changed (TnyAccountStore *account_store,
1255 const gchar *account_name,
1258 GSList *account_names, *iter, *accounts;
1259 ModestMainWindow *self;
1260 ModestMainWindowPrivate *priv;
1261 ModestWindowPrivate *parent_priv;
1262 ModestAccountMgr *mgr;
1263 gint i, num_accounts;
1264 GtkActionGroup *action_group;
1266 gchar *default_account;
1267 GtkWidget *send_receive_button, *item;
1268 GtkAction *send_receive_all = NULL;
1270 self = MODEST_MAIN_WINDOW (user_data);
1271 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1272 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1274 /* Get enabled account IDs */
1275 mgr = modest_runtime_get_account_mgr ();
1276 account_names = modest_account_mgr_account_names (mgr, TRUE);
1277 iter = account_names;
1281 ModestAccountData *account_data =
1282 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1283 accounts = g_slist_prepend (accounts, account_data);
1287 modest_account_mgr_free_account_names (account_names);
1288 account_names = NULL;
1290 /* Order the list of accounts by its display name */
1291 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1292 num_accounts = g_slist_length (accounts);
1294 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1295 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1296 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1298 /* Delete old send&receive popup items. We can not just do a
1299 menu_detach because it does not work well with
1301 if (priv->accounts_popup)
1302 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1303 (GtkCallback) gtk_widget_destroy, NULL);
1305 /* Delete old entries in the View menu. Do not free groups, it
1307 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1309 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1310 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1311 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1312 GTK_ACTION_GROUP (groups->data));
1315 if (priv->merge_ids) {
1316 for (i = 0; i < priv->merge_ids->len; i++)
1317 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1318 g_byte_array_free (priv->merge_ids, TRUE);
1320 /* We need to call this in order to ensure
1321 that the new actions are added in the right
1322 order (alphabetical */
1323 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1325 groups = g_list_next (groups);
1327 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1329 /* Get send receive button */
1330 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1331 "/ToolBar/ToolbarSendReceive");
1333 /* Create the menu */
1334 if (num_accounts > 1) {
1335 if (!priv->accounts_popup)
1336 priv->accounts_popup = gtk_menu_new ();
1337 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1338 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1339 g_signal_connect (G_OBJECT (item),
1341 G_CALLBACK (on_send_receive_csm_activated),
1343 item = gtk_separator_menu_item_new ();
1344 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1347 /* Create a new action group */
1348 default_account = modest_account_mgr_get_default_account (mgr);
1349 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1350 for (i = 0; i < num_accounts; i++) {
1351 gchar *display_name = NULL;
1353 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1355 /* Create display name. The UI specification specifies a different format string
1356 * to use for the default account, though both seem to be "%s", so
1357 * I don't see what the point is. murrayc. */
1358 if (default_account && account_data->account_name &&
1359 !(strcmp (default_account, account_data->account_name) == 0)) {
1360 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1361 account_data->display_name);
1364 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1365 account_data->display_name);
1368 /* Create action and add it to the action group. The
1369 action name must be the account name, this way we
1370 could know in the handlers the account to show */
1371 if(account_data && account_data->account_name) {
1372 gchar* item_name, *refresh_action_name;
1373 guint8 merge_id = 0;
1374 GtkAction *view_account_action, *refresh_account_action;
1376 view_account_action = gtk_action_new (account_data->account_name,
1377 display_name, NULL, NULL);
1378 gtk_action_group_add_action (action_group, view_account_action);
1380 /* Add ui from account data. We allow 2^9-1 account
1381 changes in a single execution because we're
1382 downcasting the guint to a guint8 in order to use a
1383 GByteArray. It should be enough. */
1384 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1385 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1386 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1387 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1389 "/MenuBar/ViewMenu/ViewMenuAdditions",
1391 account_data->account_name,
1392 GTK_UI_MANAGER_MENUITEM,
1395 /* Connect the action signal "activate" */
1396 g_signal_connect (G_OBJECT (view_account_action),
1398 G_CALLBACK (on_show_account_action_activated),
1401 /* Create the items for the Tools->Send&Receive submenu */
1402 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1403 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1404 display_name, NULL, NULL);
1405 printf("DEBUG: %s: menu display_name=%s\n", __FUNCTION__, display_name);
1406 gtk_action_group_add_action (action_group, refresh_account_action);
1408 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1409 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1410 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1412 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1414 refresh_action_name,
1415 GTK_UI_MANAGER_MENUITEM,
1417 g_free (refresh_action_name);
1419 g_signal_connect_data (G_OBJECT (refresh_account_action),
1421 G_CALLBACK (on_refresh_account_action_activated),
1422 g_strdup (account_data->account_name),
1423 (GClosureNotify) g_free,
1426 /* Create item and add it to the send&receive
1427 CSM. If there is only one account then
1429 if (priv->accounts_popup) {
1430 GtkWidget *label = gtk_label_new(NULL);
1431 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1432 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1434 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1435 gtk_label_set_markup (GTK_LABEL (label), escaped);
1440 gtk_label_set_text (GTK_LABEL (label), display_name);
1443 item = gtk_menu_item_new ();
1444 gtk_container_add (GTK_CONTAINER (item), label);
1446 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1447 g_signal_connect_data (G_OBJECT (item),
1449 G_CALLBACK (on_send_receive_csm_activated),
1450 g_strdup (account_data->account_name),
1451 (GClosureNotify) g_free,
1458 g_free (display_name);
1461 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1463 /* We cannot do this in the loop above because this relies on the action
1464 * group being inserted. This makes the default account appear in bold.
1465 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1466 for (i = 0; i < num_accounts; i++) {
1467 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1469 if(account_data->account_name && default_account &&
1470 strcmp (account_data->account_name, default_account) == 0) {
1471 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1473 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1474 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1478 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1479 if (GTK_IS_LABEL (child)) {
1480 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1481 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1482 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1487 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1488 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1492 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1493 if (GTK_IS_LABEL (child)) {
1494 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1495 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1496 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1504 modest_account_mgr_free_account_data (mgr, account_data);
1507 if (priv->accounts_popup) {
1508 /* Mandatory in order to view the menu contents */
1509 gtk_widget_show_all (priv->accounts_popup);
1511 /* Setup tap_and_hold just if was not done before*/
1512 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1513 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1517 g_slist_free (accounts);
1518 g_free (default_account);
1521 /* Make sure that at least one account is viewed if there are any
1522 * accounts, for instance when adding the first account: */
1523 set_at_least_one_account_visible (self);
1527 * This function manages the key events used to navigate between
1528 * header and folder views (when the window is in split view)
1531 * -------------------------------------------------
1532 * HeaderView GDK_Left Move focus to folder view
1533 * FolderView GDK_Right Move focus to header view
1535 * There is no need to scroll to selected row, the widgets will be the
1536 * responsibles of doing that (probably managing the focus-in event
1539 on_inner_widgets_key_pressed (GtkWidget *widget,
1543 ModestMainWindowPrivate *priv;
1545 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1547 /* Do nothing if we're in SIMPLE style */
1548 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1551 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1552 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1553 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1554 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1560 set_alignment (GtkWidget *widget,
1563 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1564 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1568 create_empty_view (void)
1570 GtkLabel *label = NULL;
1571 GtkWidget *align = NULL;
1573 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1574 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1575 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1576 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1578 return GTK_WIDGET(align);
1582 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1584 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1589 gchar *gray_color_markup;
1591 vbox = gtk_vbox_new (FALSE, 0);
1593 /* Obtain the secondary text color. We need a realized widget, that's why
1594 we get styled_widget from outside */
1595 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1597 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1598 gray_color_markup = modest_text_utils_get_color_string (&color);
1600 // gray_color_markup is freed below
1601 gray_color_markup = g_strdup ("#BBBBBB");
1603 /* Account description: */
1605 if (modest_tny_account_is_virtual_local_folders (account)
1606 || (modest_tny_account_is_memory_card_account (account))) {
1608 /* Local folders: */
1610 /* Get device name */
1611 gchar *device_name = NULL;
1612 if (modest_tny_account_is_virtual_local_folders (account))
1613 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1614 MODEST_CONF_DEVICE_NAME, NULL);
1616 device_name = g_strdup (tny_account_get_name (account));
1618 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1619 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1620 gray_color_markup, tmp, device_name);
1622 label_w = gtk_label_new (NULL);
1623 gtk_label_set_markup (GTK_LABEL (label_w), label);
1624 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1625 g_free (device_name);
1628 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1629 gtk_box_pack_start (GTK_BOX (vbox),
1630 gtk_label_new (tny_account_get_name (account)),
1633 /* Other accounts, such as IMAP and POP: */
1638 /* Put proto in uppercase */
1639 proto = g_string_new (tny_account_get_proto (account));
1640 proto = g_string_ascii_up (proto);
1642 /* note: mcen_fi_localroot_description is something like "%s account"
1643 * however, we should display "%s account: %s"... therefore, ugly tmp */
1644 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1645 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1646 gray_color_markup, tmp, tny_account_get_name (account));
1649 label_w = gtk_label_new (NULL);
1650 gtk_label_set_markup (GTK_LABEL (label_w), label);
1651 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1652 g_string_free (proto, TRUE);
1658 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1659 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1660 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1661 modest_tny_folder_store_get_message_count (folder_store));
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);
1668 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1670 _("mcen_fi_rootfolder_folders"),
1671 modest_tny_folder_store_get_folder_count (folder_store));
1672 label_w = gtk_label_new (NULL);
1673 gtk_label_set_markup (GTK_LABEL (label_w), label);
1674 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1678 if (modest_tny_account_is_virtual_local_folders (account)
1679 || modest_tny_account_is_memory_card_account (account)) {
1681 gchar *size = modest_text_utils_get_display_size (
1682 modest_tny_folder_store_get_local_size (folder_store));
1684 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1685 gray_color_markup, _("mcen_fi_rootfolder_size"),
1689 label_w = gtk_label_new (NULL);
1690 gtk_label_set_markup (GTK_LABEL (label_w), label);
1691 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1693 } else if (TNY_IS_ACCOUNT(folder_store)) {
1694 TnyAccount *account = TNY_ACCOUNT(folder_store);
1696 time_t last_updated;
1697 gchar *last_updated_string;
1698 /* Get last updated from configuration */
1699 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1700 tny_account_get_id (account),
1701 MODEST_ACCOUNT_LAST_UPDATED,
1703 if (last_updated > 0)
1704 last_updated_string = modest_text_utils_get_display_date(last_updated);
1706 last_updated_string = g_strdup (_("mcen_va_never"));
1708 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1709 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1710 label_w = gtk_label_new (NULL);
1711 gtk_label_set_markup (GTK_LABEL (label_w), label);
1712 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1713 g_free (last_updated_string);
1717 g_free (gray_color_markup);
1720 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1726 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1728 ModestMainWindowPrivate *priv = NULL;
1730 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1732 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1734 return priv->send_receive_in_progress;
1738 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1740 GtkAction *action = NULL;
1741 GtkWidget *widget = NULL;
1742 ModestMainWindowPrivate *priv = NULL;
1744 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1745 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1747 priv->send_receive_in_progress = TRUE;
1749 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1750 gtk_action_set_sensitive (action, FALSE);
1751 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1752 /* gtk_action_set_sensitive (action, FALSE); */
1753 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1754 gtk_widget_set_sensitive (widget, FALSE);
1758 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1760 GtkAction *action = NULL;
1761 GtkWidget *widget = NULL;
1762 ModestMainWindowPrivate *priv = NULL;
1764 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1765 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1767 priv->send_receive_in_progress = FALSE;
1769 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1770 gtk_action_set_sensitive (action, TRUE);
1771 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1772 /* gtk_action_set_sensitive (action, TRUE); */
1773 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1774 gtk_widget_set_sensitive (widget, TRUE);
1779 _on_msg_count_changed (ModestHeaderView *header_view,
1781 TnyFolderChange *change,
1782 ModestMainWindow *main_window)
1784 printf ("DEBUG: %s\n", __FUNCTION__);
1785 gboolean folder_empty = FALSE;
1786 TnyFolderChangeChanged changed;
1787 ModestMainWindowPrivate *priv;
1789 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1790 g_return_if_fail (TNY_IS_FOLDER(folder));
1791 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1792 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1794 changed = tny_folder_change_get_changed (change);
1796 /* If something changes */
1797 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1798 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1800 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1802 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1804 /* Set contents style of headers view */
1806 modest_main_window_set_contents_style (main_window,
1807 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1808 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1811 modest_main_window_set_contents_style (main_window,
1812 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1818 modest_main_window_set_contents_style (ModestMainWindow *self,
1819 ModestMainWindowContentsStyle style)
1821 ModestMainWindowPrivate *priv;
1823 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1825 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1827 /* We allow to set the same content style than the previously
1828 set if there are details, because it could happen when we're
1829 selecting different accounts consecutively */
1830 if ((priv->contents_style == style) &&
1831 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1834 /* Remove previous child. Delete it if it was an account
1836 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1838 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1839 g_object_ref (content);
1840 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1841 g_object_ref (priv->empty_view);
1842 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1845 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1848 priv->contents_style = style;
1850 switch (priv->contents_style) {
1851 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1852 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1853 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1856 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1858 TnyFolderStore *selected_folderstore =
1859 modest_folder_view_get_selected (priv->folder_view);
1860 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1861 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1862 TNY_ACCOUNT (selected_folderstore));
1864 wrap_in_scrolled_window (priv->contents_widget,
1865 priv->details_widget);
1867 g_object_unref (selected_folderstore);
1868 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1874 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1875 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1876 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1880 g_return_if_reached ();
1884 gtk_widget_show_all (priv->contents_widget);
1887 ModestMainWindowContentsStyle
1888 modest_main_window_get_contents_style (ModestMainWindow *self)
1890 ModestMainWindowPrivate *priv;
1892 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1894 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1895 return priv->contents_style;
1900 on_configuration_key_changed (ModestConf* conf,
1902 ModestConfEvent event,
1903 ModestConfNotificationId id,
1904 ModestMainWindow *self)
1906 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1907 TnyAccount *account;
1910 priv->notification_id != id ||
1911 strcmp (key, MODEST_CONF_DEVICE_NAME))
1914 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1917 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1918 if (TNY_IS_ACCOUNT (account) &&
1919 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1922 const gchar *device_name;
1926 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1927 label = GTK_LABEL (children->data);
1929 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1930 MODEST_CONF_DEVICE_NAME, NULL);
1932 new_text = g_strdup_printf ("%s: %s",
1933 _("mcen_fi_localroot_description"),
1936 gtk_label_set_text (label, new_text);
1937 gtk_widget_show (GTK_WIDGET (label));
1940 g_list_free (children);
1942 g_object_unref (account);
1946 set_toolbar_transfer_mode (ModestMainWindow *self)
1948 ModestMainWindowPrivate *priv = NULL;
1950 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1952 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1954 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1956 if (priv->progress_bar_timeout > 0) {
1957 g_source_remove (priv->progress_bar_timeout);
1958 priv->progress_bar_timeout = 0;
1965 set_toolbar_mode (ModestMainWindow *self,
1966 ModestToolBarModes mode)
1968 ModestWindowPrivate *parent_priv = NULL;
1969 ModestMainWindowPrivate *priv = NULL;
1970 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1972 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1974 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1975 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1977 /* In case this was called before the toolbar exists: */
1978 if (!(parent_priv->toolbar))
1981 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1983 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1984 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1985 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1987 /* Sets current toolbar mode */
1988 priv->current_toolbar_mode = mode;
1990 /* Show and hide toolbar items */
1992 case TOOLBAR_MODE_NORMAL:
1994 gtk_action_set_visible (sort_action, TRUE);
1996 gtk_action_set_visible (refresh_action, TRUE);
1997 if (priv->progress_toolitem) {
1998 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1999 gtk_widget_hide (priv->progress_toolitem);
2001 if (priv->progress_bar)
2002 gtk_widget_hide (priv->progress_bar);
2005 gtk_action_set_visible (cancel_action, FALSE);
2006 /* if (priv->sort_toolitem) */
2007 /* gtk_widget_show (priv->sort_toolitem); */
2009 /* if (priv->refresh_toolitem) */
2010 /* gtk_widget_show (priv->refresh_toolitem); */
2012 /* if (priv->progress_toolitem) */
2013 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
2014 /* if (priv->progress_bar) */
2015 /* gtk_widget_hide (priv->progress_bar); */
2017 /* if (priv->cancel_toolitem) */
2018 /* gtk_widget_hide (priv->cancel_toolitem); */
2020 /* Hide toolbar if optimized view is enabled */
2021 if (priv->optimized_view)
2022 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2024 case TOOLBAR_MODE_TRANSFER:
2026 gtk_action_set_visible (sort_action, FALSE);
2028 gtk_action_set_visible (refresh_action, FALSE);
2030 gtk_action_set_visible (cancel_action, TRUE);
2031 if (priv->progress_toolitem) {
2032 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2033 gtk_widget_show (priv->progress_toolitem);
2035 if (priv->progress_bar)
2036 gtk_widget_show (priv->progress_bar);
2038 /* if (priv->sort_toolitem) */
2039 /* gtk_widget_hide (priv->sort_toolitem); */
2041 /* if (priv->refresh_toolitem) */
2042 /* gtk_widget_hide (priv->refresh_toolitem); */
2044 /* if (priv->progress_toolitem) */
2045 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2046 /* if (priv->progress_bar) */
2047 /* gtk_widget_show (priv->progress_bar); */
2049 /* if (priv->cancel_toolitem) */
2050 /* gtk_widget_show (priv->cancel_toolitem); */
2052 /* Show toolbar if it's hiden (optimized view ) */
2053 if (priv->optimized_view)
2054 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2057 g_return_if_reached ();
2062 cancel_progressbar (GtkToolButton *toolbutton,
2063 ModestMainWindow *self)
2066 ModestMainWindowPrivate *priv;
2068 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2070 /* Get operation observers and cancel all the operations */
2071 tmp = priv->progress_widgets;
2073 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2074 tmp=g_slist_next(tmp);
2079 observers_empty (ModestMainWindow *self)
2082 ModestMainWindowPrivate *priv;
2083 gboolean is_empty = TRUE;
2084 guint pending_ops = 0;
2086 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2087 tmp = priv->progress_widgets;
2089 /* Check all observers */
2090 while (tmp && is_empty) {
2091 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2092 is_empty = pending_ops == 0;
2094 tmp = g_slist_next(tmp);
2101 on_queue_changed (ModestMailOperationQueue *queue,
2102 ModestMailOperation *mail_op,
2103 ModestMailOperationQueueNotification type,
2104 ModestMainWindow *self)
2106 ModestMainWindowPrivate *priv;
2107 ModestMailOperationTypeOperation op_type;
2108 ModestToolBarModes mode;
2110 gboolean mode_changed = FALSE;
2111 /* ModestMailOperationStatus status; */
2113 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2114 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2116 /* Get toolbar mode from operation id*/
2117 op_type = modest_mail_operation_get_type_operation (mail_op);
2119 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2120 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2121 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2122 mode = TOOLBAR_MODE_TRANSFER;
2123 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2124 mode_changed = TRUE;
2127 mode = TOOLBAR_MODE_NORMAL;
2132 /* Add operation observers and change toolbar if neccessary*/
2133 tmp = priv->progress_widgets;
2135 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2136 if (mode == TOOLBAR_MODE_TRANSFER) {
2138 set_toolbar_transfer_mode(self);
2140 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2142 tmp = g_slist_next (tmp);
2146 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2147 /* Change toolbar mode */
2148 if (mode == TOOLBAR_MODE_TRANSFER) {
2150 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2152 tmp = g_slist_next (tmp);
2155 /* If no more operations are being observed, NORMAL mode is enabled again */
2156 if (observers_empty (self)) {
2157 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2168 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2170 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2172 /* Get account data */
2173 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2174 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2176 /* Set the new visible & active account */
2177 if (acc_data && acc_data->store_account) {
2178 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2179 acc_data->store_account->account_name);
2180 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2183 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2187 modest_account_mgr_free_account_data (mgr, acc_data);
2190 /* Make sure that at least one account is "viewed": */
2192 set_at_least_one_account_visible(ModestMainWindow *self)
2194 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2195 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2197 if (!(priv->folder_view)) {
2198 /* It is too early to do this. */
2202 const gchar *active_server_account_name =
2203 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2204 if (!active_server_account_name ||
2205 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2207 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2208 if (first_modest_name) {
2209 set_account_visible (self, first_modest_name);
2210 g_free (first_modest_name);
2216 on_show_account_action_activated (GtkAction *action,
2219 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2221 const gchar *acc_name = gtk_action_get_name (action);
2222 set_account_visible (self, acc_name);
2226 refresh_account (const gchar *account_name)
2230 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2232 /* If account_name == NULL, we must update all (option All) */
2234 modest_ui_actions_do_send_receive_all (win);
2236 modest_ui_actions_do_send_receive (account_name, win);
2241 on_refresh_account_action_activated (GtkAction *action,
2244 refresh_account ((const gchar*) user_data);
2248 on_send_receive_csm_activated (GtkMenuItem *item,
2251 refresh_account ((const gchar*) user_data);
2255 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2257 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2259 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2265 on_folder_view_focus_in (GtkWidget *widget,
2266 GdkEventFocus *event,
2269 ModestMainWindow *main_window = NULL;
2271 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2272 main_window = MODEST_MAIN_WINDOW (userdata);
2274 /* Update toolbar dimming state */
2275 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2281 on_header_view_focus_in (GtkWidget *widget,
2282 GdkEventFocus *event,
2285 ModestMainWindow *main_window = NULL;
2286 ModestMainWindowPrivate *priv = NULL;
2288 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2289 main_window = MODEST_MAIN_WINDOW (userdata);
2290 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2292 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2293 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2294 TnyIterator *iterator = tny_list_create_iterator (selection);
2297 tny_iterator_first (iterator);
2298 header = TNY_HEADER (tny_iterator_get_current (iterator));
2300 if (tny_header_get_subject (header))
2301 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2303 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2306 g_object_unref (header);
2308 g_object_unref (iterator);
2309 g_object_unref (selection);
2313 /* Update toolbar dimming state */
2314 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2320 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2321 TnyFolderStore *folder_store,
2323 ModestMainWindow *main_window)
2325 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2326 GtkAction *action = NULL;
2327 gboolean show_reply = TRUE;
2328 gboolean show_forward = TRUE;
2329 gboolean show_cancel_send = FALSE;
2330 gboolean show_clipboard = TRUE;
2331 gboolean show_delete = TRUE;
2334 if (TNY_IS_ACCOUNT (folder_store)) {
2335 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2336 } else if (TNY_IS_FOLDER (folder_store)) {
2337 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2338 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2339 TNY_FOLDER (folder_store));
2340 switch (folder_type) {
2341 case TNY_FOLDER_TYPE_DRAFTS:
2342 show_clipboard = show_delete = TRUE;
2343 show_reply = show_forward = show_cancel_send = FALSE;
2345 case TNY_FOLDER_TYPE_SENT:
2346 show_forward = show_clipboard = show_delete = TRUE;
2347 show_reply = show_cancel_send = FALSE;
2349 case TNY_FOLDER_TYPE_OUTBOX:
2350 show_clipboard = show_delete = show_cancel_send = TRUE;
2351 show_reply = show_forward = FALSE;
2354 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2355 show_cancel_send = FALSE;
2358 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2359 show_cancel_send = FALSE;
2364 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2365 gtk_action_set_visible (action, show_reply);
2366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2367 gtk_action_set_visible (action, show_reply);
2368 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2369 gtk_action_set_visible (action, show_forward);
2370 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2371 gtk_action_set_visible (action, show_cancel_send);
2372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2373 gtk_action_set_visible (action, show_clipboard);
2374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2375 gtk_action_set_visible (action, show_clipboard);
2376 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2377 gtk_action_set_visible (action, show_clipboard);
2378 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2379 gtk_action_set_visible (action, show_delete);
2381 /* We finally call to the ui actions handler, after updating properly
2382 * the header view CSM */
2383 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2388 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2389 GtkTreeModel *model,
2390 GtkTreeRowReference *row_reference,
2391 ModestMainWindow *self)
2393 ModestMainWindowPrivate *priv = NULL;
2394 GtkTreeModel *header_model = NULL;
2395 GtkTreePath *path = NULL;
2397 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2398 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2399 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2401 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2402 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2404 /* Do nothing if we changed the folder in the main view */
2405 if (header_model != model)
2408 /* Select the message in the header view */
2409 path = gtk_tree_row_reference_get_path (row_reference);
2410 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2412 gtk_tree_path_free (path);