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-runtime.h>
37 #include "modest-ui-priv.h"
38 #include "modest-ui.h"
39 #include "modest-ui-actions.h"
40 #include "modest-icon-names.h"
41 #include "modest-tny-platform-factory.h"
42 #include "modest-account-view-window.h"
43 #include "modest-account-mgr-helpers.h"
44 #include "modest-main-window.h"
45 #include "modest-mail-operation.h"
46 #include <modest-widget-memory.h>
47 #include <tny-error.h>
48 #include <tny-simple-list.h>
49 #include <tny-msg-view.h>
50 #include <tny-device.h>
52 #define MODEST_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
56 typedef struct _GetMsgAsyncHelper {
57 ModestMainWindow *main_window;
63 typedef enum _ReplyForwardAction {
69 typedef struct _ReplyForwardHelper {
70 guint reply_forward_type;
71 ReplyForwardAction action;
76 static GObjectClass *parent_class = NULL;
78 /* 'private'/'protected' functions */
79 static void modest_ui_class_init (ModestUIClass *klass);
80 static void modest_ui_init (ModestUI *obj);
81 static void modest_ui_finalize (GObject *obj);
83 static void register_stock_icons ();
84 static void connect_signals (ModestUI *self);
86 static void reply_forward_func (gpointer data,
88 static void read_msg_func (gpointer data,
90 static void get_msg_cb (TnyFolder *folder,
95 static void reply_forward (GtkWidget *widget,
96 ReplyForwardAction action,
97 ModestMainWindow *main_window);
99 static gchar* ask_for_folder_name (GtkWindow *parent_window,
102 static void _modest_ui_actions_on_connection_changed (TnyDevice *device,
104 ModestUI *modest_ui);
107 static void _modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store,
111 modest_ui_get_type (void)
113 static GType my_type = 0;
115 static const GTypeInfo my_info = {
116 sizeof(ModestUIClass),
117 NULL, /* base init */
118 NULL, /* base finalize */
119 (GClassInitFunc) modest_ui_class_init,
120 NULL, /* class finalize */
121 NULL, /* class data */
124 (GInstanceInitFunc) modest_ui_init,
127 my_type = g_type_register_static (G_TYPE_OBJECT,
136 modest_ui_class_init (ModestUIClass *klass)
138 GObjectClass *gobject_class;
139 gobject_class = (GObjectClass*) klass;
141 parent_class = g_type_class_peek_parent (klass);
142 gobject_class->finalize = modest_ui_finalize;
144 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
150 modest_ui_init (ModestUI *obj)
152 ModestUIPrivate *priv;
154 priv = MODEST_UI_GET_PRIVATE(obj);
156 priv->main_window = NULL;
161 modest_ui_finalize (GObject *obj)
163 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
165 if (priv->ui_manager) {
166 g_object_unref (G_OBJECT(priv->ui_manager));
167 priv->ui_manager = NULL;
170 priv->main_window = NULL;
172 G_OBJECT_CLASS(parent_class)->finalize (obj);
180 ModestUIPrivate *priv;
182 obj = g_object_new(MODEST_TYPE_UI, NULL);
183 priv = MODEST_UI_GET_PRIVATE(obj);
185 /* Register our own icons as stock icons in order to
186 use them with the UI manager */
187 register_stock_icons ();
189 return MODEST_UI(obj);
193 on_main_window_destroy (GtkObject *widget, ModestUI *self)
195 /* FIXME: check if there any viewer/editing windows opened */
202 modest_ui_main_window (ModestUI *self)
204 ModestUIPrivate *priv;
206 g_return_val_if_fail (self, NULL);
207 priv = MODEST_UI_GET_PRIVATE(self);
209 if (!priv->main_window) {
210 priv->main_window = modest_main_window_new ();
211 connect_signals (self);
214 if (!priv->main_window)
215 g_printerr ("modest: could not create main window\n");
217 return priv->main_window;
221 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
223 ModestUIPrivate *priv;
224 ModestWindow *edit_window;
226 g_return_val_if_fail (self, NULL);
227 priv = MODEST_UI_GET_PRIVATE(self);
230 edit_window = modest_edit_msg_window_new (edit_type);
232 /* Connect Edit Window signals */
233 /* connect_edit_window_signals (self); */
239 * This function registers our custom toolbar icons, so they can be
240 * themed. The idea of this function was taken from the gtk-demo
243 register_stock_icons ()
245 static gboolean registered = FALSE;
249 GtkIconFactory *factory;
252 static GtkStockItem items[] = {
253 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
254 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
255 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
256 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
257 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
258 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
259 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
260 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
261 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
262 /* { MODEST_STOCK_STOP, "stop", 0, 0, NULL } */
265 static gchar *items_names [] = {
266 MODEST_TOOLBAR_ICON_MAIL_SEND,
267 MODEST_TOOLBAR_ICON_NEW_MAIL,
268 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
269 MODEST_TOOLBAR_ICON_REPLY,
270 MODEST_TOOLBAR_ICON_REPLY_ALL,
271 MODEST_TOOLBAR_ICON_FORWARD,
272 MODEST_TOOLBAR_ICON_DELETE,
273 MODEST_TOOLBAR_ICON_NEXT,
274 MODEST_TOOLBAR_ICON_PREV,
275 /* MODEST_TOOLBAR_ICON_STOP */
280 /* Register our stock items */
281 gtk_stock_add (items, G_N_ELEMENTS (items));
283 /* Add our custom icon factory to the list of defaults */
284 factory = gtk_icon_factory_new ();
285 gtk_icon_factory_add_default (factory);
287 /* Register icons to accompany stock items */
288 for (i = 0; i < G_N_ELEMENTS (items); i++) {
290 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
292 if (pixbuf != NULL) {
293 GtkIconSet *icon_set;
294 GdkPixbuf *transparent;
296 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
298 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
299 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
300 gtk_icon_set_unref (icon_set);
301 g_object_unref (pixbuf);
302 g_object_unref (transparent);
305 g_warning ("failed to load %s icon", items_names[i]);
307 /* Drop our reference to the factory, GTK will hold a reference. */
308 g_object_unref (factory);
312 /* FIXME: uninit these as well */
314 connect_signals (ModestUI *self)
317 TnyAccountStore *account_store;
318 ModestUIPrivate *priv;
319 ModestFolderView *folder_view;
320 ModestHeaderView *header_view;
321 ModestMsgView *msg_view;
323 ModestWidgetFactory *widget_factory;
325 priv = MODEST_UI_GET_PRIVATE(self);
327 widget_factory = modest_runtime_get_widget_factory ();
329 folder_view = modest_widget_factory_get_folder_view (widget_factory);
330 header_view = modest_widget_factory_get_header_view (widget_factory);
331 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
332 toggle = modest_widget_factory_get_online_toggle (widget_factory);
333 account_store = TNY_ACCOUNT_STORE(modest_runtime_get_account_store());
334 device = tny_account_store_get_device (account_store);
337 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
338 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
341 g_signal_connect (G_OBJECT(header_view), "status_update",
342 G_CALLBACK(_modest_ui_actions_on_header_status_update),
344 g_signal_connect (G_OBJECT(header_view), "header_selected",
345 G_CALLBACK(_modest_ui_actions_on_header_selected),
347 g_signal_connect (G_OBJECT(header_view), "item_not_found",
348 G_CALLBACK(_modest_ui_actions_on_item_not_found),
351 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
352 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
354 g_signal_connect (G_OBJECT(msg_view), "link_hover",
355 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
357 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
358 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
362 g_signal_connect (G_OBJECT (account_store), "accounts_reloaded",
363 G_CALLBACK (_modest_ui_actions_on_accounts_reloaded),
367 g_signal_connect (G_OBJECT(device), "connection_changed",
368 G_CALLBACK(_modest_ui_actions_on_connection_changed),
371 priv->toggle_button_signal=
372 g_signal_connect (G_OBJECT(toggle), "toggled",
373 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
377 g_signal_connect (G_OBJECT(priv->main_window),
379 G_CALLBACK(on_main_window_destroy),
382 /* Init toggle in correct state */
383 _modest_ui_actions_on_connection_changed (device,
384 tny_device_is_online (device),
389 /* ***************************************************************** */
390 /* M O D E S T U I A C T I O N S */
391 /* ***************************************************************** */
393 _modest_ui_actions_on_about (GtkWidget *widget,
394 ModestMainWindow *main_window)
397 const gchar *authors[] = {
398 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
401 about = gtk_about_dialog_new ();
402 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
403 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
404 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
405 _("Copyright (c) 2006, Nokia Corporation\n"
406 "All rights reserved."));
407 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
408 _("a modest e-mail client\n\n"
409 "design and implementation: Dirk-Jan C. Binnema\n"
410 "contributions from the fine people at KernelConcepts and Igalia\n"
411 "uses the tinymail email framework written by Philip van Hoof"));
412 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
413 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
415 gtk_dialog_run (GTK_DIALOG (about));
416 gtk_widget_destroy(about);
420 _modest_ui_actions_on_delete (GtkWidget *widget,
421 ModestMainWindow *main_window)
423 ModestWidgetFactory *widget_factory;
424 ModestHeaderView *header_view;
425 TnyList *header_list;
429 widget_factory = modest_runtime_get_widget_factory ();
430 header_view = modest_widget_factory_get_header_view (widget_factory);
431 header_list = modest_header_view_get_selected_headers (header_view);
434 iter = tny_list_create_iterator (header_list);
435 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
436 if (GTK_IS_TREE_MODEL_SORT (model))
437 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
440 ModestMailOperation *mail_op;
442 header = TNY_HEADER (tny_iterator_get_current (iter));
443 /* TODO: thick grain mail operation involving
444 a list of objects. Composite pattern ??? */
445 mail_op = modest_mail_operation_new ();
447 /* TODO: add confirmation dialog */
450 modest_mail_operation_remove_msg (mail_op, header, TRUE);
452 /* Remove from tree model */
453 if (modest_mail_operation_get_status (mail_op) ==
454 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
455 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
457 /* TODO: error handling management */
459 error = modest_mail_operation_get_error (mail_op);
460 g_warning (error->message);
463 g_object_unref (G_OBJECT (mail_op));
464 g_object_unref (header);
465 tny_iterator_next (iter);
467 } while (!tny_iterator_is_done (iter));
472 _modest_ui_actions_on_quit (GtkWidget *widget,
473 ModestMainWindow *main_window)
475 /* FIXME: save size of main window */
476 /* save_sizes (main_window); */
477 gtk_widget_destroy (GTK_WIDGET (main_window));
481 _modest_ui_actions_on_accounts (GtkWidget *widget,
482 ModestMainWindow *main_window)
484 GtkWidget *account_win;
485 account_win = modest_account_view_window_new (modest_runtime_get_widget_factory());
487 gtk_window_set_transient_for (GTK_WINDOW (account_win),
488 GTK_WINDOW (main_window));
490 gtk_widget_show (account_win);
494 _modest_ui_actions_on_new_msg (GtkWidget *widget,
495 ModestMainWindow *main_window)
497 ModestWindow *msg_win;
498 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
499 gtk_widget_show_all (GTK_WIDGET (msg_win));
503 reply_forward_func (gpointer data, gpointer user_data)
505 TnyMsg *msg, *new_msg;
506 GetMsgAsyncHelper *helper;
507 ReplyForwardHelper *rf_helper;
508 ModestWindow *msg_win;
509 ModestEditType edit_type;
511 msg = TNY_MSG (data);
512 helper = (GetMsgAsyncHelper *) user_data;
513 rf_helper = (ReplyForwardHelper *) helper->user_data;
515 /* Create reply mail */
516 switch (rf_helper->action) {
519 modest_mail_operation_create_reply_mail (msg,
521 rf_helper->reply_forward_type,
522 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
524 case ACTION_REPLY_TO_ALL:
526 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
527 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
528 edit_type = MODEST_EDIT_TYPE_REPLY;
532 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
533 edit_type = MODEST_EDIT_TYPE_FORWARD;
536 g_return_if_reached ();
540 g_warning ("Unable to create a message");
544 /* Show edit window */
545 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
546 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
548 gtk_widget_show_all (GTK_WIDGET (msg_win));
551 g_object_unref (G_OBJECT (new_msg));
554 g_free (rf_helper->from);
555 g_slice_free (ReplyForwardHelper, rf_helper);
559 * Common code for the reply and forward actions
562 reply_forward (GtkWidget *widget,
563 ReplyForwardAction action,
564 ModestMainWindow *main_window)
566 ModestHeaderView *header_view;
567 ModestAccountMgr *account_mgr;
568 TnyList *header_list;
569 guint reply_forward_type;
571 ModestAccountData *default_account_data;
574 gchar *from, *key, *default_account_name;
575 GetMsgAsyncHelper *helper;
576 ReplyForwardHelper *rf_helper;
578 conf = modest_runtime_get_conf ();
580 /* Get reply or forward type */
581 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
582 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
583 reply_forward_type = modest_conf_get_int (conf, key, NULL);
586 /* Get the list of headers */
587 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
588 header_list = modest_header_view_get_selected_headers (header_view);
592 /* We assume that we can only select messages of the
593 same folder and that we reply all of them from the
594 same account. In fact the interface currently only
595 allows single selection */
596 account_mgr = modest_runtime_get_account_mgr();
597 default_account_name = modest_account_mgr_get_default_account (account_mgr);
598 default_account_data =
599 modest_account_mgr_get_account_data (account_mgr,
600 (const gchar*) default_account_name);
601 from = g_strdup (default_account_data->email);
602 modest_account_mgr_free_account_data (account_mgr, default_account_data);
603 g_free (default_account_name);
606 rf_helper = g_slice_new0 (ReplyForwardHelper);
607 rf_helper->reply_forward_type = reply_forward_type;
608 rf_helper->action = action;
609 rf_helper->from = from;
611 helper = g_slice_new0 (GetMsgAsyncHelper);
612 helper->main_window = main_window;
613 helper->func = reply_forward_func;
614 helper->iter = tny_list_create_iterator (header_list);
615 helper->user_data = rf_helper;
617 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
618 folder = tny_header_get_folder (header);
620 /* The callback will call it per each header */
621 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
624 g_object_unref (G_OBJECT (header));
625 g_object_unref (G_OBJECT (folder));
629 _modest_ui_actions_on_reply (GtkWidget *widget,
630 ModestMainWindow *main_window)
632 reply_forward (widget, ACTION_REPLY, main_window);
636 _modest_ui_actions_on_forward (GtkWidget *widget,
637 ModestMainWindow *main_window)
639 reply_forward (widget, ACTION_FORWARD, main_window);
643 _modest_ui_actions_on_reply_all (GtkWidget *widget,
644 ModestMainWindow *main_window)
646 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
650 _modest_ui_actions_on_next (GtkWidget *widget,
651 ModestMainWindow *main_window)
653 ModestHeaderView *header_view;
655 header_view = modest_widget_factory_get_header_view
656 (modest_runtime_get_widget_factory());
658 modest_header_view_select_next (header_view);
662 _modest_ui_actions_toggle_view (GtkWidget *widget,
663 ModestMainWindow *main_window)
666 ModestHeaderView *header_view;
668 header_view = modest_widget_factory_get_header_view
669 (modest_runtime_get_widget_factory());
671 conf = modest_runtime_get_conf ();
673 /* what is saved/restored is depending on the style; thus; we save with
674 * old style, then update the style, and restore for this new style*/
675 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
677 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
678 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
680 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
682 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
688 * Marks a message as read and passes it to the msg preview widget
691 read_msg_func (gpointer data, gpointer user_data)
693 ModestMsgView *msg_view;
696 GetMsgAsyncHelper *helper;
697 TnyHeaderFlags header_flags;
699 msg = TNY_MSG (data);
700 helper = (GetMsgAsyncHelper *) user_data;
702 /* mark message as seen; _set_flags crashes, bug in tinymail? */
703 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
704 header_flags = tny_header_get_flags (header);
705 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
706 g_object_unref (G_OBJECT (header));
708 /* Set message on msg view */
709 msg_view = modest_widget_factory_get_msg_preview
710 (modest_runtime_get_widget_factory());
711 modest_msg_view_set_message (msg_view, msg);
715 * This function is a generic handler for the tny_folder_get_msg_async
716 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
717 * contains a user provided function that is called inside this
718 * method. This will allow us to use this callback in many different
719 * places. This callback performs the common actions for the
720 * get_msg_async call, more specific actions will be done by the user
724 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
726 GetMsgAsyncHelper *helper;
728 helper = (GetMsgAsyncHelper *) user_data;
730 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
731 ModestHeaderView *header_view;
732 header_view = modest_widget_factory_get_header_view
733 (modest_runtime_get_widget_factory());
734 _modest_ui_actions_on_item_not_found (header_view,
735 MODEST_ITEM_TYPE_MESSAGE,
736 helper->main_window);
740 /* Call user function */
741 helper->func (msg, user_data);
743 /* Process next element (if exists) */
744 tny_iterator_next (helper->iter);
745 if (tny_iterator_is_done (helper->iter)) {
747 headers = tny_iterator_get_list (helper->iter);
749 g_object_unref (G_OBJECT (headers));
750 g_object_unref (G_OBJECT (helper->iter));
751 g_slice_free (GetMsgAsyncHelper, helper);
754 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
755 tny_folder_get_msg_async (folder, header,
757 g_object_unref (G_OBJECT(header));
762 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
764 ModestMainWindow *main_window)
767 GetMsgAsyncHelper *helper;
770 /* when there's no header, clear the msgview */
772 ModestMsgView *msg_view;
773 msg_view = modest_widget_factory_get_msg_preview
774 (modest_runtime_get_widget_factory());
775 modest_msg_view_set_message (msg_view, NULL);
779 folder = tny_header_get_folder (TNY_HEADER(header));
782 list = tny_simple_list_new ();
783 tny_list_prepend (list, G_OBJECT (header));
785 /* Fill helper data */
786 helper = g_slice_new0 (GetMsgAsyncHelper);
787 helper->main_window = main_window;
788 helper->iter = tny_list_create_iterator (list);
789 helper->func = read_msg_func;
791 tny_folder_get_msg_async (TNY_FOLDER(folder),
796 g_object_unref (G_OBJECT (folder));
800 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
803 ModestMainWindow *main_window)
805 GtkLabel *folder_info_label;
808 ModestHeaderView *header_view;
811 GTK_LABEL (modest_widget_factory_get_folder_info_label
812 (modest_runtime_get_widget_factory()));
815 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
819 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
820 conf = modest_runtime_get_conf ();
822 if (!selected) { /* the folder was unselected; save it's settings */
823 modest_widget_memory_save (conf, G_OBJECT (header_view),
825 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
826 modest_header_view_set_folder (header_view, NULL);
827 } else { /* the folder was selected */
828 if (folder) { /* folder may be NULL */
832 num = tny_folder_get_all_count (folder);
833 unread = tny_folder_get_unread_count (folder);
835 title = g_strdup_printf ("Modest: %s",
836 tny_folder_get_name (folder));
838 gtk_window_set_title (GTK_WINDOW(main_window), title);
841 txt = g_strdup_printf (_("%d %s, %d unread"),
842 num, num==1 ? _("item") : _("items"), unread);
843 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
846 modest_header_view_set_folder (header_view, folder);
847 modest_widget_memory_restore (conf, G_OBJECT(header_view),
853 /****************************************************/
855 * below some stuff to clearup statusbar messages after 1,5 seconds....
858 progress_bar_clean (GtkWidget *bar)
860 if (GTK_IS_PROGRESS_BAR(bar)) {
861 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
862 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
868 statusbar_clean (GtkWidget *bar)
870 if (GTK_IS_STATUSBAR(bar))
871 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
877 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
879 GtkWidget *status_bar, *progress_bar;
884 progress_bar = modest_widget_factory_get_progress_bar (factory);
885 status_bar = modest_widget_factory_get_status_bar (factory);
887 gtk_widget_show (GTK_WIDGET(status_bar));
888 gtk_widget_show (GTK_WIDGET(progress_bar));
890 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
892 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
893 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
895 /****************************************************************************/
898 _modest_ui_actions_on_connection_changed (TnyDevice *device,
902 GtkWidget *online_toggle;
903 ModestHeaderView *header_view;
904 ModestWidgetFactory *widget_factory;
905 ModestUIPrivate *priv;
907 const gchar *icon_name;
909 g_return_if_fail (device);
910 g_return_if_fail (self);
912 priv = MODEST_UI_GET_PRIVATE (self);
914 icon_name = online ? GTK_STOCK_CONNECT : GTK_STOCK_DISCONNECT;
915 icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
917 widget_factory = modest_runtime_get_widget_factory ();
918 header_view = modest_widget_factory_get_header_view (widget_factory);
919 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
921 /* Block handlers in order to avoid unnecessary calls */
922 g_signal_handler_block (G_OBJECT (online_toggle), priv->toggle_button_signal);
923 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle), online);
924 g_signal_handler_unblock (G_OBJECT (online_toggle), priv->toggle_button_signal);
926 gtk_button_set_image (GTK_BUTTON(online_toggle), icon);
927 statusbar_push (widget_factory, 0,
928 online ? _("Modest went online") : _("Modest went offline"));
930 /* If Modest has became online and the header view has a
931 header selected then show it */
932 /* FIXME: there is a race condition if some account needs to
933 ask the user for a password */
936 /* GtkTreeSelection *selected; */
938 /* selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view)); */
939 /* _modest_header_view_change_selection (selected, header_view); */
944 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
945 ModestMainWindow *main_window)
950 device = tny_account_store_get_device
951 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
953 online = gtk_toggle_button_get_active (toggle);
956 tny_device_force_online (device);
958 tny_device_force_offline (device);
962 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
964 ModestMainWindow *main_window)
970 TnyAccountStore *account_store;
972 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
974 /* Get device. Do not ask the platform factory for it, because
975 it returns always a new one */
976 account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
977 device = tny_account_store_get_device (account_store);
979 if (g_main_depth > 0)
980 gdk_threads_enter ();
981 online = tny_device_is_online (device);
984 /* already online -- the item is simply not there... */
985 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
989 _("The %s you selected cannot be found"),
991 gtk_dialog_run (GTK_DIALOG(dialog));
994 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
995 GTK_WINDOW (main_window),
1000 GTK_RESPONSE_ACCEPT,
1003 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1004 "Do you want to get online?"), item);
1005 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1006 gtk_label_new (txt), FALSE, FALSE, 0);
1007 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1010 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1011 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1012 tny_device_force_online (device);
1015 gtk_widget_destroy (dialog);
1016 if (g_main_depth > 0)
1017 gdk_threads_leave ();
1023 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1027 ModestMainWindow *main_window)
1029 GtkWidget *progress_bar;
1032 progress_bar = modest_widget_factory_get_progress_bar
1033 (modest_runtime_get_widget_factory());
1035 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1036 (gdouble)num/(gdouble)total);
1038 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1040 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1041 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1044 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1050 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1052 ModestMainWindow *main_window)
1054 statusbar_push (modest_runtime_get_widget_factory(), 0, link);
1056 /* TODO: do something */
1061 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1063 ModestMainWindow *main_window)
1067 msg = g_strdup_printf (_("Opening %s..."), link);
1068 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1071 /* TODO: do something */
1075 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1077 ModestMainWindow *main_window)
1081 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1082 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1085 /* TODO: do something */
1089 _modest_ui_actions_on_send (GtkWidget *widget,
1090 ModestEditMsgWindow *edit_window)
1092 TnyTransportAccount *transport_account;
1093 ModestMailOperation *mail_operation;
1095 gchar *account_name, *from;
1096 ModestAccountMgr *account_mgr;
1099 data = modest_edit_msg_window_get_msg_data (edit_window);
1101 /* FIXME: Code added just for testing. The final version will
1102 use the send queue provided by tinymail and some
1104 account_mgr = modest_runtime_get_account_mgr();
1105 account_name = modest_account_mgr_get_default_account (account_mgr);
1106 if (!account_name) {
1107 g_printerr ("modest: no default account found\n");
1108 modest_edit_msg_window_free_msg_data (edit_window, data);
1112 TNY_TRANSPORT_ACCOUNT(modest_account_mgr_get_tny_account (account_mgr,
1114 TNY_ACCOUNT_TYPE_TRANSPORT));
1115 if (!transport_account) {
1116 g_printerr ("modest: no transport account found\n");
1117 g_free (account_name);
1118 modest_edit_msg_window_free_msg_data (edit_window, data);
1121 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1123 mail_operation = modest_mail_operation_new ();
1124 modest_mail_operation_send_new_mail (mail_operation,
1135 g_free (account_name);
1136 g_object_unref (G_OBJECT (mail_operation));
1137 g_object_unref (G_OBJECT (transport_account));
1138 modest_edit_msg_window_free_msg_data (edit_window, data);
1140 /* Save settings and close the window */
1141 /* save_settings (edit_window) */
1142 gtk_widget_destroy (GTK_WIDGET (edit_window));
1146 * Shows a dialog with an entry that asks for some text. The returned
1147 * value must be freed by the caller. The dialog window title will be
1151 ask_for_folder_name (GtkWindow *parent_window,
1154 GtkWidget *dialog, *entry;
1155 gchar *folder_name = NULL;
1157 /* Ask for folder name */
1158 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1162 GTK_RESPONSE_REJECT,
1164 GTK_RESPONSE_ACCEPT,
1166 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1167 gtk_label_new(title),
1170 entry = gtk_entry_new_with_max_length (40);
1171 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1175 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1177 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1178 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1180 gtk_widget_destroy (dialog);
1186 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1187 ModestMainWindow *main_window)
1189 TnyFolder *parent_folder;
1190 ModestFolderView *folder_view;
1192 folder_view = modest_widget_factory_get_folder_view
1193 (modest_runtime_get_widget_factory());
1194 parent_folder = modest_folder_view_get_selected (folder_view);
1196 if (parent_folder) {
1199 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1200 _("Please enter a name for the new folder"));
1202 if (folder_name != NULL && strlen (folder_name) > 0) {
1203 TnyFolder *new_folder;
1204 ModestMailOperation *mail_op;
1206 mail_op = modest_mail_operation_new ();
1207 new_folder = modest_mail_operation_create_folder (mail_op,
1208 TNY_FOLDER_STORE (parent_folder),
1209 (const gchar *) folder_name);
1211 /* Do anything more? The model
1212 is automatically updated */
1213 g_object_unref (new_folder);
1215 g_object_unref (mail_op);
1217 g_object_unref (parent_folder);
1222 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1223 ModestMainWindow *main_window)
1226 ModestFolderView *folder_view;
1228 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1229 folder = modest_folder_view_get_selected (folder_view);
1234 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1235 _("Please enter a new name for the folder"));
1237 if (folder_name != NULL && strlen (folder_name) > 0) {
1238 ModestMailOperation *mail_op;
1240 mail_op = modest_mail_operation_new ();
1241 modest_mail_operation_rename_folder (mail_op,
1243 (const gchar *) folder_name);
1244 g_object_unref (mail_op);
1246 g_object_unref (folder);
1251 delete_folder (ModestMainWindow *main_window,
1252 gboolean move_to_trash)
1255 ModestFolderView *folder_view;
1256 ModestMailOperation *mail_op;
1258 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1259 folder = modest_folder_view_get_selected (folder_view);
1261 mail_op = modest_mail_operation_new ();
1262 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1263 g_object_unref (mail_op);
1267 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1268 ModestMainWindow *main_window)
1270 delete_folder (main_window, FALSE);
1274 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1275 ModestMainWindow *main_window)
1277 delete_folder (main_window, TRUE);
1281 _modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store, gpointer user_data)
1283 ModestFolderView *folder_view;
1285 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1286 modest_folder_view_update_model (folder_view, store);