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)) || !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);
724 /* Call user function */
725 helper->func (msg, user_data);
727 /* Process next element (if exists) */
728 tny_iterator_next (helper->iter);
729 if (tny_iterator_is_done (helper->iter)) {
731 headers = tny_iterator_get_list (helper->iter);
733 g_object_unref (G_OBJECT (headers));
734 g_object_unref (G_OBJECT (helper->iter));
735 g_slice_free (GetMsgAsyncHelper, helper);
737 tny_folder_get_msg_async (folder,
738 TNY_HEADER (tny_iterator_get_current (helper->iter)),
743 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
745 ModestMainWindow *main_window)
748 GetMsgAsyncHelper *helper;
751 /* when there's no header, clear the msgview */
753 ModestMsgView *msg_view;
754 msg_view = modest_widget_factory_get_msg_preview
755 (modest_runtime_get_widget_factory());
756 modest_msg_view_set_message (msg_view, NULL);
760 folder = tny_header_get_folder (TNY_HEADER(header));
763 list = tny_simple_list_new ();
764 tny_list_prepend (list, G_OBJECT (header));
766 /* Fill helper data */
767 helper = g_slice_new0 (GetMsgAsyncHelper);
768 helper->main_window = main_window;
769 helper->iter = tny_list_create_iterator (list);
770 helper->func = read_msg_func;
772 tny_folder_get_msg_async (TNY_FOLDER(folder),
777 g_object_unref (G_OBJECT (folder));
781 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
784 ModestMainWindow *main_window)
786 GtkLabel *folder_info_label;
789 ModestHeaderView *header_view;
792 GTK_LABEL (modest_widget_factory_get_folder_info_label
793 (modest_runtime_get_widget_factory()));
796 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
800 header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
801 conf = modest_runtime_get_conf ();
803 if (!selected) { /* the folder was unselected; save it's settings */
804 modest_widget_memory_save (conf, G_OBJECT (header_view),
806 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
807 modest_header_view_set_folder (header_view, NULL);
808 } else { /* the folder was selected */
809 if (folder) { /* folder may be NULL */
813 num = tny_folder_get_all_count (folder);
814 unread = tny_folder_get_unread_count (folder);
816 title = g_strdup_printf ("Modest: %s",
817 tny_folder_get_name (folder));
819 gtk_window_set_title (GTK_WINDOW(main_window), title);
822 txt = g_strdup_printf (_("%d %s, %d unread"),
823 num, num==1 ? _("item") : _("items"), unread);
824 gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
827 modest_header_view_set_folder (header_view, folder);
828 modest_widget_memory_restore (conf, G_OBJECT(header_view),
834 /****************************************************/
836 * below some stuff to clearup statusbar messages after 1,5 seconds....
839 GtkWidget *status_bar;
840 GtkWidget *progress_bar;
846 progress_bar_clean (GtkWidget *bar)
848 if (GTK_IS_PROGRESS_BAR(bar)) {
849 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(bar), "");
850 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
856 statusbar_clean (GtkWidget *bar)
858 if (GTK_IS_STATUSBAR(bar))
859 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
865 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
867 GtkWidget *status_bar, *progress_bar;
872 progress_bar = modest_widget_factory_get_progress_bar (factory);
873 status_bar = modest_widget_factory_get_status_bar (factory);
875 gtk_widget_show (GTK_WIDGET(status_bar));
876 gtk_widget_show (GTK_WIDGET(progress_bar));
878 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
880 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
881 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
883 /****************************************************************************/
886 _modest_ui_actions_on_connection_changed (TnyDevice *device, gboolean online,
887 ModestMainWindow *main_window)
889 GtkWidget *online_toggle;
890 ModestHeaderView *header_view;
891 ModestWidgetFactory *widget_factory;
893 g_return_if_fail (main_window);
895 widget_factory = modest_runtime_get_widget_factory ();
896 header_view = modest_widget_factory_get_header_view (widget_factory);
897 online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
899 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
901 gtk_button_set_label (GTK_BUTTON(online_toggle),
902 online ? _("Online") : _("Offline"));
904 statusbar_push (widget_factory, 0,
905 online ? _("Modest went online") : _("Modest went offline"));
907 /* If Modest has became online and the header view has a
908 header selected then show it */
910 GtkTreeSelection *selected;
912 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
913 _modest_header_view_change_selection (selected, header_view);
918 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
919 ModestMainWindow *main_window)
924 device = tny_account_store_get_device
925 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
927 online = gtk_toggle_button_get_active (toggle);
930 tny_device_force_online (device);
932 tny_device_force_offline (device);
936 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
938 ModestMainWindow *main_window)
944 TnyPlatformFactory *factory;
945 TnyAccountStore *account_store;
947 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
949 /* Get device. Do not ask the platform factory for it, because
950 it returns always a new one */
951 factory = modest_tny_platform_factory_get_instance ();
952 account_store = tny_platform_factory_new_account_store (factory);
953 device = tny_account_store_get_device (account_store);
955 if (g_main_depth > 0)
956 gdk_threads_enter ();
957 online = tny_device_is_online (device);
960 /* already online -- the item is simply not there... */
961 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
965 _("The %s you selected cannot be found"),
967 gtk_dialog_run (GTK_DIALOG(dialog));
970 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
971 GTK_WINDOW (main_window),
979 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
980 "Do you want to get online?"), item);
981 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
982 gtk_label_new (txt), FALSE, FALSE, 0);
983 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
986 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
987 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
988 tny_device_force_online (device);
991 gtk_widget_destroy (dialog);
992 if (g_main_depth > 0)
993 gdk_threads_leave ();
999 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view,
1003 ModestMainWindow *main_window)
1005 GtkWidget *progress_bar;
1008 progress_bar = modest_widget_factory_get_progress_bar
1009 (modest_runtime_get_widget_factory());
1011 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1012 (gdouble)num/(gdouble)total);
1014 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1016 txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1017 gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1020 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1026 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview,
1028 ModestMainWindow *main_window)
1030 statusbar_push (modest_runtime_get_widget_factory(), 0, link);
1032 /* TODO: do something */
1037 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview,
1039 ModestMainWindow *main_window)
1043 msg = g_strdup_printf (_("Opening %s..."), link);
1044 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1047 /* TODO: do something */
1051 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview,
1053 ModestMainWindow *main_window)
1057 msg = g_strdup_printf (_("Opening attachment %d..."), index);
1058 statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1061 /* TODO: do something */
1065 _modest_ui_actions_on_send (GtkWidget *widget,
1066 ModestEditMsgWindow *edit_window)
1068 TnyTransportAccount *transport_account;
1069 ModestMailOperation *mail_operation;
1072 data = modest_edit_msg_window_get_msg_data (edit_window);
1074 /* FIXME: Code added just for testing. The final version will
1075 use the send queue provided by tinymail and some
1081 accounts = TNY_LIST(tny_simple_list_new ());
1082 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()),
1084 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1086 iter = tny_list_create_iterator(accounts);
1087 tny_iterator_first (iter);
1088 if (tny_iterator_is_done (iter)) {
1089 /* FIXME: Add error handling through mail operation */
1090 g_printerr("modest: no transport accounts defined\n");
1091 modest_edit_msg_window_free_msg_data (edit_window, data);
1094 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1095 g_object_ref (transport_account);
1097 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1098 g_object_unref (G_OBJECT (accounts));
1099 g_object_unref (G_OBJECT (iter));
1102 mail_operation = modest_mail_operation_new ();
1104 modest_mail_operation_send_new_mail (mail_operation,
1114 g_object_unref (G_OBJECT (mail_operation));
1115 g_object_unref (G_OBJECT (transport_account));
1116 modest_edit_msg_window_free_msg_data (edit_window, data);
1118 /* Save settings and close the window */
1119 /* save_settings (edit_window) */
1120 gtk_widget_destroy (GTK_WIDGET (edit_window));
1124 * Shows a dialog with an entry that asks for some text. The returned
1125 * value must be freed by the caller. The dialog window title will be
1129 ask_for_folder_name (GtkWindow *parent_window,
1132 GtkWidget *dialog, *entry;
1133 gchar *folder_name = NULL;
1135 /* Ask for folder name */
1136 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1140 GTK_RESPONSE_REJECT,
1142 GTK_RESPONSE_ACCEPT,
1144 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1145 gtk_label_new(title),
1148 entry = gtk_entry_new_with_max_length (40);
1149 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1153 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1155 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1156 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1158 gtk_widget_destroy (dialog);
1164 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1165 ModestMainWindow *main_window)
1167 TnyFolder *parent_folder;
1168 ModestFolderView *folder_view;
1170 folder_view = modest_widget_factory_get_folder_view
1171 (modest_runtime_get_widget_factory());
1172 parent_folder = modest_folder_view_get_selected (folder_view);
1174 if (parent_folder) {
1177 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1178 _("Please enter a name for the new folder"));
1180 if (folder_name != NULL && strlen (folder_name) > 0) {
1181 TnyFolder *new_folder;
1182 ModestMailOperation *mail_op;
1184 mail_op = modest_mail_operation_new ();
1185 new_folder = modest_mail_operation_create_folder (mail_op,
1186 TNY_FOLDER_STORE (parent_folder),
1187 (const gchar *) folder_name);
1189 /* Do anything more? The model
1190 is automatically updated */
1191 g_object_unref (new_folder);
1193 g_object_unref (mail_op);
1195 g_object_unref (parent_folder);
1200 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1201 ModestMainWindow *main_window)
1204 ModestFolderView *folder_view;
1206 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1207 folder = modest_folder_view_get_selected (folder_view);
1212 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1213 _("Please enter a new name for the folder"));
1215 if (folder_name != NULL && strlen (folder_name) > 0) {
1216 ModestMailOperation *mail_op;
1218 mail_op = modest_mail_operation_new ();
1219 modest_mail_operation_rename_folder (mail_op,
1221 (const gchar *) folder_name);
1222 g_object_unref (mail_op);
1224 g_object_unref (folder);
1229 delete_folder (ModestMainWindow *main_window,
1230 gboolean move_to_trash)
1233 ModestFolderView *folder_view;
1234 ModestMailOperation *mail_op;
1236 folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1237 folder = modest_folder_view_get_selected (folder_view);
1239 mail_op = modest_mail_operation_new ();
1240 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1241 g_object_unref (mail_op);
1245 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1246 ModestMainWindow *main_window)
1248 delete_folder (main_window, FALSE);
1252 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1253 ModestMainWindow *main_window)
1255 delete_folder (main_window, TRUE);