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_accounts_reloaded (TnyAccountStore *store,
106 modest_ui_get_type (void)
108 static GType my_type = 0;
110 static const GTypeInfo my_info = {
111 sizeof(ModestUIClass),
112 NULL, /* base init */
113 NULL, /* base finalize */
114 (GClassInitFunc) modest_ui_class_init,
115 NULL, /* class finalize */
116 NULL, /* class data */
119 (GInstanceInitFunc) modest_ui_init,
122 my_type = g_type_register_static (G_TYPE_OBJECT,
131 modest_ui_class_init (ModestUIClass *klass)
133 GObjectClass *gobject_class;
134 gobject_class = (GObjectClass*) klass;
136 parent_class = g_type_class_peek_parent (klass);
137 gobject_class->finalize = modest_ui_finalize;
139 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
145 modest_ui_init (ModestUI *obj)
147 ModestUIPrivate *priv;
149 priv = MODEST_UI_GET_PRIVATE(obj);
151 priv->main_window = NULL;
156 modest_ui_finalize (GObject *obj)
158 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
160 if (priv->ui_manager) {
161 g_object_unref (G_OBJECT(priv->ui_manager));
162 priv->ui_manager = NULL;
165 priv->main_window = NULL;
167 G_OBJECT_CLASS(parent_class)->finalize (obj);
175 ModestUIPrivate *priv;
177 obj = g_object_new(MODEST_TYPE_UI, NULL);
178 priv = MODEST_UI_GET_PRIVATE(obj);
180 /* Register our own icons as stock icons in order to
181 use them with the UI manager */
182 register_stock_icons ();
184 return MODEST_UI(obj);
188 on_main_window_destroy (GtkObject *widget, ModestUI *self)
190 /* FIXME: check if there any viewer/editing windows opened */
197 modest_ui_main_window (ModestUI *self)
199 ModestUIPrivate *priv;
201 g_return_val_if_fail (self, NULL);
202 priv = MODEST_UI_GET_PRIVATE(self);
204 if (!priv->main_window) {
205 priv->main_window = modest_main_window_new ();
206 connect_signals (self);
209 if (!priv->main_window)
210 g_printerr ("modest: could not create main window\n");
212 return priv->main_window;
216 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
218 ModestUIPrivate *priv;
219 ModestWindow *edit_window;
221 g_return_val_if_fail (self, NULL);
222 priv = MODEST_UI_GET_PRIVATE(self);
225 edit_window = modest_edit_msg_window_new (edit_type);
227 /* Connect Edit Window signals */
228 /* connect_edit_window_signals (self); */
234 * This function registers our custom toolbar icons, so they can be
235 * themed. The idea of this function was taken from the gtk-demo
238 register_stock_icons ()
240 static gboolean registered = FALSE;
244 GtkIconFactory *factory;
247 static GtkStockItem items[] = {
248 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
249 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
250 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
251 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
252 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
253 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
254 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
255 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
256 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
257 /* { MODEST_STOCK_STOP, "stop", 0, 0, NULL } */
260 static gchar *items_names [] = {
261 MODEST_TOOLBAR_ICON_MAIL_SEND,
262 MODEST_TOOLBAR_ICON_NEW_MAIL,
263 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
264 MODEST_TOOLBAR_ICON_REPLY,
265 MODEST_TOOLBAR_ICON_REPLY_ALL,
266 MODEST_TOOLBAR_ICON_FORWARD,
267 MODEST_TOOLBAR_ICON_DELETE,
268 MODEST_TOOLBAR_ICON_NEXT,
269 MODEST_TOOLBAR_ICON_PREV,
270 /* MODEST_TOOLBAR_ICON_STOP */
275 /* Register our stock items */
276 gtk_stock_add (items, G_N_ELEMENTS (items));
278 /* Add our custom icon factory to the list of defaults */
279 factory = gtk_icon_factory_new ();
280 gtk_icon_factory_add_default (factory);
282 /* Register icons to accompany stock items */
283 for (i = 0; i < G_N_ELEMENTS (items); i++) {
285 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
287 if (pixbuf != NULL) {
288 GtkIconSet *icon_set;
289 GdkPixbuf *transparent;
291 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
293 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
294 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
295 gtk_icon_set_unref (icon_set);
296 g_object_unref (pixbuf);
297 g_object_unref (transparent);
300 g_warning ("failed to load %s icon", items_names[i]);
302 /* Drop our reference to the factory, GTK will hold a reference. */
303 g_object_unref (factory);
307 /* FIXME: uninit these as well */
309 connect_signals (ModestUI *self)
312 TnyAccountStore *account_store;
313 ModestUIPrivate *priv;
314 ModestFolderView *folder_view;
315 ModestHeaderView *header_view;
316 ModestMsgView *msg_view;
318 ModestWidgetFactory *widget_factory;
320 priv = MODEST_UI_GET_PRIVATE(self);
322 widget_factory = modest_runtime_get_widget_factory ();
324 folder_view = modest_widget_factory_get_folder_view (widget_factory);
325 header_view = modest_widget_factory_get_header_view (widget_factory);
326 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
327 toggle = modest_widget_factory_get_online_toggle (widget_factory);
328 account_store = TNY_ACCOUNT_STORE(modest_runtime_get_account_store());
329 device = tny_account_store_get_device (account_store);
332 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
333 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
336 g_signal_connect (G_OBJECT(header_view), "status_update",
337 G_CALLBACK(_modest_ui_actions_on_header_status_update),
339 g_signal_connect (G_OBJECT(header_view), "header_selected",
340 G_CALLBACK(_modest_ui_actions_on_header_selected),
342 g_signal_connect (G_OBJECT(header_view), "item_not_found",
343 G_CALLBACK(_modest_ui_actions_on_item_not_found),
346 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
347 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
349 g_signal_connect (G_OBJECT(msg_view), "link_hover",
350 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
352 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
353 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
357 g_signal_connect (G_OBJECT (account_store), "accounts_reloaded",
358 G_CALLBACK (_modest_ui_actions_on_accounts_reloaded),
362 g_signal_connect (G_OBJECT(device), "connection_changed",
363 G_CALLBACK(_modest_ui_actions_on_connection_changed),
365 g_signal_connect (G_OBJECT(toggle), "toggled",
366 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
370 g_signal_connect (G_OBJECT(priv->main_window),
372 G_CALLBACK(on_main_window_destroy),
375 /* Init toggle in correct state */
376 _modest_ui_actions_on_connection_changed (device,
377 tny_device_is_online (device),
378 MODEST_MAIN_WINDOW (priv->main_window));
382 /* ***************************************************************** */
383 /* M O D E S T U I A C T I O N S */
384 /* ***************************************************************** */
386 _modest_ui_actions_on_about (GtkWidget *widget,
387 ModestMainWindow *main_window)
390 const gchar *authors[] = {
391 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
394 about = gtk_about_dialog_new ();
395 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
396 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
397 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
398 _("Copyright (c) 2006, Nokia Corporation\n"
399 "All rights reserved."));
400 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
401 _("a modest e-mail client\n\n"
402 "design and implementation: Dirk-Jan C. Binnema\n"
403 "contributions from the fine people at KernelConcepts and Igalia\n"
404 "uses the tinymail email framework written by Philip van Hoof"));
405 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
406 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
408 gtk_dialog_run (GTK_DIALOG (about));
409 gtk_widget_destroy(about);
413 _modest_ui_actions_on_delete (GtkWidget *widget,
414 ModestMainWindow *main_window)
416 ModestWidgetFactory *widget_factory;
417 ModestHeaderView *header_view;
418 TnyList *header_list;
422 widget_factory = modest_runtime_get_widget_factory ();
423 header_view = modest_widget_factory_get_header_view (widget_factory);
424 header_list = modest_header_view_get_selected_headers (header_view);
427 iter = tny_list_create_iterator (header_list);
428 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
429 if (GTK_IS_TREE_MODEL_SORT (model))
430 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
433 ModestMailOperation *mail_op;
435 header = TNY_HEADER (tny_iterator_get_current (iter));
436 /* TODO: thick grain mail operation involving
437 a list of objects. Composite pattern ??? */
438 mail_op = modest_mail_operation_new ();
440 /* TODO: add confirmation dialog */
443 modest_mail_operation_remove_msg (mail_op, header, TRUE);
445 /* Remove from tree model */
446 if (modest_mail_operation_get_status (mail_op) ==
447 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
448 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
450 /* TODO: error handling management */
452 error = modest_mail_operation_get_error (mail_op);
453 g_warning (error->message);
456 g_object_unref (G_OBJECT (mail_op));
457 g_object_unref (header);
458 tny_iterator_next (iter);
460 } while (!tny_iterator_is_done (iter));
465 _modest_ui_actions_on_quit (GtkWidget *widget,
466 ModestMainWindow *main_window)
468 /* FIXME: save size of main window */
469 /* save_sizes (main_window); */
470 gtk_widget_destroy (GTK_WIDGET (main_window));
474 _modest_ui_actions_on_accounts (GtkWidget *widget,
475 ModestMainWindow *main_window)
477 GtkWidget *account_win;
478 account_win = modest_account_view_window_new (modest_runtime_get_widget_factory());
480 gtk_window_set_transient_for (GTK_WINDOW (account_win),
481 GTK_WINDOW (main_window));
483 gtk_widget_show (account_win);
487 _modest_ui_actions_on_new_msg (GtkWidget *widget,
488 ModestMainWindow *main_window)
490 ModestWindow *msg_win;
491 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
492 gtk_widget_show_all (GTK_WIDGET (msg_win));
496 reply_forward_func (gpointer data, gpointer user_data)
498 TnyMsg *msg, *new_msg;
499 GetMsgAsyncHelper *helper;
500 ReplyForwardHelper *rf_helper;
501 ModestWindow *msg_win;
502 ModestEditType edit_type;
504 msg = TNY_MSG (data);
505 helper = (GetMsgAsyncHelper *) user_data;
506 rf_helper = (ReplyForwardHelper *) helper->user_data;
508 /* Create reply mail */
509 switch (rf_helper->action) {
512 modest_mail_operation_create_reply_mail (msg,
514 rf_helper->reply_forward_type,
515 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
517 case ACTION_REPLY_TO_ALL:
519 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
520 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
521 edit_type = MODEST_EDIT_TYPE_REPLY;
525 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
526 edit_type = MODEST_EDIT_TYPE_FORWARD;
529 g_return_if_reached ();
533 g_warning ("Unable to create a message");
537 /* Show edit window */
538 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
539 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
541 gtk_widget_show_all (GTK_WIDGET (msg_win));
544 g_object_unref (G_OBJECT (new_msg));
547 g_free (rf_helper->from);
548 g_slice_free (ReplyForwardHelper, rf_helper);
552 * Common code for the reply and forward actions
555 reply_forward (GtkWidget *widget,
556 ReplyForwardAction action,
557 ModestMainWindow *main_window)
559 ModestHeaderView *header_view;
560 ModestAccountMgr *account_mgr;
561 TnyList *header_list;
562 guint reply_forward_type;
564 ModestAccountData *default_account_data;
567 gchar *from, *key, *default_account_name;
568 GetMsgAsyncHelper *helper;
569 ReplyForwardHelper *rf_helper;
571 conf = modest_runtime_get_conf ();
573 /* Get reply or forward type */
574 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
575 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
576 reply_forward_type = modest_conf_get_int (conf, key, NULL);
579 /* Get the list of headers */
580 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
581 header_list = modest_header_view_get_selected_headers (header_view);
585 /* We assume that we can only select messages of the
586 same folder and that we reply all of them from the
587 same account. In fact the interface currently only
588 allows single selection */
589 account_mgr = modest_runtime_get_account_mgr();
590 default_account_name = modest_account_mgr_get_default_account (account_mgr);
591 default_account_data =
592 modest_account_mgr_get_account_data (account_mgr,
593 (const gchar*) default_account_name);
594 from = g_strdup (default_account_data->email);
595 modest_account_mgr_free_account_data (account_mgr, default_account_data);
596 g_free (default_account_name);
599 rf_helper = g_slice_new0 (ReplyForwardHelper);
600 rf_helper->reply_forward_type = reply_forward_type;
601 rf_helper->action = action;
602 rf_helper->from = from;
604 helper = g_slice_new0 (GetMsgAsyncHelper);
605 helper->main_window = main_window;
606 helper->func = reply_forward_func;
607 helper->iter = tny_list_create_iterator (header_list);
608 helper->user_data = rf_helper;
610 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
611 folder = tny_header_get_folder (header);
613 /* The callback will call it per each header */
614 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
617 g_object_unref (G_OBJECT (folder));
621 _modest_ui_actions_on_reply (GtkWidget *widget,
622 ModestMainWindow *main_window)
624 reply_forward (widget, ACTION_REPLY, main_window);
628 _modest_ui_actions_on_forward (GtkWidget *widget,
629 ModestMainWindow *main_window)
631 reply_forward (widget, ACTION_FORWARD, main_window);
635 _modest_ui_actions_on_reply_all (GtkWidget *widget,
636 ModestMainWindow *main_window)
638 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
642 _modest_ui_actions_on_next (GtkWidget *widget,
643 ModestMainWindow *main_window)
645 ModestHeaderView *header_view;
647 header_view = modest_widget_factory_get_header_view
648 (modest_runtime_get_widget_factory());
650 modest_header_view_select_next (header_view);
654 _modest_ui_actions_toggle_view (GtkWidget *widget,
655 ModestMainWindow *main_window)
658 ModestHeaderView *header_view;
660 header_view = modest_widget_factory_get_header_view
661 (modest_runtime_get_widget_factory());
663 conf = modest_runtime_get_conf ();
665 /* what is saved/restored is depending on the style; thus; we save with
666 * old style, then update the style, and restore for this new style*/
667 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
669 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
670 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
672 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
674 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
680 * Marks a message as read and passes it to the msg preview widget
683 read_msg_func (gpointer data, gpointer user_data)
685 ModestMsgView *msg_view;
688 GetMsgAsyncHelper *helper;
689 TnyHeaderFlags header_flags;
691 msg = TNY_MSG (data);
692 helper = (GetMsgAsyncHelper *) user_data;
694 /* mark message as seen; _set_flags crashes, bug in tinymail? */
695 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
696 header_flags = tny_header_get_flags (header);
697 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
698 g_object_unref (G_OBJECT (header));
700 /* Set message on msg view */
701 msg_view = modest_widget_factory_get_msg_preview
702 (modest_runtime_get_widget_factory());
703 modest_msg_view_set_message (msg_view, msg);
707 * This function is a generic handler for the tny_folder_get_msg_async
708 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
709 * contains a user provided function that is called inside this
710 * method. This will allow us to use this callback in many different
711 * places. This callback performs the common actions for the
712 * get_msg_async call, more specific actions will be done by the user
716 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
718 GetMsgAsyncHelper *helper;
720 helper = (GetMsgAsyncHelper *) user_data;
722 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
723 ModestHeaderView *header_view;
724 header_view = modest_widget_factory_get_header_view
725 (modest_runtime_get_widget_factory());
726 _modest_ui_actions_on_item_not_found (header_view,
727 MODEST_ITEM_TYPE_MESSAGE,
728 helper->main_window);
732 /* Call user function */
733 helper->func (msg, user_data);
735 /* Process next element (if exists) */
736 tny_iterator_next (helper->iter);
737 if (tny_iterator_is_done (helper->iter)) {
739 headers = tny_iterator_get_list (helper->iter);
741 g_object_unref (G_OBJECT (headers));
742 g_object_unref (G_OBJECT (helper->iter));
743 g_slice_free (GetMsgAsyncHelper, helper);
745 tny_folder_get_msg_async (folder,
746 TNY_HEADER (tny_iterator_get_current (helper->iter)),
751 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
753 ModestMainWindow *main_window)
756 GetMsgAsyncHelper *helper;
759 /* when there's no header, clear the msgview */
761 ModestMsgView *msg_view;
762 msg_view = modest_widget_factory_get_msg_preview
763 (modest_runtime_get_widget_factory());
764 modest_msg_view_set_message (msg_view, NULL);
768 folder = tny_header_get_folder (TNY_HEADER(header));
771 list = tny_simple_list_new ();
772 tny_list_prepend (list, G_OBJECT (header));
774 /* Fill helper data */
775 helper = g_slice_new0 (GetMsgAsyncHelper);
776 helper->main_window = main_window;
777 helper->iter = tny_list_create_iterator (list);
778 helper->func = read_msg_func;
780 tny_folder_get_msg_async (TNY_FOLDER(folder),
785 g_object_unref (G_OBJECT (folder));
789 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
792 ModestMainWindow *main_window)
794 GtkLabel *folder_info_label;
797 ModestHeaderView *header_view;
800 GTK_LABEL (modest_widget_factory_get_folder_info_label
801 (modest_runtime_get_widget_factory()));
804 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
808 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
809 conf = modest_runtime_get_conf ();
811 if (!selected) { /* the folder was unselected; save it's settings */
812 modest_widget_memory_save (conf, G_OBJECT (header_view),
814 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
815 modest_header_view_set_folder (header_view, NULL);
816 } else { /* the folder was selected */
817 if (folder) { /* folder may be NULL */
821 num = tny_folder_get_all_count (folder);
822 unread = tny_folder_get_unread_count (folder);
824 title = g_strdup_printf ("Modest: %s",
825 tny_folder_get_name (folder));
827 gtk_window_set_title (GTK_WINDOW(main_window), title);
830 txt = g_strdup_printf (_("%d %s, %d unread"),
831 num, num==1 ? _("item") : _("items"), unread);
832 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
835 modest_header_view_set_folder (header_view, folder);
836 modest_widget_memory_restore (conf, G_OBJECT(header_view),
842 /****************************************************/
844 * below some stuff to clearup statusbar messages after 1,5 seconds....
847 GtkWidget *status_bar;
848 GtkWidget *progress_bar;
854 progress_bar_clean (GtkWidget *bar)
856 if (GTK_IS_PROGRESS_BAR(bar)) {
857 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
858 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
864 statusbar_clean (GtkWidget *bar)
866 if (GTK_IS_STATUSBAR(bar))
867 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
873 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
875 GtkWidget *status_bar, *progress_bar;
880 progress_bar = modest_widget_factory_get_progress_bar (factory);
881 status_bar = modest_widget_factory_get_status_bar (factory);
883 gtk_widget_show (GTK_WIDGET(status_bar));
884 gtk_widget_show (GTK_WIDGET(progress_bar));
886 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
888 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
889 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
891 /****************************************************************************/
894 _modest_ui_actions_on_connection_changed (TnyDevice *device, gboolean online,
895 ModestMainWindow *main_window)
897 GtkWidget *online_toggle;
898 ModestHeaderView *header_view;
899 ModestWidgetFactory *widget_factory;
901 const gchar *icon_name;
903 g_return_if_fail (device);
904 g_return_if_fail (main_window);
906 icon_name = online ? GTK_STOCK_CONNECT : GTK_STOCK_DISCONNECT;
907 icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
909 widget_factory = modest_runtime_get_widget_factory ();
910 header_view = modest_widget_factory_get_header_view (widget_factory);
911 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
913 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
915 gtk_button_set_image (GTK_BUTTON(online_toggle), icon);
916 statusbar_push (widget_factory, 0,
917 online ? _("Modest went online") : _("Modest went offline"));
919 /* If Modest has became online and the header view has a
920 header selected then show it */
922 GtkTreeSelection *selected;
924 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
925 _modest_header_view_change_selection (selected, header_view);
930 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
931 ModestMainWindow *main_window)
936 device = tny_account_store_get_device
937 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
939 online = gtk_toggle_button_get_active (toggle);
942 tny_device_force_online (device);
944 tny_device_force_offline (device);
948 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
950 ModestMainWindow *main_window)
956 TnyPlatformFactory *factory;
957 TnyAccountStore *account_store;
959 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
961 /* Get device. Do not ask the platform factory for it, because
962 it returns always a new one */
963 factory = modest_tny_platform_factory_get_instance ();
964 account_store = tny_platform_factory_new_account_store (factory);
965 device = tny_account_store_get_device (account_store);
967 if (g_main_depth > 0)
968 gdk_threads_enter ();
969 online = tny_device_is_online (device);
972 /* already online -- the item is simply not there... */
973 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
977 _("The %s you selected cannot be found"),
979 gtk_dialog_run (GTK_DIALOG(dialog));
982 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
983 GTK_WINDOW (main_window),
991 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
992 "Do you want to get online?"), item);
993 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
994 gtk_label_new (txt), FALSE, FALSE, 0);
995 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
998 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
999 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1000 tny_device_force_online (device);
1003 gtk_widget_destroy (dialog);
1004 if (g_main_depth > 0)
1005 gdk_threads_leave ();
1011 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1015 ModestMainWindow *main_window)
1017 GtkWidget *progress_bar;
1020 progress_bar = modest_widget_factory_get_progress_bar
1021 (modest_runtime_get_widget_factory());
1023 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1024 (gdouble)num/(gdouble)total);
1026 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1028 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1029 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1032 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1038 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1040 ModestMainWindow *main_window)
1042 statusbar_push (modest_runtime_get_widget_factory(), 0, link);
1044 /* TODO: do something */
1049 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1051 ModestMainWindow *main_window)
1055 msg = g_strdup_printf (_("Opening %s..."), link);
1056 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1059 /* TODO: do something */
1063 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1065 ModestMainWindow *main_window)
1069 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1070 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1073 /* TODO: do something */
1077 _modest_ui_actions_on_send (GtkWidget *widget,
1078 ModestEditMsgWindow *edit_window)
1080 TnyTransportAccount *transport_account;
1081 ModestMailOperation *mail_operation;
1084 data = modest_edit_msg_window_get_msg_data (edit_window);
1086 /* FIXME: Code added just for testing. The final version will
1087 use the send queue provided by tinymail and some
1093 accounts = TNY_LIST(tny_simple_list_new ());
1094 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()),
1096 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1098 iter = tny_list_create_iterator(accounts);
1099 tny_iterator_first (iter);
1100 if (tny_iterator_is_done (iter)) {
1101 /* FIXME: Add error handling through mail operation */
1102 g_printerr("modest: no transport accounts defined\n");
1103 modest_edit_msg_window_free_msg_data (edit_window, data);
1106 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1107 g_object_ref (transport_account);
1109 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1110 g_object_unref (G_OBJECT (accounts));
1111 g_object_unref (G_OBJECT (iter));
1114 mail_operation = modest_mail_operation_new ();
1116 modest_mail_operation_send_new_mail (mail_operation,
1126 g_object_unref (G_OBJECT (mail_operation));
1127 g_object_unref (G_OBJECT (transport_account));
1128 modest_edit_msg_window_free_msg_data (edit_window, data);
1130 /* Save settings and close the window */
1131 /* save_settings (edit_window) */
1132 gtk_widget_destroy (GTK_WIDGET (edit_window));
1136 * Shows a dialog with an entry that asks for some text. The returned
1137 * value must be freed by the caller. The dialog window title will be
1141 ask_for_folder_name (GtkWindow *parent_window,
1144 GtkWidget *dialog, *entry;
1145 gchar *folder_name = NULL;
1147 /* Ask for folder name */
1148 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1152 GTK_RESPONSE_REJECT,
1154 GTK_RESPONSE_ACCEPT,
1156 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1157 gtk_label_new(title),
1160 entry = gtk_entry_new_with_max_length (40);
1161 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1165 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1167 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1168 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1170 gtk_widget_destroy (dialog);
1176 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1177 ModestMainWindow *main_window)
1179 TnyFolder *parent_folder;
1180 ModestFolderView *folder_view;
1182 folder_view = modest_widget_factory_get_folder_view
1183 (modest_runtime_get_widget_factory());
1184 parent_folder = modest_folder_view_get_selected (folder_view);
1186 if (parent_folder) {
1189 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1190 _("Please enter a name for the new folder"));
1192 if (folder_name != NULL && strlen (folder_name) > 0) {
1193 TnyFolder *new_folder;
1194 ModestMailOperation *mail_op;
1196 mail_op = modest_mail_operation_new ();
1197 new_folder = modest_mail_operation_create_folder (mail_op,
1198 TNY_FOLDER_STORE (parent_folder),
1199 (const gchar *) folder_name);
1201 /* Do anything more? The model
1202 is automatically updated */
1203 g_object_unref (new_folder);
1205 g_object_unref (mail_op);
1207 g_object_unref (parent_folder);
1212 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1213 ModestMainWindow *main_window)
1216 ModestFolderView *folder_view;
1218 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1219 folder = modest_folder_view_get_selected (folder_view);
1224 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1225 _("Please enter a new name for the folder"));
1227 if (folder_name != NULL && strlen (folder_name) > 0) {
1228 ModestMailOperation *mail_op;
1230 mail_op = modest_mail_operation_new ();
1231 modest_mail_operation_rename_folder (mail_op,
1233 (const gchar *) folder_name);
1234 g_object_unref (mail_op);
1236 g_object_unref (folder);
1241 delete_folder (ModestMainWindow *main_window,
1242 gboolean move_to_trash)
1245 ModestFolderView *folder_view;
1246 ModestMailOperation *mail_op;
1248 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1249 folder = modest_folder_view_get_selected (folder_view);
1251 mail_op = modest_mail_operation_new ();
1252 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1253 g_object_unref (mail_op);
1257 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1258 ModestMainWindow *main_window)
1260 delete_folder (main_window, FALSE);
1264 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1265 ModestMainWindow *main_window)
1267 delete_folder (main_window, TRUE);
1271 _modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store, gpointer user_data)
1273 ModestFolderView *folder_view;
1275 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1276 modest_folder_view_update_model (folder_view, store);