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,
103 modest_ui_get_type (void)
105 static GType my_type = 0;
107 static const GTypeInfo my_info = {
108 sizeof(ModestUIClass),
109 NULL, /* base init */
110 NULL, /* base finalize */
111 (GClassInitFunc) modest_ui_class_init,
112 NULL, /* class finalize */
113 NULL, /* class data */
116 (GInstanceInitFunc) modest_ui_init,
119 my_type = g_type_register_static (G_TYPE_OBJECT,
128 modest_ui_class_init (ModestUIClass *klass)
130 GObjectClass *gobject_class;
131 gobject_class = (GObjectClass*) klass;
133 parent_class = g_type_class_peek_parent (klass);
134 gobject_class->finalize = modest_ui_finalize;
136 g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
142 modest_ui_init (ModestUI *obj)
144 ModestUIPrivate *priv;
146 priv = MODEST_UI_GET_PRIVATE(obj);
148 priv->main_window = NULL;
153 modest_ui_finalize (GObject *obj)
155 ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
157 if (priv->ui_manager) {
158 g_object_unref (G_OBJECT(priv->ui_manager));
159 priv->ui_manager = NULL;
162 priv->main_window = NULL;
164 G_OBJECT_CLASS(parent_class)->finalize (obj);
172 ModestUIPrivate *priv;
174 obj = g_object_new(MODEST_TYPE_UI, NULL);
175 priv = MODEST_UI_GET_PRIVATE(obj);
177 /* Register our own icons as stock icons in order to
178 use them with the UI manager */
179 register_stock_icons ();
181 return MODEST_UI(obj);
185 on_main_window_destroy (GtkObject *widget, ModestUI *self)
187 /* FIXME: check if there any viewer/editing windows opened */
194 modest_ui_main_window (ModestUI *self)
196 ModestUIPrivate *priv;
198 g_return_val_if_fail (self, NULL);
199 priv = MODEST_UI_GET_PRIVATE(self);
201 if (!priv->main_window) {
202 priv->main_window = modest_main_window_new ();
203 connect_signals (self);
206 if (!priv->main_window)
207 g_printerr ("modest: could not create main window\n");
209 return priv->main_window;
213 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
215 ModestUIPrivate *priv;
216 ModestWindow *edit_window;
218 g_return_val_if_fail (self, NULL);
219 priv = MODEST_UI_GET_PRIVATE(self);
222 edit_window = modest_edit_msg_window_new (edit_type);
224 /* Connect Edit Window signals */
225 /* connect_edit_window_signals (self); */
231 * This function registers our custom toolbar icons, so they can be
232 * themed. The idea of this function was taken from the gtk-demo
235 register_stock_icons ()
237 static gboolean registered = FALSE;
241 GtkIconFactory *factory;
244 static GtkStockItem items[] = {
245 { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
246 { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
247 { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
248 { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
249 { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
250 { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
251 { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
252 { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
253 { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
254 /* { MODEST_STOCK_STOP, "stop", 0, 0, NULL } */
257 static gchar *items_names [] = {
258 MODEST_TOOLBAR_ICON_MAIL_SEND,
259 MODEST_TOOLBAR_ICON_NEW_MAIL,
260 MODEST_TOOLBAR_ICON_SEND_RECEIVE,
261 MODEST_TOOLBAR_ICON_REPLY,
262 MODEST_TOOLBAR_ICON_REPLY_ALL,
263 MODEST_TOOLBAR_ICON_FORWARD,
264 MODEST_TOOLBAR_ICON_DELETE,
265 MODEST_TOOLBAR_ICON_NEXT,
266 MODEST_TOOLBAR_ICON_PREV,
267 /* MODEST_TOOLBAR_ICON_STOP */
272 /* Register our stock items */
273 gtk_stock_add (items, G_N_ELEMENTS (items));
275 /* Add our custom icon factory to the list of defaults */
276 factory = gtk_icon_factory_new ();
277 gtk_icon_factory_add_default (factory);
279 /* Register icons to accompany stock items */
280 for (i = 0; i < G_N_ELEMENTS (items); i++) {
282 pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
284 if (pixbuf != NULL) {
285 GtkIconSet *icon_set;
286 GdkPixbuf *transparent;
288 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
290 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
291 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
292 gtk_icon_set_unref (icon_set);
293 g_object_unref (pixbuf);
294 g_object_unref (transparent);
297 g_warning ("failed to load %s icon", items_names[i]);
299 /* Drop our reference to the factory, GTK will hold a reference. */
300 g_object_unref (factory);
304 /* FIXME: uninit these as well */
306 connect_signals (ModestUI *self)
309 ModestUIPrivate *priv;
310 ModestFolderView *folder_view;
311 ModestHeaderView *header_view;
312 ModestMsgView *msg_view;
314 ModestWidgetFactory *widget_factory;
316 priv = MODEST_UI_GET_PRIVATE(self);
318 widget_factory = modest_runtime_get_widget_factory ();
320 folder_view = modest_widget_factory_get_folder_view (widget_factory);
321 header_view = modest_widget_factory_get_header_view (widget_factory);
322 msg_view = modest_widget_factory_get_msg_preview (widget_factory);
323 toggle = modest_widget_factory_get_online_toggle (widget_factory);
324 device = tny_account_store_get_device
325 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
328 g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
329 G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
332 g_signal_connect (G_OBJECT(header_view), "status_update",
333 G_CALLBACK(_modest_ui_actions_on_header_status_update),
335 g_signal_connect (G_OBJECT(header_view), "header_selected",
336 G_CALLBACK(_modest_ui_actions_on_header_selected),
338 g_signal_connect (G_OBJECT(header_view), "item_not_found",
339 G_CALLBACK(_modest_ui_actions_on_item_not_found),
342 g_signal_connect (G_OBJECT(msg_view), "link_clicked",
343 G_CALLBACK(_modest_ui_actions_on_msg_link_clicked),
345 g_signal_connect (G_OBJECT(msg_view), "link_hover",
346 G_CALLBACK(_modest_ui_actions_on_msg_link_hover),
348 g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
349 G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked),
353 g_signal_connect (G_OBJECT(device), "connection_changed",
354 G_CALLBACK(_modest_ui_actions_on_connection_changed),
356 g_signal_connect (G_OBJECT(toggle), "toggled",
357 G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
361 g_signal_connect (G_OBJECT(priv->main_window),
363 G_CALLBACK(on_main_window_destroy),
367 /* Init toggle in correct state */
368 _modest_ui_actions_on_connection_changed (device,
369 tny_device_is_online (device),
370 MODEST_MAIN_WINDOW (priv->main_window));
374 /* ***************************************************************** */
375 /* M O D E S T U I A C T I O N S */
376 /* ***************************************************************** */
378 _modest_ui_actions_on_about (GtkWidget *widget,
379 ModestMainWindow *main_window)
382 const gchar *authors[] = {
383 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
386 about = gtk_about_dialog_new ();
387 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
388 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
389 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
390 _("Copyright (c) 2006, Nokia Corporation\n"
391 "All rights reserved."));
392 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
393 _("a modest e-mail client\n\n"
394 "design and implementation: Dirk-Jan C. Binnema\n"
395 "contributions from the fine people at KernelConcepts and Igalia\n"
396 "uses the tinymail email framework written by Philip van Hoof"));
397 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
398 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
400 gtk_dialog_run (GTK_DIALOG (about));
401 gtk_widget_destroy(about);
405 _modest_ui_actions_on_delete (GtkWidget *widget,
406 ModestMainWindow *main_window)
408 ModestWidgetFactory *widget_factory;
409 ModestHeaderView *header_view;
410 TnyList *header_list;
414 widget_factory = modest_runtime_get_widget_factory ();
415 header_view = modest_widget_factory_get_header_view (widget_factory);
416 header_list = modest_header_view_get_selected_headers (header_view);
419 iter = tny_list_create_iterator (header_list);
420 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
421 if (GTK_IS_TREE_MODEL_SORT (model))
422 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
425 ModestMailOperation *mail_op;
427 header = TNY_HEADER (tny_iterator_get_current (iter));
428 /* TODO: thick grain mail operation involving
429 a list of objects. Composite pattern ??? */
430 mail_op = modest_mail_operation_new ();
432 /* TODO: add confirmation dialog */
435 modest_mail_operation_remove_msg (mail_op, header, TRUE);
437 /* Remove from tree model */
438 if (modest_mail_operation_get_status (mail_op) ==
439 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
440 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
442 /* TODO: error handling management */
444 error = modest_mail_operation_get_error (mail_op);
445 g_warning (error->message);
448 g_object_unref (G_OBJECT (mail_op));
449 g_object_unref (header);
450 tny_iterator_next (iter);
452 } while (!tny_iterator_is_done (iter));
457 _modest_ui_actions_on_quit (GtkWidget *widget,
458 ModestMainWindow *main_window)
460 /* FIXME: save size of main window */
461 /* save_sizes (main_window); */
462 gtk_widget_destroy (GTK_WIDGET (main_window));
466 _modest_ui_actions_on_accounts (GtkWidget *widget,
467 ModestMainWindow *main_window)
469 GtkWidget *account_win;
470 account_win = modest_account_view_window_new (modest_runtime_get_widget_factory());
472 gtk_window_set_transient_for (GTK_WINDOW (account_win),
473 GTK_WINDOW (main_window));
475 gtk_widget_show (account_win);
479 _modest_ui_actions_on_new_msg (GtkWidget *widget,
480 ModestMainWindow *main_window)
482 ModestWindow *msg_win;
483 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
484 gtk_widget_show_all (GTK_WIDGET (msg_win));
488 reply_forward_func (gpointer data, gpointer user_data)
490 TnyMsg *msg, *new_msg;
491 GetMsgAsyncHelper *helper;
492 ReplyForwardHelper *rf_helper;
493 ModestWindow *msg_win;
494 ModestEditType edit_type;
496 msg = TNY_MSG (data);
497 helper = (GetMsgAsyncHelper *) user_data;
498 rf_helper = (ReplyForwardHelper *) helper->user_data;
500 /* Create reply mail */
501 switch (rf_helper->action) {
504 modest_mail_operation_create_reply_mail (msg,
506 rf_helper->reply_forward_type,
507 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
509 case ACTION_REPLY_TO_ALL:
511 modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
512 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
513 edit_type = MODEST_EDIT_TYPE_REPLY;
517 modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
518 edit_type = MODEST_EDIT_TYPE_FORWARD;
521 g_return_if_reached ();
525 g_warning ("Unable to create a message");
529 /* Show edit window */
530 msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
531 modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
533 gtk_widget_show_all (GTK_WIDGET (msg_win));
536 g_object_unref (G_OBJECT (new_msg));
539 g_free (rf_helper->from);
540 g_slice_free (ReplyForwardHelper, rf_helper);
544 * Common code for the reply and forward actions
547 reply_forward (GtkWidget *widget,
548 ReplyForwardAction action,
549 ModestMainWindow *main_window)
551 ModestHeaderView *header_view;
552 ModestAccountMgr *account_mgr;
553 TnyList *header_list;
554 guint reply_forward_type;
556 ModestAccountData *default_account_data;
559 gchar *from, *key, *default_account_name;
560 GetMsgAsyncHelper *helper;
561 ReplyForwardHelper *rf_helper;
563 conf = modest_runtime_get_conf ();
565 /* Get reply or forward type */
566 key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE,
567 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
568 reply_forward_type = modest_conf_get_int (conf, key, NULL);
571 /* Get the list of headers */
572 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
573 header_list = modest_header_view_get_selected_headers (header_view);
577 /* We assume that we can only select messages of the
578 same folder and that we reply all of them from the
579 same account. In fact the interface currently only
580 allows single selection */
581 account_mgr = modest_runtime_get_account_mgr();
582 default_account_name = modest_account_mgr_get_default_account (account_mgr);
583 default_account_data =
584 modest_account_mgr_get_account_data (account_mgr,
585 (const gchar*) default_account_name);
586 from = g_strdup (default_account_data->email);
587 modest_account_mgr_free_account_data (account_mgr, default_account_data);
588 g_free (default_account_name);
591 rf_helper = g_slice_new0 (ReplyForwardHelper);
592 rf_helper->reply_forward_type = reply_forward_type;
593 rf_helper->action = action;
594 rf_helper->from = from;
596 helper = g_slice_new0 (GetMsgAsyncHelper);
597 helper->main_window = main_window;
598 helper->func = reply_forward_func;
599 helper->iter = tny_list_create_iterator (header_list);
600 helper->user_data = rf_helper;
602 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
603 folder = tny_header_get_folder (header);
605 /* The callback will call it per each header */
606 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
609 g_object_unref (G_OBJECT (folder));
613 _modest_ui_actions_on_reply (GtkWidget *widget,
614 ModestMainWindow *main_window)
616 reply_forward (widget, ACTION_REPLY, main_window);
620 _modest_ui_actions_on_forward (GtkWidget *widget,
621 ModestMainWindow *main_window)
623 reply_forward (widget, ACTION_FORWARD, main_window);
627 _modest_ui_actions_on_reply_all (GtkWidget *widget,
628 ModestMainWindow *main_window)
630 reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
634 _modest_ui_actions_on_next (GtkWidget *widget,
635 ModestMainWindow *main_window)
637 ModestHeaderView *header_view;
639 header_view = modest_widget_factory_get_header_view
640 (modest_runtime_get_widget_factory());
642 modest_header_view_select_next (header_view);
646 _modest_ui_actions_toggle_view (GtkWidget *widget,
647 ModestMainWindow *main_window)
650 ModestHeaderView *header_view;
652 header_view = modest_widget_factory_get_header_view
653 (modest_runtime_get_widget_factory());
655 conf = modest_runtime_get_conf ();
657 /* what is saved/restored is depending on the style; thus; we save with
658 * old style, then update the style, and restore for this new style*/
659 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
661 if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
662 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
664 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
666 modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
672 * Marks a message as read and passes it to the msg preview widget
675 read_msg_func (gpointer data, gpointer user_data)
677 ModestMsgView *msg_view;
680 GetMsgAsyncHelper *helper;
681 TnyHeaderFlags header_flags;
683 msg = TNY_MSG (data);
684 helper = (GetMsgAsyncHelper *) user_data;
686 /* mark message as seen; _set_flags crashes, bug in tinymail? */
687 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
688 header_flags = tny_header_get_flags (header);
689 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
690 g_object_unref (G_OBJECT (header));
692 /* Set message on msg view */
693 msg_view = modest_widget_factory_get_msg_preview
694 (modest_runtime_get_widget_factory());
695 modest_msg_view_set_message (msg_view, msg);
699 * This function is a generic handler for the tny_folder_get_msg_async
700 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
701 * contains a user provided function that is called inside this
702 * method. This will allow us to use this callback in many different
703 * places. This callback performs the common actions for the
704 * get_msg_async call, more specific actions will be done by the user
708 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
710 GetMsgAsyncHelper *helper;
712 helper = (GetMsgAsyncHelper *) user_data;
714 if (*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) {
715 ModestHeaderView *header_view;
716 header_view = modest_widget_factory_get_header_view
717 (modest_runtime_get_widget_factory());
718 _modest_ui_actions_on_item_not_found (header_view,
719 MODEST_ITEM_TYPE_MESSAGE,
720 helper->main_window);
727 /* Call user function */
728 helper->func (msg, user_data);
730 /* Process next element (if exists) */
731 tny_iterator_next (helper->iter);
732 if (tny_iterator_is_done (helper->iter)) {
734 headers = tny_iterator_get_list (helper->iter);
736 g_object_unref (G_OBJECT (headers));
737 g_object_unref (G_OBJECT (helper->iter));
738 g_slice_free (GetMsgAsyncHelper, helper);
740 tny_folder_get_msg_async (folder,
741 TNY_HEADER (tny_iterator_get_current (helper->iter)),
746 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
748 ModestMainWindow *main_window)
751 GetMsgAsyncHelper *helper;
754 /* when there's no header, clear the msgview */
756 ModestMsgView *msg_view;
757 msg_view = modest_widget_factory_get_msg_preview
758 (modest_runtime_get_widget_factory());
759 modest_msg_view_set_message (msg_view, NULL);
763 folder = tny_header_get_folder (TNY_HEADER(header));
766 list = tny_simple_list_new ();
767 tny_list_prepend (list, G_OBJECT (header));
769 /* Fill helper data */
770 helper = g_slice_new0 (GetMsgAsyncHelper);
771 helper->main_window = main_window;
772 helper->iter = tny_list_create_iterator (list);
773 helper->func = read_msg_func;
775 tny_folder_get_msg_async (TNY_FOLDER(folder),
780 g_object_unref (G_OBJECT (folder));
784 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
787 ModestMainWindow *main_window)
789 GtkLabel *folder_info_label;
792 ModestHeaderView *header_view;
795 GTK_LABEL (modest_widget_factory_get_folder_info_label
796 (modest_runtime_get_widget_factory()));
799 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
803 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
804 conf = modest_runtime_get_conf ();
806 if (!selected) { /* the folder was unselected; save it's settings */
807 modest_widget_memory_save (conf, G_OBJECT (header_view),
809 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
810 modest_header_view_set_folder (header_view, NULL);
811 } else { /* the folder was selected */
812 if (folder) { /* folder may be NULL */
816 num = tny_folder_get_all_count (folder);
817 unread = tny_folder_get_unread_count (folder);
819 title = g_strdup_printf ("Modest: %s",
820 tny_folder_get_name (folder));
822 gtk_window_set_title (GTK_WINDOW(main_window), title);
825 txt = g_strdup_printf (_("%d %s, %d unread"),
826 num, num==1 ? _("item") : _("items"), unread);
827 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
830 modest_header_view_set_folder (header_view, folder);
831 modest_widget_memory_restore (conf, G_OBJECT(header_view),
837 /****************************************************/
839 * below some stuff to clearup statusbar messages after 1,5 seconds....
842 GtkWidget *status_bar;
843 GtkWidget *progress_bar;
849 progress_bar_clean (GtkWidget *bar)
851 if (GTK_IS_PROGRESS_BAR(bar)) {
852 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
853 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
859 statusbar_clean (GtkWidget *bar)
861 if (GTK_IS_STATUSBAR(bar))
862 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
868 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
870 GtkWidget *status_bar, *progress_bar;
875 progress_bar = modest_widget_factory_get_progress_bar (factory);
876 status_bar = modest_widget_factory_get_status_bar (factory);
878 gtk_widget_show (GTK_WIDGET(status_bar));
879 gtk_widget_show (GTK_WIDGET(progress_bar));
881 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
883 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
884 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
886 /****************************************************************************/
889 _modest_ui_actions_on_connection_changed (TnyDevice *device, gboolean online,
890 ModestMainWindow *main_window)
892 GtkWidget *online_toggle;
893 ModestHeaderView *header_view;
894 ModestWidgetFactory *widget_factory;
896 g_return_if_fail (main_window);
898 widget_factory = modest_runtime_get_widget_factory ();
899 header_view = modest_widget_factory_get_header_view (widget_factory);
900 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
902 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
904 gtk_button_set_label (GTK_BUTTON(online_toggle),
905 online ? _("Online") : _("Offline"));
907 statusbar_push (widget_factory, 0,
908 online ? _("Modest went online") : _("Modest went offline"));
910 /* If Modest has became online and the header view has a
911 header selected then show it */
913 GtkTreeSelection *selected;
915 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
916 _modest_header_view_change_selection (selected, header_view);
921 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
922 ModestMainWindow *main_window)
927 device = tny_account_store_get_device
928 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
930 online = gtk_toggle_button_get_active (toggle);
933 tny_device_force_online (device);
935 tny_device_force_offline (device);
939 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
941 ModestMainWindow *main_window)
947 TnyPlatformFactory *factory;
948 TnyAccountStore *account_store;
950 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
952 /* Get device. Do not ask the platform factory for it, because
953 it returns always a new one */
954 factory = modest_tny_platform_factory_get_instance ();
955 account_store = tny_platform_factory_new_account_store (factory);
956 device = tny_account_store_get_device (account_store);
958 if (g_main_depth > 0)
959 gdk_threads_enter ();
960 online = tny_device_is_online (device);
963 /* already online -- the item is simply not there... */
964 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
968 _("The %s you selected cannot be found"),
970 gtk_dialog_run (GTK_DIALOG(dialog));
973 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
974 GTK_WINDOW (main_window),
982 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
983 "Do you want to get online?"), item);
984 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
985 gtk_label_new (txt), FALSE, FALSE, 0);
986 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
989 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
990 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
991 tny_device_force_online (device);
994 gtk_widget_destroy (dialog);
995 if (g_main_depth > 0)
996 gdk_threads_leave ();
1002 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1006 ModestMainWindow *main_window)
1008 GtkWidget *progress_bar;
1011 progress_bar = modest_widget_factory_get_progress_bar
1012 (modest_runtime_get_widget_factory());
1014 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1015 (gdouble)num/(gdouble)total);
1017 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1019 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1020 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1023 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1029 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1031 ModestMainWindow *main_window)
1033 statusbar_push (modest_runtime_get_widget_factory(), 0, link);
1035 /* TODO: do something */
1040 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1042 ModestMainWindow *main_window)
1046 msg = g_strdup_printf (_("Opening %s..."), link);
1047 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1050 /* TODO: do something */
1054 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1056 ModestMainWindow *main_window)
1060 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1061 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1064 /* TODO: do something */
1068 _modest_ui_actions_on_send (GtkWidget *widget,
1069 ModestEditMsgWindow *edit_window)
1071 TnyTransportAccount *transport_account;
1072 ModestMailOperation *mail_operation;
1075 data = modest_edit_msg_window_get_msg_data (edit_window);
1077 /* FIXME: Code added just for testing. The final version will
1078 use the send queue provided by tinymail and some
1084 accounts = TNY_LIST(tny_simple_list_new ());
1085 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()),
1087 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1089 iter = tny_list_create_iterator(accounts);
1090 tny_iterator_first (iter);
1091 if (tny_iterator_is_done (iter)) {
1092 /* FIXME: Add error handling through mail operation */
1093 g_printerr("modest: no transport accounts defined\n");
1094 modest_edit_msg_window_free_msg_data (edit_window, data);
1097 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1098 g_object_ref (transport_account);
1100 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1101 g_object_unref (G_OBJECT (accounts));
1102 g_object_unref (G_OBJECT (iter));
1105 mail_operation = modest_mail_operation_new ();
1107 modest_mail_operation_send_new_mail (mail_operation,
1117 g_object_unref (G_OBJECT (mail_operation));
1118 g_object_unref (G_OBJECT (transport_account));
1119 modest_edit_msg_window_free_msg_data (edit_window, data);
1121 /* Save settings and close the window */
1122 /* save_settings (edit_window) */
1123 gtk_widget_destroy (GTK_WIDGET (edit_window));
1127 * Shows a dialog with an entry that asks for some text. The returned
1128 * value must be freed by the caller. The dialog window title will be
1132 ask_for_folder_name (GtkWindow *parent_window,
1135 GtkWidget *dialog, *entry;
1136 gchar *folder_name = NULL;
1138 /* Ask for folder name */
1139 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1143 GTK_RESPONSE_REJECT,
1145 GTK_RESPONSE_ACCEPT,
1147 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1148 gtk_label_new(title),
1151 entry = gtk_entry_new_with_max_length (40);
1152 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1156 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1158 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1159 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1161 gtk_widget_destroy (dialog);
1167 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1168 ModestMainWindow *main_window)
1170 TnyFolder *parent_folder;
1171 ModestFolderView *folder_view;
1173 folder_view = modest_widget_factory_get_folder_view
1174 (modest_runtime_get_widget_factory());
1175 parent_folder = modest_folder_view_get_selected (folder_view);
1177 if (parent_folder) {
1180 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1181 _("Please enter a name for the new folder"));
1183 if (folder_name != NULL && strlen (folder_name) > 0) {
1184 TnyFolder *new_folder;
1185 ModestMailOperation *mail_op;
1187 mail_op = modest_mail_operation_new ();
1188 new_folder = modest_mail_operation_create_folder (mail_op,
1189 TNY_FOLDER_STORE (parent_folder),
1190 (const gchar *) folder_name);
1192 /* Do anything more? The model
1193 is automatically updated */
1194 g_object_unref (new_folder);
1196 g_object_unref (mail_op);
1198 g_object_unref (parent_folder);
1203 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1204 ModestMainWindow *main_window)
1207 ModestFolderView *folder_view;
1209 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1210 folder = modest_folder_view_get_selected (folder_view);
1215 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1216 _("Please enter a new name for the folder"));
1218 if (folder_name != NULL && strlen (folder_name) > 0) {
1219 ModestMailOperation *mail_op;
1221 mail_op = modest_mail_operation_new ();
1222 modest_mail_operation_rename_folder (mail_op,
1224 (const gchar *) folder_name);
1225 g_object_unref (mail_op);
1227 g_object_unref (folder);
1232 delete_folder (ModestMainWindow *main_window,
1233 gboolean move_to_trash)
1236 ModestFolderView *folder_view;
1237 ModestMailOperation *mail_op;
1239 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1240 folder = modest_folder_view_get_selected (folder_view);
1242 mail_op = modest_mail_operation_new ();
1243 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1244 g_object_unref (mail_op);
1248 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1249 ModestMainWindow *main_window)
1251 delete_folder (main_window, FALSE);
1255 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1256 ModestMainWindow *main_window)
1258 delete_folder (main_window, TRUE);