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-account-mgr-helpers.h"
43 #include "modest-main-window.h"
44 #include "modest-mail-operation.h"
45 #include <modest-widget-memory.h>
46 #include <tny-error.h>
47 #include <tny-simple-list.h>
48 #include <tny-msg-view.h>
50 #define MODEST_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
54 typedef struct _GetMsgAsyncHelper {
55 ModestMainWindow *main_window;
61 typedef enum _ReplyForwardAction {
67 typedef struct _ReplyForwardHelper {
68 guint reply_forward_type;
69 ReplyForwardAction action;
74 static GObjectClass *parent_class = NULL;
76 /* 'private'/'protected' functions */
77 static void modest_ui_class_init (ModestUIClass *klass);
78 static void modest_ui_init (ModestUI *obj);
79 static void modest_ui_finalize (GObject *obj);
81 static void register_stock_icons ();
82 static void connect_signals (ModestUI *self);
84 static void reply_forward_func (gpointer data,
86 static void read_msg_func (gpointer data,
88 static void get_msg_cb (TnyFolder *folder,
93 static void reply_forward (GtkWidget *widget,
94 ReplyForwardAction action,
95 ModestMainWindow *main_window);
97 static gchar* ask_for_folder_name (GtkWindow *parent_window,
101 modest_ui_get_type (void)
103 static GType my_type = 0;
105 static const GTypeInfo my_info = {
106 sizeof(ModestUIClass),
107 NULL, /* base init */
108 NULL, /* base finalize */
109 (GClassInitFunc) modest_ui_class_init,
110 NULL, /* class finalize */
111 NULL, /* class data */
114 (GInstanceInitFunc) modest_ui_init,
117 my_type = g_type_register_static (G_TYPE_OBJECT,
126 modest_ui_class_init (ModestUIClass *klass)
128 GObjectClass *gobject_class;
129 gobject_class = (GObjectClass*) klass;
131 parent_class = g_type_class_peek_parent (klass);
132 gobject_class->finalize = modest_ui_finalize;
134 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
140 modest_ui_init (ModestUI *obj)
142 ModestUIPrivate *priv;
144 priv = MODEST_UI_GET_PRIVATE(obj);
146 priv->widget_factory = NULL;
147 priv->main_window = NULL;
148 priv->account_store = NULL;
153 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->main_window),
389 G_CALLBACK(on_main_window_destroy),
393 /* Init toggle in correct state */
394 _modest_ui_actions_on_connection_changed (device,
395 tny_device_is_online (device),
396 MODEST_MAIN_WINDOW (priv->main_window));
400 /* ***************************************************************** */
401 /* M O D E S T U I A C T I O N S */
402 /* ***************************************************************** */
404 _modest_ui_actions_on_about (GtkWidget *widget,
405 ModestMainWindow *main_window)
408 const gchar *authors[] = {
409 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
412 about = gtk_about_dialog_new ();
413 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
414 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
415 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
416 _("Copyright (c) 2006, Nokia Corporation\n"
417 "All rights reserved."));
418 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
419 _("a modest e-mail client\n\n"
420 "design and implementation: Dirk-Jan C. Binnema\n"
421 "contributions from the fine people at KernelConcepts and Igalia\n"
422 "uses the tinymail email framework written by Philip van Hoof"));
423 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
424 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
426 gtk_dialog_run (GTK_DIALOG (about));
427 gtk_widget_destroy(about);
431 _modest_ui_actions_on_delete (GtkWidget *widget,
432 ModestMainWindow *main_window)
434 ModestWidgetFactory *widget_factory;
435 ModestHeaderView *header_view;
436 TnyList *header_list;
440 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
441 header_view = modest_widget_factory_get_header_view (widget_factory);
442 header_list = modest_header_view_get_selected_headers (header_view);
443 g_object_unref (G_OBJECT(widget_factory));
446 iter = tny_list_create_iterator (header_list);
447 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
448 if (GTK_IS_TREE_MODEL_SORT (model))
449 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
452 ModestMailOperation *mail_op;
454 header = TNY_HEADER (tny_iterator_get_current (iter));
455 /* TODO: thick grain mail operation involving
456 a list of objects. Composite pattern ??? */
457 mail_op = modest_mail_operation_new ();
459 /* TODO: add confirmation dialog */
462 modest_mail_operation_remove_msg (mail_op, header, TRUE);
464 /* Remove from tree model */
465 if (modest_mail_operation_get_status (mail_op) ==
466 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
467 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
469 /* TODO: error handling management */
471 error = modest_mail_operation_get_error (mail_op);
472 g_warning (error->message);
475 g_object_unref (G_OBJECT (mail_op));
476 g_object_unref (header);
477 tny_iterator_next (iter);
479 } while (!tny_iterator_is_done (iter));
484 _modest_ui_actions_on_quit (GtkWidget *widget,
485 ModestMainWindow *main_window)
487 /* FIXME: save size of main window */
488 /* save_sizes (main_window); */
489 gtk_widget_destroy (GTK_WIDGET (main_window));
493 _modest_ui_actions_on_accounts (GtkWidget *widget,
494 ModestMainWindow *main_window)
496 GtkWidget *account_win;
497 ModestWidgetFactory *widget_factory;
499 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
500 account_win = modest_account_view_window_new (widget_factory);
501 g_object_unref (G_OBJECT(widget_factory));
503 gtk_window_set_transient_for (GTK_WINDOW (account_win),
504 GTK_WINDOW (main_window));
506 gtk_widget_show (account_win);
510 _modest_ui_actions_on_new_msg (GtkWidget *widget,
511 ModestMainWindow *main_window)
513 ModestWindow *msg_win;
514 ModestWidgetFactory *widget_factory;
515 TnyAccountStore *account_store;
517 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
518 account_store = modest_window_get_account_store (MODEST_WINDOW (main_window));
519 msg_win = modest_edit_msg_window_new (widget_factory,
521 MODEST_EDIT_TYPE_NEW);
522 g_object_unref (G_OBJECT (widget_factory));
523 g_object_unref (G_OBJECT (account_store));
525 gtk_widget_show_all (GTK_WIDGET (msg_win));
529 reply_forward_func (gpointer data, gpointer user_data)
531 ModestWidgetFactory *widget_factory;
532 TnyHeader *new_header;
533 TnyMsg *msg, *new_msg;
534 TnyAccountStore *account_store;
535 GetMsgAsyncHelper *helper;
536 ReplyForwardHelper *rf_helper;
537 ModestWindow *msg_win;
538 ModestEditType edit_type;
540 msg = TNY_MSG (data);
541 helper = (GetMsgAsyncHelper *) user_data;
542 rf_helper = (ReplyForwardHelper *) helper->user_data;
544 /* Create reply mail */
545 switch (rf_helper->action) {
548 modest_mail_operation_create_reply_mail (msg,
550 rf_helper->reply_forward_type,
551 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
553 case ACTION_REPLY_TO_ALL:
555 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
556 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
557 edit_type = MODEST_EDIT_TYPE_REPLY;
561 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
562 edit_type = MODEST_EDIT_TYPE_FORWARD;
565 g_return_if_reached ();
569 g_warning ("Unable to create a message");
573 /* /\* Set from *\/ */
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_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
580 account_store = modest_window_get_account_store (MODEST_WINDOW (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));
587 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
589 gtk_widget_show_all (GTK_WIDGET (msg_win));
592 g_object_unref (G_OBJECT (new_msg));
595 g_free (rf_helper->from);
596 g_slice_free (ReplyForwardHelper, rf_helper);
600 * Common code for the reply and forward actions
603 reply_forward (GtkWidget *widget,
604 ReplyForwardAction action,
605 ModestMainWindow *main_window)
607 ModestHeaderView *header_view;
608 ModestAccountMgr *account_mgr;
609 ModestWidgetFactory *widget_factory;
610 TnyList *header_list;
611 guint reply_forward_type;
613 ModestAccountData *default_account_data;
614 TnyPlatformFactory *plat_factory;
617 gchar *from, *key, *default_account_name;
618 GetMsgAsyncHelper *helper;
619 ReplyForwardHelper *rf_helper;
622 plat_factory = modest_tny_platform_factory_get_instance ();
623 conf = modest_tny_platform_factory_get_conf_instance
624 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
626 /* Get reply or forward type */
627 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
628 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
629 reply_forward_type = modest_conf_get_int (conf, key, NULL);
632 /* Get the list of headers */
633 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
634 header_view = modest_widget_factory_get_header_view (widget_factory);
635 header_list = modest_header_view_get_selected_headers (header_view);
636 g_object_unref (G_OBJECT(widget_factory));
641 /* We assume that we can only select messages of the
642 same folder and that we reply all of them from the
643 same account. In fact the interface currently only
644 allows single selection */
645 account_mgr = modest_tny_platform_factory_get_account_mgr_instance
646 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
647 default_account_name = modest_account_mgr_get_default_account (account_mgr);
648 default_account_data =
649 modest_account_mgr_get_account_data (account_mgr,
650 (const gchar*) default_account_name);
651 from = g_strdup (default_account_data->email);
652 modest_account_mgr_free_account_data (account_mgr, default_account_data);
653 g_free (default_account_name);
656 rf_helper = g_slice_new0 (ReplyForwardHelper);
657 rf_helper->reply_forward_type = reply_forward_type;
658 rf_helper->action = action;
659 rf_helper->from = from;
661 helper = g_slice_new0 (GetMsgAsyncHelper);
662 helper->main_window = main_window;
663 helper->func = reply_forward_func;
664 helper->iter = tny_list_create_iterator (header_list);
665 helper->user_data = rf_helper;
667 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
668 folder = tny_header_get_folder (header);
670 /* The callback will call it per each header */
671 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
674 g_object_unref (G_OBJECT (folder));
678 _modest_ui_actions_on_reply (GtkWidget *widget,
679 ModestMainWindow *main_window)
681 reply_forward (widget, ACTION_REPLY, main_window);
685 _modest_ui_actions_on_forward (GtkWidget *widget,
686 ModestMainWindow *main_window)
688 reply_forward (widget, ACTION_FORWARD, main_window);
692 _modest_ui_actions_on_reply_all (GtkWidget *widget,
693 ModestMainWindow *main_window)
695 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
699 _modest_ui_actions_on_next (GtkWidget *widget,
700 ModestMainWindow *main_window)
702 ModestHeaderView *header_view;
703 ModestWidgetFactory *widget_factory;
705 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
706 header_view = modest_widget_factory_get_header_view (widget_factory);
707 g_object_unref (G_OBJECT(widget_factory));
709 modest_header_view_select_next (header_view);
713 _modest_ui_actions_toggle_view (GtkWidget *widget,
714 ModestMainWindow *main_window)
716 ModestHeaderView *header_view;
717 ModestWidgetFactory *widget_factory;
719 TnyPlatformFactory *plat_factory;
722 plat_factory = modest_tny_platform_factory_get_instance ();
723 conf = modest_tny_platform_factory_get_conf_instance
724 (MODEST_TNY_PLATFORM_FACTORY(plat_factory));
725 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
726 header_view = modest_widget_factory_get_header_view (widget_factory);
727 g_object_unref (G_OBJECT(widget_factory));
729 /* what is saved/restored is depending on the style; thus; we save with
730 * old style, then update the style, and restore for this new style*/
731 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
733 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
734 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
736 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
738 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
744 * Marks a message as read and passes it to the msg preview widget
747 read_msg_func (gpointer data, gpointer user_data)
749 ModestMsgView *msg_view;
750 ModestWidgetFactory *widget_factory;
753 GetMsgAsyncHelper *helper;
754 TnyHeaderFlags header_flags;
756 msg = TNY_MSG (data);
757 helper = (GetMsgAsyncHelper *) user_data;
759 /* mark message as seen; _set_flags crashes, bug in tinymail? */
760 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
761 header_flags = tny_header_get_flags (header);
762 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
763 g_object_unref (G_OBJECT (header));
765 /* Set message on msg view */
766 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
767 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
768 g_object_unref (G_OBJECT(widget_factory));
769 modest_msg_view_set_message (msg_view, msg);
773 * This function is a generic handler for the tny_folder_get_msg_async
774 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
775 * contains a user provided function that is called inside this
776 * method. This will allow us to use this callback in many different
777 * places. This callback performs the common actions for the
778 * get_msg_async call, more specific actions will be done by the user
782 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
784 GetMsgAsyncHelper *helper;
786 helper = (GetMsgAsyncHelper *) user_data;
788 if (*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) {
789 ModestHeaderView *header_view;
790 ModestWidgetFactory *widget_factory;
792 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (helper->main_window));
793 header_view = modest_widget_factory_get_header_view (widget_factory);
794 g_object_unref (G_OBJECT (widget_factory));
795 _modest_ui_actions_on_item_not_found (header_view,
796 MODEST_ITEM_TYPE_MESSAGE,
797 helper->main_window);
804 /* Call user function */
805 helper->func (msg, user_data);
807 /* Process next element (if exists) */
808 tny_iterator_next (helper->iter);
809 if (tny_iterator_is_done (helper->iter)) {
811 headers = tny_iterator_get_list (helper->iter);
813 g_object_unref (G_OBJECT (headers));
814 g_object_unref (G_OBJECT (helper->iter));
815 g_slice_free (GetMsgAsyncHelper, helper);
817 tny_folder_get_msg_async (folder,
818 TNY_HEADER (tny_iterator_get_current (helper->iter)),
823 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
825 ModestMainWindow *main_window)
828 GetMsgAsyncHelper *helper;
831 /* when there's no header, clear the msgview */
833 ModestMsgView *msg_view;
834 ModestWidgetFactory *widget_factory;
835 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
836 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
837 modest_msg_view_set_message (msg_view, NULL);
841 folder = tny_header_get_folder (TNY_HEADER(header));
844 list = tny_simple_list_new ();
845 tny_list_prepend (list, G_OBJECT (header));
847 /* Fill helper data */
848 helper = g_slice_new0 (GetMsgAsyncHelper);
849 helper->main_window = main_window;
850 helper->iter = tny_list_create_iterator (list);
851 helper->func = read_msg_func;
853 tny_folder_get_msg_async (TNY_FOLDER(folder),
858 g_object_unref (G_OBJECT (folder));
862 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
865 ModestMainWindow *main_window)
867 GtkLabel *folder_info_label;
868 TnyPlatformFactory *factory;
871 ModestHeaderView *header_view;
872 ModestWidgetFactory *widget_factory;
874 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
876 GTK_LABEL (modest_widget_factory_get_folder_info_label (widget_factory));
879 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
883 factory = modest_tny_platform_factory_get_instance ();
884 header_view = modest_widget_factory_get_header_view (widget_factory);
885 conf = modest_tny_platform_factory_get_conf_instance
886 (MODEST_TNY_PLATFORM_FACTORY(factory));
887 g_object_unref (G_OBJECT (widget_factory));
889 if (!selected) { /* the folder was unselected; save it's settings */
890 modest_widget_memory_save (conf, G_OBJECT (header_view),
892 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
893 modest_header_view_set_folder (header_view, NULL);
894 } else { /* the folder was selected */
895 if (folder) { /* folder may be NULL */
899 num = tny_folder_get_all_count (folder);
900 unread = tny_folder_get_unread_count (folder);
902 title = g_strdup_printf ("Modest: %s",
903 tny_folder_get_name (folder));
905 gtk_window_set_title (GTK_WINDOW(main_window), title);
908 txt = g_strdup_printf (_("%d %s, %d unread"),
909 num, num==1 ? _("item") : _("items"), unread);
910 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
913 modest_header_view_set_folder (header_view, folder);
914 modest_widget_memory_restore (conf, G_OBJECT(header_view),
920 /****************************************************/
922 * below some stuff to clearup statusbar messages after 1,5 seconds....
925 GtkWidget *status_bar;
926 GtkWidget *progress_bar;
932 progress_bar_clean (GtkWidget *bar)
934 if (GTK_IS_PROGRESS_BAR(bar)) {
935 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
936 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
942 statusbar_clean (GtkWidget *bar)
944 if (GTK_IS_STATUSBAR(bar))
945 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
951 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
953 GtkWidget *status_bar, *progress_bar;
958 progress_bar = modest_widget_factory_get_progress_bar (factory);
959 status_bar = modest_widget_factory_get_status_bar (factory);
961 gtk_widget_show (GTK_WIDGET(status_bar));
962 gtk_widget_show (GTK_WIDGET(progress_bar));
964 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
966 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
967 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
969 /****************************************************************************/
972 _modest_ui_actions_on_connection_changed (TnyDevice *device,
974 ModestMainWindow *main_window)
976 GtkWidget *online_toggle;
977 ModestHeaderView *header_view;
978 ModestWidgetFactory *widget_factory;
980 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
981 header_view = modest_widget_factory_get_header_view (widget_factory);
982 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
984 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
986 gtk_button_set_label (GTK_BUTTON(online_toggle),
987 online ? _("Online") : _("Offline"));
989 statusbar_push (widget_factory, 0,
990 online ? _("Modest went online") : _("Modest went offline"));
991 g_object_unref (G_OBJECT (widget_factory));
993 /* If Modest has became online and the header view has a
994 header selected then show it */
996 GtkTreeSelection *selected;
998 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
999 _modest_header_view_change_selection (selected, header_view);
1004 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
1005 ModestMainWindow *main_window)
1009 TnyPlatformFactory *factory;
1010 TnyAccountStore *account_store;
1012 /* Get device. Do not ask the platform factory for it, because
1013 it returns always a new one */
1014 factory = modest_tny_platform_factory_get_instance ();
1015 account_store = tny_platform_factory_new_account_store (factory);
1016 device = tny_account_store_get_device (account_store);
1018 online = gtk_toggle_button_get_active (toggle);
1021 tny_device_force_online (device);
1023 tny_device_force_offline (device);
1027 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1028 ModestItemType type,
1029 ModestMainWindow *main_window)
1035 TnyPlatformFactory *factory;
1036 TnyAccountStore *account_store;
1038 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1040 /* Get device. Do not ask the platform factory for it, because
1041 it returns always a new one */
1042 factory = modest_tny_platform_factory_get_instance ();
1043 account_store = tny_platform_factory_new_account_store (factory);
1044 device = tny_account_store_get_device (account_store);
1046 if (g_main_depth > 0)
1047 gdk_threads_enter ();
1048 online = tny_device_is_online (device);
1051 /* already online -- the item is simply not there... */
1052 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1054 GTK_MESSAGE_WARNING,
1056 _("The %s you selected cannot be found"),
1058 gtk_dialog_run (GTK_DIALOG(dialog));
1061 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1062 GTK_WINDOW (main_window),
1065 GTK_RESPONSE_REJECT,
1067 GTK_RESPONSE_ACCEPT,
1070 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1071 "Do you want to get online?"), item);
1072 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1073 gtk_label_new (txt), FALSE, FALSE, 0);
1074 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1077 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1078 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1079 tny_device_force_online (device);
1082 gtk_widget_destroy (dialog);
1083 if (g_main_depth > 0)
1084 gdk_threads_leave ();
1090 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1094 ModestMainWindow *main_window)
1096 GtkWidget *progress_bar;
1097 ModestWidgetFactory *widget_factory;
1100 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1101 progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1104 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1105 (gdouble)num/(gdouble)total);
1107 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1109 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1110 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1113 statusbar_push (widget_factory, 0, msg);
1116 g_object_unref (G_OBJECT (widget_factory));
1122 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1124 ModestMainWindow *main_window)
1126 ModestWidgetFactory *widget_factory;
1128 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1129 statusbar_push (widget_factory, 0, link);
1130 g_object_unref (G_OBJECT (widget_factory));
1132 /* TODO: do something */
1137 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1139 ModestMainWindow *main_window)
1142 ModestWidgetFactory *widget_factory;
1144 msg = g_strdup_printf (_("Opening %s..."), link);
1145 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1146 statusbar_push (widget_factory, 0, msg);
1148 g_object_unref (G_OBJECT (widget_factory));
1152 /* TODO: do something */
1156 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1158 ModestMainWindow *main_window)
1161 ModestWidgetFactory *widget_factory;
1163 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1164 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1165 statusbar_push (widget_factory, 0, msg);
1168 g_object_unref (G_OBJECT (widget_factory));
1169 /* TODO: do something */
1173 _modest_ui_actions_on_send (GtkWidget *widget,
1174 ModestEditMsgWindow *edit_window)
1176 TnyTransportAccount *transport_account;
1177 ModestMailOperation *mail_operation;
1180 data = modest_edit_msg_window_get_msg_data (edit_window);
1182 /* FIXME: Code added just for testing. The final version will
1183 use the send queue provided by tinymail and some
1188 TnyAccountStore *account_store;
1190 accounts = TNY_LIST(tny_simple_list_new ());
1191 account_store = modest_window_get_account_store (MODEST_WINDOW (edit_window));
1192 tny_account_store_get_accounts (account_store, accounts,
1193 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1194 g_object_unref (G_OBJECT (account_store));
1196 iter = tny_list_create_iterator(accounts);
1197 tny_iterator_first (iter);
1198 if (tny_iterator_is_done (iter)) {
1199 /* FIXME: Add error handling through mail operation */
1200 g_printerr("modest: no transport accounts defined\n");
1201 modest_edit_msg_window_free_msg_data (edit_window, data);
1204 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1205 g_object_ref (transport_account);
1207 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1208 g_object_unref (G_OBJECT (accounts));
1209 g_object_unref (G_OBJECT (iter));
1212 mail_operation = modest_mail_operation_new ();
1214 modest_mail_operation_send_new_mail (mail_operation,
1224 g_object_unref (G_OBJECT (mail_operation));
1225 g_object_unref (G_OBJECT (transport_account));
1226 modest_edit_msg_window_free_msg_data (edit_window, data);
1228 /* Save settings and close the window */
1229 /* save_settings (edit_window) */
1230 gtk_widget_destroy (GTK_WIDGET (edit_window));
1234 * Shows a dialog with an entry that asks for some text. The returned
1235 * value must be freed by the caller. The dialog window title will be
1239 ask_for_folder_name (GtkWindow *parent_window,
1242 GtkWidget *dialog, *entry;
1243 gchar *folder_name = NULL;
1245 /* Ask for folder name */
1246 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1250 GTK_RESPONSE_REJECT,
1252 GTK_RESPONSE_ACCEPT,
1254 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1255 gtk_label_new(title),
1258 entry = gtk_entry_new_with_max_length (40);
1259 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1263 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1265 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1266 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1268 gtk_widget_destroy (dialog);
1274 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1275 ModestMainWindow *main_window)
1277 TnyFolder *parent_folder;
1278 ModestFolderView *folder_view;
1279 ModestWidgetFactory *widget_factory;
1281 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1282 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1283 parent_folder = modest_folder_view_get_selected (folder_view);
1285 if (parent_folder) {
1288 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1289 _("Please enter a name for the new folder"));
1291 if (folder_name != NULL && strlen (folder_name) > 0) {
1292 TnyFolder *new_folder;
1293 ModestMailOperation *mail_op;
1295 mail_op = modest_mail_operation_new ();
1296 new_folder = modest_mail_operation_create_folder (mail_op,
1297 TNY_FOLDER_STORE (parent_folder),
1298 (const gchar *) folder_name);
1300 /* Do anything more? The model
1301 is automatically updated */
1302 g_object_unref (new_folder);
1304 g_object_unref (mail_op);
1306 g_object_unref (parent_folder);
1308 g_object_unref (G_OBJECT (widget_factory));
1312 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1313 ModestMainWindow *main_window)
1316 ModestFolderView *folder_view;
1317 ModestWidgetFactory *widget_factory;
1319 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1320 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1321 folder = modest_folder_view_get_selected (folder_view);
1326 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1327 _("Please enter a new name for the folder"));
1329 if (folder_name != NULL && strlen (folder_name) > 0) {
1330 ModestMailOperation *mail_op;
1332 mail_op = modest_mail_operation_new ();
1333 modest_mail_operation_rename_folder (mail_op,
1335 (const gchar *) folder_name);
1336 g_object_unref (mail_op);
1338 g_object_unref (folder);
1340 g_object_unref (G_OBJECT (widget_factory));
1344 delete_folder (ModestMainWindow *main_window,
1345 gboolean move_to_trash)
1348 ModestFolderView *folder_view;
1349 ModestWidgetFactory *widget_factory;
1350 ModestMailOperation *mail_op;
1352 widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1353 folder_view = modest_widget_factory_get_folder_view (widget_factory);
1354 folder = modest_folder_view_get_selected (folder_view);
1356 mail_op = modest_mail_operation_new ();
1357 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1358 g_object_unref (mail_op);
1362 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1363 ModestMainWindow *main_window)
1365 delete_folder (main_window, FALSE);
1369 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1370 ModestMainWindow *main_window)
1372 delete_folder (main_window, TRUE);