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-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
42 #include "modest-ui-actions.h"
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
47 #include <widgets/modest-main-window.h>
48 #include <widgets/modest-msg-view-window.h>
49 #include <widgets/modest-account-view-window.h>
50 #include <widgets/modest-details-dialog.h>
52 #include "modest-account-mgr-helpers.h"
53 #include "modest-mail-operation.h"
54 #include "modest-text-utils.h"
56 #ifdef MODEST_HAVE_EASYSETUP
57 #include "easysetup/modest-easysetup-wizard.h"
58 #endif /*MODEST_HAVE_EASYSETUP*/
60 #include <modest-widget-memory.h>
61 #include <tny-error.h>
62 #include <tny-simple-list.h>
63 #include <tny-msg-view.h>
64 #include <tny-device.h>
66 typedef struct _GetMsgAsyncHelper {
68 ModestMailOperation *mail_op;
75 typedef enum _ReplyForwardAction {
81 typedef struct _ReplyForwardHelper {
82 guint reply_forward_type;
83 ReplyForwardAction action;
88 * The do_headers_action uses this kind of functions to perform some
89 * action to each member of a list of headers
91 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
94 do_headers_action (ModestWindow *win,
99 static void reply_forward_func (gpointer data, gpointer user_data);
101 static void get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err,
103 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
105 static gchar* ask_for_folder_name (GtkWindow *parent_window, const gchar *title);
108 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
111 const gchar *authors[] = {
112 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
115 about = gtk_about_dialog_new ();
116 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
117 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
118 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
119 _("Copyright (c) 2006, Nokia Corporation\n"
120 "All rights reserved."));
121 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
122 _("a modest e-mail client\n\n"
123 "design and implementation: Dirk-Jan C. Binnema\n"
124 "contributions from the fine people at KC and Ig\n"
125 "uses the tinymail email framework written by Philip van Hoof"));
126 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
127 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
129 gtk_dialog_run (GTK_DIALOG (about));
130 gtk_widget_destroy(about);
135 get_selected_headers (ModestWindow *win)
137 if (MODEST_IS_MAIN_WINDOW(win)) {
138 GtkWidget *header_view;
140 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
141 MODEST_WIDGET_TYPE_HEADER_VIEW);
142 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
144 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
145 /* for MsgViewWindows, we simply return a list with one element */
148 TnyList *list = NULL;
150 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
152 header = tny_msg_get_header (msg);
153 list = tny_simple_list_new ();
154 tny_list_prepend (list, G_OBJECT(header));
155 g_object_unref (G_OBJECT(header));
164 headers_action_delete (TnyHeader *header,
168 ModestMailOperation *mail_op;
170 /* TODO: add confirmation dialog */
171 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE);
172 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
175 /* Always delete. TODO: Move to trash still not supported */
176 modest_mail_operation_remove_msg (mail_op, header, FALSE);
177 g_object_unref (G_OBJECT (mail_op));
181 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
183 g_return_if_fail (MODEST_IS_WINDOW(win));
185 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
187 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
191 /* Remove each header */
192 do_headers_action (win, headers_action_delete, NULL);
194 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
195 gtk_widget_destroy (GTK_WIDGET(win));
201 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
207 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
209 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
210 gtk_widget_destroy (GTK_WIDGET (win));
211 } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
213 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
214 } else if (MODEST_IS_WINDOW (win)) {
215 gtk_widget_destroy (GTK_WIDGET (win));
217 g_return_if_reached ();
222 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
224 GtkClipboard *clipboard = NULL;
225 gchar *selection = NULL;
227 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
228 selection = gtk_clipboard_wait_for_text (clipboard);
230 modest_address_book_add_address (selection);
235 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
238 /* This is currently only implemented for Maemo,
239 * because it requires a providers preset file which is not publically available.
241 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
242 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
243 TRUE /* enabled accounts only */);
244 gboolean accounts_exist = account_names != NULL;
245 g_slist_free (account_names);
247 if (!accounts_exist) {
248 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
249 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
250 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
251 gtk_dialog_run (GTK_DIALOG (wizard));
252 gtk_widget_destroy (GTK_WIDGET (wizard));
254 /* Show the list of accounts: */
255 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
256 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
257 gtk_dialog_run (account_win);
258 gtk_widget_destroy (GTK_WIDGET(account_win));
261 GtkWidget *dialog, *label;
263 /* Create the widgets */
265 dialog = gtk_dialog_new_with_buttons ("Message",
267 GTK_DIALOG_DESTROY_WITH_PARENT,
271 label = gtk_label_new ("Hello World!");
273 /* Ensure that the dialog box is destroyed when the user responds. */
275 g_signal_connect_swapped (dialog, "response",
276 G_CALLBACK (gtk_widget_destroy),
279 /* Add the label, and show everything we've added to the dialog. */
281 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
283 gtk_widget_show_all (dialog);
284 #endif /* MODEST_PLATFORM_MAEMO */
288 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
290 ModestWindow *msg_win;
292 TnyFolder *folder = NULL;
293 gchar *account_name = NULL;
294 gchar *from_str = NULL;
295 /* GError *err = NULL; */
296 TnyAccount *account = NULL;
297 ModestWindowMgr *mgr;
298 gchar *signature = NULL;
300 account_name = g_strdup(modest_window_get_active_account (win));
302 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
304 g_printerr ("modest: no account found\n");
308 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
310 TNY_ACCOUNT_TYPE_STORE);
312 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
316 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
318 g_printerr ("modest: failed get from string for '%s'\n", account_name);
322 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
323 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
324 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
325 MODEST_ACCOUNT_SIGNATURE, FALSE);
327 signature = g_strdup ("");
330 msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
332 g_printerr ("modest: failed to create new msg\n");
336 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
338 g_printerr ("modest: failed to find Drafts folder\n");
342 /* tny_folder_add_msg (folder, msg, &err); */
344 /* g_printerr ("modest: error adding msg to Drafts folder: %s", */
346 /* g_error_free (err); */
350 /* Create and register edit window */
351 msg_win = modest_msg_edit_window_new (msg, account_name);
352 mgr = modest_runtime_get_window_mgr ();
353 modest_window_mgr_register_window (mgr, msg_win);
356 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
358 gtk_widget_show_all (GTK_WIDGET (msg_win));
361 g_free (account_name);
365 g_object_unref (G_OBJECT(account));
367 g_object_unref (G_OBJECT(msg));
369 g_object_unref (G_OBJECT(folder));
373 headers_action_open (TnyHeader *header,
377 modest_ui_actions_on_header_activated (MODEST_HEADER_VIEW (user_data),
379 MODEST_MAIN_WINDOW (win));
383 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
385 GtkWidget *header_view;
387 /* Get header view */
388 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
389 MODEST_WIDGET_TYPE_HEADER_VIEW);
391 /* Open each message */
392 do_headers_action (win, headers_action_open, header_view);
397 reply_forward_func (gpointer data, gpointer user_data)
399 TnyMsg *msg, *new_msg;
400 GetMsgAsyncHelper *helper;
401 ReplyForwardHelper *rf_helper;
402 ModestWindow *msg_win;
403 ModestEditType edit_type;
406 TnyFolder *folder = NULL;
407 TnyAccount *account = NULL;
408 ModestWindowMgr *mgr;
409 gchar *signature = NULL;
411 msg = TNY_MSG (data);
412 helper = (GetMsgAsyncHelper *) user_data;
413 rf_helper = (ReplyForwardHelper *) helper->user_data;
415 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
416 rf_helper->account_name);
417 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
418 rf_helper->account_name,
419 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
420 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
421 rf_helper->account_name,
422 MODEST_ACCOUNT_SIGNATURE, FALSE);
424 /* Create reply mail */
425 switch (rf_helper->action) {
428 modest_tny_msg_create_reply_msg (msg, from, signature,
429 rf_helper->reply_forward_type,
430 MODEST_TNY_MSG_REPLY_MODE_SENDER);
432 case ACTION_REPLY_TO_ALL:
434 modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
435 MODEST_TNY_MSG_REPLY_MODE_ALL);
436 edit_type = MODEST_EDIT_TYPE_REPLY;
440 modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
441 edit_type = MODEST_EDIT_TYPE_FORWARD;
444 g_return_if_reached ();
451 g_printerr ("modest: failed to create message\n");
455 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
456 rf_helper->account_name,
457 TNY_ACCOUNT_TYPE_STORE);
459 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
463 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
465 g_printerr ("modest: failed to find Drafts folder\n");
469 tny_folder_add_msg (folder, msg, &err);
471 g_printerr ("modest: error adding msg to Drafts folder: %s",
477 /* Create and register the windows */
478 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
479 mgr = modest_runtime_get_window_mgr ();
480 modest_window_mgr_register_window (mgr, msg_win);
482 /* Show edit window */
483 gtk_widget_show_all (GTK_WIDGET (msg_win));
487 g_object_unref (G_OBJECT (new_msg));
489 g_object_unref (G_OBJECT (folder));
491 g_object_unref (G_OBJECT (account));
493 /* g_free (rf_helper->account_name); */
494 /* g_slice_free (ReplyForwardHelper, rf_helper); */
497 * Common code for the reply and forward actions
500 reply_forward (ReplyForwardAction action, ModestWindow *win)
502 TnyList *header_list;
503 guint reply_forward_type;
505 /* TnyFolder *folder; */
506 GetMsgAsyncHelper *helper;
507 ReplyForwardHelper *rf_helper;
509 g_return_if_fail (MODEST_IS_WINDOW(win));
511 header_list = get_selected_headers (win);
515 reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
516 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
518 /* We assume that we can only select messages of the
519 same folder and that we reply all of them from the
520 same account. In fact the interface currently only
521 allows single selection */
524 rf_helper = g_slice_new0 (ReplyForwardHelper);
525 rf_helper->reply_forward_type = reply_forward_type;
526 rf_helper->action = action;
528 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
529 if (!rf_helper->account_name)
530 rf_helper->account_name =
531 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
533 helper = g_slice_new0 (GetMsgAsyncHelper);
534 helper->window = win;
535 helper->func = reply_forward_func;
536 helper->iter = tny_list_create_iterator (header_list);
537 helper->user_data = rf_helper;
538 helper->num_ops = tny_list_get_length (header_list);
540 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
542 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
544 g_printerr ("modest: no message found\n");
547 reply_forward_func (msg, helper);
549 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
551 /* folder = tny_header_get_folder (header); */
553 /* /\* The callback will call it per each header *\/ */
554 /* tny_folder_get_msg_async (folder, header, get_msg_cb, NULL, helper); */
555 /* g_object_unref (G_OBJECT (folder)); */
557 /* g_printerr ("modest: no folder for header\n"); */
559 helper->mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
560 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), helper->mail_op);
561 modest_mail_operation_process_msg (helper->mail_op, header, helper->num_ops, get_msg_cb, helper);
564 g_object_unref (G_OBJECT (header));
570 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
572 g_return_if_fail (MODEST_IS_WINDOW(win));
574 reply_forward (ACTION_REPLY, win);
578 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
580 g_return_if_fail (MODEST_IS_WINDOW(win));
582 reply_forward (ACTION_FORWARD, win);
586 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
588 g_return_if_fail (MODEST_IS_WINDOW(win));
590 reply_forward (ACTION_REPLY_TO_ALL, win);
594 modest_ui_actions_on_next (GtkAction *action,
595 ModestWindow *window)
597 if (MODEST_IS_MAIN_WINDOW (window)) {
598 GtkWidget *header_view;
600 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
601 MODEST_WIDGET_TYPE_HEADER_VIEW);
605 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view));
606 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
607 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
609 g_return_if_reached ();
614 modest_ui_actions_on_prev (GtkAction *action,
615 ModestWindow *window)
617 g_return_if_fail (MODEST_IS_WINDOW(window));
619 if (MODEST_IS_MAIN_WINDOW (window)) {
620 GtkWidget *header_view;
621 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
622 MODEST_WIDGET_TYPE_HEADER_VIEW);
626 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
627 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
628 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
630 g_return_if_reached ();
635 modest_ui_actions_on_sort (GtkAction *action,
636 ModestWindow *window)
638 g_return_if_fail (MODEST_IS_WINDOW(window));
640 if (MODEST_IS_MAIN_WINDOW (window)) {
641 GtkWidget *header_view;
642 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
643 MODEST_WIDGET_TYPE_HEADER_VIEW);
647 /* Show sorting dialog */
648 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
654 action_send (const gchar* account_name)
656 TnyAccount *tny_account;
657 ModestTnySendQueue *send_queue;
659 g_return_val_if_fail (account_name, FALSE);
661 /* Get the transport account according to the open connection,
662 * because the account might specify connection-specific SMTP servers.
665 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
668 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
672 send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
674 g_object_unref (G_OBJECT(tny_account));
675 g_printerr ("modest: cannot get send queue for %s\n", account_name);
679 modest_tny_send_queue_flush (send_queue);
681 g_object_unref (G_OBJECT(send_queue));
682 g_object_unref (G_OBJECT(tny_account));
689 action_receive (const gchar* account_name)
691 TnyAccount *tny_account;
692 ModestMailOperation *mail_op;
694 g_return_val_if_fail (account_name, FALSE);
697 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
699 TNY_ACCOUNT_TYPE_STORE);
701 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
705 /* Create the mail operation */
706 /* TODO: The spec wants us to first do any pending deletions, before receiving. */
707 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
708 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
709 modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
711 g_object_unref (G_OBJECT(tny_account));
712 g_object_unref (G_OBJECT (mail_op));
717 /** Check that an appropriate connection is open.
719 gboolean check_for_connection (const gchar *account_name)
721 TnyDevice *device = modest_runtime_get_device ();
724 g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
726 TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
729 if (tny_device_is_online (device))
732 modest_platform_connect_and_wait (NULL);
734 /* TODO: Wait until a result. */
740 do_send_receive_current_or_default (ModestWindow *win)
744 g_message ("%s: online? %s", __FUNCTION__,
745 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
747 /* As per the UI spec, only the active account should be affected,
748 * else the default folder if there is no active account: */
750 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
752 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
754 g_printerr ("modest: cannot get default account\n");
758 /* Do not continue if no suitable connection is open: */
759 if (check_for_connection (account_name)) {
760 /* As per the UI spec,
761 * for POP accounts, we should receive,
762 * for IMAP we should synchronize everything, including receiving,
763 * for SMTP we should send,
764 * first receiving, then sending:
766 if (!action_receive(account_name))
767 g_printerr ("modest: failed to receive\n");
768 if (!action_send(account_name))
769 g_printerr ("modest: failed to send\n");
771 g_free (account_name);
777 do_send_receive_auto (ModestWindow *win)
779 g_message ("%s: online? %s", __FUNCTION__,
780 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
782 /* TODO: Delete the item->data strings as well as the list? */
783 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
784 TRUE /* enabled accounts only */);
785 GSList *iter = account_names;
787 const gchar * account_name = (const char*) iter->data;
789 /* Do not continue if no suitable connection is open: */
790 if (account_name && check_for_connection (account_name)) {
791 /* As per the UI spec,
792 * for POP accounts, we should receive,
793 * for IMAP we should synchronize everything, including receiving,
794 * for SMTP we should send,
795 * first receiving, then sending:
797 if (!action_receive(account_name))
798 g_printerr ("modest: failed to receive for account %s\n", account_name);
799 if (!action_send(account_name))
800 g_printerr ("modest: failed to send for account %s\n", account_name);
805 g_slist_free (account_names);
809 do_send_receive (ModestWindow *win)
811 const gboolean auto_update = TRUE; /* TODO: Get gconf setting. */
813 do_send_receive_current_or_default (win);
815 do_send_receive_auto (win);
819 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
821 /* Check that at least one account exists: */
822 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
823 TRUE /* enabled accounts only */);
824 gboolean accounts_exist = account_names != NULL;
825 g_slist_free (account_names);
827 /* If not, allow the user to create an account before trying to send/receive. */
828 if (!accounts_exist) {
829 modest_ui_actions_on_accounts (NULL, win);
832 do_send_receive (win);
839 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
842 GtkWidget *header_view;
844 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
846 header_view = modest_main_window_get_child_widget (main_window,
847 MODEST_WIDGET_TYPE_HEADER_VIEW);
851 conf = modest_runtime_get_conf ();
853 /* what is saved/restored is depending on the style; thus; we save with
854 * old style, then update the style, and restore for this new style
856 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
858 if (modest_header_view_get_style
859 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
860 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
861 MODEST_HEADER_VIEW_STYLE_TWOLINES);
863 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
864 MODEST_HEADER_VIEW_STYLE_DETAILS);
866 modest_widget_memory_restore (conf, G_OBJECT(header_view),
867 MODEST_CONF_HEADER_VIEW_KEY);
871 * This function is a generic handler for the tny_folder_get_msg_async
872 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
873 * contains a user provided function that is called inside this
874 * method. This will allow us to use this callback in many different
875 * places. This callback performs the common actions for the
876 * get_msg_async call, more specific actions will be done by the user
880 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
882 GetMsgAsyncHelper *helper;
884 helper = (GetMsgAsyncHelper *) user_data;
887 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
888 modest_ui_actions_on_item_not_found (NULL,
889 MODEST_ITEM_TYPE_MESSAGE,
894 /* Call user function */
896 helper->func (msg, user_data);
898 /* Process next element (if exists) */
899 tny_iterator_next (helper->iter);
900 if (tny_iterator_is_done (helper->iter)) {
901 /* Notify the queue */
902 if (helper->mail_op != NULL)
903 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), helper->mail_op);
907 ReplyForwardHelper *rf_helper = (ReplyForwardHelper *) helper->user_data;
908 headers = tny_iterator_get_list (helper->iter);
909 g_object_unref (G_OBJECT (headers));
910 g_object_unref (G_OBJECT (helper->iter));
911 if (rf_helper != NULL) {
912 g_free (rf_helper->account_name);
913 g_slice_free (ReplyForwardHelper, rf_helper);
915 g_slice_free (GetMsgAsyncHelper, helper);
918 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
919 /* tny_folder_get_msg_async (folder, header, */
920 /* get_msg_cb, NULL, helper); */
921 modest_mail_operation_process_msg (helper->mail_op, header, helper->num_ops, get_msg_cb, helper);
923 g_object_unref (G_OBJECT(header));
928 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
930 ModestMainWindow *main_window)
932 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
934 /* Update Main window title */
935 if (GTK_WIDGET_HAS_FOCUS (header_view)) {
936 const gchar *subject = tny_header_get_subject (header);
937 if (subject && strcmp (subject, ""))
938 gtk_window_set_title (GTK_WINDOW (main_window), subject);
940 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
947 modest_ui_actions_on_header_activated (ModestHeaderView *header_view, TnyHeader *header,
948 ModestMainWindow *main_window)
950 ModestWindow *win = NULL;
951 TnyFolder *folder = NULL;
953 ModestWindowMgr *mgr;
956 GtkTreeSelection *sel = NULL;
957 GList *sel_list = NULL;
959 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
964 folder = tny_header_get_folder (header);
966 g_printerr ("modest: cannot get folder for header\n");
970 /* FIXME: make async?; check error */
971 msg = tny_folder_get_msg (folder, header, NULL);
973 g_printerr ("modest: cannot get msg for header\n");
977 /* Look if we already have a message view for that header */
978 mgr = modest_runtime_get_window_mgr ();
979 win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
981 /* If not, create a new window */
985 account = g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
987 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
989 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
990 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
991 if (sel_list != NULL) {
992 gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data);
994 win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
995 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
996 g_list_free (sel_list);
998 win = modest_msg_view_window_new (msg, account);
1000 modest_window_mgr_register_window (mgr, win);
1002 gtk_window_set_transient_for (GTK_WINDOW (win),
1003 GTK_WINDOW (main_window));
1006 gtk_widget_show_all (GTK_WIDGET(win));
1008 g_object_unref (G_OBJECT (msg));
1011 g_object_unref (G_OBJECT (folder));
1015 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1016 TnyFolderStore *folder_store,
1018 ModestMainWindow *main_window)
1021 GtkWidget *header_view;
1023 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1025 header_view = modest_main_window_get_child_widget(main_window,
1026 MODEST_WIDGET_TYPE_HEADER_VIEW);
1030 conf = modest_runtime_get_conf ();
1032 if (TNY_IS_FOLDER (folder_store)) {
1034 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1037 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1038 TNY_FOLDER (folder_store));
1039 modest_widget_memory_restore (conf, G_OBJECT(header_view),
1040 MODEST_CONF_HEADER_VIEW_KEY);
1042 modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1043 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1045 } else if (TNY_IS_ACCOUNT (folder_store)) {
1047 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1052 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1059 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1061 if (g_main_depth > 0)
1062 gdk_threads_enter ();
1063 online = tny_device_is_online (modest_runtime_get_device());
1066 /* already online -- the item is simply not there... */
1067 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1069 GTK_MESSAGE_WARNING,
1071 _("The %s you selected cannot be found"),
1073 gtk_dialog_run (GTK_DIALOG(dialog));
1075 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1079 GTK_RESPONSE_REJECT,
1081 GTK_RESPONSE_ACCEPT,
1083 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1084 "Do you want to get online?"), item);
1085 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1086 gtk_label_new (txt), FALSE, FALSE, 0);
1087 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1090 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1091 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1092 // modest_platform_connect_and_wait ();;
1095 gtk_widget_destroy (dialog);
1096 if (g_main_depth > 0)
1097 gdk_threads_leave ();
1101 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1104 g_message ("%s %s", __FUNCTION__, link);
1109 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1112 modest_platform_activate_uri (link);
1116 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1119 modest_platform_show_uri_popup (link);
1123 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1126 g_message (__FUNCTION__);
1131 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1132 const gchar *address,
1135 g_message ("%s %s", __FUNCTION__, address);
1139 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1141 TnyTransportAccount *transport_account;
1142 ModestMailOperation *mail_operation;
1144 gchar *account_name, *from;
1145 ModestAccountMgr *account_mgr;
1147 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1149 data = modest_msg_edit_window_get_msg_data (edit_window);
1151 account_mgr = modest_runtime_get_account_mgr();
1152 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1154 account_name = modest_account_mgr_get_default_account (account_mgr);
1155 if (!account_name) {
1156 g_printerr ("modest: no account found\n");
1157 modest_msg_edit_window_free_msg_data (edit_window, data);
1161 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1162 (modest_runtime_get_account_store(),
1164 TNY_ACCOUNT_TYPE_TRANSPORT));
1165 if (!transport_account) {
1166 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1167 g_free (account_name);
1168 modest_msg_edit_window_free_msg_data (edit_window, data);
1171 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1173 /* Create the mail operation */
1174 mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1175 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1177 modest_mail_operation_save_to_drafts (mail_operation,
1187 data->priority_flags);
1190 g_free (account_name);
1191 g_object_unref (G_OBJECT (transport_account));
1192 g_object_unref (G_OBJECT (mail_operation));
1194 modest_msg_edit_window_free_msg_data (edit_window, data);
1196 /* Save settings and close the window */
1197 gtk_widget_destroy (GTK_WIDGET (edit_window));
1200 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1202 TnyTransportAccount *transport_account;
1203 ModestMailOperation *mail_operation;
1205 gchar *account_name, *from;
1206 ModestAccountMgr *account_mgr;
1208 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1210 if (!modest_msg_edit_window_check_names (edit_window))
1213 data = modest_msg_edit_window_get_msg_data (edit_window);
1215 /* FIXME: Code added just for testing. The final version will
1216 use the send queue provided by tinymail and some
1218 account_mgr = modest_runtime_get_account_mgr();
1219 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1221 account_name = modest_account_mgr_get_default_account (account_mgr);
1222 if (!account_name) {
1223 g_printerr ("modest: no account found\n");
1224 modest_msg_edit_window_free_msg_data (edit_window, data);
1228 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1229 (modest_runtime_get_account_store(),
1231 if (!transport_account) {
1232 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1233 g_free (account_name);
1234 modest_msg_edit_window_free_msg_data (edit_window, data);
1237 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1239 /* Create the mail operation */
1240 mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND);
1241 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1243 modest_mail_operation_send_new_mail (mail_operation,
1253 data->priority_flags);
1256 g_free (account_name);
1257 g_object_unref (G_OBJECT (transport_account));
1258 g_object_unref (G_OBJECT (mail_operation));
1260 modest_msg_edit_window_free_msg_data (edit_window, data);
1262 /* Save settings and close the window */
1263 gtk_widget_destroy (GTK_WIDGET (edit_window));
1267 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1268 ModestMsgEditWindow *window)
1270 ModestMsgEditFormatState *format_state = NULL;
1272 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1273 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1275 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1278 format_state = modest_msg_edit_window_get_format_state (window);
1279 g_return_if_fail (format_state != NULL);
1281 format_state->bold = gtk_toggle_action_get_active (action);
1282 modest_msg_edit_window_set_format_state (window, format_state);
1283 g_free (format_state);
1288 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1289 ModestMsgEditWindow *window)
1291 ModestMsgEditFormatState *format_state = NULL;
1293 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1294 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1296 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1299 format_state = modest_msg_edit_window_get_format_state (window);
1300 g_return_if_fail (format_state != NULL);
1302 format_state->italics = gtk_toggle_action_get_active (action);
1303 modest_msg_edit_window_set_format_state (window, format_state);
1304 g_free (format_state);
1309 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1310 ModestMsgEditWindow *window)
1312 ModestMsgEditFormatState *format_state = NULL;
1314 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1315 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1317 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1320 format_state = modest_msg_edit_window_get_format_state (window);
1321 g_return_if_fail (format_state != NULL);
1323 format_state->bullet = gtk_toggle_action_get_active (action);
1324 modest_msg_edit_window_set_format_state (window, format_state);
1325 g_free (format_state);
1330 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1331 GtkRadioAction *selected,
1332 ModestMsgEditWindow *window)
1334 ModestMsgEditFormatState *format_state = NULL;
1335 GtkJustification value;
1337 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1339 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1342 value = gtk_radio_action_get_current_value (selected);
1344 format_state = modest_msg_edit_window_get_format_state (window);
1345 g_return_if_fail (format_state != NULL);
1347 format_state->justification = value;
1348 modest_msg_edit_window_set_format_state (window, format_state);
1349 g_free (format_state);
1353 modest_ui_actions_on_select_editor_color (GtkAction *action,
1354 ModestMsgEditWindow *window)
1356 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1357 g_return_if_fail (GTK_IS_ACTION (action));
1359 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1362 modest_msg_edit_window_select_color (window);
1366 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1367 ModestMsgEditWindow *window)
1369 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1370 g_return_if_fail (GTK_IS_ACTION (action));
1372 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1375 modest_msg_edit_window_select_background_color (window);
1379 modest_ui_actions_on_insert_image (GtkAction *action,
1380 ModestMsgEditWindow *window)
1382 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1383 g_return_if_fail (GTK_IS_ACTION (action));
1385 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1388 modest_msg_edit_window_insert_image (window);
1392 * Shows a dialog with an entry that asks for some text. The returned
1393 * value must be freed by the caller. The dialog window title will be
1397 ask_for_folder_name (GtkWindow *parent_window,
1400 GtkWidget *dialog, *entry;
1401 gchar *folder_name = NULL;
1403 /* Ask for folder name */
1404 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1408 GTK_RESPONSE_REJECT,
1410 GTK_RESPONSE_ACCEPT,
1412 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1413 gtk_label_new(title),
1416 entry = gtk_entry_new_with_max_length (40);
1417 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1421 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1423 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1424 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1426 gtk_widget_destroy (dialog);
1432 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1434 TnyFolderStore *parent_folder;
1435 GtkWidget *folder_view;
1437 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1439 folder_view = modest_main_window_get_child_widget (main_window,
1440 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1444 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1446 if (parent_folder) {
1447 gboolean finished = FALSE;
1449 gchar *folder_name = NULL, *suggested_name = NULL;
1451 /* Run the new folder dialog */
1453 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1458 if (result == GTK_RESPONSE_REJECT) {
1461 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1462 TnyFolder *new_folder = NULL;
1464 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1467 new_folder = modest_mail_operation_create_folder (mail_op,
1469 (const gchar *) folder_name);
1471 g_object_unref (new_folder);
1475 /* /\* TODO: check error and follow proper actions *\/ */
1476 /* /\* suggested_name = X; *\/ */
1477 /* /\* Show error to the user *\/ */
1478 /* modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1479 /* MODEST_INFORMATION_CREATE_FOLDER); */
1481 g_object_unref (mail_op);
1483 g_free (folder_name);
1487 g_object_unref (parent_folder);
1492 modest_ui_actions_on_rename_folder (GtkAction *action,
1493 ModestMainWindow *main_window)
1495 TnyFolderStore *folder;
1496 GtkWidget *folder_view;
1498 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1500 folder_view = modest_main_window_get_child_widget (main_window,
1501 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1505 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1507 if (folder && TNY_IS_FOLDER (folder)) {
1509 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1510 _("Please enter a new name for the folder"));
1512 if (folder_name != NULL && strlen (folder_name) > 0) {
1513 ModestMailOperation *mail_op;
1515 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1516 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1519 modest_mail_operation_rename_folder (mail_op,
1520 TNY_FOLDER (folder),
1521 (const gchar *) folder_name);
1523 g_object_unref (mail_op);
1524 g_free (folder_name);
1526 g_object_unref (folder);
1531 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
1533 TnyFolderStore *folder;
1534 GtkWidget *folder_view;
1538 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1540 folder_view = modest_main_window_get_child_widget (main_window,
1541 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1545 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1548 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
1549 tny_folder_get_name (TNY_FOLDER (folder)));
1550 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
1551 (const gchar *) message);
1554 if (response == GTK_RESPONSE_OK) {
1555 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE);
1557 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1559 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1561 /* Show error if happened */
1562 if (modest_mail_operation_get_error (mail_op))
1563 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1564 MODEST_INFORMATION_DELETE_FOLDER);
1566 g_object_unref (G_OBJECT (mail_op));
1569 g_object_unref (G_OBJECT (folder));
1573 modest_ui_actions_on_delete_folder (GtkAction *action,
1574 ModestMainWindow *main_window)
1576 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1578 delete_folder (main_window, FALSE);
1582 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1584 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1586 delete_folder (main_window, TRUE);
1590 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
1591 const gchar* account_name,
1595 ModestMainWindow *main_window)
1598 GtkWidget *dialog, *entry, *remember_pass_check;
1600 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1604 GTK_RESPONSE_REJECT,
1606 GTK_RESPONSE_ACCEPT,
1608 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1610 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1611 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1615 entry = gtk_entry_new_with_max_length (40);
1616 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1617 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1619 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1622 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1623 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1626 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1628 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1629 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1636 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1641 gtk_widget_destroy (dialog);
1645 modest_ui_actions_on_cut (GtkAction *action,
1646 ModestWindow *window)
1648 GtkWidget *focused_widget;
1650 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1651 if (GTK_IS_EDITABLE (focused_widget)) {
1652 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1653 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1654 GtkTextBuffer *buffer;
1655 GtkClipboard *clipboard;
1657 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1658 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1659 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1664 modest_ui_actions_on_copy (GtkAction *action,
1665 ModestWindow *window)
1667 GtkClipboard *clipboard;
1668 GtkWidget *focused_widget;
1670 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1671 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1672 if (GTK_IS_LABEL (focused_widget)) {
1673 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1674 } else if (GTK_IS_EDITABLE (focused_widget)) {
1675 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1676 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1677 GtkTextBuffer *buffer;
1679 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1680 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1685 modest_ui_actions_on_undo (GtkAction *action,
1686 ModestWindow *window)
1688 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1689 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1691 g_return_if_reached ();
1696 modest_ui_actions_on_paste (GtkAction *action,
1697 ModestWindow *window)
1699 GtkWidget *focused_widget;
1701 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1702 if (GTK_IS_EDITABLE (focused_widget)) {
1703 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1704 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1705 GtkTextBuffer *buffer;
1706 GtkClipboard *clipboard;
1708 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1709 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1710 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1715 modest_ui_actions_on_select_all (GtkAction *action,
1716 ModestWindow *window)
1718 GtkWidget *focused_widget;
1720 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1721 if (GTK_IS_LABEL (focused_widget)) {
1722 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1723 } else if (GTK_IS_EDITABLE (focused_widget)) {
1724 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1725 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1726 GtkTextBuffer *buffer;
1727 GtkTextIter start, end;
1729 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1730 gtk_text_buffer_get_start_iter (buffer, &start);
1731 gtk_text_buffer_get_end_iter (buffer, &end);
1732 gtk_text_buffer_select_range (buffer, &start, &end);
1737 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1738 GtkRadioAction *selected,
1739 ModestWindow *window)
1743 value = gtk_radio_action_get_current_value (selected);
1744 if (MODEST_IS_WINDOW (window)) {
1745 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1749 void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1750 GtkRadioAction *selected,
1751 ModestWindow *window)
1753 TnyHeaderFlags flags;
1754 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1756 flags = gtk_radio_action_get_current_value (selected);
1757 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1760 void modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1761 GtkRadioAction *selected,
1762 ModestWindow *window)
1766 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1768 file_format = gtk_radio_action_get_current_value (selected);
1769 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1774 modest_ui_actions_on_zoom_plus (GtkAction *action,
1775 ModestWindow *window)
1777 g_return_if_fail (MODEST_IS_WINDOW (window));
1779 modest_window_zoom_plus (MODEST_WINDOW (window));
1783 modest_ui_actions_on_zoom_minus (GtkAction *action,
1784 ModestWindow *window)
1786 g_return_if_fail (MODEST_IS_WINDOW (window));
1788 modest_window_zoom_minus (MODEST_WINDOW (window));
1792 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
1793 ModestWindow *window)
1795 ModestWindowMgr *mgr;
1796 gboolean fullscreen, active;
1797 g_return_if_fail (MODEST_IS_WINDOW (window));
1799 mgr = modest_runtime_get_window_mgr ();
1801 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1802 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1804 if (active != fullscreen) {
1805 modest_window_mgr_set_fullscreen_mode (mgr, active);
1806 gtk_window_present (GTK_WINDOW (window));
1811 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1812 ModestWindow *window)
1814 ModestWindowMgr *mgr;
1815 gboolean fullscreen;
1817 g_return_if_fail (MODEST_IS_WINDOW (window));
1819 mgr = modest_runtime_get_window_mgr ();
1820 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1821 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1823 gtk_window_present (GTK_WINDOW (window));
1827 * Used by modest_ui_actions_on_details to call do_headers_action
1830 headers_action_show_details (TnyHeader *header,
1831 ModestWindow *window,
1838 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
1841 gtk_widget_show_all (dialog);
1842 gtk_dialog_run (GTK_DIALOG (dialog));
1844 gtk_widget_destroy (dialog);
1848 * Show the folder details in a ModestDetailsDialog widget
1851 show_folder_details (TnyFolder *folder,
1857 dialog = modest_details_dialog_new_with_folder (window, folder);
1860 gtk_widget_show_all (dialog);
1861 gtk_dialog_run (GTK_DIALOG (dialog));
1863 gtk_widget_destroy (dialog);
1867 * Show the header details in a ModestDetailsDialog widget
1870 modest_ui_actions_on_details (GtkAction *action,
1873 TnyList * headers_list;
1877 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1880 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1884 headers_list = get_selected_headers (win);
1888 iter = tny_list_create_iterator (headers_list);
1890 header = TNY_HEADER (tny_iterator_get_current (iter));
1891 headers_action_show_details (header, win, NULL);
1892 g_object_unref (header);
1894 g_object_unref (iter);
1896 } else if (MODEST_IS_MAIN_WINDOW (win)) {
1897 GtkWidget *folder_view, *header_view;
1899 /* Check which widget has the focus */
1900 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1901 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1902 if (gtk_widget_is_focus (folder_view)) {
1905 folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1907 /* Show only when it's a folder */
1908 if (!folder || !TNY_IS_FOLDER (folder))
1911 show_folder_details (folder, GTK_WINDOW (win));
1914 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1915 MODEST_WIDGET_TYPE_HEADER_VIEW);
1916 /* Show details of each header */
1917 do_headers_action (win, headers_action_show_details, header_view);
1923 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1924 ModestMsgEditWindow *window)
1926 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1928 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1932 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1933 ModestMsgEditWindow *window)
1935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1937 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1941 modest_ui_actions_toggle_folders_view (GtkAction *action,
1942 ModestMainWindow *main_window)
1946 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1948 conf = modest_runtime_get_conf ();
1950 if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1951 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1953 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1957 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
1958 ModestWindow *window)
1960 gboolean active, fullscreen = FALSE;
1961 ModestWindowMgr *mgr;
1963 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1965 /* Check if we want to toggle the toolbar vuew in fullscreen
1967 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
1968 "ViewShowToolbarFullScreen")) {
1972 /* Toggle toolbar */
1973 mgr = modest_runtime_get_window_mgr ();
1974 modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1978 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
1979 ModestMsgEditWindow *window)
1981 modest_msg_edit_window_select_font (window);
1985 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
1986 const gchar *display_name,
1989 /* Do not change the application name if the widget has not
1990 the focus. This callback could be called even if the folder
1991 view has not the focus, because the handled signal could be
1992 emitted when the folder view is redrawn */
1993 if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
1995 gtk_window_set_title (window, display_name);
1997 gtk_window_set_title (window, " ");
2002 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2004 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2005 modest_msg_edit_window_select_contacts (window);
2009 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2011 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2012 modest_msg_edit_window_check_names (window);
2017 create_move_to_dialog (ModestWindow *win,
2018 GtkWidget *folder_view,
2019 GtkWidget **tree_view)
2021 GtkWidget *dialog, *scroll;
2023 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2025 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2027 GTK_RESPONSE_ACCEPT,
2029 GTK_RESPONSE_REJECT,
2032 /* Create scrolled window */
2033 scroll = gtk_scrolled_window_new (NULL, NULL);
2034 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
2035 GTK_POLICY_AUTOMATIC,
2036 GTK_POLICY_AUTOMATIC);
2038 /* Create folder view */
2039 *tree_view = modest_folder_view_new (NULL);
2040 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2041 gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2042 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2044 /* Add scroll to dialog */
2045 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
2046 scroll, FALSE, FALSE, 0);
2048 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2054 * Returns TRUE if at least one of the headers of the list belongs to
2055 * a message that has been fully retrieved.
2058 has_retrieved_msgs (TnyList *list)
2061 gboolean found = FALSE;
2063 iter = tny_list_create_iterator (list);
2064 while (tny_iterator_is_done (iter) && !found) {
2066 TnyHeaderFlags flags;
2068 header = TNY_HEADER (tny_iterator_get_current (iter));
2069 flags = tny_header_get_flags (header);
2070 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2074 tny_iterator_next (iter);
2076 g_object_unref (iter);
2082 * Shows a confirmation dialog to the user when we're moving messages
2083 * from a remote server to the local storage. Returns the dialog
2084 * response. If it's other kind of movement the it always returns
2088 msgs_move_to_confirmation (GtkWindow *win,
2089 TnyFolder *dest_folder,
2092 gint response = GTK_RESPONSE_OK;
2094 /* If the destination is a local folder */
2095 if (modest_tny_folder_is_local_folder (dest_folder)) {
2096 TnyFolder *src_folder;
2100 /* Get source folder */
2101 iter = tny_list_create_iterator (headers);
2102 header = TNY_HEADER (tny_iterator_get_current (iter));
2103 src_folder = tny_header_get_folder (header);
2104 g_object_unref (header);
2105 g_object_unref (iter);
2107 /* If the source is a remote folder */
2108 if (!modest_tny_folder_is_local_folder (src_folder)) {
2109 const gchar *message;
2111 if (tny_list_get_length (headers) == 1)
2112 if (has_retrieved_msgs (headers))
2113 message = _("mcen_nc_move_retrieve");
2115 message = _("mcen_nc_move_header");
2117 if (has_retrieved_msgs (headers))
2118 message = _("mcen_nc_move_retrieves");
2120 message = _("mcen_nc_move_headers");
2122 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2123 (const gchar *) message);
2130 * UI handler for the "Move to" action when invoked from the
2134 modest_ui_actions_on_main_window_move_to (GtkAction *action,
2135 ModestMainWindow *win)
2137 GtkWidget *dialog, *folder_view, *tree_view = NULL;
2139 TnyFolderStore *folder_store;
2140 ModestMailOperation *mail_op = NULL;
2142 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2144 /* Get the folder view */
2145 folder_view = modest_main_window_get_child_widget (win,
2146 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2148 /* Create and run the dialog */
2149 dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2150 result = gtk_dialog_run (GTK_DIALOG(dialog));
2152 /* We do this to save an indentation level ;-) */
2153 if (result != GTK_RESPONSE_ACCEPT)
2156 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2158 if (TNY_IS_ACCOUNT (folder_store))
2161 /* Get folder or messages to transfer */
2162 if (gtk_widget_is_focus (folder_view)) {
2163 TnyFolderStore *src_folder;
2164 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2166 if (TNY_IS_FOLDER (src_folder)) {
2167 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2168 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2171 modest_mail_operation_xfer_folder (mail_op,
2172 TNY_FOLDER (src_folder),
2175 g_object_unref (G_OBJECT (mail_op));
2179 g_object_unref (G_OBJECT (src_folder));
2181 GtkWidget *header_view;
2182 header_view = modest_main_window_get_child_widget (win,
2183 MODEST_WIDGET_TYPE_HEADER_VIEW);
2184 if (gtk_widget_is_focus (header_view)) {
2188 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2190 /* Ask for user confirmation */
2191 response = msgs_move_to_confirmation (GTK_WINDOW (win),
2192 TNY_FOLDER (folder_store),
2195 /* Transfer messages */
2196 if (response == GTK_RESPONSE_OK) {
2197 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2198 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2201 modest_mail_operation_xfer_msgs (mail_op,
2203 TNY_FOLDER (folder_store),
2205 g_object_unref (G_OBJECT (mail_op));
2209 g_object_unref (folder_store);
2212 gtk_widget_destroy (dialog);
2217 * UI handler for the "Move to" action when invoked from the
2218 * ModestMsgViewWindow
2221 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
2222 ModestMsgViewWindow *win)
2224 GtkWidget *dialog, *folder_view, *tree_view = NULL;
2226 ModestMainWindow *main_window;
2231 /* Get the folder view */
2232 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2233 folder_view = modest_main_window_get_child_widget (main_window,
2234 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2236 /* Create and run the dialog */
2237 dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2238 result = gtk_dialog_run (GTK_DIALOG(dialog));
2240 if (result == GTK_RESPONSE_ACCEPT) {
2241 TnyFolderStore *folder_store;
2244 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2246 /* Create header list */
2247 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2248 header = tny_msg_get_header (msg);
2249 headers = tny_simple_list_new ();
2250 tny_list_prepend (headers, G_OBJECT (header));
2251 g_object_unref (header);
2252 g_object_unref (msg);
2254 /* Ask user for confirmation. MSG-NOT404 */
2255 response = msgs_move_to_confirmation (GTK_WINDOW (win),
2256 TNY_FOLDER (folder_store),
2259 /* Transfer current msg */
2260 if (response == GTK_RESPONSE_OK) {
2261 ModestMailOperation *mail_op;
2263 /* Create mail op */
2264 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2265 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2268 /* Transfer messages */
2269 modest_mail_operation_xfer_msgs (mail_op,
2271 TNY_FOLDER (folder_store),
2273 g_object_unref (G_OBJECT (mail_op));
2275 g_object_unref (headers);
2277 g_object_unref (folder_store);
2279 gtk_widget_destroy (dialog);
2283 modest_ui_actions_on_move_to (GtkAction *action,
2286 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2287 MODEST_IS_MSG_VIEW_WINDOW (win));
2289 if (MODEST_IS_MAIN_WINDOW (win))
2290 modest_ui_actions_on_main_window_move_to (action,
2291 MODEST_MAIN_WINDOW (win));
2293 modest_ui_actions_on_msg_view_window_move_to (action,
2294 MODEST_MSG_VIEW_WINDOW (win));
2298 * Calls #HeadersFunc for each header already selected in the main
2299 * window or the message currently being shown in the msg view window
2302 do_headers_action (ModestWindow *win,
2306 TnyList *headers_list;
2310 headers_list = get_selected_headers (win);
2314 /* Call the function for each header */
2315 iter = tny_list_create_iterator (headers_list);
2316 while (!tny_iterator_is_done (iter)) {
2319 header = TNY_HEADER (tny_iterator_get_current (iter));
2320 func (header, win, user_data);
2321 g_object_unref (header);
2322 tny_iterator_next (iter);
2324 g_object_unref (iter);