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.
32 #endif /*HAVE_CONFIG_H*/
34 #include <glib/gi18n.h>
36 #include "modest-ui-priv.h"
37 #include "modest-ui.h"
38 #include "modest-ui-actions.h"
39 #include "modest-icon-names.h"
40 #include "modest-tny-platform-factory.h"
41 #include "modest-account-view-window.h"
42 #include "modest-main-window.h"
43 #include "modest-mail-operation.h"
44 #include <modest-widget-memory.h>
45 #include <tny-error.h>
46 #include <tny-simple-list.h>
47 #include <tny-msg-view.h>
49 #define MODEST_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
53 typedef struct _GetMsgAsyncHelper {
54 ModestMainWindow *main_window;
60 typedef enum _ReplyForwardAction {
66 typedef struct _ReplyForwardHelper {
67 guint reply_forward_type;
68 ReplyForwardAction action;
73 static GObjectClass *parent_class = NULL;
75 /* 'private'/'protected' functions */
76 static void modest_ui_class_init (ModestUIClass *klass);
77 static void modest_ui_init (ModestUI *obj);
78 static void modest_ui_finalize (GObject *obj);
80 static void register_stock_icons ();
81 static void connect_signals (ModestUI *self);
83 static void reply_forward_func (gpointer data,
85 static void read_msg_func (gpointer data,
87 static void get_msg_cb (TnyFolder *folder,
92 static void reply_forward (GtkWidget *widget,
93 ReplyForwardAction action,
94 ModestMainWindow *main_window);
96 static gchar* ask_for_folder_name (GtkWindow *parent_window,
99 static void _modest_ui_actions_on_password_requested (ModestTnyAccountStore *account_store,
100 const gchar* account_name,
104 ModestMainWindow *main_window);
107 modest_ui_get_type (void)
109 static GType my_type = 0;
111 static const GTypeInfo my_info = {
112 sizeof(ModestUIClass),
113 NULL, /* base init */
114 NULL, /* base finalize */
115 (GClassInitFunc) modest_ui_class_init,
116 NULL, /* class finalize */
117 NULL, /* class data */
120 (GInstanceInitFunc) modest_ui_init,
123 my_type = g_type_register_static (G_TYPE_OBJECT,
132 modest_ui_class_init (ModestUIClass *klass)
134 GObjectClass *gobject_class;
135 gobject_class = (GObjectClass*) klass;
137 parent_class = g_type_class_peek_parent (klass);
138 gobject_class->finalize = modest_ui_finalize;
140 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
146 modest_ui_init (ModestUI *obj)
148 ModestUIPrivate *priv;
150 priv = MODEST_UI_GET_PRIVATE(obj);
152 priv->widget_factory = NULL;
153 priv->main_window = NULL;
154 priv->account_store = NULL;
159 modest_ui_finalize (GObject *obj)
161 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
163 if (priv->widget_factory) {
164 g_object_unref (G_OBJECT(priv->widget_factory));
165 priv->widget_factory = NULL;
168 if (priv->ui_manager) {
169 g_object_unref (G_OBJECT(priv->ui_manager));
170 priv->ui_manager = NULL;
173 G_OBJECT_CLASS(parent_class)->finalize (obj);
178 modest_ui_new (TnyAccountStore *account_store)
181 ModestUIPrivate *priv;
182 TnyPlatformFactory *fact;
183 ModestAccountMgr *account_mgr;
185 obj = g_object_new(MODEST_TYPE_UI, NULL);
186 priv = MODEST_UI_GET_PRIVATE(obj);
188 /* Get the platform-dependent instances */
189 fact = modest_tny_platform_factory_get_instance ();
191 priv->account_store = account_store;
193 account_mgr = modest_tny_platform_factory_get_account_mgr_instance
194 (MODEST_TNY_PLATFORM_FACTORY(fact));
196 g_printerr ("modest: could not create ModestAccountMgr instance\n");
197 g_object_unref (obj);
201 priv->widget_factory = modest_widget_factory_new ();
202 if (!priv->widget_factory) {
203 g_printerr ("modest: could not initialize widget factory\n");
207 /* Register our own icons as stock icons in order to
208 use them with the UI manager */
209 register_stock_icons ();
211 return MODEST_UI(obj);
215 on_main_window_destroy (GtkObject *widget, ModestUI *self)
217 /* FIXME: check if there any viewer/editing windows opened */
224 modest_ui_main_window (ModestUI *self)
226 ModestUIPrivate *priv;
228 g_return_val_if_fail (self, NULL);
229 priv = MODEST_UI_GET_PRIVATE(self);
231 if (!priv->main_window) {
233 /* Create main window */
234 priv->main_window = modest_main_window_new (priv->widget_factory,
235 priv->account_store);
237 connect_signals (self);
240 if (!priv->main_window)
241 g_printerr ("modest: could not create main window\n");
243 return priv->main_window;
247 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
249 ModestUIPrivate *priv;
250 ModestWindow *edit_window;
252 g_return_val_if_fail (self, NULL);
253 priv = MODEST_UI_GET_PRIVATE(self);
256 edit_window = modest_edit_msg_window_new (priv->widget_factory,
260 /* Connect Edit Window signals */
261 /* connect_edit_window_signals (self); */
267 * This function registers our custom toolbar icons, so they can be
268 * themed. The idea of this function was taken from the gtk-demo
271 register_stock_icons ()
273 static gboolean registered = FALSE;
277 GtkIconFactory *factory;
280 static GtkStockItem items[] = {
281 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
282 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
283 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
284 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
285 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
286 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
287 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
288 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
289 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
290 { MODEST_STOCK_STOP, "stop", 0, 0, NULL }
293 static gchar *items_names [] = {
294 MODEST_TOOLBAR_ICON_MAIL_SEND,
295 MODEST_TOOLBAR_ICON_NEW_MAIL,
296 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
297 MODEST_TOOLBAR_ICON_REPLY,
298 MODEST_TOOLBAR_ICON_REPLY_ALL,
299 MODEST_TOOLBAR_ICON_FORWARD,
300 MODEST_TOOLBAR_ICON_DELETE,
301 MODEST_TOOLBAR_ICON_NEXT,
302 MODEST_TOOLBAR_ICON_PREV,
303 MODEST_TOOLBAR_ICON_STOP
308 /* Register our stock items */
309 gtk_stock_add (items, G_N_ELEMENTS (items));
311 /* Add our custom icon factory to the list of defaults */
312 factory = gtk_icon_factory_new ();
313 gtk_icon_factory_add_default (factory);
315 /* Register icons to accompany stock items */
316 for (i = 0; i < G_N_ELEMENTS (items); i++) {
318 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
320 if (pixbuf != NULL) {
321 GtkIconSet *icon_set;
322 GdkPixbuf *transparent;
324 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
326 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
327 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
328 gtk_icon_set_unref (icon_set);
329 g_object_unref (pixbuf);
330 g_object_unref (transparent);
333 g_warning ("failed to load %s icon", items_names[i]);
335 /* Drop our reference to the factory, GTK will hold a reference. */
336 g_object_unref (factory);
340 /* FIXME: uninit these as well */
342 connect_signals (ModestUI *self)
345 ModestUIPrivate *priv;
346 ModestFolderView *folder_view;
347 ModestHeaderView *header_view;
348 ModestMsgView *msg_view;
351 priv = MODEST_UI_GET_PRIVATE(self);
353 folder_view = modest_widget_factory_get_folder_view (priv->widget_factory);
354 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
355 msg_view = modest_widget_factory_get_msg_preview (priv->widget_factory);
356 toggle = modest_widget_factory_get_online_toggle (priv->widget_factory);
357 device = tny_account_store_get_device (priv->account_store);
360 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
361 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
364 g_signal_connect (G_OBJECT(header_view), "status_update",
365 G_CALLBACK(_modest_ui_actions_on_header_status_update),
367 g_signal_connect (G_OBJECT(header_view), "header_selected",
368 G_CALLBACK(_modest_ui_actions_on_header_selected),
370 g_signal_connect (G_OBJECT(header_view), "item_not_found",
371 G_CALLBACK(_modest_ui_actions_on_item_not_found),
374 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
375 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
377 g_signal_connect (G_OBJECT(msg_view), "link_hover",
378 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
380 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
381 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
385 g_signal_connect (G_OBJECT(device), "connection_changed",
386 G_CALLBACK(_modest_ui_actions_on_connection_changed),
388 g_signal_connect (G_OBJECT(toggle), "toggled",
389 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
393 g_signal_connect (G_OBJECT (priv->account_store),
394 "password_requested",
395 G_CALLBACK(_modest_ui_actions_on_password_requested),
399 g_signal_connect (G_OBJECT(priv->main_window),
401 G_CALLBACK(on_main_window_destroy),
405 /* Init toggle in correct state */
406 _modest_ui_actions_on_connection_changed (device,
407 tny_device_is_online (device),
408 MODEST_MAIN_WINDOW (priv->main_window));
412 /* ***************************************************************** */
413 /* M O D E S T U I A C T I O N S */
414 /* ***************************************************************** */
416 _modest_ui_actions_on_about (GtkWidget *widget,
417 ModestMainWindow *main_window)
420 const gchar *authors[] = {
421 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
424 about = gtk_about_dialog_new ();
425 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
426 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
427 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
428 _("Copyright (c) 2006, Nokia Corporation\n"
429 "All rights reserved."));
430 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
431 _("a modest e-mail client\n\n"
432 "design and implementation: Dirk-Jan C. Binnema\n"
433 "contributions from the fine people at KernelConcepts and Igalia\n"
434 "uses the tinymail email framework written by Philip van Hoof"));
435 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
436 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
438 gtk_dialog_run (GTK_DIALOG (about));
439 gtk_widget_destroy(about);
443 _modest_ui_actions_on_delete (GtkWidget *widget,
444 ModestMainWindow *main_window)
446 ModestWidgetFactory *widget_factory;
447 ModestHeaderView *header_view;
448 TnyList *header_list;
452 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
453 header_view = modest_widget_factory_get_header_view (widget_factory);
454 header_list = modest_header_view_get_selected_headers (header_view);
455 g_object_unref (G_OBJECT(widget_factory));
458 iter = tny_list_create_iterator (header_list);
459 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
460 if (GTK_IS_TREE_MODEL_SORT (model))
461 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
464 ModestMailOperation *mail_op;
466 header = TNY_HEADER (tny_iterator_get_current (iter));
467 /* TODO: thick grain mail operation involving
468 a list of objects. Composite pattern ??? */
469 mail_op = modest_mail_operation_new ();
471 /* TODO: add confirmation dialog */
474 modest_mail_operation_remove_msg (mail_op, header, TRUE);
476 /* Remove from tree model */
477 if (modest_mail_operation_get_status (mail_op) ==
478 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
479 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
481 /* TODO: error handling management */
483 error = modest_mail_operation_get_error (mail_op);
484 g_warning (error->message);
487 g_object_unref (G_OBJECT (mail_op));
488 g_object_unref (header);
489 tny_iterator_next (iter);
491 } while (!tny_iterator_is_done (iter));
496 _modest_ui_actions_on_quit (GtkWidget *widget,
497 ModestMainWindow *main_window)
499 /* FIXME: save size of main window */
500 /* save_sizes (main_window); */
501 gtk_widget_destroy (GTK_WIDGET (main_window));
505 _modest_ui_actions_on_accounts (GtkWidget *widget,
506 ModestMainWindow *main_window)
508 GtkWidget *account_win;
509 ModestWidgetFactory *widget_factory;
511 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
512 account_win = modest_account_view_window_new (widget_factory);
513 g_object_unref (G_OBJECT(widget_factory));
515 gtk_window_set_transient_for (GTK_WINDOW (account_win),
516 GTK_WINDOW (main_window));
518 gtk_widget_show (account_win);
522 _modest_ui_actions_on_new_msg (GtkWidget *widget,
523 ModestMainWindow *main_window)
525 ModestWindow *msg_win;
526 ModestWidgetFactory *widget_factory;
527 TnyAccountStore *account_store;
529 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
530 account_store = modest_window_get_account_store (MODEST_WINDOW (main_window));
531 msg_win = modest_edit_msg_window_new (widget_factory,
533 MODEST_EDIT_TYPE_NEW);
534 g_object_unref (G_OBJECT (widget_factory));
535 g_object_unref (G_OBJECT (account_store));
537 gtk_widget_show_all (GTK_WIDGET (msg_win));
541 reply_forward_func (gpointer data, gpointer user_data)
543 ModestWidgetFactory *widget_factory;
544 TnyHeader *new_header;
545 TnyMsg *msg, *new_msg;
546 TnyAccountStore *account_store;
547 GetMsgAsyncHelper *helper;
548 ReplyForwardHelper *rf_helper;
549 ModestWindow *msg_win;
550 ModestEditType edit_type;
552 msg = TNY_MSG (data);
553 helper = (GetMsgAsyncHelper *) user_data;
554 rf_helper = (ReplyForwardHelper *) helper->user_data;
556 /* Create reply mail */
557 switch (rf_helper->action) {
560 modest_mail_operation_create_reply_mail (msg,
562 rf_helper->reply_forward_type,
563 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
564 case ACTION_REPLY_TO_ALL:
566 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
567 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
568 edit_type = MODEST_EDIT_TYPE_REPLY;
572 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
573 edit_type = MODEST_EDIT_TYPE_FORWARD;
576 g_return_if_reached ();
580 new_header = tny_msg_get_header (new_msg);
581 tny_header_set_from (new_header, rf_helper->from);
582 g_object_unref (G_OBJECT (new_header));
584 /* Show edit window */
585 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
586 account_store = modest_window_get_account_store (MODEST_WINDOW (helper->main_window));
587 msg_win = modest_edit_msg_window_new (widget_factory,
589 MODEST_EDIT_TYPE_NEW);
590 g_object_unref (G_OBJECT (widget_factory));
591 g_object_unref (G_OBJECT (account_store));
592 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
594 gtk_widget_show_all (GTK_WIDGET (msg_win));
597 g_object_unref (G_OBJECT (new_msg));
598 g_free (rf_helper->from);
599 g_slice_free (ReplyForwardHelper, rf_helper);
603 * Common code for the reply and forward actions
606 reply_forward (GtkWidget *widget,
607 ReplyForwardAction action,
608 ModestMainWindow *main_window)
610 ModestHeaderView *header_view;
611 ModestWidgetFactory *widget_factory;
612 TnyList *header_list;
613 guint reply_forward_type;
615 TnyPlatformFactory *plat_factory;
619 GetMsgAsyncHelper *helper;
620 ReplyForwardHelper *rf_helper;
623 plat_factory = modest_tny_platform_factory_get_instance ();
624 conf = modest_tny_platform_factory_get_conf_instance
625 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
627 /* Get reply or forward type */
628 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
629 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
630 reply_forward_type = modest_conf_get_int (conf, key, NULL);
633 /* Get the list of headers */
634 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
635 header_view = modest_widget_factory_get_header_view (widget_factory);
636 header_list = modest_header_view_get_selected_headers (header_view);
637 g_object_unref (G_OBJECT(widget_factory));
642 /* We assume that we can only select messages of the
643 same folder and that we reply all of them from the
644 same account. In fact the interface currently only
645 allows single selection */
647 /* TODO: get the from string from account */
648 from = g_strdup ("Invalid");
651 rf_helper = g_slice_new0 (ReplyForwardHelper);
652 rf_helper->reply_forward_type = reply_forward_type;
653 rf_helper->action = action;
654 rf_helper->from = from;
656 helper = g_slice_new0 (GetMsgAsyncHelper);
657 helper->main_window = main_window;
658 helper->func = reply_forward_func;
659 helper->iter = tny_list_create_iterator (header_list);
660 helper->user_data = rf_helper;
662 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
663 folder = tny_header_get_folder (header);
665 /* The callback will call it per each header */
666 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
669 g_object_unref (G_OBJECT (folder));
673 _modest_ui_actions_on_reply (GtkWidget *widget,
674 ModestMainWindow *main_window)
676 reply_forward (widget, ACTION_REPLY, main_window);
680 _modest_ui_actions_on_forward (GtkWidget *widget,
681 ModestMainWindow *main_window)
683 reply_forward (widget, ACTION_FORWARD, main_window);
687 _modest_ui_actions_on_reply_all (GtkWidget *widget,
688 ModestMainWindow *main_window)
690 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
694 _modest_ui_actions_on_next (GtkWidget *widget,
695 ModestMainWindow *main_window)
697 ModestHeaderView *header_view;
698 ModestWidgetFactory *widget_factory;
700 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
701 header_view = modest_widget_factory_get_header_view (widget_factory);
702 g_object_unref (G_OBJECT(widget_factory));
704 modest_header_view_select_next (header_view);
708 _modest_ui_actions_toggle_view (GtkWidget *widget,
709 ModestMainWindow *main_window)
711 ModestHeaderView *header_view;
712 ModestWidgetFactory *widget_factory;
714 TnyPlatformFactory *plat_factory;
717 plat_factory = modest_tny_platform_factory_get_instance ();
718 conf = modest_tny_platform_factory_get_conf_instance
719 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
720 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
721 header_view = modest_widget_factory_get_header_view (widget_factory);
722 g_object_unref (G_OBJECT(widget_factory));
724 /* what is saved/restored is depending on the style; thus; we save with
725 * old style, then update the style, and restore for this new style*/
726 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
728 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
729 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
731 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
733 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
739 * Marks a message as read and passes it to the msg preview widget
742 read_msg_func (gpointer data, gpointer user_data)
744 ModestMsgView *msg_view;
745 ModestWidgetFactory *widget_factory;
748 GetMsgAsyncHelper *helper;
749 TnyHeaderFlags header_flags;
751 msg = TNY_MSG (data);
752 helper = (GetMsgAsyncHelper *) user_data;
754 /* mark message as seen; _set_flags crashes, bug in tinymail? */
755 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
756 header_flags = tny_header_get_flags (header);
757 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
758 g_object_unref (G_OBJECT (header));
760 /* Set message on msg view */
761 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
762 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
763 g_object_unref (G_OBJECT(widget_factory));
764 modest_msg_view_set_message (msg_view, msg);
768 * This function is a generic handler for the tny_folder_get_msg_async
769 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
770 * contains a user provided function that is called inside this
771 * method. This will allow us to use this callback in many different
772 * places. This callback performs the common actions for the
773 * get_msg_async call, more specific actions will be done by the user
777 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
779 GetMsgAsyncHelper *helper;
781 helper = (GetMsgAsyncHelper *) user_data;
783 if (*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) {
784 ModestHeaderView *header_view;
785 ModestWidgetFactory *widget_factory;
787 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
788 header_view = modest_widget_factory_get_header_view (widget_factory);
789 g_object_unref (G_OBJECT (widget_factory));
790 _modest_ui_actions_on_item_not_found (header_view,
791 MODEST_ITEM_TYPE_MESSAGE,
792 helper->main_window);
799 /* Call user function */
800 helper->func (msg, user_data);
802 /* Process next element (if exists) */
803 tny_iterator_next (helper->iter);
804 if (tny_iterator_is_done (helper->iter)) {
806 headers = tny_iterator_get_list (helper->iter);
808 g_object_unref (G_OBJECT (headers));
809 g_object_unref (G_OBJECT (helper->iter));
810 g_slice_free (GetMsgAsyncHelper, helper);
812 tny_folder_get_msg_async (folder,
813 TNY_HEADER (tny_iterator_get_current (helper->iter)),
818 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
820 ModestMainWindow *main_window)
823 GetMsgAsyncHelper *helper;
826 /* when there's no header, clear the msgview */
828 ModestMsgView *msg_view;
829 ModestWidgetFactory *widget_factory;
830 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
831 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
832 modest_msg_view_set_message (msg_view, NULL);
836 folder = tny_header_get_folder (TNY_HEADER(header));
839 list = tny_simple_list_new ();
840 tny_list_prepend (list, G_OBJECT (header));
842 /* Fill helper data */
843 helper = g_slice_new0 (GetMsgAsyncHelper);
844 helper->main_window = main_window;
845 helper->iter = tny_list_create_iterator (list);
846 helper->func = read_msg_func;
848 tny_folder_get_msg_async (TNY_FOLDER(folder),
853 g_object_unref (G_OBJECT (folder));
857 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
860 ModestMainWindow *main_window)
862 GtkLabel *folder_info_label;
863 TnyPlatformFactory *factory;
866 ModestHeaderView *header_view;
867 ModestWidgetFactory *widget_factory;
869 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
871 GTK_LABEL (modest_widget_factory_get_folder_info_label (widget_factory));
874 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
878 factory = modest_tny_platform_factory_get_instance ();
879 header_view = modest_widget_factory_get_header_view (widget_factory);
880 conf = modest_tny_platform_factory_get_conf_instance
881 (MODEST_TNY_PLATFORM_FACTORY(factory));
882 g_object_unref (G_OBJECT (widget_factory));
884 if (!selected) { /* the folder was unselected; save it's settings */
885 modest_widget_memory_save (conf, G_OBJECT (header_view),
887 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
888 modest_header_view_set_folder (header_view, NULL);
889 } else { /* the folder was selected */
890 if (folder) { /* folder may be NULL */
894 num = tny_folder_get_all_count (folder);
895 unread = tny_folder_get_unread_count (folder);
897 title = g_strdup_printf ("Modest: %s",
898 tny_folder_get_name (folder));
900 gtk_window_set_title (GTK_WINDOW(main_window), title);
903 txt = g_strdup_printf (_("%d %s, %d unread"),
904 num, num==1 ? _("item") : _("items"), unread);
905 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
908 modest_header_view_set_folder (header_view, folder);
909 modest_widget_memory_restore (conf, G_OBJECT(header_view),
915 _modest_ui_actions_on_password_requested (ModestTnyAccountStore *account_store,
916 const gchar* account_name,
920 ModestMainWindow *main_window)
923 GtkWidget *dialog, *entry, *remember_pass_check;
925 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
926 GTK_WINDOW (main_window),
934 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
935 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
939 entry = gtk_entry_new_with_max_length (40);
940 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
941 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
943 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
946 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
947 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
950 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
952 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
953 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
960 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
965 gtk_widget_destroy (dialog);
967 while (gtk_events_pending ())
968 gtk_main_iteration ();
973 progress_bar_clean (GtkWidget *bar)
975 if (GTK_IS_PROGRESS_BAR(bar)) {
976 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
977 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
982 statusbar_clean (GtkWidget *bar)
984 if (GTK_IS_STATUSBAR(bar))
985 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
991 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
993 GtkWidget *status_bar, *progress_bar;
998 progress_bar = modest_widget_factory_get_progress_bar (factory);
999 status_bar = modest_widget_factory_get_status_bar (factory);
1001 gtk_widget_show (GTK_WIDGET(status_bar));
1002 gtk_widget_show (GTK_WIDGET(progress_bar));
1004 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
1006 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
1007 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
1009 /****************************************************************************/
1012 _modest_ui_actions_on_connection_changed (TnyDevice *device,
1014 ModestMainWindow *main_window)
1016 GtkWidget *online_toggle;
1017 ModestHeaderView *header_view;
1018 ModestWidgetFactory *widget_factory;
1020 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1021 header_view = modest_widget_factory_get_header_view (widget_factory);
1022 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
1024 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
1026 gtk_button_set_label (GTK_BUTTON(online_toggle),
1027 online ? _("Online") : _("Offline"));
1029 statusbar_push (widget_factory, 0,
1030 online ? _("Modest went online") : _("Modest went offline"));
1031 g_object_unref (G_OBJECT (widget_factory));
1033 /* If Modest has became online and the header view has a
1034 header selected then show it */
1036 GtkTreeSelection *selected;
1038 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1039 _modest_header_view_change_selection (selected, header_view);
1044 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
1045 ModestMainWindow *main_window)
1049 TnyPlatformFactory *factory;
1050 TnyAccountStore *account_store;
1052 /* Get device. Do not ask the platform factory for it, because
1053 it returns always a new one */
1054 factory = modest_tny_platform_factory_get_instance ();
1055 account_store = tny_platform_factory_new_account_store (factory);
1056 device = tny_account_store_get_device (account_store);
1058 online = gtk_toggle_button_get_active (toggle);
1061 tny_device_force_online (device);
1063 tny_device_force_offline (device);
1067 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1068 ModestItemType type,
1069 ModestMainWindow *main_window)
1075 TnyPlatformFactory *factory;
1076 TnyAccountStore *account_store;
1078 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1080 /* Get device. Do not ask the platform factory for it, because
1081 it returns always a new one */
1082 factory = modest_tny_platform_factory_get_instance ();
1083 account_store = tny_platform_factory_new_account_store (factory);
1084 device = tny_account_store_get_device (account_store);
1086 gdk_threads_enter ();
1087 online = tny_device_is_online (device);
1090 /* already online -- the item is simply not there... */
1091 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1093 GTK_MESSAGE_WARNING,
1095 _("The %s you selected cannot be found"),
1097 gtk_dialog_run (GTK_DIALOG(dialog));
1100 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1101 GTK_WINDOW (main_window),
1104 GTK_RESPONSE_REJECT,
1106 GTK_RESPONSE_ACCEPT,
1109 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1110 "Do you want to get online?"), item);
1111 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1112 gtk_label_new (txt), FALSE, FALSE, 0);
1113 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1116 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1117 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1118 tny_device_force_online (device);
1121 gtk_widget_destroy (dialog);
1122 gdk_threads_leave ();
1128 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1132 ModestMainWindow *main_window)
1134 GtkWidget *progress_bar;
1135 ModestWidgetFactory *widget_factory;
1138 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1139 progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1142 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1143 (gdouble)num/(gdouble)total);
1145 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1147 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1148 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1151 statusbar_push (widget_factory, 0, msg);
1154 g_object_unref (G_OBJECT (widget_factory));
1160 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1162 ModestMainWindow *main_window)
1164 ModestWidgetFactory *widget_factory;
1166 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1167 statusbar_push (widget_factory, 0, link);
1168 g_object_unref (G_OBJECT (widget_factory));
1170 /* TODO: do something */
1175 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1177 ModestMainWindow *main_window)
1180 ModestWidgetFactory *widget_factory;
1182 msg = g_strdup_printf (_("Opening %s..."), link);
1183 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1184 statusbar_push (widget_factory, 0, msg);
1186 g_object_unref (G_OBJECT (widget_factory));
1190 /* TODO: do something */
1194 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1196 ModestMainWindow *main_window)
1199 ModestWidgetFactory *widget_factory;
1201 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1202 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1203 statusbar_push (widget_factory, 0, msg);
1206 g_object_unref (G_OBJECT (widget_factory));
1207 /* TODO: do something */
1211 _modest_ui_actions_on_send (GtkWidget *widget,
1212 ModestEditMsgWindow *edit_window)
1214 TnyTransportAccount *transport_account;
1215 ModestMailOperation *mail_operation;
1218 data = modest_edit_msg_window_get_msg_data (edit_window);
1220 /* FIXME: Code added just for testing. The final version will
1221 use the send queue provided by tinymail and some
1226 TnyAccountStore *account_store;
1228 accounts = TNY_LIST(tny_simple_list_new ());
1229 account_store = modest_window_get_account_store (MODEST_WINDOW (edit_window));
1230 tny_account_store_get_accounts (account_store, accounts,
1231 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1232 g_object_unref (G_OBJECT (account_store));
1234 iter = tny_list_create_iterator(accounts);
1235 tny_iterator_first (iter);
1236 if (tny_iterator_is_done (iter)) {
1237 /* FIXME: Add error handling through mail operation */
1238 g_printerr("modest: no transport accounts defined\n");
1239 modest_edit_msg_window_free_msg_data (edit_window, data);
1242 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1243 g_object_ref (transport_account);
1245 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1246 g_object_unref (G_OBJECT (accounts));
1247 g_object_unref (G_OBJECT (iter));
1250 mail_operation = modest_mail_operation_new ();
1252 modest_mail_operation_send_new_mail (mail_operation,
1262 g_object_unref (G_OBJECT (mail_operation));
1263 g_object_unref (G_OBJECT (transport_account));
1264 modest_edit_msg_window_free_msg_data (edit_window, data);
1266 /* Save settings and close the window */
1267 /* save_settings (edit_window) */
1268 gtk_widget_destroy (GTK_WIDGET (edit_window));
1272 * Shows a dialog with an entry that asks for some text. The returned
1273 * value must be freed by the caller. The dialog window title will be
1277 ask_for_folder_name (GtkWindow *parent_window,
1280 GtkWidget *dialog, *entry;
1281 gchar *folder_name = NULL;
1283 /* Ask for folder name */
1284 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1288 GTK_RESPONSE_REJECT,
1290 GTK_RESPONSE_ACCEPT,
1292 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1293 gtk_label_new(title),
1296 entry = gtk_entry_new_with_max_length (40);
1297 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1301 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1303 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1304 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1306 gtk_widget_destroy (dialog);
1312 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1313 ModestMainWindow *main_window)
1315 TnyFolder *parent_folder;
1316 ModestFolderView *folder_view;
1317 ModestWidgetFactory *widget_factory;
1319 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1320 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1321 parent_folder = modest_folder_view_get_selected (folder_view);
1323 if (parent_folder) {
1326 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1327 _("Please enter a name for the new folder"));
1329 if (folder_name != NULL && strlen (folder_name) > 0) {
1330 TnyFolder *new_folder;
1331 ModestMailOperation *mail_op;
1333 mail_op = modest_mail_operation_new ();
1334 new_folder = modest_mail_operation_create_folder (mail_op,
1335 TNY_FOLDER_STORE (parent_folder),
1336 (const gchar *) folder_name);
1338 /* Do anything more? The model
1339 is automatically updated */
1340 g_object_unref (new_folder);
1342 g_object_unref (mail_op);
1344 g_object_unref (parent_folder);
1346 g_object_unref (G_OBJECT (widget_factory));
1350 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1351 ModestMainWindow *main_window)
1354 ModestFolderView *folder_view;
1355 ModestWidgetFactory *widget_factory;
1357 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1358 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1359 folder = modest_folder_view_get_selected (folder_view);
1364 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1365 _("Please enter a new name for the folder"));
1367 if (folder_name != NULL && strlen (folder_name) > 0) {
1368 ModestMailOperation *mail_op;
1370 mail_op = modest_mail_operation_new ();
1371 modest_mail_operation_rename_folder (mail_op,
1373 (const gchar *) folder_name);
1374 g_object_unref (mail_op);
1376 g_object_unref (folder);
1378 g_object_unref (G_OBJECT (widget_factory));
1382 delete_folder (ModestMainWindow *main_window,
1383 gboolean move_to_trash)
1386 ModestFolderView *folder_view;
1387 ModestWidgetFactory *widget_factory;
1388 ModestMailOperation *mail_op;
1390 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1391 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1392 folder = modest_folder_view_get_selected (folder_view);
1394 mail_op = modest_mail_operation_new ();
1395 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1396 g_object_unref (mail_op);
1400 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1401 ModestMainWindow *main_window)
1403 delete_folder (main_window, FALSE);
1407 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1408 ModestMainWindow *main_window)
1410 delete_folder (main_window, TRUE);