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>
35 #include "modest-ui-priv.h"
36 #include "modest-ui.h"
37 #include "modest-ui-actions.h"
38 #include "modest-icon-names.h"
39 #include "modest-tny-platform-factory.h"
40 #include "modest-account-view-window.h"
41 #include "modest-main-window.h"
42 #include <modest-widget-memory.h>
43 #include <tny-error.h>
44 #include <tny-simple-list.h>
46 #define MODEST_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
50 typedef struct _GetMsgAsyncHelper {
51 ModestMainWindow *main_window;
57 typedef enum _ReplyForwardAction {
63 typedef struct _ReplyForwardHelper {
64 guint reply_forward_type;
65 ReplyForwardAction action;
70 static GObjectClass *parent_class = NULL;
72 /* 'private'/'protected' functions */
73 static void modest_ui_class_init (ModestUIClass *klass);
74 static void modest_ui_init (ModestUI *obj);
75 static void modest_ui_finalize (GObject *obj);
77 static void register_stock_icons ();
78 static void connect_signals (ModestUI *self);
79 /* static GtkUIManager *create_ui_manager (); */
81 static void reply_forward_func (gpointer data, gpointer user_data);
82 static void read_msg_func (gpointer data, gpointer user_data);
83 static void get_msg_cb (TnyFolder *folder,
88 static void reply_forward (GtkWidget *widget,
89 ReplyForwardAction action,
90 ModestMainWindow *main_window);
92 static void _modest_ui_actions_on_password_requested (ModestTnyAccountStore *account_store,
93 const gchar* account_name,
97 ModestMainWindow *main_window);
100 modest_ui_get_type (void)
102 static GType my_type = 0;
104 static const GTypeInfo my_info = {
105 sizeof(ModestUIClass),
106 NULL, /* base init */
107 NULL, /* base finalize */
108 (GClassInitFunc) modest_ui_class_init,
109 NULL, /* class finalize */
110 NULL, /* class data */
113 (GInstanceInitFunc) modest_ui_init,
116 my_type = g_type_register_static (G_TYPE_OBJECT,
125 modest_ui_class_init (ModestUIClass *klass)
127 GObjectClass *gobject_class;
128 gobject_class = (GObjectClass*) klass;
130 parent_class = g_type_class_peek_parent (klass);
131 gobject_class->finalize = modest_ui_finalize;
133 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
139 modest_ui_init (ModestUI *obj)
141 ModestUIPrivate *priv;
143 priv = MODEST_UI_GET_PRIVATE(obj);
145 priv->widget_factory = NULL;
146 priv->main_window = NULL;
147 priv->account_store = NULL;
152 modest_ui_finalize (GObject *obj)
155 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
157 if (priv->widget_factory) {
158 g_object_unref (G_OBJECT(priv->widget_factory));
159 priv->widget_factory = NULL;
162 if (priv->ui_manager) {
163 g_object_unref (G_OBJECT(priv->ui_manager));
164 priv->ui_manager = NULL;
167 G_OBJECT_CLASS(parent_class)->finalize (obj);
172 modest_ui_new (TnyAccountStore *account_store)
175 ModestUIPrivate *priv;
176 TnyPlatformFactory *fact;
177 ModestAccountMgr *account_mgr;
179 obj = g_object_new(MODEST_TYPE_UI, NULL);
180 priv = MODEST_UI_GET_PRIVATE(obj);
182 /* Get the platform-dependent instances */
183 fact = modest_tny_platform_factory_get_instance ();
185 priv->account_store = account_store;
187 account_mgr = modest_tny_platform_factory_get_account_mgr_instance
188 (MODEST_TNY_PLATFORM_FACTORY(fact));
190 g_printerr ("modest: could not create ModestAccountMgr instance\n");
191 g_object_unref (obj);
195 priv->widget_factory = modest_widget_factory_new ();
196 if (!priv->widget_factory) {
197 g_printerr ("modest: could not initialize widget factory\n");
201 /* Register our own icons as stock icons in order to
202 use them with the UI manager */
203 register_stock_icons ();
205 return MODEST_UI(obj);
209 on_main_window_destroy (GtkObject *widget, ModestUI *self)
211 /* FIXME: check if there any viewer/editing windows opened */
218 modest_ui_main_window (ModestUI *self)
220 ModestUIPrivate *priv;
222 g_return_val_if_fail (self, NULL);
223 priv = MODEST_UI_GET_PRIVATE(self);
225 if (!priv->main_window) {
227 /* Create main window */
228 priv->main_window = modest_main_window_new (priv->widget_factory,
229 priv->account_store);
231 connect_signals (self);
234 if (!priv->main_window)
235 g_printerr ("modest: could not create main window\n");
237 return priv->main_window;
241 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
243 ModestUIPrivate *priv;
244 ModestWindow *edit_window;
246 g_return_val_if_fail (self, NULL);
247 priv = MODEST_UI_GET_PRIVATE(self);
250 edit_window = modest_edit_msg_window_new (priv->widget_factory,
254 /* Connect Edit Window signals */
255 /* connect_edit_window_signals (self); */
261 * This function registers our custom toolbar icons, so they can be
262 * themed. The idea of this function was taken from the gtk-demo
265 register_stock_icons ()
267 static gboolean registered = FALSE;
271 GtkIconFactory *factory;
274 static GtkStockItem items[] = {
275 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
276 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
277 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
278 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
279 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
280 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
281 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
282 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
283 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
284 { MODEST_STOCK_STOP, "stop", 0, 0, NULL }
287 static gchar *items_names [] = {
288 MODEST_TOOLBAR_ICON_MAIL_SEND,
289 MODEST_TOOLBAR_ICON_NEW_MAIL,
290 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
291 MODEST_TOOLBAR_ICON_REPLY,
292 MODEST_TOOLBAR_ICON_REPLY_ALL,
293 MODEST_TOOLBAR_ICON_FORWARD,
294 MODEST_TOOLBAR_ICON_DELETE,
295 MODEST_TOOLBAR_ICON_NEXT,
296 MODEST_TOOLBAR_ICON_PREV,
297 MODEST_TOOLBAR_ICON_STOP
302 /* Register our stock items */
303 gtk_stock_add (items, G_N_ELEMENTS (items));
305 /* Add our custom icon factory to the list of defaults */
306 factory = gtk_icon_factory_new ();
307 gtk_icon_factory_add_default (factory);
309 /* Register icons to accompany stock items */
310 for (i = 0; i < G_N_ELEMENTS (items); i++) {
312 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
314 if (pixbuf != NULL) {
315 GtkIconSet *icon_set;
316 GdkPixbuf *transparent;
318 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
320 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
321 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
322 gtk_icon_set_unref (icon_set);
323 g_object_unref (pixbuf);
324 g_object_unref (transparent);
327 g_warning ("failed to load %s icon", items_names[i]);
329 /* Drop our reference to the factory, GTK will hold a reference. */
330 g_object_unref (factory);
334 /* FIXME: uninit these as well */
336 connect_signals (ModestUI *self)
339 ModestUIPrivate *priv;
340 ModestFolderView *folder_view;
341 ModestHeaderView *header_view;
342 ModestMsgView *msg_view;
345 priv = MODEST_UI_GET_PRIVATE(self);
347 folder_view = modest_widget_factory_get_folder_view (priv->widget_factory);
348 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
349 msg_view = modest_widget_factory_get_msg_preview (priv->widget_factory);
350 toggle = modest_widget_factory_get_online_toggle (priv->widget_factory);
351 device = tny_account_store_get_device (priv->account_store);
354 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
355 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
358 g_signal_connect (G_OBJECT(header_view), "status_update",
359 G_CALLBACK(_modest_ui_actions_on_header_status_update),
361 g_signal_connect (G_OBJECT(header_view), "header_selected",
362 G_CALLBACK(_modest_ui_actions_on_header_selected),
364 g_signal_connect (G_OBJECT(header_view), "item_not_found",
365 G_CALLBACK(_modest_ui_actions_on_item_not_found),
368 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
369 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
371 g_signal_connect (G_OBJECT(msg_view), "link_hover",
372 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
374 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
375 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
379 g_signal_connect (G_OBJECT(device), "connection_changed",
380 G_CALLBACK(_modest_ui_actions_on_connection_changed),
382 g_signal_connect (G_OBJECT(toggle), "toggled",
383 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
387 g_signal_connect (G_OBJECT (priv->account_store),
388 "password_requested",
389 G_CALLBACK(_modest_ui_actions_on_password_requested),
393 g_signal_connect (G_OBJECT(priv->main_window),
395 G_CALLBACK(on_main_window_destroy),
399 /* Init toggle in correct state */
400 _modest_ui_actions_on_connection_changed (device,
401 tny_device_is_online (device),
402 MODEST_MAIN_WINDOW (priv->main_window));
406 /* ***************************************************************** */
407 /* M O D E S T U I A C T I O N S */
408 /* ***************************************************************** */
410 _modest_ui_actions_on_about (GtkWidget *widget,
411 ModestMainWindow *main_window)
414 const gchar *authors[] = {
415 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
418 about = gtk_about_dialog_new ();
419 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
420 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
421 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
422 _("Copyright (c) 2006, Nokia Corporation\n"
423 "All rights reserved."));
424 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
425 _("a modest e-mail client\n\n"
426 "design and implementation: Dirk-Jan C. Binnema\n"
427 "contributions from the fine people at KernelConcepts and Igalia\n"
428 "uses the tinymail email framework written by Philip van Hoof"));
429 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
430 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
432 gtk_dialog_run (GTK_DIALOG (about));
433 gtk_widget_destroy(about);
437 _modest_ui_actions_on_delete (GtkWidget *widget,
438 ModestMainWindow *main_window)
440 ModestWidgetFactory *widget_factory;
441 ModestHeaderView *header_view;
442 TnyList *header_list;
446 widget_factory = modest_main_window_get_widget_factory (main_window);
447 header_view = modest_widget_factory_get_header_view (widget_factory);
448 header_list = modest_header_view_get_selected_headers (header_view);
449 g_object_unref (G_OBJECT(widget_factory));
452 iter = tny_list_create_iterator (header_list);
453 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
454 if (GTK_IS_TREE_MODEL_SORT (model))
455 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
458 ModestMailOperation *mail_op;
460 header = TNY_HEADER (tny_iterator_get_current (iter));
461 /* TODO: thick grain mail operation involving
462 a list of objects. Composite pattern ??? */
463 mail_op = modest_mail_operation_new ();
465 /* TODO: add confirmation dialog */
468 modest_mail_operation_remove_msg (mail_op, header, TRUE);
470 /* Remove from tree model */
471 if (modest_mail_operation_get_status (mail_op) ==
472 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
473 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
475 /* TODO: error handling management */
477 error = modest_mail_operation_get_error (mail_op);
478 g_warning (error->message);
481 g_object_unref (G_OBJECT (mail_op));
482 g_object_unref (header);
483 tny_iterator_next (iter);
485 } while (!tny_iterator_is_done (iter));
490 _modest_ui_actions_on_quit (GtkWidget *widget,
491 ModestMainWindow *main_window)
493 /* FIXME: save size of main window */
494 /* save_sizes (main_window); */
495 gtk_widget_destroy (GTK_WIDGET (main_window));
499 _modest_ui_actions_on_accounts (GtkWidget *widget,
500 ModestMainWindow *main_window)
502 GtkWidget *account_win;
503 ModestWidgetFactory *widget_factory;
505 widget_factory = modest_main_window_get_widget_factory (main_window);
506 account_win = modest_account_view_window_new (widget_factory);
507 g_object_unref (G_OBJECT(widget_factory));
509 gtk_window_set_transient_for (GTK_WINDOW (account_win),
510 GTK_WINDOW (main_window));
512 gtk_widget_show (account_win);
516 _modest_ui_actions_on_new_msg (GtkWidget *widget,
517 ModestMainWindow *main_window)
519 ModestWindow *msg_win;
520 ModestWidgetFactory *widget_factory;
521 TnyAccountStore *account_store;
523 widget_factory = modest_main_window_get_widget_factory (main_window);
524 account_store = modest_main_window_get_account_store (main_window);
525 msg_win = modest_edit_msg_window_new (widget_factory,
527 MODEST_EDIT_TYPE_NEW);
528 g_object_unref (G_OBJECT (widget_factory));
529 g_object_unref (G_OBJECT (account_store));
531 gtk_widget_show (GTK_WIDGET (msg_win));
535 reply_forward_func (gpointer data, gpointer user_data)
537 ModestWidgetFactory *widget_factory;
538 TnyHeader *new_header;
539 TnyMsg *msg, *new_msg;
540 TnyAccountStore *account_store;
541 GetMsgAsyncHelper *helper;
542 ReplyForwardHelper *rf_helper;
544 ModestEditType edit_type;
546 msg = TNY_MSG (data);
547 helper = (GetMsgAsyncHelper *) user_data;
548 rf_helper = (ReplyForwardHelper *) helper->user_data;
550 /* Create reply mail */
551 switch (rf_helper->action) {
554 modest_mail_operation_create_reply_mail (msg,
556 rf_helper->reply_forward_type,
557 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
558 case ACTION_REPLY_TO_ALL:
560 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
561 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
562 edit_type = MODEST_EDIT_TYPE_REPLY;
566 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
567 edit_type = MODEST_EDIT_TYPE_FORWARD;
570 g_return_if_reached ();
574 new_header = tny_msg_get_header (new_msg);
575 tny_header_set_from (new_header, rf_helper->from);
576 g_object_unref (G_OBJECT (new_header));
578 /* Show edit window */
579 widget_factory = modest_main_window_get_widget_factory (helper->main_window);
580 account_store = modest_main_window_get_account_store (helper->main_window);
581 msg_win = modest_edit_msg_window_new (widget_factory,
583 MODEST_EDIT_TYPE_NEW);
584 g_object_unref (G_OBJECT (widget_factory));
585 g_object_unref (G_OBJECT (account_store));
586 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
588 gtk_widget_show (GTK_WIDGET (msg_win));
591 g_object_unref (G_OBJECT (new_msg));
592 g_free (rf_helper->from);
593 g_slice_free (ReplyForwardHelper, rf_helper);
597 * Common code for the reply and forward actions
600 reply_forward (GtkWidget *widget,
601 ReplyForwardAction action,
602 ModestMainWindow *main_window)
604 ModestHeaderView *header_view;
605 ModestWidgetFactory *widget_factory;
606 TnyList *header_list;
607 guint reply_forward_type;
609 TnyPlatformFactory *plat_factory;
613 GetMsgAsyncHelper *helper;
614 ReplyForwardHelper *rf_helper;
617 plat_factory = modest_tny_platform_factory_get_instance ();
618 conf = modest_tny_platform_factory_get_conf_instance
619 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
621 /* Get reply or forward type */
622 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
623 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
624 reply_forward_type = modest_conf_get_int (conf, key, NULL);
627 /* Get the list of headers */
628 widget_factory = modest_main_window_get_widget_factory (main_window);
629 header_view = modest_widget_factory_get_header_view (widget_factory);
630 header_list = modest_header_view_get_selected_headers (header_view);
631 g_object_unref (G_OBJECT(widget_factory));
636 /* We assume that we can only select messages of the
637 same folder and that we reply all of them from the
638 same account. In fact the interface currently only
639 allows single selection */
641 /* TODO: get the from string from account */
642 from = g_strdup ("Invalid");
645 rf_helper = g_slice_new0 (ReplyForwardHelper);
646 rf_helper->reply_forward_type = reply_forward_type;
647 rf_helper->action = action;
648 rf_helper->from = from;
650 helper = g_slice_new0 (GetMsgAsyncHelper);
651 helper->main_window = main_window;
652 helper->func = reply_forward_func;
653 helper->iter = tny_list_create_iterator (header_list);
654 helper->user_data = rf_helper;
656 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
657 folder = tny_header_get_folder (header);
659 /* The callback will call it per each header */
660 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
663 g_object_unref (G_OBJECT (folder));
667 _modest_ui_actions_on_reply (GtkWidget *widget,
668 ModestMainWindow *main_window)
670 reply_forward (widget, ACTION_REPLY, main_window);
674 _modest_ui_actions_on_forward (GtkWidget *widget,
675 ModestMainWindow *main_window)
677 reply_forward (widget, ACTION_FORWARD, main_window);
681 _modest_ui_actions_on_reply_all (GtkWidget *widget,
682 ModestMainWindow *main_window)
684 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
688 _modest_ui_actions_on_next (GtkWidget *widget,
689 ModestMainWindow *main_window)
691 ModestHeaderView *header_view;
692 ModestWidgetFactory *widget_factory;
694 widget_factory = modest_main_window_get_widget_factory (main_window);
695 header_view = modest_widget_factory_get_header_view (widget_factory);
696 g_object_unref (G_OBJECT(widget_factory));
698 modest_header_view_select_next (header_view);
702 _modest_ui_actions_toggle_view (GtkWidget *widget,
703 ModestMainWindow *main_window)
705 ModestHeaderView *header_view;
706 ModestWidgetFactory *widget_factory;
708 TnyPlatformFactory *plat_factory;
711 plat_factory = modest_tny_platform_factory_get_instance ();
712 conf = modest_tny_platform_factory_get_conf_instance
713 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
714 widget_factory = modest_main_window_get_widget_factory (main_window);
715 header_view = modest_widget_factory_get_header_view (widget_factory);
716 g_object_unref (G_OBJECT(widget_factory));
718 /* what is saved/restored is depending on the style; thus; we save with
719 * old style, then update the style, and restore for this new style*/
720 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
722 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
723 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
725 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
727 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
733 * Marks a message as read and passes it to the msg preview widget
736 read_msg_func (gpointer data, gpointer user_data)
738 ModestMsgView *msg_view;
739 ModestWidgetFactory *widget_factory;
742 GetMsgAsyncHelper *helper;
743 TnyHeaderFlags header_flags;
745 msg = TNY_MSG (data);
746 helper = (GetMsgAsyncHelper *) user_data;
748 /* mark message as seen; _set_flags crashes, bug in tinymail? */
749 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
750 header_flags = tny_header_get_flags (header);
751 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
752 g_object_unref (G_OBJECT (header));
754 /* Set message on msg view */
755 widget_factory = modest_main_window_get_widget_factory (helper->main_window);
756 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
757 g_object_unref (G_OBJECT(widget_factory));
758 modest_msg_view_set_message (msg_view, msg);
762 * This function is a generic handler for the tny_folder_get_msg_async
763 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
764 * contains a user provided function that is called inside this
765 * method. This will allow us to use this callback in many different
766 * places. This callback performs the common actions for the
767 * get_msg_async call, more specific actions will be done by the user
771 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
773 GetMsgAsyncHelper *helper;
775 helper = (GetMsgAsyncHelper *) user_data;
777 if (*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) {
778 ModestHeaderView *header_view;
779 ModestWidgetFactory *widget_factory;
781 widget_factory = modest_main_window_get_widget_factory (helper->main_window);
782 header_view = modest_widget_factory_get_header_view (widget_factory);
783 g_object_unref (G_OBJECT (widget_factory));
784 _modest_ui_actions_on_item_not_found (header_view,
785 MODEST_ITEM_TYPE_MESSAGE,
786 helper->main_window);
793 /* Call user function */
794 helper->func (msg, user_data);
796 /* Process next element (if exists) */
797 tny_iterator_next (helper->iter);
798 if (tny_iterator_is_done (helper->iter)) {
800 headers = tny_iterator_get_list (helper->iter);
802 g_object_unref (G_OBJECT (headers));
803 g_object_unref (G_OBJECT (helper->iter));
804 g_slice_free (GetMsgAsyncHelper, helper);
806 tny_folder_get_msg_async (folder,
807 TNY_HEADER (tny_iterator_get_current (helper->iter)),
812 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
814 ModestMainWindow *main_window)
817 GetMsgAsyncHelper *helper;
820 /* when there's no header, clear the msgview */
822 ModestMsgView *msg_view;
823 ModestWidgetFactory *widget_factory;
824 widget_factory = modest_main_window_get_widget_factory (main_window);
825 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
826 modest_msg_view_set_message (msg_view, NULL);
830 folder = tny_header_get_folder (TNY_HEADER(header));
833 list = tny_simple_list_new ();
834 tny_list_prepend (list, G_OBJECT (header));
836 /* Fill helper data */
837 helper = g_slice_new0 (GetMsgAsyncHelper);
838 helper->main_window = main_window;
839 helper->iter = tny_list_create_iterator (list);
840 helper->func = read_msg_func;
842 tny_folder_get_msg_async (TNY_FOLDER(folder),
847 g_object_unref (G_OBJECT (folder));
851 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
854 ModestMainWindow *main_window)
856 GtkLabel *folder_info_label;
857 TnyPlatformFactory *factory;
860 ModestHeaderView *header_view;
861 ModestWidgetFactory *widget_factory;
863 widget_factory = modest_main_window_get_widget_factory (main_window);
865 GTK_LABEL (modest_widget_factory_get_folder_info_label (widget_factory));
868 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
872 factory = modest_tny_platform_factory_get_instance ();
873 header_view = modest_widget_factory_get_header_view (widget_factory);
874 conf = modest_tny_platform_factory_get_conf_instance
875 (MODEST_TNY_PLATFORM_FACTORY(factory));
876 g_object_unref (G_OBJECT (widget_factory));
878 if (!selected) { /* the folder was unselected; save it's settings */
879 modest_widget_memory_save (conf, G_OBJECT (header_view),
881 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
882 modest_header_view_set_folder (header_view, NULL);
883 } else { /* the folder was selected */
886 num = tny_folder_get_all_count (folder);
887 unread = tny_folder_get_unread_count (folder);
889 title = g_strdup_printf ("Modest: %s",
890 tny_folder_get_name (folder));
892 gtk_window_set_title (GTK_WINDOW(main_window), title);
895 txt = g_strdup_printf (_("%d %s, %d unread"),
896 num, num==1 ? _("item") : _("items"), unread);
897 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
900 modest_header_view_set_folder (header_view, folder);
901 modest_widget_memory_restore (conf, G_OBJECT(header_view),
907 _modest_ui_actions_on_password_requested (ModestTnyAccountStore *account_store,
908 const gchar* account_name,
912 ModestMainWindow *main_window)
915 GtkWidget *dialog, *entry, *remember_pass_check;
917 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
918 GTK_WINDOW (main_window),
926 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
927 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
931 entry = gtk_entry_new_with_max_length (40);
932 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
933 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
935 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
938 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
939 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
942 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
944 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
945 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
952 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
957 gtk_widget_destroy (dialog);
959 while (gtk_events_pending ())
960 gtk_main_iteration ();
963 /****************************************************/
965 * below some stuff to clearup statusbar messages after 1,5 seconds....
968 GtkWidget *status_bar;
969 GtkWidget *progress_bar;
974 on_statusbar_remove_msg (StatusRemoveData *data)
976 /* we need to test types, as this callback maybe called after the
977 * widgets have been destroyed
979 if (GTK_IS_STATUSBAR(data->status_bar))
980 gtk_statusbar_remove (GTK_STATUSBAR(data->status_bar),
982 if (GTK_IS_PROGRESS_BAR(data->progress_bar))
983 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(data->progress_bar),
990 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
993 StatusRemoveData *data;
994 GtkWidget *status_bar, *progress_bar;
999 progress_bar = modest_widget_factory_get_progress_bar (factory);
1000 status_bar = modest_widget_factory_get_status_bar (factory);
1002 id = gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
1004 data = g_new (StatusRemoveData, 1);
1005 data->status_bar = status_bar;
1006 data->progress_bar = progress_bar;
1009 g_timeout_add (1500, (GSourceFunc)on_statusbar_remove_msg, data);
1011 /****************************************************************************/
1014 _modest_ui_actions_on_connection_changed (TnyDevice *device,
1016 ModestMainWindow *main_window)
1018 GtkWidget *online_toggle;
1019 ModestHeaderView *header_view;
1020 ModestWidgetFactory *widget_factory;
1022 widget_factory = modest_main_window_get_widget_factory (main_window);
1023 header_view = modest_widget_factory_get_header_view (widget_factory);
1024 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
1026 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
1028 gtk_button_set_label (GTK_BUTTON(online_toggle),
1029 online ? _("Online") : _("Offline"));
1031 statusbar_push (widget_factory, 0,
1032 online ? _("Modest went online") : _("Modest went offline"));
1033 g_object_unref (G_OBJECT (widget_factory));
1035 /* If Modest has became online and the header view has a
1036 header selected then show it */
1038 GtkTreeSelection *selected;
1040 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1041 _modest_header_view_change_selection (selected, header_view);
1046 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
1047 ModestMainWindow *main_window)
1051 TnyPlatformFactory *factory;
1052 TnyAccountStore *account_store;
1054 /* Get device. Do not ask the platform factory for it, because
1055 it returns always a new one */
1056 factory = modest_tny_platform_factory_get_instance ();
1057 account_store = tny_platform_factory_new_account_store (factory);
1058 device = tny_account_store_get_device (account_store);
1060 online = gtk_toggle_button_get_active (toggle);
1063 tny_device_force_online (device);
1065 tny_device_force_offline (device);
1069 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1070 ModestItemType type,
1071 ModestMainWindow *main_window)
1077 TnyPlatformFactory *factory;
1078 TnyAccountStore *account_store;
1080 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1082 /* Get device. Do not ask the platform factory for it, because
1083 it returns always a new one */
1084 factory = modest_tny_platform_factory_get_instance ();
1085 account_store = tny_platform_factory_new_account_store (factory);
1086 device = tny_account_store_get_device (account_store);
1088 gdk_threads_enter ();
1089 online = tny_device_is_online (device);
1092 /* already online -- the item is simply not there... */
1093 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1095 GTK_MESSAGE_WARNING,
1097 _("The %s you selected cannot be found"),
1099 gtk_dialog_run (GTK_DIALOG(dialog));
1102 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1103 GTK_WINDOW (main_window),
1106 GTK_RESPONSE_REJECT,
1108 GTK_RESPONSE_ACCEPT,
1111 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1112 "Do you want to get online?"), item);
1113 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1114 gtk_label_new (txt), FALSE, FALSE, 0);
1115 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1118 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1119 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1120 tny_device_force_online (device);
1123 gtk_widget_destroy (dialog);
1124 gdk_threads_leave ();
1130 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1134 ModestMainWindow *main_window)
1136 GtkWidget *progress_bar;
1137 ModestWidgetFactory *widget_factory;
1139 widget_factory = modest_main_window_get_widget_factory (main_window);
1140 progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1143 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1144 (gdouble)num/(gdouble)total);
1146 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1148 statusbar_push (widget_factory, 0, msg);
1151 g_object_unref (G_OBJECT (widget_factory));
1157 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1159 ModestMainWindow *main_window)
1161 ModestWidgetFactory *widget_factory;
1163 widget_factory = modest_main_window_get_widget_factory (main_window);
1164 statusbar_push (widget_factory, 0, link);
1165 g_object_unref (G_OBJECT (widget_factory));
1167 /* TODO: do something */
1172 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1174 ModestMainWindow *main_window)
1177 ModestWidgetFactory *widget_factory;
1179 msg = g_strdup_printf (_("Opening %s..."), link);
1180 widget_factory = modest_main_window_get_widget_factory (main_window);
1181 statusbar_push (widget_factory, 0, msg);
1183 g_object_unref (G_OBJECT (widget_factory));
1187 /* TODO: do something */
1191 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1193 ModestMainWindow *main_window)
1196 ModestWidgetFactory *widget_factory;
1198 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1199 widget_factory = modest_main_window_get_widget_factory (main_window);
1200 statusbar_push (widget_factory, 0, msg);
1203 g_object_unref (G_OBJECT (widget_factory));
1204 /* TODO: do something */
1208 _modest_ui_actions_on_send (GtkWidget *widget,
1209 ModestEditMsgWindow *edit_window)
1211 TnyTransportAccount *transport_account;
1212 ModestMailOperation *mail_operation;
1215 data = modest_edit_msg_window_get_msg_data (edit_window);
1217 /* FIXME: Code added just for testing. The final version will
1218 use the send queue provided by tinymail and some
1223 TnyAccountStore *account_store;
1225 accounts = TNY_LIST(tny_simple_list_new ());
1226 account_store = modest_edit_msg_window_get_account_store (edit_window);
1227 tny_account_store_get_accounts (account_store, accounts,
1228 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1229 g_object_unref (G_OBJECT (account_store));
1231 iter = tny_list_create_iterator(accounts);
1232 tny_iterator_first (iter);
1233 if (tny_iterator_is_done (iter)) {
1234 /* FIXME: Add error handling through mail operation */
1235 g_printerr("modest: no transport accounts defined\n");
1236 modest_edit_msg_window_free_msg_data (edit_window, data);
1239 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1240 g_object_ref (transport_account);
1242 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1243 g_object_unref (G_OBJECT (accounts));
1244 g_object_unref (G_OBJECT (iter));
1247 mail_operation = modest_mail_operation_new ();
1249 modest_mail_operation_send_new_mail (mail_operation,
1259 g_object_unref (G_OBJECT (mail_operation));
1260 g_object_unref (G_OBJECT (transport_account));
1261 modest_edit_msg_window_free_msg_data (edit_window, data);
1263 /* Save settings and close the window */
1264 /* save_settings (edit_window) */
1265 gtk_widget_destroy (GTK_WIDGET (edit_window));