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"
66 #include "modest-signal-mgr.h"
68 #ifdef MODEST_HAVE_HILDON0_WIDGETS
69 #include <hildon-widgets/hildon-program.h>
71 #include <hildon/hildon-program.h>
72 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
74 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
81 /* 'private'/'protected' functions */
82 static void modest_main_window_class_init (ModestMainWindowClass *klass);
83 static void modest_main_window_init (ModestMainWindow *obj);
84 static void modest_main_window_finalize (GObject *obj);
86 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
87 GdkEventWindowState *event,
90 static void connect_signals (ModestMainWindow *self);
92 static void modest_main_window_disconnect_signals (ModestWindow *self);
94 static void restore_settings (ModestMainWindow *self,
95 gboolean do_folder_view_too);
97 static void save_state (ModestWindow *self);
99 static void modest_main_window_show_toolbar (ModestWindow *window,
100 gboolean show_toolbar);
102 static void cancel_progressbar (GtkToolButton *toolbutton,
103 ModestMainWindow *self);
105 static void on_queue_changed (ModestMailOperationQueue *queue,
106 ModestMailOperation *mail_op,
107 ModestMailOperationQueueNotification type,
108 ModestMainWindow *self);
110 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
112 static void account_number_changed (TnyAccountStore *account_store,
113 const gchar *account_name,
116 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
120 static void on_configuration_key_changed (ModestConf* conf,
122 ModestConfEvent event,
123 ModestConfNotificationId id,
124 ModestMainWindow *self);
126 static void set_toolbar_mode (ModestMainWindow *self,
127 ModestToolBarModes mode);
129 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
131 static void on_show_account_action_activated (GtkAction *action,
134 static void on_refresh_account_action_activated (GtkAction *action,
137 static void on_send_receive_csm_activated (GtkMenuItem *item,
141 _on_msg_count_changed (ModestHeaderView *header_view,
143 TnyFolderChange *change,
144 ModestMainWindow *main_window);
147 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
150 static GtkWidget * create_empty_view (void);
153 on_folder_view_focus_in (GtkWidget *widget,
154 GdkEventFocus *event,
157 on_header_view_focus_in (GtkWidget *widget,
158 GdkEventFocus *event,
161 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
162 TnyFolderStore *folder_store,
164 ModestMainWindow *main_window);
167 set_at_least_one_account_visible(ModestMainWindow *self);
169 /* list my signals */
176 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
177 struct _ModestMainWindowPrivate {
178 GtkWidget *msg_paned;
179 GtkWidget *main_paned;
180 GtkWidget *main_vbox;
181 GtkWidget *contents_widget;
182 GtkWidget *empty_view;
184 /* Progress observers */
185 GtkWidget *progress_bar;
186 GSList *progress_widgets;
189 GtkWidget *progress_toolitem;
190 GtkWidget *cancel_toolitem;
191 GtkWidget *sort_toolitem;
192 GtkWidget *refresh_toolitem;
193 ModestToolBarModes current_toolbar_mode;
195 /* Merge ids used to add/remove accounts to the ViewMenu*/
196 GByteArray *merge_ids;
198 /* On-demand widgets */
199 GtkWidget *accounts_popup;
200 GtkWidget *details_widget;
202 /* Optimized view enabled */
203 gboolean optimized_view;
205 /* Optimized view enabled */
206 gboolean send_receive_in_progress;
208 ModestHeaderView *header_view;
209 ModestFolderView *folder_view;
211 ModestMainWindowStyle style;
212 ModestMainWindowContentsStyle contents_style;
214 guint progress_bar_timeout;
216 /* Signal handler UIDs */
217 GList *queue_err_signals;
220 ModestConfNotificationId notification_id;
222 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
223 MODEST_TYPE_MAIN_WINDOW, \
224 ModestMainWindowPrivate))
226 typedef struct _GetMsgAsyncHelper {
227 ModestMainWindowPrivate *main_window_private;
229 ModestTnyMsgReplyType reply_type;
230 ModestTnyMsgForwardType forward_type;
237 static GtkWindowClass *parent_class = NULL;
240 /* Private actions */
241 /* This is the context sensitive menu: */
242 static const GtkActionEntry modest_folder_view_action_entries [] = {
244 /* Folder View CSM actions */
245 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
246 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
247 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)},
248 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
249 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
250 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
253 static const GtkActionEntry modest_header_view_action_entries [] = {
255 /* Header View CSM actions */
256 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_open) },
257 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
258 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
259 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
260 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
261 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
262 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
263 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
264 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
265 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
268 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
269 { "ToggleFolders", MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
272 /************************************************************************/
275 modest_main_window_get_type (void)
277 static GType my_type = 0;
279 static const GTypeInfo my_info = {
280 sizeof(ModestMainWindowClass),
281 NULL, /* base init */
282 NULL, /* base finalize */
283 (GClassInitFunc) modest_main_window_class_init,
284 NULL, /* class finalize */
285 NULL, /* class data */
286 sizeof(ModestMainWindow),
288 (GInstanceInitFunc) modest_main_window_init,
291 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
299 modest_main_window_class_init (ModestMainWindowClass *klass)
301 GObjectClass *gobject_class;
302 gobject_class = (GObjectClass*) klass;
303 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
305 parent_class = g_type_class_peek_parent (klass);
306 gobject_class->finalize = modest_main_window_finalize;
308 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
310 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
311 modest_window_class->save_state_func = save_state;
312 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
313 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
314 modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
318 modest_main_window_init (ModestMainWindow *obj)
320 ModestMainWindowPrivate *priv;
322 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
324 priv->queue_err_signals = NULL;
325 priv->msg_paned = NULL;
326 priv->main_paned = NULL;
327 priv->main_vbox = NULL;
328 priv->header_view = NULL;
329 priv->folder_view = NULL;
330 priv->contents_widget = NULL;
331 priv->accounts_popup = NULL;
332 priv->details_widget = NULL;
333 priv->empty_view = NULL;
334 priv->progress_widgets = NULL;
335 priv->progress_bar = NULL;
336 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
337 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
338 priv->contents_style = -1; /* invalid contents style. We need this to select it for the first time */
339 priv->merge_ids = NULL;
340 priv->optimized_view = FALSE;
341 priv->send_receive_in_progress = FALSE;
342 priv->progress_bar_timeout = 0;
343 priv->sighandlers = NULL;
347 modest_main_window_finalize (GObject *obj)
349 ModestMainWindowPrivate *priv;
351 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
353 if (priv->notification_id) {
354 modest_conf_forget_namespace (modest_runtime_get_conf (),
355 MODEST_CONF_NAMESPACE,
356 priv->notification_id);
359 /* Sanity check: shouldn't be needed, the window mgr should
360 call this function before */
361 modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
363 modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
365 g_slist_free (priv->progress_widgets);
367 g_byte_array_free (priv->merge_ids, TRUE);
369 if (priv->progress_bar_timeout > 0) {
370 g_source_remove (priv->progress_bar_timeout);
371 priv->progress_bar_timeout = 0;
374 G_OBJECT_CLASS(parent_class)->finalize (obj);
378 modest_main_window_get_child_widget (ModestMainWindow *self,
379 ModestWidgetType widget_type)
381 ModestMainWindowPrivate *priv;
384 g_return_val_if_fail (self, NULL);
385 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
388 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
390 switch (widget_type) {
391 case MODEST_WIDGET_TYPE_HEADER_VIEW:
392 widget = (GtkWidget*)priv->header_view; break;
393 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
394 widget = (GtkWidget*)priv->folder_view; break;
399 return widget ? GTK_WIDGET(widget) : NULL;
404 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
407 ModestMainWindowPrivate *priv;
409 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
411 conf = modest_runtime_get_conf ();
413 modest_widget_memory_restore (conf, G_OBJECT(self),
414 MODEST_CONF_MAIN_WINDOW_KEY);
416 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
417 MODEST_CONF_HEADER_VIEW_KEY);
419 if (do_folder_view_too)
420 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
421 MODEST_CONF_FOLDER_VIEW_KEY);
423 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
424 MODEST_CONF_MAIN_PANED_KEY);
426 /* We need to force a redraw here in order to get the right
427 position of the horizontal paned separator */
428 gtk_widget_show (GTK_WIDGET (self));
433 save_state (ModestWindow *window)
436 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
437 ModestMainWindowPrivate *priv;
439 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
440 conf = modest_runtime_get_conf ();
442 modest_widget_memory_save (conf,G_OBJECT(self),
443 MODEST_CONF_MAIN_WINDOW_KEY);
444 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
445 MODEST_CONF_MAIN_PANED_KEY);
446 // modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
447 // MODEST_CONF_HEADER_VIEW_KEY);
448 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
449 MODEST_CONF_FOLDER_VIEW_KEY);
453 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
455 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
456 gtk_scrolled_window_add_with_viewport
457 (GTK_SCROLLED_WINDOW(win), widget);
459 gtk_container_add (GTK_CONTAINER(win),
464 /* static gboolean */
465 /* on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self) */
467 /* modest_window_save_state (MODEST_WINDOW(self)); */
472 /* on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data) */
475 /* printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message); */
477 /* if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL) */
478 /* /\* Don't show waste the user's time by showing him a dialog telling him */
479 /* * that he has just cancelled something: *\/ */
483 /* /\* Get the server name: *\/ */
484 /* const gchar* server_name = NULL; */
486 /* TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account ( */
487 /* TNY_CAMEL_SEND_QUEUE (self)); */
488 /* if (server_account) { */
489 /* server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account)); */
491 /* g_object_unref (server_account); */
492 /* server_account = NULL; */
495 /* if (!server_name) */
496 /* server_name = _("Unknown Server"); */
498 /* /\* Show the appropriate message text for the GError: *\/ */
499 /* gchar *message = NULL; */
501 /* switch (err->code) { */
502 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED: */
503 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
505 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE: */
506 /* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */
508 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED: */
509 /* /\* TODO: This logical ID seems more suitable for a wrong username or password than for a */
510 /* * wrong authentication method. The user is unlikely to guess at the real cause. */
512 /* message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name); */
514 /* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND: */
515 /* /\* TODO: Tinymail is still sending this sometimes when it should */
516 /* * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. *\/ */
518 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
522 /* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */
525 /* modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message); */
526 /* g_free (message); */
528 /* /\* TODO: Offer to remove the message, to avoid messages in future? *\/ */
530 /* TnyFolder *outbox = tny_send_queue_get_outbox (queue); */
531 /* tny_folder_remove_msg (outbox, header, NULL); */
532 /* tny_folder_sync (outbox, TRUE, NULL); */
533 /* g_object_unref (outbox); */
543 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
545 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
547 GList *oerrsignals = priv->queue_err_signals;
548 while (oerrsignals) {
549 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
550 g_signal_handler_disconnect (esignal->queue, esignal->signal);
551 g_slice_free (QueueErrorSignal, esignal);
552 oerrsignals = g_list_next (oerrsignals);
554 g_list_free (priv->queue_err_signals);
555 priv->queue_err_signals = NULL;
559 /* on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self) */
561 /* ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); */
563 /* /\* When going online, do the equivalent of pressing the send/receive button, */
564 /* * as per the specification: */
565 /* * (without the check for >0 accounts, though that is not specified): *\/ */
567 /* TnyDevice *device = tny_account_store_get_device (store); */
569 /* /\* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); *\/ */
571 /* /\* Check that we are really online. */
572 /* * This signal should not be emitted when we are not connected, */
573 /* * but it seems to happen sometimes: *\/ */
574 /* if (!tny_device_is_online (device)) */
577 /* const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device)); */
578 /* printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id); */
580 /* /\* Stop the existing send queues: *\/ */
581 /* modest_runtime_remove_all_send_queues (); */
583 /* /\* Create the send queues again, using the appropriate transport accounts */
584 /* * for this new connection. */
585 /* * This could be the first time that they are created if this is the first */
586 /* * connection. *\/ */
587 /* /\* TODO: Does this really destroy the TnySendQueues and their threads */
588 /* * We do not want 2 TnySendQueues to exist with the same underlying */
589 /* * outbox directory. *\/ */
591 /* modest_main_window_cleanup_queue_error_signals (self); */
593 /* GSList *account_names = modest_account_mgr_account_names ( */
594 /* modest_runtime_get_account_mgr(), */
595 /* TRUE /\* enabled accounts only *\/); */
596 /* GSList *iter = account_names; */
598 /* const gchar *account_name = (const gchar*)(iter->data); */
599 /* if (account_name) { */
600 /* TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT ( */
601 /* modest_tny_account_store_get_transport_account_for_open_connection */
602 /* (modest_runtime_get_account_store(), account_name)); */
604 /* /\* Q: Is this the first location where the send-queues are requested? *\/ */
605 /* QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal); */
606 /* printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name, */
607 /* tny_account_get_id(TNY_ACCOUNT(account))); */
608 /* esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account)); */
609 /* esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened", */
610 /* G_CALLBACK (on_sendqueue_error_happened), self); */
611 /* priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal); */
615 /* iter = g_slist_next (iter); */
618 /* modest_account_mgr_free_account_names (account_names); */
619 /* account_names = NULL; */
621 /* modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self)); */
625 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
627 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
630 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
634 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
636 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
638 /* Update visibility */
641 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
645 modest_main_window_disconnect_signals (ModestWindow *self)
647 ModestMainWindowPrivate *priv;
648 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
650 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
651 priv->sighandlers = NULL;
655 connect_signals (ModestMainWindow *self)
657 ModestWindowPrivate *parent_priv;
658 ModestMainWindowPrivate *priv;
661 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
662 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
666 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
667 G_OBJECT(priv->folder_view), "key-press-event",
668 G_CALLBACK(on_inner_widgets_key_pressed), self);
669 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder_selection_changed",
670 G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
671 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
672 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
673 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event",
674 G_CALLBACK (on_folder_view_focus_in), self);
676 /* Folder view CSM */
677 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
678 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
679 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
680 G_CALLBACK(_folder_view_csm_menu_activated),
683 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
684 G_CALLBACK(modest_ui_actions_on_header_selected), self);
685 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
686 G_CALLBACK(modest_ui_actions_on_header_activated), self);
687 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
688 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
689 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
690 G_CALLBACK(on_inner_widgets_key_pressed), self);
691 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
692 G_CALLBACK(_on_msg_count_changed), self);
693 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
694 G_CALLBACK (on_header_view_focus_in), self);
696 /* Header view CSM */
697 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
698 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
699 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
700 G_CALLBACK(_header_view_csm_menu_activated),
704 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
705 G_CALLBACK (modest_main_window_window_state_event),
708 /* Mail Operation Queue */
709 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_mail_operation_queue ()),
710 "queue-changed", G_CALLBACK (on_queue_changed), self);
712 /* Track changes in the device name */
713 priv->notification_id = modest_conf_listen_to_namespace (modest_runtime_get_conf (),
714 MODEST_CONF_NAMESPACE);
715 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(modest_runtime_get_conf ()),
716 "key_changed", G_CALLBACK (on_configuration_key_changed),
719 /* Track account changes. We need to refresh the toolbar */
720 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
721 "account_inserted", G_CALLBACK (account_number_changed),
723 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
724 "account_removed", G_CALLBACK (account_number_changed),
727 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store()),
728 "password_requested",
729 G_CALLBACK (modest_ui_actions_on_password_requested), self);
733 /** Idle handler, to send/receive at startup .*/
735 sync_accounts_cb (ModestMainWindow *win)
737 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
738 return FALSE; /* Do not call this idle handler again. */
742 static void on_hildon_program_is_topmost_notify(GObject *self,
743 GParamSpec *propert_param, gpointer user_data)
745 HildonProgram *app = HILDON_PROGRAM (self);
748 ModestWindow* self = MODEST_WINDOW(user_data);
751 /* Note that use of hildon_program_set_can_hibernate()
752 * is generally referred to as "setting the killable flag",
753 * though hibernation does not seem equal to death.
756 if (hildon_program_get_is_topmost (app)) {
757 /* Prevent hibernation when the progam comes to the foreground,
758 * because hibernation should only happen when the application
759 * is in the background: */
760 hildon_program_set_can_hibernate (app, FALSE);
762 /* Allow hibernation if the program has gone to the background: */
764 /* However, prevent hibernation while the settings are being changed: */
765 const gboolean hibernation_prevented =
766 modest_window_mgr_get_hibernation_is_prevented (
767 modest_runtime_get_window_mgr ());
769 if (hibernation_prevented)
770 hildon_program_set_can_hibernate (app, FALSE);
772 /* Allow hibernation, after saving the state: */
773 modest_osso_save_state();
774 hildon_program_set_can_hibernate (app, TRUE);
781 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
783 GtkWidget *folder_win = (GtkWidget *) user_data;
784 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
786 priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
787 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
788 /* wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
790 gtk_widget_show (GTK_WIDGET (priv->folder_view));
792 /* Connect signals */
793 connect_signals ((ModestMainWindow*)self);
795 /* Set account store */
796 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
797 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
799 /* Load previous osso state, for instance if we are being restored from
801 modest_osso_load_state ();
803 /* Restore window & widget settings */
805 restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
807 /* The UI spec wants us to show a connection dialog when the application is
808 * started by the user, if there is no connection.
809 * Do this before showing the account wizard,
810 * because wizard needs a connection to discover capabilities. */
811 modest_platform_connect_and_wait (GTK_WINDOW (self), NULL);
813 /* Check if accounts exist and show the account wizard if not */
814 gboolean accounts_exist =
815 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
817 if (!accounts_exist) {
818 /* This is necessary to have the main window shown behind the dialog
819 It's an ugly hack... jschmid */
820 gtk_widget_show_all(GTK_WIDGET(self));
821 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
824 GtkAction *send_receive_all;
825 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
826 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
827 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
828 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
829 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
830 modest_account_mgr_free_account_names (accounts);
835 modest_main_window_new (void)
837 ModestMainWindow *self = NULL;
838 ModestMainWindowPrivate *priv = NULL;
839 ModestWindowPrivate *parent_priv = NULL;
840 GtkWidget *folder_win = NULL;
841 ModestDimmingRulesGroup *menu_rules_group = NULL;
842 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
843 GtkActionGroup *action_group = NULL;
844 GError *error = NULL;
845 ModestConf *conf = NULL;
846 GtkAction *action = NULL;
847 GdkPixbuf *window_icon;
849 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
850 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
851 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
853 parent_priv->ui_manager = gtk_ui_manager_new();
854 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
856 action_group = gtk_action_group_new ("ModestMainWindowActions");
857 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
859 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
860 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
862 /* Add common actions */
863 gtk_action_group_add_actions (action_group,
864 modest_action_entries,
865 G_N_ELEMENTS (modest_action_entries),
868 gtk_action_group_add_actions (action_group,
869 modest_folder_view_action_entries,
870 G_N_ELEMENTS (modest_folder_view_action_entries),
873 gtk_action_group_add_actions (action_group,
874 modest_header_view_action_entries,
875 G_N_ELEMENTS (modest_header_view_action_entries),
878 gtk_action_group_add_toggle_actions (action_group,
879 modest_toggle_action_entries,
880 G_N_ELEMENTS (modest_toggle_action_entries),
883 gtk_action_group_add_toggle_actions (action_group,
884 modest_main_window_toggle_action_entries,
885 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
888 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
889 g_object_unref (action_group);
891 /* Load the UI definition */
892 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
893 MODEST_UIDIR "modest-main-window-ui.xml", &error);
895 g_warning ("Could not merge modest-ui.xml: %s", error->message);
896 g_error_free (error);
900 /* Add common dimming rules */
901 modest_dimming_rules_group_add_rules (menu_rules_group,
902 modest_main_window_menu_dimming_entries,
903 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
905 modest_dimming_rules_group_add_rules (toolbar_rules_group,
906 modest_main_window_toolbar_dimming_entries,
907 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
910 /* Insert dimming rules group for this window */
911 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
912 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
913 g_object_unref (menu_rules_group);
914 g_object_unref (toolbar_rules_group);
916 /* Add accelerators */
917 gtk_window_add_accel_group (GTK_WINDOW (self),
918 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
920 /* Menubar. Update the state of some toggles */
921 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
922 conf = modest_runtime_get_conf ();
923 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
924 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
925 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
926 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
927 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
928 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
929 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
930 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
931 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
932 gtk_widget_show (parent_priv->menubar);
934 /* Get device name */
935 modest_maemo_utils_get_device_name ();
939 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
940 if (!priv->header_view)
941 g_printerr ("modest: cannot instantiate header view\n");
942 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
943 modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
944 MODEST_CONF_HEADER_VIEW_KEY);
946 /* Other style properties of header view */
947 g_object_set (G_OBJECT (priv->header_view),
950 /* gtk_widget_show (priv->header_view); */
953 priv->empty_view = create_empty_view ();
954 gtk_widget_show (priv->empty_view);
956 /* Create scrolled windows */
957 folder_win = gtk_scrolled_window_new (NULL, NULL);
958 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
959 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
961 GTK_POLICY_AUTOMATIC);
962 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
964 GTK_POLICY_AUTOMATIC);
965 /* gtk_widget_show (priv->contents_widget); */
968 priv->main_paned = gtk_hpaned_new ();
969 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
970 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
971 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
973 /* putting it all together... */
974 priv->main_vbox = gtk_vbox_new (FALSE, 6);
975 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
976 gtk_widget_show (priv->main_vbox);
978 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
980 HildonProgram *app = hildon_program_get_instance ();
981 hildon_program_add_window (app, HILDON_WINDOW (self));
983 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
984 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
986 g_signal_connect (G_OBJECT(self), "show",
987 G_CALLBACK (modest_main_window_on_show), folder_win);
989 /* Set window icon */
990 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
992 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
993 g_object_unref (window_icon);
996 /* Dont't restore settings here,
997 * because it requires a gtk_widget_show(),
998 * and we don't want to do that until later,
999 * so that the UI is not visible for non-menu D-Bus activation.
1001 /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1003 return MODEST_WINDOW(self);
1007 modest_main_window_close_all (ModestMainWindow *self)
1010 GtkResponseType response;
1012 /* Create the confirmation dialog MSG-NOT308 */
1013 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1014 _("emev_nc_close_windows"),
1015 _("mcen_bd_yes"), GTK_RESPONSE_YES,
1016 _("mcen_bd_no"), GTK_RESPONSE_NO,
1019 response = gtk_dialog_run (GTK_DIALOG (note));
1020 gtk_widget_destroy (GTK_WIDGET (note));
1022 if (response == GTK_RESPONSE_YES)
1030 modest_main_window_set_style (ModestMainWindow *self,
1031 ModestMainWindowStyle style)
1033 ModestMainWindowPrivate *priv;
1034 ModestWindowPrivate *parent_priv;
1038 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1040 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1041 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1043 /* no change -> nothing to do */
1044 if (priv->style == style)
1047 /* Get toggle button and update the state if needed. This will
1048 happen only when the set_style is not invoked from the UI,
1049 for example when it's called from widget memory */
1050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1051 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1052 if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1053 (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1054 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1055 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1056 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1059 priv->style = style;
1061 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1062 /* Remove main paned */
1063 g_object_ref (priv->main_paned);
1064 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1066 /* Reparent the contents widget to the main vbox */
1067 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1069 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1070 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1071 TnyIterator *iterator = tny_list_create_iterator (selection);
1073 tny_iterator_first (iterator);
1074 header = TNY_HEADER (tny_iterator_get_current (iterator));
1075 if (tny_header_get_subject (header))
1076 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1078 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1081 g_object_unref (header);
1083 g_object_unref (iterator);
1084 g_object_unref (selection);
1088 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1089 /* Remove header view */
1090 g_object_ref (priv->contents_widget);
1091 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1093 /* Reparent the main paned */
1094 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1095 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1099 g_return_if_reached ();
1102 /* Let header view grab the focus if it's being shown */
1103 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1104 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1106 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1109 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1112 ModestMainWindowStyle
1113 modest_main_window_get_style (ModestMainWindow *self)
1115 ModestMainWindowPrivate *priv;
1117 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1119 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1126 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1128 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1129 ModestWindowPrivate *parent_priv;
1130 ModestWindowMgr *mgr;
1131 gboolean is_fullscreen;
1132 GtkAction *fs_toggle_action;
1135 mgr = modest_runtime_get_window_mgr ();
1137 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1139 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1141 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1142 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1143 if (is_fullscreen != active) {
1144 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1153 set_homogeneous (GtkWidget *widget,
1156 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1157 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1161 modest_main_window_show_toolbar (ModestWindow *self,
1162 gboolean show_toolbar)
1164 ModestMainWindowPrivate *priv = NULL;
1165 ModestWindowPrivate *parent_priv = NULL;
1166 GtkWidget *reply_button = NULL, *menu = NULL;
1167 GtkWidget *placeholder = NULL;
1170 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1171 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1172 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1174 /* Set optimized view status */
1175 priv->optimized_view = !show_toolbar;
1177 if (!parent_priv->toolbar) {
1178 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1181 /* Set homogeneous toolbar */
1182 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1183 set_homogeneous, NULL);
1185 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1186 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1187 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1188 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1189 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1190 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1191 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1192 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1194 /* Add ProgressBar (Transfer toolbar) */
1195 priv->progress_bar = modest_progress_bar_widget_new ();
1196 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1197 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1198 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1199 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1200 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1202 /* Connect cancel 'clicked' signal to abort progress mode */
1203 g_signal_connect(priv->cancel_toolitem, "clicked",
1204 G_CALLBACK(cancel_progressbar),
1207 /* Add it to the observers list */
1208 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1211 hildon_window_add_toolbar (HILDON_WINDOW (self),
1212 GTK_TOOLBAR (parent_priv->toolbar));
1214 /* Set reply button tap and hold menu */
1215 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1216 "/ToolBar/ToolbarMessageReply");
1217 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1218 "/ToolbarReplyCSM");
1219 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1221 /* Set send & receive button tap and hold menu */
1222 account_number_changed (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1227 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1228 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1229 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1231 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1232 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1234 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1239 compare_display_names (ModestAccountData *a,
1240 ModestAccountData *b)
1242 return strcmp (a->display_name, b->display_name);
1246 account_number_changed (TnyAccountStore *account_store,
1247 const gchar *account_name,
1250 GSList *account_names, *iter, *accounts;
1251 ModestMainWindow *self;
1252 ModestMainWindowPrivate *priv;
1253 ModestWindowPrivate *parent_priv;
1254 ModestAccountMgr *mgr;
1255 gint i, num_accounts;
1256 GtkActionGroup *action_group;
1258 gchar *default_account;
1259 GtkWidget *send_receive_button, *item;
1260 GtkAction *send_receive_all = NULL;
1262 self = MODEST_MAIN_WINDOW (user_data);
1263 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1264 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1266 /* Get enabled account IDs */
1267 mgr = modest_runtime_get_account_mgr ();
1268 account_names = modest_account_mgr_account_names (mgr, TRUE);
1269 iter = account_names;
1273 ModestAccountData *account_data =
1274 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1275 accounts = g_slist_prepend (accounts, account_data);
1279 modest_account_mgr_free_account_names (account_names);
1280 account_names = NULL;
1282 /* Order the list of accounts by its display name */
1283 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1284 num_accounts = g_slist_length (accounts);
1286 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager,
1287 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1288 gtk_action_set_visible (send_receive_all, num_accounts > 1);
1290 /* Delete old send&receive popup items. We can not just do a
1291 menu_detach because it does not work well with
1293 if (priv->accounts_popup)
1294 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1295 (GtkCallback) gtk_widget_destroy, NULL);
1297 /* Delete old entries in the View menu. Do not free groups, it
1299 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1301 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1302 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1303 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1304 GTK_ACTION_GROUP (groups->data));
1307 if (priv->merge_ids) {
1308 for (i = 0; i < priv->merge_ids->len; i++)
1309 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1310 g_byte_array_free (priv->merge_ids, TRUE);
1312 /* We need to call this in order to ensure
1313 that the new actions are added in the right
1314 order (alphabetical */
1315 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1317 groups = g_list_next (groups);
1319 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1321 /* Get send receive button */
1322 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1323 "/ToolBar/ToolbarSendReceive");
1325 /* Create the menu */
1326 if (num_accounts > 1) {
1327 if (!priv->accounts_popup)
1328 priv->accounts_popup = gtk_menu_new ();
1329 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1330 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1331 g_signal_connect (G_OBJECT (item),
1333 G_CALLBACK (on_send_receive_csm_activated),
1335 item = gtk_separator_menu_item_new ();
1336 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1339 /* Create a new action group */
1340 default_account = modest_account_mgr_get_default_account (mgr);
1341 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1342 for (i = 0; i < num_accounts; i++) {
1343 gchar *display_name = NULL;
1345 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1347 /* Create display name. The UI specification specifies a different format string
1348 * to use for the default account, though both seem to be "%s", so
1349 * I don't see what the point is. murrayc. */
1350 if (default_account && account_data->account_name &&
1351 !(strcmp (default_account, account_data->account_name) == 0)) {
1352 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1353 account_data->display_name);
1356 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1357 account_data->display_name);
1360 /* Create action and add it to the action group. The
1361 action name must be the account name, this way we
1362 could know in the handlers the account to show */
1363 if(account_data && account_data->account_name) {
1364 gchar* item_name, *refresh_action_name;
1365 guint8 merge_id = 0;
1366 GtkAction *view_account_action, *refresh_account_action;
1368 view_account_action = gtk_action_new (account_data->account_name,
1369 display_name, NULL, NULL);
1370 gtk_action_group_add_action (action_group, view_account_action);
1372 /* Add ui from account data. We allow 2^9-1 account
1373 changes in a single execution because we're
1374 downcasting the guint to a guint8 in order to use a
1375 GByteArray. It should be enough. */
1376 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1377 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1378 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1379 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1381 "/MenuBar/ViewMenu/ViewMenuAdditions",
1383 account_data->account_name,
1384 GTK_UI_MANAGER_MENUITEM,
1387 /* Connect the action signal "activate" */
1388 g_signal_connect (G_OBJECT (view_account_action),
1390 G_CALLBACK (on_show_account_action_activated),
1393 /* Create the items for the Tools->Send&Receive submenu */
1394 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1395 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1396 display_name, NULL, NULL);
1397 printf("DEBUG: %s: menu display_name=%s\n", __FUNCTION__, display_name);
1398 gtk_action_group_add_action (action_group, refresh_account_action);
1400 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1401 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1402 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1404 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1406 refresh_action_name,
1407 GTK_UI_MANAGER_MENUITEM,
1409 g_free (refresh_action_name);
1411 g_signal_connect_data (G_OBJECT (refresh_account_action),
1413 G_CALLBACK (on_refresh_account_action_activated),
1414 g_strdup (account_data->account_name),
1415 (GClosureNotify) g_free,
1418 /* Create item and add it to the send&receive
1419 CSM. If there is only one account then
1421 if (priv->accounts_popup) {
1422 GtkWidget *label = gtk_label_new(NULL);
1423 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1424 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1426 gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1427 gtk_label_set_markup (GTK_LABEL (label), escaped);
1432 gtk_label_set_text (GTK_LABEL (label), display_name);
1435 item = gtk_menu_item_new ();
1436 gtk_container_add (GTK_CONTAINER (item), label);
1438 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1439 g_signal_connect_data (G_OBJECT (item),
1441 G_CALLBACK (on_send_receive_csm_activated),
1442 g_strdup (account_data->account_name),
1443 (GClosureNotify) g_free,
1450 g_free (display_name);
1453 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1455 /* We cannot do this in the loop above because this relies on the action
1456 * group being inserted. This makes the default account appear in bold.
1457 * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1458 for (i = 0; i < num_accounts; i++) {
1459 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1461 if(account_data->account_name && default_account &&
1462 strcmp (account_data->account_name, default_account) == 0) {
1463 gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1465 gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1466 GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1470 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1471 if (GTK_IS_LABEL (child)) {
1472 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1473 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1474 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1479 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1480 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1484 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1485 if (GTK_IS_LABEL (child)) {
1486 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1487 gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1488 gtk_label_set_markup (GTK_LABEL (child), bold_name);
1496 modest_account_mgr_free_account_data (mgr, account_data);
1499 if (priv->accounts_popup) {
1500 /* Mandatory in order to view the menu contents */
1501 gtk_widget_show_all (priv->accounts_popup);
1503 /* Setup tap_and_hold just if was not done before*/
1504 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1505 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1509 g_slist_free (accounts);
1510 g_free (default_account);
1513 /* Make sure that at least one account is viewed if there are any
1514 * accounts, for instance when adding the first account: */
1515 set_at_least_one_account_visible (self);
1519 * This function manages the key events used to navigate between
1520 * header and folder views (when the window is in split view)
1523 * -------------------------------------------------
1524 * HeaderView GDK_Left Move focus to folder view
1525 * FolderView GDK_Right Move focus to header view
1527 * There is no need to scroll to selected row, the widgets will be the
1528 * responsibles of doing that (probably managing the focus-in event
1531 on_inner_widgets_key_pressed (GtkWidget *widget,
1535 ModestMainWindowPrivate *priv;
1537 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1539 /* Do nothing if we're in SIMPLE style */
1540 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1543 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1544 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1545 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1546 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1552 set_alignment (GtkWidget *widget,
1555 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1556 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1560 create_empty_view (void)
1562 GtkLabel *label = NULL;
1563 GtkWidget *align = NULL;
1565 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1566 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1567 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1568 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1570 return GTK_WIDGET(align);
1574 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1576 /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1581 gchar *gray_color_markup;
1583 vbox = gtk_vbox_new (FALSE, 0);
1585 /* Obtain the secondary text color. We need a realized widget, that's why
1586 we get styled_widget from outside */
1587 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1589 gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1590 gray_color_markup = modest_text_utils_get_color_string (&color);
1592 // gray_color_markup is freed below
1593 gray_color_markup = g_strdup ("#BBBBBB");
1595 /* Account description: */
1597 if (modest_tny_account_is_virtual_local_folders (account)
1598 || (modest_tny_account_is_memory_card_account (account))) {
1600 /* Local folders: */
1602 /* Get device name */
1603 gchar *device_name = NULL;
1604 if (modest_tny_account_is_virtual_local_folders (account))
1605 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1606 MODEST_CONF_DEVICE_NAME, NULL);
1608 device_name = g_strdup (tny_account_get_name (account));
1610 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1611 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1612 gray_color_markup, tmp, device_name);
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);
1617 g_free (device_name);
1620 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1621 gtk_box_pack_start (GTK_BOX (vbox),
1622 gtk_label_new (tny_account_get_name (account)),
1625 /* Other accounts, such as IMAP and POP: */
1630 /* Put proto in uppercase */
1631 proto = g_string_new (tny_account_get_proto (account));
1632 proto = g_string_ascii_up (proto);
1634 /* note: mcen_fi_localroot_description is something like "%s account"
1635 * however, we should display "%s account: %s"... therefore, ugly tmp */
1636 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1637 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1638 gray_color_markup, tmp, tny_account_get_name (account));
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);
1644 g_string_free (proto, TRUE);
1650 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1651 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d",
1652 gray_color_markup, _("mcen_fi_rootfolder_messages"),
1653 modest_tny_folder_store_get_message_count (folder_store));
1654 label_w = gtk_label_new (NULL);
1655 gtk_label_set_markup (GTK_LABEL (label_w), label);
1656 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1660 label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d",
1662 _("mcen_fi_rootfolder_folders"),
1663 modest_tny_folder_store_get_folder_count (folder_store));
1664 label_w = gtk_label_new (NULL);
1665 gtk_label_set_markup (GTK_LABEL (label_w), label);
1666 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1670 if (modest_tny_account_is_virtual_local_folders (account)
1671 || modest_tny_account_is_memory_card_account (account)) {
1673 gchar *size = modest_text_utils_get_display_size (
1674 modest_tny_folder_store_get_local_size (folder_store));
1676 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1677 gray_color_markup, _("mcen_fi_rootfolder_size"),
1681 label_w = gtk_label_new (NULL);
1682 gtk_label_set_markup (GTK_LABEL (label_w), label);
1683 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1685 } else if (TNY_IS_ACCOUNT(folder_store)) {
1686 TnyAccount *account = TNY_ACCOUNT(folder_store);
1688 time_t last_updated;
1689 gchar *last_updated_string;
1690 /* Get last updated from configuration */
1691 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1692 tny_account_get_id (account),
1693 MODEST_ACCOUNT_LAST_UPDATED,
1695 if (last_updated > 0)
1696 last_updated_string = modest_text_utils_get_display_date(last_updated);
1698 last_updated_string = g_strdup (_("mcen_va_never"));
1700 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s",
1701 gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1702 label_w = gtk_label_new (NULL);
1703 gtk_label_set_markup (GTK_LABEL (label_w), label);
1704 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1705 g_free (last_updated_string);
1709 g_free (gray_color_markup);
1712 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1718 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1720 ModestMainWindowPrivate *priv = NULL;
1722 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1724 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1726 return priv->send_receive_in_progress;
1730 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1732 GtkAction *action = NULL;
1733 GtkWidget *widget = NULL;
1734 ModestMainWindowPrivate *priv = NULL;
1736 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1737 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1739 priv->send_receive_in_progress = TRUE;
1741 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1742 gtk_action_set_sensitive (action, FALSE);
1743 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1744 /* gtk_action_set_sensitive (action, FALSE); */
1745 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1746 gtk_widget_set_sensitive (widget, FALSE);
1750 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1752 GtkAction *action = NULL;
1753 GtkWidget *widget = NULL;
1754 ModestMainWindowPrivate *priv = NULL;
1756 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1757 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1759 priv->send_receive_in_progress = FALSE;
1761 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1762 gtk_action_set_sensitive (action, TRUE);
1763 /* action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1764 /* gtk_action_set_sensitive (action, TRUE); */
1765 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1766 gtk_widget_set_sensitive (widget, TRUE);
1771 _on_msg_count_changed (ModestHeaderView *header_view,
1773 TnyFolderChange *change,
1774 ModestMainWindow *main_window)
1776 printf ("DEBUG: %s\n", __FUNCTION__);
1777 gboolean folder_empty = FALSE;
1778 TnyFolderChangeChanged changed;
1779 ModestMainWindowPrivate *priv;
1781 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1782 g_return_if_fail (TNY_IS_FOLDER(folder));
1783 g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1784 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1786 changed = tny_folder_change_get_changed (change);
1788 /* If something changes */
1789 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1790 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1792 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1794 printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1796 /* Check header removed (hide marked as DELETED headers) */
1797 if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1798 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1801 /* Set contents style of headers view */
1803 modest_main_window_set_contents_style (main_window,
1804 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1805 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1808 modest_main_window_set_contents_style (main_window,
1809 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1815 modest_main_window_set_contents_style (ModestMainWindow *self,
1816 ModestMainWindowContentsStyle style)
1818 ModestMainWindowPrivate *priv;
1820 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1822 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1824 /* We allow to set the same content style than the previously
1825 set if there are details, because it could happen when we're
1826 selecting different accounts consecutively */
1827 if ((priv->contents_style == style) &&
1828 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1831 /* Remove previous child. Delete it if it was an account
1833 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1835 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1836 g_object_ref (content);
1837 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1838 g_object_ref (priv->empty_view);
1839 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1842 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1845 priv->contents_style = style;
1847 switch (priv->contents_style) {
1848 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1849 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1850 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1853 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1855 TnyFolderStore *selected_folderstore =
1856 modest_folder_view_get_selected (priv->folder_view);
1857 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1858 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1859 TNY_ACCOUNT (selected_folderstore));
1861 wrap_in_scrolled_window (priv->contents_widget,
1862 priv->details_widget);
1864 g_object_unref (selected_folderstore);
1865 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1871 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1872 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1873 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1877 g_return_if_reached ();
1881 gtk_widget_show_all (priv->contents_widget);
1884 ModestMainWindowContentsStyle
1885 modest_main_window_get_contents_style (ModestMainWindow *self)
1887 ModestMainWindowPrivate *priv;
1889 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1891 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1892 return priv->contents_style;
1897 on_configuration_key_changed (ModestConf* conf,
1899 ModestConfEvent event,
1900 ModestConfNotificationId id,
1901 ModestMainWindow *self)
1903 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1904 TnyAccount *account;
1907 priv->notification_id != id ||
1908 strcmp (key, MODEST_CONF_DEVICE_NAME))
1911 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1914 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1915 if (TNY_IS_ACCOUNT (account) &&
1916 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1919 const gchar *device_name;
1923 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1924 label = GTK_LABEL (children->data);
1926 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1927 MODEST_CONF_DEVICE_NAME, NULL);
1929 new_text = g_strdup_printf ("%s: %s",
1930 _("mcen_fi_localroot_description"),
1933 gtk_label_set_text (label, new_text);
1934 gtk_widget_show (GTK_WIDGET (label));
1937 g_list_free (children);
1939 g_object_unref (account);
1943 set_toolbar_transfer_mode (ModestMainWindow *self)
1945 ModestMainWindowPrivate *priv = NULL;
1947 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1949 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1951 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1953 if (priv->progress_bar_timeout > 0) {
1954 g_source_remove (priv->progress_bar_timeout);
1955 priv->progress_bar_timeout = 0;
1962 set_toolbar_mode (ModestMainWindow *self,
1963 ModestToolBarModes mode)
1965 ModestWindowPrivate *parent_priv = NULL;
1966 ModestMainWindowPrivate *priv = NULL;
1967 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1969 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1971 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1972 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1974 /* In case this was called before the toolbar exists: */
1975 if (!(parent_priv->toolbar))
1978 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1980 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1981 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1982 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1984 /* Sets current toolbar mode */
1985 priv->current_toolbar_mode = mode;
1987 /* Show and hide toolbar items */
1989 case TOOLBAR_MODE_NORMAL:
1991 gtk_action_set_visible (sort_action, TRUE);
1993 gtk_action_set_visible (refresh_action, TRUE);
1994 if (priv->progress_toolitem) {
1995 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1996 gtk_widget_hide (priv->progress_toolitem);
1998 if (priv->progress_bar)
1999 gtk_widget_hide (priv->progress_bar);
2002 gtk_action_set_visible (cancel_action, FALSE);
2003 /* if (priv->sort_toolitem) */
2004 /* gtk_widget_show (priv->sort_toolitem); */
2006 /* if (priv->refresh_toolitem) */
2007 /* gtk_widget_show (priv->refresh_toolitem); */
2009 /* if (priv->progress_toolitem) */
2010 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
2011 /* if (priv->progress_bar) */
2012 /* gtk_widget_hide (priv->progress_bar); */
2014 /* if (priv->cancel_toolitem) */
2015 /* gtk_widget_hide (priv->cancel_toolitem); */
2017 /* Hide toolbar if optimized view is enabled */
2018 if (priv->optimized_view)
2019 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2021 case TOOLBAR_MODE_TRANSFER:
2023 gtk_action_set_visible (sort_action, FALSE);
2025 gtk_action_set_visible (refresh_action, FALSE);
2027 gtk_action_set_visible (cancel_action, TRUE);
2028 if (priv->progress_toolitem) {
2029 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2030 gtk_widget_show (priv->progress_toolitem);
2032 if (priv->progress_bar)
2033 gtk_widget_show (priv->progress_bar);
2035 /* if (priv->sort_toolitem) */
2036 /* gtk_widget_hide (priv->sort_toolitem); */
2038 /* if (priv->refresh_toolitem) */
2039 /* gtk_widget_hide (priv->refresh_toolitem); */
2041 /* if (priv->progress_toolitem) */
2042 /* gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2043 /* if (priv->progress_bar) */
2044 /* gtk_widget_show (priv->progress_bar); */
2046 /* if (priv->cancel_toolitem) */
2047 /* gtk_widget_show (priv->cancel_toolitem); */
2049 /* Show toolbar if it's hiden (optimized view ) */
2050 if (priv->optimized_view)
2051 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2054 g_return_if_reached ();
2059 cancel_progressbar (GtkToolButton *toolbutton,
2060 ModestMainWindow *self)
2063 ModestMainWindowPrivate *priv;
2065 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2067 /* Get operation observers and cancel all the operations */
2068 tmp = priv->progress_widgets;
2070 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2071 tmp=g_slist_next(tmp);
2076 observers_empty (ModestMainWindow *self)
2079 ModestMainWindowPrivate *priv;
2080 gboolean is_empty = TRUE;
2081 guint pending_ops = 0;
2083 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2084 tmp = priv->progress_widgets;
2086 /* Check all observers */
2087 while (tmp && is_empty) {
2088 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2089 is_empty = pending_ops == 0;
2091 tmp = g_slist_next(tmp);
2098 on_queue_changed (ModestMailOperationQueue *queue,
2099 ModestMailOperation *mail_op,
2100 ModestMailOperationQueueNotification type,
2101 ModestMainWindow *self)
2103 ModestMainWindowPrivate *priv;
2104 ModestMailOperationTypeOperation op_type;
2105 ModestToolBarModes mode;
2107 gboolean mode_changed = FALSE;
2108 /* ModestMailOperationStatus status; */
2110 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2111 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2113 /* Get toolbar mode from operation id*/
2114 op_type = modest_mail_operation_get_type_operation (mail_op);
2116 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
2117 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2118 case MODEST_MAIL_OPERATION_TYPE_OPEN:
2119 mode = TOOLBAR_MODE_TRANSFER;
2120 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2121 mode_changed = TRUE;
2124 mode = TOOLBAR_MODE_NORMAL;
2129 /* Add operation observers and change toolbar if neccessary*/
2130 tmp = priv->progress_widgets;
2132 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2133 if (mode == TOOLBAR_MODE_TRANSFER) {
2135 set_toolbar_transfer_mode(self);
2137 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2139 tmp = g_slist_next (tmp);
2143 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2144 /* Change toolbar mode */
2145 if (mode == TOOLBAR_MODE_TRANSFER) {
2147 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2149 tmp = g_slist_next (tmp);
2152 /* If no more operations are being observed, NORMAL mode is enabled again */
2153 if (observers_empty (self)) {
2154 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2165 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2167 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2169 /* Get account data */
2170 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2171 ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2173 /* Set the new visible & active account */
2174 if (acc_data && acc_data->store_account) {
2175 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2176 acc_data->store_account->account_name);
2177 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2180 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2184 modest_account_mgr_free_account_data (mgr, acc_data);
2187 /* Make sure that at least one account is "viewed": */
2189 set_at_least_one_account_visible(ModestMainWindow *self)
2191 ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2192 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2194 if (!(priv->folder_view)) {
2195 /* It is too early to do this. */
2199 const gchar *active_server_account_name =
2200 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2201 if (!active_server_account_name ||
2202 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2204 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2205 if (first_modest_name) {
2206 set_account_visible (self, first_modest_name);
2207 g_free (first_modest_name);
2213 on_show_account_action_activated (GtkAction *action,
2216 ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2218 const gchar *acc_name = gtk_action_get_name (action);
2219 set_account_visible (self, acc_name);
2223 refresh_account (const gchar *account_name)
2227 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2229 /* If account_name == NULL, we must update all (option All) */
2231 modest_ui_actions_do_send_receive_all (win);
2233 modest_ui_actions_do_send_receive (account_name, win);
2238 on_refresh_account_action_activated (GtkAction *action,
2241 refresh_account ((const gchar*) user_data);
2245 on_send_receive_csm_activated (GtkMenuItem *item,
2248 refresh_account ((const gchar*) user_data);
2252 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2254 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2256 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2262 on_folder_view_focus_in (GtkWidget *widget,
2263 GdkEventFocus *event,
2266 ModestMainWindow *main_window = NULL;
2268 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2269 main_window = MODEST_MAIN_WINDOW (userdata);
2271 /* Update toolbar dimming state */
2272 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2278 on_header_view_focus_in (GtkWidget *widget,
2279 GdkEventFocus *event,
2282 ModestMainWindow *main_window = NULL;
2283 ModestMainWindowPrivate *priv = NULL;
2285 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2286 main_window = MODEST_MAIN_WINDOW (userdata);
2287 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2289 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2290 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2291 TnyIterator *iterator = tny_list_create_iterator (selection);
2294 tny_iterator_first (iterator);
2295 header = TNY_HEADER (tny_iterator_get_current (iterator));
2297 if (tny_header_get_subject (header))
2298 gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2300 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2303 g_object_unref (header);
2305 g_object_unref (iterator);
2306 g_object_unref (selection);
2310 /* Update toolbar dimming state */
2311 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2317 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2318 TnyFolderStore *folder_store,
2320 ModestMainWindow *main_window)
2322 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2323 GtkAction *action = NULL;
2324 gboolean show_reply = TRUE;
2325 gboolean show_forward = TRUE;
2326 gboolean show_cancel_send = FALSE;
2327 gboolean show_clipboard = TRUE;
2328 gboolean show_delete = TRUE;
2331 if (TNY_IS_ACCOUNT (folder_store)) {
2332 show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2333 } else if (TNY_IS_FOLDER (folder_store)) {
2334 if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2335 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2336 TNY_FOLDER (folder_store));
2337 switch (folder_type) {
2338 case TNY_FOLDER_TYPE_DRAFTS:
2339 show_clipboard = show_delete = TRUE;
2340 show_reply = show_forward = show_cancel_send = FALSE;
2342 case TNY_FOLDER_TYPE_SENT:
2343 show_forward = show_clipboard = show_delete = TRUE;
2344 show_reply = show_cancel_send = FALSE;
2346 case TNY_FOLDER_TYPE_OUTBOX:
2347 show_clipboard = show_delete = show_cancel_send = TRUE;
2348 show_reply = show_forward = FALSE;
2351 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2352 show_cancel_send = FALSE;
2355 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2356 show_cancel_send = FALSE;
2361 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2362 gtk_action_set_visible (action, show_reply);
2363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2364 gtk_action_set_visible (action, show_reply);
2365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2366 gtk_action_set_visible (action, show_forward);
2367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2368 gtk_action_set_visible (action, show_cancel_send);
2369 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2370 gtk_action_set_visible (action, show_clipboard);
2371 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2372 gtk_action_set_visible (action, show_clipboard);
2373 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2374 gtk_action_set_visible (action, show_clipboard);
2375 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2376 gtk_action_set_visible (action, show_delete);
2378 /* We finally call to the ui actions handler, after updating properly
2379 * the header view CSM */
2380 modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2385 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2386 GtkTreeModel *model,
2387 GtkTreeRowReference *row_reference,
2388 ModestMainWindow *self)
2390 ModestMainWindowPrivate *priv = NULL;
2391 GtkTreeModel *header_model = NULL;
2392 GtkTreePath *path = NULL;
2394 g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2395 g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2396 g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2398 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2399 header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2401 /* Do nothing if we changed the folder in the main view */
2402 if (header_model != model)
2405 /* Select the message in the header view */
2406 path = gtk_tree_row_reference_get_path (row_reference);
2407 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2409 gtk_tree_path_free (path);