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,
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)
154 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
156 if (priv->widget_factory) {
157 g_object_unref (G_OBJECT(priv->widget_factory));
158 priv->widget_factory = NULL;
161 if (priv->ui_manager) {
162 g_object_unref (G_OBJECT(priv->ui_manager));
163 priv->ui_manager = NULL;
166 G_OBJECT_CLASS(parent_class)->finalize (obj);
171 modest_ui_new (TnyAccountStore *account_store)
174 ModestUIPrivate *priv;
175 TnyPlatformFactory *fact;
176 ModestAccountMgr *account_mgr;
178 obj = g_object_new(MODEST_TYPE_UI, NULL);
179 priv = MODEST_UI_GET_PRIVATE(obj);
181 /* Get the platform-dependent instances */
182 fact = modest_tny_platform_factory_get_instance ();
184 priv->account_store = account_store;
186 account_mgr = modest_tny_platform_factory_get_account_mgr_instance
187 (MODEST_TNY_PLATFORM_FACTORY(fact));
189 g_printerr ("modest: could not create ModestAccountMgr instance\n");
190 g_object_unref (obj);
194 priv->widget_factory = modest_widget_factory_new ();
195 if (!priv->widget_factory) {
196 g_printerr ("modest: could not initialize widget factory\n");
200 /* Register our own icons as stock icons in order to
201 use them with the UI manager */
202 register_stock_icons ();
204 return MODEST_UI(obj);
208 on_main_window_destroy (GtkObject *widget, ModestUI *self)
210 /* FIXME: check if there any viewer/editing windows opened */
217 modest_ui_main_window (ModestUI *self)
219 ModestUIPrivate *priv;
221 g_return_val_if_fail (self, NULL);
222 priv = MODEST_UI_GET_PRIVATE(self);
224 if (!priv->main_window) {
226 /* Create main window */
227 priv->main_window = modest_main_window_new (priv->widget_factory,
228 priv->account_store);
230 connect_signals (self);
233 if (!priv->main_window)
234 g_printerr ("modest: could not create main window\n");
236 return priv->main_window;
240 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
242 ModestUIPrivate *priv;
243 ModestWindow *edit_window;
245 g_return_val_if_fail (self, NULL);
246 priv = MODEST_UI_GET_PRIVATE(self);
249 edit_window = modest_edit_msg_window_new (priv->widget_factory,
253 /* Connect Edit Window signals */
254 /* connect_edit_window_signals (self); */
260 * This function registers our custom toolbar icons, so they can be
261 * themed. The idea of this function was taken from the gtk-demo
264 register_stock_icons ()
266 static gboolean registered = FALSE;
270 GtkIconFactory *factory;
273 static GtkStockItem items[] = {
274 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
275 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
276 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
277 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
278 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
279 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
280 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
281 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
282 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
283 /* { MODEST_STOCK_STOP, "stop", 0, 0, NULL } */
286 static gchar *items_names [] = {
287 MODEST_TOOLBAR_ICON_MAIL_SEND,
288 MODEST_TOOLBAR_ICON_NEW_MAIL,
289 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
290 MODEST_TOOLBAR_ICON_REPLY,
291 MODEST_TOOLBAR_ICON_REPLY_ALL,
292 MODEST_TOOLBAR_ICON_FORWARD,
293 MODEST_TOOLBAR_ICON_DELETE,
294 MODEST_TOOLBAR_ICON_NEXT,
295 MODEST_TOOLBAR_ICON_PREV,
296 /* MODEST_TOOLBAR_ICON_STOP */
301 /* Register our stock items */
302 gtk_stock_add (items, G_N_ELEMENTS (items));
304 /* Add our custom icon factory to the list of defaults */
305 factory = gtk_icon_factory_new ();
306 gtk_icon_factory_add_default (factory);
308 /* Register icons to accompany stock items */
309 for (i = 0; i < G_N_ELEMENTS (items); i++) {
311 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
313 if (pixbuf != NULL) {
314 GtkIconSet *icon_set;
315 GdkPixbuf *transparent;
317 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
319 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
320 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
321 gtk_icon_set_unref (icon_set);
322 g_object_unref (pixbuf);
323 g_object_unref (transparent);
326 g_warning ("failed to load %s icon", items_names[i]);
328 /* Drop our reference to the factory, GTK will hold a reference. */
329 g_object_unref (factory);
333 /* FIXME: uninit these as well */
335 connect_signals (ModestUI *self)
338 ModestUIPrivate *priv;
339 ModestFolderView *folder_view;
340 ModestHeaderView *header_view;
341 ModestMsgView *msg_view;
344 priv = MODEST_UI_GET_PRIVATE(self);
346 folder_view = modest_widget_factory_get_folder_view (priv->widget_factory);
347 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
348 msg_view = modest_widget_factory_get_msg_preview (priv->widget_factory);
349 toggle = modest_widget_factory_get_online_toggle (priv->widget_factory);
350 device = tny_account_store_get_device (priv->account_store);
353 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
354 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
357 g_signal_connect (G_OBJECT(header_view), "status_update",
358 G_CALLBACK(_modest_ui_actions_on_header_status_update),
360 g_signal_connect (G_OBJECT(header_view), "header_selected",
361 G_CALLBACK(_modest_ui_actions_on_header_selected),
363 g_signal_connect (G_OBJECT(header_view), "item_not_found",
364 G_CALLBACK(_modest_ui_actions_on_item_not_found),
367 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
368 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
370 g_signal_connect (G_OBJECT(msg_view), "link_hover",
371 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
373 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
374 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
378 g_signal_connect (G_OBJECT(device), "connection_changed",
379 G_CALLBACK(_modest_ui_actions_on_connection_changed),
381 g_signal_connect (G_OBJECT(toggle), "toggled",
382 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
386 g_signal_connect (G_OBJECT(priv->main_window),
388 G_CALLBACK(on_main_window_destroy),
392 /* Init toggle in correct state */
393 _modest_ui_actions_on_connection_changed (device,
394 tny_device_is_online (device),
395 MODEST_MAIN_WINDOW (priv->main_window));
399 /* ***************************************************************** */
400 /* M O D E S T U I A C T I O N S */
401 /* ***************************************************************** */
403 _modest_ui_actions_on_about (GtkWidget *widget,
404 ModestMainWindow *main_window)
407 const gchar *authors[] = {
408 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
411 about = gtk_about_dialog_new ();
412 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
413 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
414 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
415 _("Copyright (c) 2006, Nokia Corporation\n"
416 "All rights reserved."));
417 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
418 _("a modest e-mail client\n\n"
419 "design and implementation: Dirk-Jan C. Binnema\n"
420 "contributions from the fine people at KernelConcepts and Igalia\n"
421 "uses the tinymail email framework written by Philip van Hoof"));
422 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
423 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
425 gtk_dialog_run (GTK_DIALOG (about));
426 gtk_widget_destroy(about);
430 _modest_ui_actions_on_delete (GtkWidget *widget,
431 ModestMainWindow *main_window)
433 ModestWidgetFactory *widget_factory;
434 ModestHeaderView *header_view;
435 TnyList *header_list;
439 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
440 header_view = modest_widget_factory_get_header_view (widget_factory);
441 header_list = modest_header_view_get_selected_headers (header_view);
442 g_object_unref (G_OBJECT(widget_factory));
445 iter = tny_list_create_iterator (header_list);
446 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
447 if (GTK_IS_TREE_MODEL_SORT (model))
448 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
451 ModestMailOperation *mail_op;
453 header = TNY_HEADER (tny_iterator_get_current (iter));
454 /* TODO: thick grain mail operation involving
455 a list of objects. Composite pattern ??? */
456 mail_op = modest_mail_operation_new ();
458 /* TODO: add confirmation dialog */
461 modest_mail_operation_remove_msg (mail_op, header, TRUE);
463 /* Remove from tree model */
464 if (modest_mail_operation_get_status (mail_op) ==
465 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
466 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
468 /* TODO: error handling management */
470 error = modest_mail_operation_get_error (mail_op);
471 g_warning (error->message);
474 g_object_unref (G_OBJECT (mail_op));
475 g_object_unref (header);
476 tny_iterator_next (iter);
478 } while (!tny_iterator_is_done (iter));
483 _modest_ui_actions_on_quit (GtkWidget *widget,
484 ModestMainWindow *main_window)
486 /* FIXME: save size of main window */
487 /* save_sizes (main_window); */
488 gtk_widget_destroy (GTK_WIDGET (main_window));
492 _modest_ui_actions_on_accounts (GtkWidget *widget,
493 ModestMainWindow *main_window)
495 GtkWidget *account_win;
496 ModestWidgetFactory *widget_factory;
498 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
499 account_win = modest_account_view_window_new (widget_factory);
500 g_object_unref (G_OBJECT(widget_factory));
502 gtk_window_set_transient_for (GTK_WINDOW (account_win),
503 GTK_WINDOW (main_window));
505 gtk_widget_show (account_win);
509 _modest_ui_actions_on_new_msg (GtkWidget *widget,
510 ModestMainWindow *main_window)
512 ModestWindow *msg_win;
513 ModestWidgetFactory *widget_factory;
514 TnyAccountStore *account_store;
516 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
517 account_store = modest_window_get_account_store (MODEST_WINDOW (main_window));
518 msg_win = modest_edit_msg_window_new (widget_factory,
520 MODEST_EDIT_TYPE_NEW);
521 g_object_unref (G_OBJECT (widget_factory));
522 g_object_unref (G_OBJECT (account_store));
524 gtk_widget_show_all (GTK_WIDGET (msg_win));
528 reply_forward_func (gpointer data, gpointer user_data)
530 ModestWidgetFactory *widget_factory;
531 TnyHeader *new_header;
532 TnyMsg *msg, *new_msg;
533 TnyAccountStore *account_store;
534 GetMsgAsyncHelper *helper;
535 ReplyForwardHelper *rf_helper;
536 ModestWindow *msg_win;
537 ModestEditType edit_type;
539 msg = TNY_MSG (data);
540 helper = (GetMsgAsyncHelper *) user_data;
541 rf_helper = (ReplyForwardHelper *) helper->user_data;
543 /* Create reply mail */
544 switch (rf_helper->action) {
547 modest_mail_operation_create_reply_mail (msg,
549 rf_helper->reply_forward_type,
550 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
552 case ACTION_REPLY_TO_ALL:
554 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
555 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
556 edit_type = MODEST_EDIT_TYPE_REPLY;
560 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
561 edit_type = MODEST_EDIT_TYPE_FORWARD;
564 g_return_if_reached ();
568 g_warning ("Unable to create a message");
572 /* /\* Set from *\/ */
573 /* new_header = tny_msg_get_header (new_msg); */
574 /* tny_header_set_from (new_header, rf_helper->from); */
575 /* g_object_unref (G_OBJECT (new_header)); */
577 /* Show edit window */
578 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
579 account_store = modest_window_get_account_store (MODEST_WINDOW (helper->main_window));
580 msg_win = modest_edit_msg_window_new (widget_factory,
582 MODEST_EDIT_TYPE_NEW);
583 g_object_unref (G_OBJECT (widget_factory));
584 g_object_unref (G_OBJECT (account_store));
586 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
588 gtk_widget_show_all (GTK_WIDGET (msg_win));
591 g_object_unref (G_OBJECT (new_msg));
594 g_free (rf_helper->from);
595 g_slice_free (ReplyForwardHelper, rf_helper);
599 * Common code for the reply and forward actions
602 reply_forward (GtkWidget *widget,
603 ReplyForwardAction action,
604 ModestMainWindow *main_window)
606 ModestHeaderView *header_view;
607 ModestWidgetFactory *widget_factory;
608 TnyList *header_list;
609 guint reply_forward_type;
611 TnyPlatformFactory *plat_factory;
615 GetMsgAsyncHelper *helper;
616 ReplyForwardHelper *rf_helper;
619 plat_factory = modest_tny_platform_factory_get_instance ();
620 conf = modest_tny_platform_factory_get_conf_instance
621 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
623 /* Get reply or forward type */
624 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
625 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
626 reply_forward_type = modest_conf_get_int (conf, key, NULL);
629 /* Get the list of headers */
630 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
631 header_view = modest_widget_factory_get_header_view (widget_factory);
632 header_list = modest_header_view_get_selected_headers (header_view);
633 g_object_unref (G_OBJECT(widget_factory));
638 /* We assume that we can only select messages of the
639 same folder and that we reply all of them from the
640 same account. In fact the interface currently only
641 allows single selection */
643 /* TODO: get the from string from account */
644 from = g_strdup ("Invalid");
647 rf_helper = g_slice_new0 (ReplyForwardHelper);
648 rf_helper->reply_forward_type = reply_forward_type;
649 rf_helper->action = action;
650 rf_helper->from = from;
652 helper = g_slice_new0 (GetMsgAsyncHelper);
653 helper->main_window = main_window;
654 helper->func = reply_forward_func;
655 helper->iter = tny_list_create_iterator (header_list);
656 helper->user_data = rf_helper;
658 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
659 folder = tny_header_get_folder (header);
661 /* The callback will call it per each header */
662 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
665 g_object_unref (G_OBJECT (folder));
669 _modest_ui_actions_on_reply (GtkWidget *widget,
670 ModestMainWindow *main_window)
672 reply_forward (widget, ACTION_REPLY, main_window);
676 _modest_ui_actions_on_forward (GtkWidget *widget,
677 ModestMainWindow *main_window)
679 reply_forward (widget, ACTION_FORWARD, main_window);
683 _modest_ui_actions_on_reply_all (GtkWidget *widget,
684 ModestMainWindow *main_window)
686 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
690 _modest_ui_actions_on_next (GtkWidget *widget,
691 ModestMainWindow *main_window)
693 ModestHeaderView *header_view;
694 ModestWidgetFactory *widget_factory;
696 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
697 header_view = modest_widget_factory_get_header_view (widget_factory);
698 g_object_unref (G_OBJECT(widget_factory));
700 modest_header_view_select_next (header_view);
704 _modest_ui_actions_toggle_view (GtkWidget *widget,
705 ModestMainWindow *main_window)
707 ModestHeaderView *header_view;
708 ModestWidgetFactory *widget_factory;
710 TnyPlatformFactory *plat_factory;
713 plat_factory = modest_tny_platform_factory_get_instance ();
714 conf = modest_tny_platform_factory_get_conf_instance
715 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
716 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
717 header_view = modest_widget_factory_get_header_view (widget_factory);
718 g_object_unref (G_OBJECT(widget_factory));
720 /* what is saved/restored is depending on the style; thus; we save with
721 * old style, then update the style, and restore for this new style*/
722 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
724 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
725 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
727 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
729 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
735 * Marks a message as read and passes it to the msg preview widget
738 read_msg_func (gpointer data, gpointer user_data)
740 ModestMsgView *msg_view;
741 ModestWidgetFactory *widget_factory;
744 GetMsgAsyncHelper *helper;
745 TnyHeaderFlags header_flags;
747 msg = TNY_MSG (data);
748 helper = (GetMsgAsyncHelper *) user_data;
750 /* mark message as seen; _set_flags crashes, bug in tinymail? */
751 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
752 header_flags = tny_header_get_flags (header);
753 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
754 g_object_unref (G_OBJECT (header));
756 /* Set message on msg view */
757 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
758 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
759 g_object_unref (G_OBJECT(widget_factory));
760 modest_msg_view_set_message (msg_view, msg);
764 * This function is a generic handler for the tny_folder_get_msg_async
765 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
766 * contains a user provided function that is called inside this
767 * method. This will allow us to use this callback in many different
768 * places. This callback performs the common actions for the
769 * get_msg_async call, more specific actions will be done by the user
773 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
775 GetMsgAsyncHelper *helper;
777 helper = (GetMsgAsyncHelper *) user_data;
779 if (*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) {
780 ModestHeaderView *header_view;
781 ModestWidgetFactory *widget_factory;
783 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
784 header_view = modest_widget_factory_get_header_view (widget_factory);
785 g_object_unref (G_OBJECT (widget_factory));
786 _modest_ui_actions_on_item_not_found (header_view,
787 MODEST_ITEM_TYPE_MESSAGE,
788 helper->main_window);
795 /* Call user function */
796 helper->func (msg, user_data);
798 /* Process next element (if exists) */
799 tny_iterator_next (helper->iter);
800 if (tny_iterator_is_done (helper->iter)) {
802 headers = tny_iterator_get_list (helper->iter);
804 g_object_unref (G_OBJECT (headers));
805 g_object_unref (G_OBJECT (helper->iter));
806 g_slice_free (GetMsgAsyncHelper, helper);
808 tny_folder_get_msg_async (folder,
809 TNY_HEADER (tny_iterator_get_current (helper->iter)),
814 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
816 ModestMainWindow *main_window)
819 GetMsgAsyncHelper *helper;
822 /* when there's no header, clear the msgview */
824 ModestMsgView *msg_view;
825 ModestWidgetFactory *widget_factory;
826 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
827 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
828 modest_msg_view_set_message (msg_view, NULL);
832 folder = tny_header_get_folder (TNY_HEADER(header));
835 list = tny_simple_list_new ();
836 tny_list_prepend (list, G_OBJECT (header));
838 /* Fill helper data */
839 helper = g_slice_new0 (GetMsgAsyncHelper);
840 helper->main_window = main_window;
841 helper->iter = tny_list_create_iterator (list);
842 helper->func = read_msg_func;
844 tny_folder_get_msg_async (TNY_FOLDER(folder),
849 g_object_unref (G_OBJECT (folder));
853 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
856 ModestMainWindow *main_window)
858 GtkLabel *folder_info_label;
859 TnyPlatformFactory *factory;
862 ModestHeaderView *header_view;
863 ModestWidgetFactory *widget_factory;
865 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
867 GTK_LABEL (modest_widget_factory_get_folder_info_label (widget_factory));
870 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
874 factory = modest_tny_platform_factory_get_instance ();
875 header_view = modest_widget_factory_get_header_view (widget_factory);
876 conf = modest_tny_platform_factory_get_conf_instance
877 (MODEST_TNY_PLATFORM_FACTORY(factory));
878 g_object_unref (G_OBJECT (widget_factory));
880 if (!selected) { /* the folder was unselected; save it's settings */
881 modest_widget_memory_save (conf, G_OBJECT (header_view),
883 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
884 modest_header_view_set_folder (header_view, NULL);
885 } else { /* the folder was selected */
886 if (folder) { /* folder may be NULL */
890 num = tny_folder_get_all_count (folder);
891 unread = tny_folder_get_unread_count (folder);
893 title = g_strdup_printf ("Modest: %s",
894 tny_folder_get_name (folder));
896 gtk_window_set_title (GTK_WINDOW(main_window), title);
899 txt = g_strdup_printf (_("%d %s, %d unread"),
900 num, num==1 ? _("item") : _("items"), unread);
901 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
904 modest_header_view_set_folder (header_view, folder);
905 modest_widget_memory_restore (conf, G_OBJECT(header_view),
913 progress_bar_clean (GtkWidget *bar)
915 if (GTK_IS_PROGRESS_BAR(bar)) {
916 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
917 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
922 statusbar_clean (GtkWidget *bar)
924 if (GTK_IS_STATUSBAR(bar))
925 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
931 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
933 GtkWidget *status_bar, *progress_bar;
938 progress_bar = modest_widget_factory_get_progress_bar (factory);
939 status_bar = modest_widget_factory_get_status_bar (factory);
941 gtk_widget_show (GTK_WIDGET(status_bar));
942 gtk_widget_show (GTK_WIDGET(progress_bar));
944 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
946 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
947 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
949 /****************************************************************************/
952 _modest_ui_actions_on_connection_changed (TnyDevice *device,
954 ModestMainWindow *main_window)
956 GtkWidget *online_toggle;
957 ModestHeaderView *header_view;
958 ModestWidgetFactory *widget_factory;
960 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
961 header_view = modest_widget_factory_get_header_view (widget_factory);
962 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
964 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
966 gtk_button_set_label (GTK_BUTTON(online_toggle),
967 online ? _("Online") : _("Offline"));
969 statusbar_push (widget_factory, 0,
970 online ? _("Modest went online") : _("Modest went offline"));
971 g_object_unref (G_OBJECT (widget_factory));
973 /* If Modest has became online and the header view has a
974 header selected then show it */
976 GtkTreeSelection *selected;
978 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
979 _modest_header_view_change_selection (selected, header_view);
984 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
985 ModestMainWindow *main_window)
989 TnyPlatformFactory *factory;
990 TnyAccountStore *account_store;
992 /* Get device. Do not ask the platform factory for it, because
993 it returns always a new one */
994 factory = modest_tny_platform_factory_get_instance ();
995 account_store = tny_platform_factory_new_account_store (factory);
996 device = tny_account_store_get_device (account_store);
998 online = gtk_toggle_button_get_active (toggle);
1001 tny_device_force_online (device);
1003 tny_device_force_offline (device);
1007 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1008 ModestItemType type,
1009 ModestMainWindow *main_window)
1015 TnyPlatformFactory *factory;
1016 TnyAccountStore *account_store;
1018 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1020 /* Get device. Do not ask the platform factory for it, because
1021 it returns always a new one */
1022 factory = modest_tny_platform_factory_get_instance ();
1023 account_store = tny_platform_factory_new_account_store (factory);
1024 device = tny_account_store_get_device (account_store);
1026 if (g_main_depth > 0)
1027 gdk_threads_enter ();
1028 online = tny_device_is_online (device);
1031 /* already online -- the item is simply not there... */
1032 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1034 GTK_MESSAGE_WARNING,
1036 _("The %s you selected cannot be found"),
1038 gtk_dialog_run (GTK_DIALOG(dialog));
1041 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1042 GTK_WINDOW (main_window),
1045 GTK_RESPONSE_REJECT,
1047 GTK_RESPONSE_ACCEPT,
1050 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1051 "Do you want to get online?"), item);
1052 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1053 gtk_label_new (txt), FALSE, FALSE, 0);
1054 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1057 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1058 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1059 tny_device_force_online (device);
1062 gtk_widget_destroy (dialog);
1063 if (g_main_depth > 0)
1064 gdk_threads_leave ();
1070 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1074 ModestMainWindow *main_window)
1076 GtkWidget *progress_bar;
1077 ModestWidgetFactory *widget_factory;
1080 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1081 progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1084 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1085 (gdouble)num/(gdouble)total);
1087 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1089 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1090 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1093 statusbar_push (widget_factory, 0, msg);
1096 g_object_unref (G_OBJECT (widget_factory));
1102 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1104 ModestMainWindow *main_window)
1106 ModestWidgetFactory *widget_factory;
1108 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1109 statusbar_push (widget_factory, 0, link);
1110 g_object_unref (G_OBJECT (widget_factory));
1112 /* TODO: do something */
1117 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1119 ModestMainWindow *main_window)
1122 ModestWidgetFactory *widget_factory;
1124 msg = g_strdup_printf (_("Opening %s..."), link);
1125 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1126 statusbar_push (widget_factory, 0, msg);
1128 g_object_unref (G_OBJECT (widget_factory));
1132 /* TODO: do something */
1136 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1138 ModestMainWindow *main_window)
1141 ModestWidgetFactory *widget_factory;
1143 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1144 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1145 statusbar_push (widget_factory, 0, msg);
1148 g_object_unref (G_OBJECT (widget_factory));
1149 /* TODO: do something */
1153 _modest_ui_actions_on_send (GtkWidget *widget,
1154 ModestEditMsgWindow *edit_window)
1156 TnyTransportAccount *transport_account;
1157 ModestMailOperation *mail_operation;
1160 data = modest_edit_msg_window_get_msg_data (edit_window);
1162 /* FIXME: Code added just for testing. The final version will
1163 use the send queue provided by tinymail and some
1168 TnyAccountStore *account_store;
1170 accounts = TNY_LIST(tny_simple_list_new ());
1171 account_store = modest_window_get_account_store (MODEST_WINDOW (edit_window));
1172 tny_account_store_get_accounts (account_store, accounts,
1173 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1174 g_object_unref (G_OBJECT (account_store));
1176 iter = tny_list_create_iterator(accounts);
1177 tny_iterator_first (iter);
1178 if (tny_iterator_is_done (iter)) {
1179 /* FIXME: Add error handling through mail operation */
1180 g_printerr("modest: no transport accounts defined\n");
1181 modest_edit_msg_window_free_msg_data (edit_window, data);
1184 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1185 g_object_ref (transport_account);
1187 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1188 g_object_unref (G_OBJECT (accounts));
1189 g_object_unref (G_OBJECT (iter));
1192 mail_operation = modest_mail_operation_new ();
1194 modest_mail_operation_send_new_mail (mail_operation,
1204 g_object_unref (G_OBJECT (mail_operation));
1205 g_object_unref (G_OBJECT (transport_account));
1206 modest_edit_msg_window_free_msg_data (edit_window, data);
1208 /* Save settings and close the window */
1209 /* save_settings (edit_window) */
1210 gtk_widget_destroy (GTK_WIDGET (edit_window));
1214 * Shows a dialog with an entry that asks for some text. The returned
1215 * value must be freed by the caller. The dialog window title will be
1219 ask_for_folder_name (GtkWindow *parent_window,
1222 GtkWidget *dialog, *entry;
1223 gchar *folder_name = NULL;
1225 /* Ask for folder name */
1226 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1230 GTK_RESPONSE_REJECT,
1232 GTK_RESPONSE_ACCEPT,
1234 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1235 gtk_label_new(title),
1238 entry = gtk_entry_new_with_max_length (40);
1239 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1243 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1245 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1246 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1248 gtk_widget_destroy (dialog);
1254 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1255 ModestMainWindow *main_window)
1257 TnyFolder *parent_folder;
1258 ModestFolderView *folder_view;
1259 ModestWidgetFactory *widget_factory;
1261 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1262 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1263 parent_folder = modest_folder_view_get_selected (folder_view);
1265 if (parent_folder) {
1268 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1269 _("Please enter a name for the new folder"));
1271 if (folder_name != NULL && strlen (folder_name) > 0) {
1272 TnyFolder *new_folder;
1273 ModestMailOperation *mail_op;
1275 mail_op = modest_mail_operation_new ();
1276 new_folder = modest_mail_operation_create_folder (mail_op,
1277 TNY_FOLDER_STORE (parent_folder),
1278 (const gchar *) folder_name);
1280 /* Do anything more? The model
1281 is automatically updated */
1282 g_object_unref (new_folder);
1284 g_object_unref (mail_op);
1286 g_object_unref (parent_folder);
1288 g_object_unref (G_OBJECT (widget_factory));
1292 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1293 ModestMainWindow *main_window)
1296 ModestFolderView *folder_view;
1297 ModestWidgetFactory *widget_factory;
1299 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1300 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1301 folder = modest_folder_view_get_selected (folder_view);
1306 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1307 _("Please enter a new name for the folder"));
1309 if (folder_name != NULL && strlen (folder_name) > 0) {
1310 ModestMailOperation *mail_op;
1312 mail_op = modest_mail_operation_new ();
1313 modest_mail_operation_rename_folder (mail_op,
1315 (const gchar *) folder_name);
1316 g_object_unref (mail_op);
1318 g_object_unref (folder);
1320 g_object_unref (G_OBJECT (widget_factory));
1324 delete_folder (ModestMainWindow *main_window,
1325 gboolean move_to_trash)
1328 ModestFolderView *folder_view;
1329 ModestWidgetFactory *widget_factory;
1330 ModestMailOperation *mail_op;
1332 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1333 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1334 folder = modest_folder_view_get_selected (folder_view);
1336 mail_op = modest_mail_operation_new ();
1337 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1338 g_object_unref (mail_op);
1342 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1343 ModestMainWindow *main_window)
1345 delete_folder (main_window, FALSE);
1349 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1350 ModestMainWindow *main_window)
1352 delete_folder (main_window, TRUE);