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),
911 /****************************************************/
913 * below some stuff to clearup statusbar messages after 1,5 seconds....
916 GtkWidget *status_bar;
917 GtkWidget *progress_bar;
923 progress_bar_clean (GtkWidget *bar)
925 if (GTK_IS_PROGRESS_BAR(bar)) {
926 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
927 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
933 statusbar_clean (GtkWidget *bar)
935 if (GTK_IS_STATUSBAR(bar))
936 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
942 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
944 GtkWidget *status_bar, *progress_bar;
949 progress_bar = modest_widget_factory_get_progress_bar (factory);
950 status_bar = modest_widget_factory_get_status_bar (factory);
952 gtk_widget_show (GTK_WIDGET(status_bar));
953 gtk_widget_show (GTK_WIDGET(progress_bar));
955 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
957 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
958 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
960 /****************************************************************************/
963 _modest_ui_actions_on_connection_changed (TnyDevice *device,
965 ModestMainWindow *main_window)
967 GtkWidget *online_toggle;
968 ModestHeaderView *header_view;
969 ModestWidgetFactory *widget_factory;
971 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
972 header_view = modest_widget_factory_get_header_view (widget_factory);
973 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
975 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
977 gtk_button_set_label (GTK_BUTTON(online_toggle),
978 online ? _("Online") : _("Offline"));
980 statusbar_push (widget_factory, 0,
981 online ? _("Modest went online") : _("Modest went offline"));
982 g_object_unref (G_OBJECT (widget_factory));
984 /* If Modest has became online and the header view has a
985 header selected then show it */
987 GtkTreeSelection *selected;
989 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
990 _modest_header_view_change_selection (selected, header_view);
995 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
996 ModestMainWindow *main_window)
1000 TnyPlatformFactory *factory;
1001 TnyAccountStore *account_store;
1003 /* Get device. Do not ask the platform factory for it, because
1004 it returns always a new one */
1005 factory = modest_tny_platform_factory_get_instance ();
1006 account_store = tny_platform_factory_new_account_store (factory);
1007 device = tny_account_store_get_device (account_store);
1009 online = gtk_toggle_button_get_active (toggle);
1012 tny_device_force_online (device);
1014 tny_device_force_offline (device);
1018 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1019 ModestItemType type,
1020 ModestMainWindow *main_window)
1026 TnyPlatformFactory *factory;
1027 TnyAccountStore *account_store;
1029 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1031 /* Get device. Do not ask the platform factory for it, because
1032 it returns always a new one */
1033 factory = modest_tny_platform_factory_get_instance ();
1034 account_store = tny_platform_factory_new_account_store (factory);
1035 device = tny_account_store_get_device (account_store);
1037 if (g_main_depth > 0)
1038 gdk_threads_enter ();
1039 online = tny_device_is_online (device);
1042 /* already online -- the item is simply not there... */
1043 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1045 GTK_MESSAGE_WARNING,
1047 _("The %s you selected cannot be found"),
1049 gtk_dialog_run (GTK_DIALOG(dialog));
1052 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1053 GTK_WINDOW (main_window),
1056 GTK_RESPONSE_REJECT,
1058 GTK_RESPONSE_ACCEPT,
1061 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1062 "Do you want to get online?"), item);
1063 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1064 gtk_label_new (txt), FALSE, FALSE, 0);
1065 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1068 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1069 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1070 tny_device_force_online (device);
1073 gtk_widget_destroy (dialog);
1074 if (g_main_depth > 0)
1075 gdk_threads_leave ();
1081 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1085 ModestMainWindow *main_window)
1087 GtkWidget *progress_bar;
1088 ModestWidgetFactory *widget_factory;
1091 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1092 progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1095 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1096 (gdouble)num/(gdouble)total);
1098 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1100 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1101 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1104 statusbar_push (widget_factory, 0, msg);
1107 g_object_unref (G_OBJECT (widget_factory));
1113 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1115 ModestMainWindow *main_window)
1117 ModestWidgetFactory *widget_factory;
1119 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1120 statusbar_push (widget_factory, 0, link);
1121 g_object_unref (G_OBJECT (widget_factory));
1123 /* TODO: do something */
1128 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1130 ModestMainWindow *main_window)
1133 ModestWidgetFactory *widget_factory;
1135 msg = g_strdup_printf (_("Opening %s..."), link);
1136 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1137 statusbar_push (widget_factory, 0, msg);
1139 g_object_unref (G_OBJECT (widget_factory));
1143 /* TODO: do something */
1147 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1149 ModestMainWindow *main_window)
1152 ModestWidgetFactory *widget_factory;
1154 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1155 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1156 statusbar_push (widget_factory, 0, msg);
1159 g_object_unref (G_OBJECT (widget_factory));
1160 /* TODO: do something */
1164 _modest_ui_actions_on_send (GtkWidget *widget,
1165 ModestEditMsgWindow *edit_window)
1167 TnyTransportAccount *transport_account;
1168 ModestMailOperation *mail_operation;
1171 data = modest_edit_msg_window_get_msg_data (edit_window);
1173 /* FIXME: Code added just for testing. The final version will
1174 use the send queue provided by tinymail and some
1179 TnyAccountStore *account_store;
1181 accounts = TNY_LIST(tny_simple_list_new ());
1182 account_store = modest_window_get_account_store (MODEST_WINDOW (edit_window));
1183 tny_account_store_get_accounts (account_store, accounts,
1184 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1185 g_object_unref (G_OBJECT (account_store));
1187 iter = tny_list_create_iterator(accounts);
1188 tny_iterator_first (iter);
1189 if (tny_iterator_is_done (iter)) {
1190 /* FIXME: Add error handling through mail operation */
1191 g_printerr("modest: no transport accounts defined\n");
1192 modest_edit_msg_window_free_msg_data (edit_window, data);
1195 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1196 g_object_ref (transport_account);
1198 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1199 g_object_unref (G_OBJECT (accounts));
1200 g_object_unref (G_OBJECT (iter));
1203 mail_operation = modest_mail_operation_new ();
1205 modest_mail_operation_send_new_mail (mail_operation,
1215 g_object_unref (G_OBJECT (mail_operation));
1216 g_object_unref (G_OBJECT (transport_account));
1217 modest_edit_msg_window_free_msg_data (edit_window, data);
1219 /* Save settings and close the window */
1220 /* save_settings (edit_window) */
1221 gtk_widget_destroy (GTK_WIDGET (edit_window));
1225 * Shows a dialog with an entry that asks for some text. The returned
1226 * value must be freed by the caller. The dialog window title will be
1230 ask_for_folder_name (GtkWindow *parent_window,
1233 GtkWidget *dialog, *entry;
1234 gchar *folder_name = NULL;
1236 /* Ask for folder name */
1237 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1241 GTK_RESPONSE_REJECT,
1243 GTK_RESPONSE_ACCEPT,
1245 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1246 gtk_label_new(title),
1249 entry = gtk_entry_new_with_max_length (40);
1250 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1254 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1256 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1257 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1259 gtk_widget_destroy (dialog);
1265 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1266 ModestMainWindow *main_window)
1268 TnyFolder *parent_folder;
1269 ModestFolderView *folder_view;
1270 ModestWidgetFactory *widget_factory;
1272 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1273 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1274 parent_folder = modest_folder_view_get_selected (folder_view);
1276 if (parent_folder) {
1279 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1280 _("Please enter a name for the new folder"));
1282 if (folder_name != NULL && strlen (folder_name) > 0) {
1283 TnyFolder *new_folder;
1284 ModestMailOperation *mail_op;
1286 mail_op = modest_mail_operation_new ();
1287 new_folder = modest_mail_operation_create_folder (mail_op,
1288 TNY_FOLDER_STORE (parent_folder),
1289 (const gchar *) folder_name);
1291 /* Do anything more? The model
1292 is automatically updated */
1293 g_object_unref (new_folder);
1295 g_object_unref (mail_op);
1297 g_object_unref (parent_folder);
1299 g_object_unref (G_OBJECT (widget_factory));
1303 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1304 ModestMainWindow *main_window)
1307 ModestFolderView *folder_view;
1308 ModestWidgetFactory *widget_factory;
1310 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1311 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1312 folder = modest_folder_view_get_selected (folder_view);
1317 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1318 _("Please enter a new name for the folder"));
1320 if (folder_name != NULL && strlen (folder_name) > 0) {
1321 ModestMailOperation *mail_op;
1323 mail_op = modest_mail_operation_new ();
1324 modest_mail_operation_rename_folder (mail_op,
1326 (const gchar *) folder_name);
1327 g_object_unref (mail_op);
1329 g_object_unref (folder);
1331 g_object_unref (G_OBJECT (widget_factory));
1335 delete_folder (ModestMainWindow *main_window,
1336 gboolean move_to_trash)
1339 ModestFolderView *folder_view;
1340 ModestWidgetFactory *widget_factory;
1341 ModestMailOperation *mail_op;
1343 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1344 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1345 folder = modest_folder_view_get_selected (folder_view);
1347 mail_op = modest_mail_operation_new ();
1348 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1349 g_object_unref (mail_op);
1353 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1354 ModestMainWindow *main_window)
1356 delete_folder (main_window, FALSE);
1360 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1361 ModestMainWindow *main_window)
1363 delete_folder (main_window, TRUE);