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>
35 #include <glib/gprintf.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
48 #ifdef MODEST_PLATFORM_MAEMO
49 #include "maemo/modest-osso-state-saving.h"
50 #endif /* MODEST_PLATFORM_MAEMO */
52 #include "widgets/modest-ui-constants.h"
53 #include <widgets/modest-main-window.h>
54 #include <widgets/modest-msg-view-window.h>
55 #include <widgets/modest-account-view-window.h>
56 #include <widgets/modest-details-dialog.h>
57 #include <widgets/modest-attachments-view.h>
58 #include "widgets/modest-global-settings-dialog.h"
59 #include "modest-connection-specific-smtp-window.h"
60 #include "modest-account-mgr-helpers.h"
61 #include "modest-mail-operation.h"
62 #include "modest-text-utils.h"
64 #ifdef MODEST_HAVE_EASYSETUP
65 #include "easysetup/modest-easysetup-wizard.h"
66 #endif /* MODEST_HAVE_EASYSETUP */
68 #include <modest-widget-memory.h>
69 #include <tny-error.h>
70 #include <tny-simple-list.h>
71 #include <tny-msg-view.h>
72 #include <tny-device.h>
73 #include <tny-merge-folder.h>
75 typedef struct _GetMsgAsyncHelper {
77 ModestMailOperation *mail_op;
84 typedef enum _ReplyForwardAction {
90 typedef struct _ReplyForwardHelper {
91 guint reply_forward_type;
92 ReplyForwardAction action;
94 GtkWidget *parent_window;
98 * The do_headers_action uses this kind of functions to perform some
99 * action to each member of a list of headers
101 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
104 do_headers_action (ModestWindow *win,
109 static void open_msg_cb (ModestMailOperation *mail_op,
114 static void reply_forward_cb (ModestMailOperation *mail_op,
119 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
121 static gchar* ask_for_folder_name (GtkWindow *parent_window, const gchar *title);
124 static void _on_send_receive_progress_changed (ModestMailOperation *mail_op,
125 ModestMailOperationState *state,
131 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
134 const gchar *authors[] = {
135 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
138 about = gtk_about_dialog_new ();
139 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
140 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
141 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
142 _("Copyright (c) 2006, Nokia Corporation\n"
143 "All rights reserved."));
144 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
145 _("a modest e-mail client\n\n"
146 "design and implementation: Dirk-Jan C. Binnema\n"
147 "contributions from the fine people at KC and Ig\n"
148 "uses the tinymail email framework written by Philip van Hoof"));
149 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
150 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
152 gtk_dialog_run (GTK_DIALOG (about));
153 gtk_widget_destroy(about);
157 * Gets the list of currently selected messages. If the win is the
158 * main window, then it returns a newly allocated list of the headers
159 * selected in the header view. If win is the msg view window, then
160 * the value returned is a list with just a single header.
162 * The caller of this funcion must free the list.
165 get_selected_headers (ModestWindow *win)
167 if (MODEST_IS_MAIN_WINDOW(win)) {
168 GtkWidget *header_view;
170 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
171 MODEST_WIDGET_TYPE_HEADER_VIEW);
172 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
174 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
175 /* for MsgViewWindows, we simply return a list with one element */
177 TnyList *list = NULL;
179 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
180 if (header != NULL) {
181 list = tny_simple_list_new ();
182 tny_list_prepend (list, G_OBJECT(header));
183 g_object_unref (G_OBJECT(header));
193 headers_action_mark_as_read (TnyHeader *header,
197 TnyHeaderFlags flags;
199 g_return_if_fail (TNY_IS_HEADER(header));
201 flags = tny_header_get_flags (header);
202 if (flags & TNY_HEADER_FLAG_SEEN) return;
203 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
207 headers_action_mark_as_unread (TnyHeader *header,
211 TnyHeaderFlags flags;
213 g_return_if_fail (TNY_IS_HEADER(header));
215 flags = tny_header_get_flags (header);
216 if (flags & TNY_HEADER_FLAG_SEEN) {
217 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
223 headers_action_delete (TnyHeader *header,
227 ModestMailOperation *mail_op = NULL;
229 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
230 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
233 /* Always delete. TODO: Move to trash still not supported */
234 modest_mail_operation_remove_msg (mail_op, header, FALSE);
235 g_object_unref (G_OBJECT (mail_op));
239 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
241 TnyList *header_list = NULL;
242 TnyIterator *iter = NULL;
243 TnyHeader *header = NULL;
244 gchar *message = NULL;
248 ModestWindowMgr *mgr;
250 g_return_if_fail (MODEST_IS_WINDOW(win));
252 header_list = get_selected_headers (win);
253 if (!header_list) return;
255 /* Check if any of the headers is already opened */
256 iter = tny_list_create_iterator (header_list);
258 mgr = modest_runtime_get_window_mgr ();
259 while (!tny_iterator_is_done (iter) && !found) {
260 header = TNY_HEADER (tny_iterator_get_current (iter));
261 if (modest_window_mgr_find_window_by_header (mgr, header))
263 g_object_unref (header);
264 tny_iterator_next (iter);
266 g_object_unref (iter);
271 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
272 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
274 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
278 g_object_unref (header_list);
283 if (tny_list_get_length(header_list) > 1)
284 message = g_strdup(_("emev_nc_delete_messages"));
286 iter = tny_list_create_iterator (header_list);
287 header = TNY_HEADER (tny_iterator_get_current (iter));
288 desc = g_strdup_printf ("%s", tny_header_get_subject (header));
289 message = g_strdup_printf(_("emev_nc_delete_message"), desc);
290 g_object_unref (header);
291 g_object_unref (iter);
294 /* Confirmation dialog */
295 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
299 if (response == GTK_RESPONSE_OK) {
300 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
302 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
306 /* Remove each header */
307 do_headers_action (win, headers_action_delete, NULL);
309 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
310 gtk_widget_destroy (GTK_WIDGET(win));
317 g_object_unref (header_list);
322 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
324 #ifdef MODEST_PLATFORM_MAEMO
325 modest_osso_save_state();
326 #endif /* MODEST_PLATFORM_MAEMO */
332 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
334 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
335 gtk_widget_destroy (GTK_WIDGET (win));
336 } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
338 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
339 } else if (MODEST_IS_WINDOW (win)) {
340 gtk_widget_destroy (GTK_WIDGET (win));
342 g_return_if_reached ();
347 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
349 GtkClipboard *clipboard = NULL;
350 gchar *selection = NULL;
352 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
353 selection = gtk_clipboard_wait_for_text (clipboard);
355 /* Question: why is the clipboard being used here?
356 * It doesn't really make a lot of sense. */
360 modest_address_book_add_address (selection);
366 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
368 /* This is currently only implemented for Maemo,
369 * because it requires a providers preset file which is not publically available.
371 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
372 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
373 TRUE /* enabled accounts only */);
374 gboolean accounts_exist = account_names != NULL;
375 g_slist_free (account_names);
377 if (!accounts_exist) {
378 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
379 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
380 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
381 gtk_dialog_run (GTK_DIALOG (wizard));
382 gtk_widget_destroy (GTK_WIDGET (wizard));
384 /* Show the list of accounts: */
385 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
386 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
387 gtk_dialog_run (account_win);
388 gtk_widget_destroy (GTK_WIDGET(account_win));
391 GtkWidget *dialog, *label;
393 /* Create the widgets */
395 dialog = gtk_dialog_new_with_buttons ("Message",
397 GTK_DIALOG_DESTROY_WITH_PARENT,
401 label = gtk_label_new ("Hello World!");
403 /* Ensure that the dialog box is destroyed when the user responds. */
405 g_signal_connect_swapped (dialog, "response",
406 G_CALLBACK (gtk_widget_destroy),
409 /* Add the label, and show everything we've added to the dialog. */
411 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
413 gtk_widget_show_all (dialog);
414 #endif /* MODEST_PLATFORM_MAEMO */
418 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
420 ModestWindow *main_window = MODEST_WINDOW (user_data);
422 /* Save any changes. */
423 modest_connection_specific_smtp_window_save_server_accounts (
424 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window),
425 modest_window_get_active_account (main_window));
426 gtk_widget_destroy (GTK_WIDGET (window));
430 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
432 /* This is currently only implemented for Maemo,
433 * because it requires an API (libconic) to detect different connection
436 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
438 /* Create the window if necessary: */
439 const gchar *active_account_name = modest_window_get_active_account (win);
441 /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
442 * or show the default account?
443 * If we show the default account then the account name should be shown in
444 * the window when we show it. */
445 if (!active_account_name) {
446 g_warning ("%s: No account is active.", __FUNCTION__);
450 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
451 modest_connection_specific_smtp_window_fill_with_connections (
452 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
453 modest_runtime_get_account_mgr(),
454 active_account_name);
456 /* Show the window: */
457 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
458 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
459 gtk_widget_show (specific_window);
461 /* Save changes when the window is hidden: */
462 g_signal_connect (specific_window, "hide",
463 G_CALLBACK (on_smtp_servers_window_hide), win);
464 #endif /* MODEST_PLATFORM_MAEMO */
468 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
470 ModestWindow *msg_win;
472 TnyFolder *folder = NULL;
473 gchar *account_name = NULL;
474 gchar *from_str = NULL;
475 /* GError *err = NULL; */
476 TnyAccount *account = NULL;
477 ModestWindowMgr *mgr;
478 gchar *signature = NULL, *blank_and_signature = NULL;
480 account_name = g_strdup(modest_window_get_active_account (win));
482 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
484 g_printerr ("modest: no account found\n");
488 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
490 TNY_ACCOUNT_TYPE_STORE);
492 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
496 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
498 g_printerr ("modest: failed get from string for '%s'\n", account_name);
502 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
503 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
504 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
505 MODEST_ACCOUNT_SIGNATURE, FALSE);
506 blank_and_signature = g_strconcat ("\n", signature, NULL);
509 blank_and_signature = g_strdup ("");
512 msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
514 g_printerr ("modest: failed to create new msg\n");
518 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
520 g_printerr ("modest: failed to find Drafts folder\n");
524 /* tny_folder_add_msg (folder, msg, &err); */
526 /* g_printerr ("modest: error adding msg to Drafts folder: %s", */
528 /* g_error_free (err); */
532 /* Create and register edit window */
533 /* This is destroyed by TOOD. */
534 msg_win = modest_msg_edit_window_new (msg, account_name);
535 mgr = modest_runtime_get_window_mgr ();
536 modest_window_mgr_register_window (mgr, msg_win);
539 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
541 gtk_widget_show_all (GTK_WIDGET (msg_win));
544 g_free (account_name);
546 g_free (blank_and_signature);
548 g_object_unref (G_OBJECT(account));
550 g_object_unref (G_OBJECT(msg));
552 g_object_unref (G_OBJECT(folder));
556 open_msg_cb (ModestMailOperation *mail_op,
561 ModestWindowMgr *mgr = NULL;
562 ModestWindow *parent_win = NULL;
563 ModestWindow *win = NULL;
564 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
565 gchar *account = NULL;
568 /* TODO: Show an error? (review the specs) */
572 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
573 folder = tny_header_get_folder (header);
575 /* Mark header as read */
576 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
579 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
581 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
583 /* Gets folder type (OUTBOX headers will be opened in edit window */
584 if (modest_tny_folder_is_local_folder (folder))
585 folder_type = modest_tny_folder_get_local_folder_type (folder);
587 /* If the header is in the drafts folder then open the editor,
588 else the message view window */
589 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
590 win = modest_msg_edit_window_new (msg, account);
592 gchar *uid = modest_tny_folder_get_header_unique_id (header);
594 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
595 GtkWidget *header_view;
596 GtkTreeSelection *sel;
597 GList *sel_list = NULL;
600 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
601 MODEST_WIDGET_TYPE_HEADER_VIEW);
603 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
604 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
606 if (sel_list != NULL) {
607 GtkTreeRowReference *row_reference;
609 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
610 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
611 g_list_free (sel_list);
613 win = modest_msg_view_window_new_with_header_model (msg,
618 gtk_tree_row_reference_free (row_reference);
620 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
623 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
628 /* Register and show new window */
630 mgr = modest_runtime_get_window_mgr ();
631 modest_window_mgr_register_window (mgr, win);
632 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
633 gtk_widget_show_all (GTK_WIDGET(win));
638 g_object_unref (msg);
639 g_object_unref (folder);
640 g_object_unref (header);
644 * This function is the error handler of the
645 * modest_mail_operation_get_msgs_full operation
648 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
653 error = modest_mail_operation_get_error (mail_op);
654 if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
655 GObject *win = modest_mail_operation_get_source (mail_op);
657 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
663 * This function is used by both modest_ui_actions_on_open and
664 * modest_ui_actions_on_header_activated. This way we always do the
665 * same when trying to open messages.
668 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
670 ModestWindowMgr *mgr;
672 ModestMailOperation *mail_op;
674 /* Look if we already have a message view for each header. If
675 true, then remove the header from the list of headers to
677 mgr = modest_runtime_get_window_mgr ();
678 iter = tny_list_create_iterator (headers);
679 while (!tny_iterator_is_done (iter)) {
680 ModestWindow *window;
683 header = TNY_HEADER (tny_iterator_get_current (iter));
684 window = modest_window_mgr_find_window_by_header (mgr, header);
686 /* Do not open again the message and present
687 the window to the user */
688 tny_list_remove (headers, G_OBJECT (header));
689 gtk_window_present (GTK_WINDOW (window));
692 g_object_unref (header);
693 tny_iterator_next (iter);
696 /* Open each message */
697 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
699 modest_ui_actions_get_msgs_full_error_handler,
701 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
702 modest_mail_operation_get_msgs_full (mail_op,
709 g_object_unref(mail_op);
713 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
718 headers = get_selected_headers (win);
723 _modest_ui_actions_open (headers, win);
725 g_object_unref(headers);
730 free_reply_forward_helper (gpointer data)
732 ReplyForwardHelper *helper;
734 helper = (ReplyForwardHelper *) data;
735 g_free (helper->account_name);
736 g_slice_free (ReplyForwardHelper, helper);
740 reply_forward_cb (ModestMailOperation *mail_op,
746 ReplyForwardHelper *rf_helper;
747 ModestWindow *msg_win;
748 ModestEditType edit_type;
750 TnyAccount *account = NULL;
751 ModestWindowMgr *mgr;
752 gchar *signature = NULL;
754 g_return_if_fail (user_data != NULL);
755 rf_helper = (ReplyForwardHelper *) user_data;
757 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
758 rf_helper->account_name);
759 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
760 rf_helper->account_name,
761 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
762 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
763 rf_helper->account_name,
764 MODEST_ACCOUNT_SIGNATURE, FALSE);
767 /* Create reply mail */
768 switch (rf_helper->action) {
771 modest_tny_msg_create_reply_msg (msg, from, signature,
772 rf_helper->reply_forward_type,
773 MODEST_TNY_MSG_REPLY_MODE_SENDER);
775 case ACTION_REPLY_TO_ALL:
777 modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
778 MODEST_TNY_MSG_REPLY_MODE_ALL);
779 edit_type = MODEST_EDIT_TYPE_REPLY;
783 modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
784 edit_type = MODEST_EDIT_TYPE_FORWARD;
787 g_return_if_reached ();
794 g_printerr ("modest: failed to create message\n");
798 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
799 rf_helper->account_name,
800 TNY_ACCOUNT_TYPE_STORE);
802 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
806 /* Create and register the windows */
807 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
808 mgr = modest_runtime_get_window_mgr ();
809 modest_window_mgr_register_window (mgr, msg_win);
811 if (rf_helper->parent_window != NULL) {
814 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
815 modest_window_set_zoom (msg_win, parent_zoom);
818 /* Show edit window */
819 gtk_widget_show_all (GTK_WIDGET (msg_win));
823 g_object_unref (G_OBJECT (new_msg));
825 g_object_unref (G_OBJECT (account));
826 g_object_unref (msg);
827 g_object_unref (header);
831 * Checks a list of headers. If any of them are not currently
832 * downloaded (CACHED) then it asks the user for permission to
835 * Returns FALSE if the user does not want to download the
836 * messages. Returns TRUE if the user allowed the download or if all
837 * of them are currently downloaded
840 download_uncached_messages (TnyList *header_list, GtkWindow *win)
843 gboolean found, retval;
845 iter = tny_list_create_iterator (header_list);
847 while (!tny_iterator_is_done (iter) && !found) {
849 TnyHeaderFlags flags;
851 header = TNY_HEADER (tny_iterator_get_current (iter));
852 flags = tny_header_get_flags (header);
853 /* TODO: is this the right flag?, it seems that some
854 headers that have been previously downloaded do not
856 found = !(flags & TNY_HEADER_FLAG_CACHED);
857 g_object_unref (header);
858 tny_iterator_next (iter);
860 g_object_unref (iter);
862 /* Ask for user permission to download the messages */
865 GtkResponseType response;
867 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
868 _("mcen_nc_get_multi_msg_txt"));
869 if (response == GTK_RESPONSE_CANCEL)
877 * Common code for the reply and forward actions
880 reply_forward (ReplyForwardAction action, ModestWindow *win)
882 ModestMailOperation *mail_op = NULL;
883 TnyList *header_list = NULL;
884 ReplyForwardHelper *rf_helper = NULL;
885 guint reply_forward_type;
886 gboolean continue_download;
888 g_return_if_fail (MODEST_IS_WINDOW(win));
890 header_list = get_selected_headers (win);
894 /* Check that the messages have been previously downloaded */
895 continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
896 if (!continue_download) {
897 g_object_unref (header_list);
902 modest_conf_get_int (modest_runtime_get_conf (),
903 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
905 /* We assume that we can only select messages of the
906 same folder and that we reply all of them from the
907 same account. In fact the interface currently only
908 allows single selection */
911 rf_helper = g_slice_new0 (ReplyForwardHelper);
912 rf_helper->reply_forward_type = reply_forward_type;
913 rf_helper->action = action;
914 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
915 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
916 rf_helper->parent_window = GTK_WIDGET (win);
917 if (!rf_helper->account_name)
918 rf_helper->account_name =
919 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
921 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
924 /* Get header and message. Do not free them here, the
925 reply_forward_cb must do it */
926 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
927 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
928 if (!msg || !header) {
930 g_object_unref (msg);
932 g_object_unref (header);
933 g_printerr ("modest: no message found\n");
936 reply_forward_cb (NULL, header, msg, rf_helper);
938 /* Retrieve messages */
939 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
941 modest_ui_actions_get_msgs_full_error_handler,
943 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
944 modest_mail_operation_get_msgs_full (mail_op,
948 free_reply_forward_helper);
951 g_object_unref(mail_op);
955 g_object_unref (header_list);
959 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
961 g_return_if_fail (MODEST_IS_WINDOW(win));
963 reply_forward (ACTION_REPLY, win);
967 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
969 g_return_if_fail (MODEST_IS_WINDOW(win));
971 reply_forward (ACTION_FORWARD, win);
975 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
977 g_return_if_fail (MODEST_IS_WINDOW(win));
979 reply_forward (ACTION_REPLY_TO_ALL, win);
983 modest_ui_actions_on_next (GtkAction *action,
984 ModestWindow *window)
986 if (MODEST_IS_MAIN_WINDOW (window)) {
987 GtkWidget *header_view;
989 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
990 MODEST_WIDGET_TYPE_HEADER_VIEW);
994 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view));
995 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
996 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
998 g_return_if_reached ();
1003 modest_ui_actions_on_prev (GtkAction *action,
1004 ModestWindow *window)
1006 g_return_if_fail (MODEST_IS_WINDOW(window));
1008 if (MODEST_IS_MAIN_WINDOW (window)) {
1009 GtkWidget *header_view;
1010 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1011 MODEST_WIDGET_TYPE_HEADER_VIEW);
1015 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1016 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1017 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1019 g_return_if_reached ();
1024 modest_ui_actions_on_sort (GtkAction *action,
1025 ModestWindow *window)
1027 g_return_if_fail (MODEST_IS_WINDOW(window));
1029 if (MODEST_IS_MAIN_WINDOW (window)) {
1030 GtkWidget *header_view;
1031 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1032 MODEST_WIDGET_TYPE_HEADER_VIEW);
1036 /* Show sorting dialog */
1037 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1042 * This function performs the send & receive required actions. The
1043 * window is used to create the mail operation. Typically it should
1044 * always be the main window, but we pass it as argument in order to
1048 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1050 gchar *acc_name = NULL;
1051 ModestMailOperation *mail_op;
1053 /* If no account name was provided then get the current account, and if
1054 there is no current account then pick the default one: */
1055 if (!account_name) {
1056 acc_name = g_strdup (modest_window_get_active_account(win));
1058 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1060 g_printerr ("modest: cannot get default account\n");
1064 acc_name = g_strdup (account_name);
1067 /* Set send/receive operation in progress */
1068 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1070 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
1071 g_signal_connect (G_OBJECT(mail_op), "progress-changed",
1072 G_CALLBACK (_on_send_receive_progress_changed),
1075 /* Send & receive. */
1076 /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1077 /* Receive and then send. The operation is tagged initially as
1078 a receive operation because the account update performs a
1079 receive and then a send. The operation changes its type
1080 internally, so the progress objects will receive the proper
1081 progress information */
1082 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1083 modest_mail_operation_update_account (mail_op, acc_name);
1084 g_object_unref (G_OBJECT (mail_op));
1091 * Refreshes all accounts. This function will be used by automatic
1095 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1097 GSList *account_names, *iter;
1099 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1102 iter = account_names;
1104 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1105 iter = g_slist_next (iter);
1108 g_slist_foreach (account_names, (GFunc) g_free, NULL);
1109 g_slist_free (account_names);
1113 * Handler of the click on Send&Receive button in the main toolbar
1116 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1118 /* Check that at least one account exists: */
1119 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1120 TRUE /* enabled accounts only */);
1121 gboolean accounts_exist = account_names != NULL;
1122 g_slist_free (account_names);
1124 /* If not, allow the user to create an account before trying to send/receive. */
1125 if (!accounts_exist)
1126 modest_ui_actions_on_accounts (NULL, win);
1128 /* Refresh the active account */
1129 modest_ui_actions_do_send_receive (NULL, win);
1134 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1137 GtkWidget *header_view;
1139 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1141 header_view = modest_main_window_get_child_widget (main_window,
1142 MODEST_WIDGET_TYPE_HEADER_VIEW);
1146 conf = modest_runtime_get_conf ();
1148 /* what is saved/restored is depending on the style; thus; we save with
1149 * old style, then update the style, and restore for this new style
1151 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1153 if (modest_header_view_get_style
1154 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1155 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1156 MODEST_HEADER_VIEW_STYLE_TWOLINES);
1158 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1159 MODEST_HEADER_VIEW_STYLE_DETAILS);
1161 modest_widget_memory_restore (conf, G_OBJECT(header_view),
1162 MODEST_CONF_HEADER_VIEW_KEY);
1167 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
1169 ModestMainWindow *main_window)
1171 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1173 /* If no header has been selected then exit */
1177 /* Update Main window title */
1178 if (GTK_WIDGET_HAS_FOCUS (header_view)) {
1179 const gchar *subject = tny_header_get_subject (header);
1180 if (subject && strcmp (subject, ""))
1181 gtk_window_set_title (GTK_WINDOW (main_window), subject);
1183 gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1186 /* Update toolbar dimming state */
1187 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1191 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1193 ModestMainWindow *main_window)
1197 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1202 headers = tny_simple_list_new ();
1203 tny_list_prepend (headers, G_OBJECT (header));
1205 _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1207 g_object_unref (headers);
1211 set_active_account_from_tny_account (TnyAccount *account,
1212 ModestWindow *window)
1214 const gchar *server_acc_name = tny_account_get_id (account);
1216 /* We need the TnyAccount provided by the
1217 account store because that is the one that
1218 knows the name of the Modest account */
1219 TnyAccount *modest_server_account = modest_server_account =
1220 modest_tny_account_store_get_tny_account_by_id (modest_runtime_get_account_store (),
1223 const gchar *modest_acc_name =
1224 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1225 modest_window_set_active_account (window, modest_acc_name);
1226 g_object_unref (modest_server_account);
1230 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1231 TnyFolderStore *folder_store,
1233 ModestMainWindow *main_window)
1236 GtkWidget *header_view;
1237 gboolean folder_empty = FALSE;
1239 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1241 header_view = modest_main_window_get_child_widget(main_window,
1242 MODEST_WIDGET_TYPE_HEADER_VIEW);
1246 conf = modest_runtime_get_conf ();
1248 if (TNY_IS_ACCOUNT (folder_store)) {
1249 /* Update active account */
1250 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1251 /* Show account details */
1252 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1254 if (TNY_IS_FOLDER (folder_store) && selected) {
1256 if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1257 /* Update the active account */
1258 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1259 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1260 g_object_unref (account);
1264 /* Set folder on header view */
1265 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1266 TNY_FOLDER (folder_store));
1268 /* Set main view style */
1269 folder_empty = tny_folder_get_all_count (TNY_FOLDER (folder_store)) == 0;
1271 modest_main_window_set_contents_style (main_window,
1272 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1275 modest_main_window_set_contents_style (main_window,
1276 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1277 modest_widget_memory_restore (conf, G_OBJECT(header_view),
1278 MODEST_CONF_HEADER_VIEW_KEY);
1281 /* Update the active account */
1282 modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1283 /* Do not show folder */
1284 modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1285 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1289 /* Update toolbar dimming state */
1290 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1294 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1301 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1303 if (g_main_depth > 0)
1304 gdk_threads_enter ();
1305 online = tny_device_is_online (modest_runtime_get_device());
1308 /* already online -- the item is simply not there... */
1309 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1311 GTK_MESSAGE_WARNING,
1313 _("The %s you selected cannot be found"),
1315 gtk_dialog_run (GTK_DIALOG(dialog));
1317 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1321 GTK_RESPONSE_REJECT,
1323 GTK_RESPONSE_ACCEPT,
1325 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1326 "Do you want to get online?"), item);
1327 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1328 gtk_label_new (txt), FALSE, FALSE, 0);
1329 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1332 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1333 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1334 // modest_platform_connect_and_wait ();;
1337 gtk_widget_destroy (dialog);
1338 if (g_main_depth > 0)
1339 gdk_threads_leave ();
1343 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1346 /* g_message ("%s %s", __FUNCTION__, link); */
1351 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1354 modest_platform_activate_uri (link);
1358 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1361 modest_platform_show_uri_popup (link);
1365 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1368 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1372 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1373 const gchar *address,
1376 /* g_message ("%s %s", __FUNCTION__, address); */
1380 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1382 TnyTransportAccount *transport_account;
1383 ModestMailOperation *mail_operation;
1385 gchar *account_name, *from;
1386 ModestAccountMgr *account_mgr;
1388 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1390 data = modest_msg_edit_window_get_msg_data (edit_window);
1392 account_mgr = modest_runtime_get_account_mgr();
1393 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1395 account_name = modest_account_mgr_get_default_account (account_mgr);
1396 if (!account_name) {
1397 g_printerr ("modest: no account found\n");
1398 modest_msg_edit_window_free_msg_data (edit_window, data);
1402 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1403 account_name = g_strdup (data->account_name);
1407 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1408 (modest_runtime_get_account_store(),
1410 TNY_ACCOUNT_TYPE_TRANSPORT));
1411 if (!transport_account) {
1412 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1413 g_free (account_name);
1414 modest_msg_edit_window_free_msg_data (edit_window, data);
1417 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1419 /* Create the mail operation */
1420 mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1421 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1423 modest_mail_operation_save_to_drafts (mail_operation,
1434 data->priority_flags);
1437 g_free (account_name);
1438 g_object_unref (G_OBJECT (transport_account));
1439 g_object_unref (G_OBJECT (mail_operation));
1441 modest_msg_edit_window_free_msg_data (edit_window, data);
1443 /* Save settings and close the window */
1444 gtk_widget_destroy (GTK_WIDGET (edit_window));
1447 /* For instance, when clicking the Send toolbar button when editing a message: */
1449 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1451 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1453 if (!modest_msg_edit_window_check_names (edit_window))
1456 /* FIXME: Code added just for testing. The final version will
1457 use the send queue provided by tinymail and some
1459 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1460 gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1462 account_name = modest_account_mgr_get_default_account (account_mgr);
1464 if (!account_name) {
1465 g_printerr ("modest: no account found\n");
1469 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1471 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1472 account_name = g_strdup (data->account_name);
1475 /* Get the currently-active transport account for this modest account: */
1476 TnyTransportAccount *transport_account =
1477 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1478 (modest_runtime_get_account_store(),
1480 if (!transport_account) {
1481 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1482 g_free (account_name);
1483 modest_msg_edit_window_free_msg_data (edit_window, data);
1487 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1489 /* mail content checks and dialogs */
1490 if (data->subject == NULL || data->subject[0] == '\0') {
1491 GtkResponseType response;
1492 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1493 _("mcen_nc_subject_is_empty_send"));
1494 if (response == GTK_RESPONSE_CANCEL) {
1495 g_free (account_name);
1500 if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1501 GtkResponseType response;
1502 gchar *note_message;
1503 gchar *note_subject = data->subject;
1504 if (note_subject == NULL || note_subject[0] == '\0')
1505 note_subject = _("mail_va_no_subject");
1506 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1507 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1509 g_free (note_message);
1510 if (response == GTK_RESPONSE_CANCEL) {
1511 g_free (account_name);
1516 /* Create the mail operation */
1517 ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1518 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1520 modest_mail_operation_send_new_mail (mail_operation,
1531 data->priority_flags);
1535 g_free (account_name);
1536 g_object_unref (G_OBJECT (transport_account));
1537 g_object_unref (G_OBJECT (mail_operation));
1539 modest_msg_edit_window_free_msg_data (edit_window, data);
1541 /* Save settings and close the window: */
1542 gtk_widget_destroy (GTK_WIDGET (edit_window));
1546 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1547 ModestMsgEditWindow *window)
1549 ModestMsgEditFormatState *format_state = NULL;
1551 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1552 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1554 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1557 format_state = modest_msg_edit_window_get_format_state (window);
1558 g_return_if_fail (format_state != NULL);
1560 format_state->bold = gtk_toggle_action_get_active (action);
1561 modest_msg_edit_window_set_format_state (window, format_state);
1562 g_free (format_state);
1567 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1568 ModestMsgEditWindow *window)
1570 ModestMsgEditFormatState *format_state = NULL;
1572 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1573 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1575 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1578 format_state = modest_msg_edit_window_get_format_state (window);
1579 g_return_if_fail (format_state != NULL);
1581 format_state->italics = gtk_toggle_action_get_active (action);
1582 modest_msg_edit_window_set_format_state (window, format_state);
1583 g_free (format_state);
1588 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1589 ModestMsgEditWindow *window)
1591 ModestMsgEditFormatState *format_state = NULL;
1593 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1594 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1596 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1599 format_state = modest_msg_edit_window_get_format_state (window);
1600 g_return_if_fail (format_state != NULL);
1602 format_state->bullet = gtk_toggle_action_get_active (action);
1603 modest_msg_edit_window_set_format_state (window, format_state);
1604 g_free (format_state);
1609 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1610 GtkRadioAction *selected,
1611 ModestMsgEditWindow *window)
1613 ModestMsgEditFormatState *format_state = NULL;
1614 GtkJustification value;
1616 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1618 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1621 value = gtk_radio_action_get_current_value (selected);
1623 format_state = modest_msg_edit_window_get_format_state (window);
1624 g_return_if_fail (format_state != NULL);
1626 format_state->justification = value;
1627 modest_msg_edit_window_set_format_state (window, format_state);
1628 g_free (format_state);
1632 modest_ui_actions_on_select_editor_color (GtkAction *action,
1633 ModestMsgEditWindow *window)
1635 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1636 g_return_if_fail (GTK_IS_ACTION (action));
1638 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1641 modest_msg_edit_window_select_color (window);
1645 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1646 ModestMsgEditWindow *window)
1648 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1649 g_return_if_fail (GTK_IS_ACTION (action));
1651 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1654 modest_msg_edit_window_select_background_color (window);
1658 modest_ui_actions_on_insert_image (GtkAction *action,
1659 ModestMsgEditWindow *window)
1661 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1662 g_return_if_fail (GTK_IS_ACTION (action));
1664 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1667 modest_msg_edit_window_insert_image (window);
1671 modest_ui_actions_on_attach_file (GtkAction *action,
1672 ModestMsgEditWindow *window)
1674 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1675 g_return_if_fail (GTK_IS_ACTION (action));
1677 modest_msg_edit_window_attach_file (window);
1681 modest_ui_actions_on_remove_attachments (GtkAction *action,
1682 ModestMsgEditWindow *window)
1684 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1685 g_return_if_fail (GTK_IS_ACTION (action));
1687 modest_msg_edit_window_remove_attachments (window, NULL);
1691 * Shows a dialog with an entry that asks for some text. The returned
1692 * value must be freed by the caller. The dialog window title will be
1696 ask_for_folder_name (GtkWindow *parent_window,
1699 GtkWidget *dialog, *entry;
1700 gchar *folder_name = NULL;
1702 /* Ask for folder name */
1703 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1707 GTK_RESPONSE_REJECT,
1709 GTK_RESPONSE_ACCEPT,
1711 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1712 gtk_label_new(title),
1715 entry = gtk_entry_new_with_max_length (40);
1716 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1720 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1722 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1723 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1725 gtk_widget_destroy (dialog);
1731 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1733 TnyFolderStore *parent_folder;
1734 GtkWidget *folder_view;
1736 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1738 folder_view = modest_main_window_get_child_widget (main_window,
1739 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1743 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1745 if (parent_folder) {
1746 gboolean finished = FALSE;
1748 gchar *folder_name = NULL, *suggested_name = NULL;
1750 /* Run the new folder dialog */
1752 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1757 if (result == GTK_RESPONSE_REJECT) {
1760 ModestMailOperation *mail_op;
1761 TnyFolder *new_folder = NULL;
1763 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO,
1764 G_OBJECT(main_window));
1765 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1767 new_folder = modest_mail_operation_create_folder (mail_op,
1769 (const gchar *) folder_name);
1771 g_object_unref (new_folder);
1774 g_object_unref (mail_op);
1776 g_free (folder_name);
1780 g_object_unref (parent_folder);
1785 modest_ui_actions_on_rename_folder (GtkAction *action,
1786 ModestMainWindow *main_window)
1788 TnyFolderStore *folder;
1789 GtkWidget *folder_view;
1790 GtkWidget *header_view;
1792 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1794 folder_view = modest_main_window_get_child_widget (main_window,
1795 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1799 header_view = modest_main_window_get_child_widget (main_window,
1800 MODEST_WIDGET_TYPE_HEADER_VIEW);
1805 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1807 if (folder && TNY_IS_FOLDER (folder)) {
1809 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1810 _("Please enter a new name for the folder"));
1812 if (folder_name != NULL && strlen (folder_name) > 0) {
1813 ModestMailOperation *mail_op;
1815 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1816 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1819 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1821 modest_mail_operation_rename_folder (mail_op,
1822 TNY_FOLDER (folder),
1823 (const gchar *) folder_name);
1825 g_object_unref (mail_op);
1826 g_free (folder_name);
1828 g_object_unref (folder);
1833 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1836 GObject *win = modest_mail_operation_get_source (mail_op);
1838 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1839 _("mail_in_ui_folder_delete_error"));
1843 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
1845 TnyFolderStore *folder;
1846 GtkWidget *folder_view;
1850 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1852 folder_view = modest_main_window_get_child_widget (main_window,
1853 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1857 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1859 /* Show an error if it's an account */
1860 if (!TNY_IS_FOLDER (folder)) {
1861 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1862 _("mail_in_ui_folder_delete_error"));
1867 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
1868 tny_folder_get_name (TNY_FOLDER (folder)));
1869 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
1870 (const gchar *) message);
1873 if (response == GTK_RESPONSE_OK) {
1874 ModestMailOperation *mail_op =
1875 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE,
1876 G_OBJECT(main_window),
1877 modest_ui_actions_delete_folder_error_handler,
1880 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1882 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1883 g_object_unref (G_OBJECT (mail_op));
1886 g_object_unref (G_OBJECT (folder));
1890 modest_ui_actions_on_delete_folder (GtkAction *action,
1891 ModestMainWindow *main_window)
1893 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1895 delete_folder (main_window, FALSE);
1899 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1901 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1903 delete_folder (main_window, TRUE);
1907 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
1908 const gchar* server_account_name,
1913 ModestMainWindow *main_window)
1915 g_return_if_fail(server_account_name);
1916 /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1918 /* Initalize output parameters: */
1925 #ifdef MODEST_PLATFORM_MAEMO
1926 /* Maemo uses a different (awkward) button order,
1927 * It should probably just use gtk_alternative_dialog_button_order ().
1929 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1933 GTK_RESPONSE_ACCEPT,
1935 GTK_RESPONSE_REJECT,
1938 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1942 GTK_RESPONSE_REJECT,
1944 GTK_RESPONSE_ACCEPT,
1946 #endif /* MODEST_PLATFORM_MAEMO */
1948 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1950 gchar *server_name = modest_server_account_get_hostname (
1951 modest_runtime_get_account_mgr(), server_account_name);
1952 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
1953 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
1958 /* This causes a warning because the logical ID has no %s in it,
1959 * though the translation does, but there is not much we can do about that: */
1960 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1961 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1964 g_free (server_name);
1968 gchar *initial_username = modest_server_account_get_username (
1969 modest_runtime_get_account_mgr(), server_account_name);
1971 GtkWidget *entry_username = gtk_entry_new ();
1972 if (initial_username)
1973 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1974 /* Dim this if a connection has ever succeeded with this username,
1975 * as per the UI spec: */
1976 const gboolean username_known =
1977 modest_server_account_get_username_has_succeeded(
1978 modest_runtime_get_account_mgr(), server_account_name);
1979 gtk_widget_set_sensitive (entry_username, !username_known);
1981 #ifdef MODEST_PLATFORM_MAEMO
1982 /* Auto-capitalization is the default, so let's turn it off: */
1983 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1985 /* Create a size group to be used by all captions.
1986 * Note that HildonCaption does not create a default size group if we do not specify one.
1987 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1988 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1990 GtkWidget *caption = hildon_caption_new (sizegroup,
1991 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1992 gtk_widget_show (entry_username);
1993 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
1994 FALSE, FALSE, MODEST_MARGIN_HALF);
1995 gtk_widget_show (caption);
1997 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1999 #endif /* MODEST_PLATFORM_MAEMO */
2002 GtkWidget *entry_password = gtk_entry_new ();
2003 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2004 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2006 #ifdef MODEST_PLATFORM_MAEMO
2007 /* Auto-capitalization is the default, so let's turn it off: */
2008 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
2009 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2011 caption = hildon_caption_new (sizegroup,
2012 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2013 gtk_widget_show (entry_password);
2014 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
2015 FALSE, FALSE, MODEST_MARGIN_HALF);
2016 gtk_widget_show (caption);
2017 g_object_unref (sizegroup);
2019 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2021 #endif /* MODEST_PLATFORM_MAEMO */
2023 /* This is not in the Maemo UI spec:
2024 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2025 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2029 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2031 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2033 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2035 modest_server_account_set_username (
2036 modest_runtime_get_account_mgr(), server_account_name,
2039 const gboolean username_was_changed =
2040 (strcmp (*username, initial_username) != 0);
2041 if (username_was_changed) {
2042 /* To actually use a changed username,
2043 * we must reset the connection, according to pvanhoof.
2044 * This _might_ be a sensible way to do that: */
2045 TnyDevice *device = modest_runtime_get_device();
2046 tny_device_force_offline (device);
2047 tny_device_force_online (device);
2052 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2054 /* We do not save the password in the configuration,
2055 * because this function is only called for passwords that should
2056 * not be remembered:
2057 modest_server_account_set_password (
2058 modest_runtime_get_account_mgr(), server_account_name,
2077 /* This is not in the Maemo UI spec:
2078 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2084 gtk_widget_destroy (dialog);
2086 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2090 modest_ui_actions_on_cut (GtkAction *action,
2091 ModestWindow *window)
2093 GtkWidget *focused_widget;
2095 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2096 if (GTK_IS_EDITABLE (focused_widget)) {
2097 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2098 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2099 GtkTextBuffer *buffer;
2100 GtkClipboard *clipboard;
2102 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2103 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2104 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2109 modest_ui_actions_on_copy (GtkAction *action,
2110 ModestWindow *window)
2112 GtkClipboard *clipboard;
2113 GtkWidget *focused_widget;
2115 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2116 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2117 if (GTK_IS_LABEL (focused_widget)) {
2118 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2119 } else if (GTK_IS_EDITABLE (focused_widget)) {
2120 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2121 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2122 GtkTextBuffer *buffer;
2124 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2125 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2130 modest_ui_actions_on_undo (GtkAction *action,
2131 ModestWindow *window)
2133 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2134 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2136 g_return_if_reached ();
2141 modest_ui_actions_on_paste (GtkAction *action,
2142 ModestWindow *window)
2144 GtkWidget *focused_widget;
2146 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2147 if (GTK_IS_EDITABLE (focused_widget)) {
2148 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2149 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2150 GtkTextBuffer *buffer;
2151 GtkClipboard *clipboard;
2153 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2154 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2155 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2160 modest_ui_actions_on_select_all (GtkAction *action,
2161 ModestWindow *window)
2163 GtkWidget *focused_widget;
2165 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2166 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2167 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2168 } else if (GTK_IS_LABEL (focused_widget)) {
2169 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2170 } else if (GTK_IS_EDITABLE (focused_widget)) {
2171 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2172 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2173 GtkTextBuffer *buffer;
2174 GtkTextIter start, end;
2176 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2177 gtk_text_buffer_get_start_iter (buffer, &start);
2178 gtk_text_buffer_get_end_iter (buffer, &end);
2179 gtk_text_buffer_select_range (buffer, &start, &end);
2181 else if ((MODEST_IS_FOLDER_VIEW (focused_widget)) ||
2182 (MODEST_IS_HEADER_VIEW (focused_widget))) {
2184 GtkTreeSelection *selection = NULL;
2186 /* Get header view */
2187 GtkWidget *header_view = focused_widget;
2188 if (MODEST_IS_FOLDER_VIEW (focused_widget))
2189 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2190 MODEST_WIDGET_TYPE_HEADER_VIEW);
2192 /* Select all messages */
2193 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2194 gtk_tree_selection_select_all (selection);
2199 modest_ui_actions_on_mark_as_read (GtkAction *action,
2200 ModestWindow *window)
2202 g_return_if_fail (MODEST_IS_WINDOW(window));
2204 /* Mark each header as read */
2205 do_headers_action (window, headers_action_mark_as_read, NULL);
2209 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2210 ModestWindow *window)
2212 g_return_if_fail (MODEST_IS_WINDOW(window));
2214 /* Mark each header as read */
2215 do_headers_action (window, headers_action_mark_as_unread, NULL);
2219 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2220 GtkRadioAction *selected,
2221 ModestWindow *window)
2225 value = gtk_radio_action_get_current_value (selected);
2226 if (MODEST_IS_WINDOW (window)) {
2227 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2231 void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2232 GtkRadioAction *selected,
2233 ModestWindow *window)
2235 TnyHeaderFlags flags;
2236 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2238 flags = gtk_radio_action_get_current_value (selected);
2239 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2242 void modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2243 GtkRadioAction *selected,
2244 ModestWindow *window)
2248 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2250 file_format = gtk_radio_action_get_current_value (selected);
2251 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2256 modest_ui_actions_on_zoom_plus (GtkAction *action,
2257 ModestWindow *window)
2259 g_return_if_fail (MODEST_IS_WINDOW (window));
2261 modest_window_zoom_plus (MODEST_WINDOW (window));
2265 modest_ui_actions_on_zoom_minus (GtkAction *action,
2266 ModestWindow *window)
2268 g_return_if_fail (MODEST_IS_WINDOW (window));
2270 modest_window_zoom_minus (MODEST_WINDOW (window));
2274 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
2275 ModestWindow *window)
2277 ModestWindowMgr *mgr;
2278 gboolean fullscreen, active;
2279 g_return_if_fail (MODEST_IS_WINDOW (window));
2281 mgr = modest_runtime_get_window_mgr ();
2283 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2284 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2286 if (active != fullscreen) {
2287 modest_window_mgr_set_fullscreen_mode (mgr, active);
2288 gtk_window_present (GTK_WINDOW (window));
2293 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2294 ModestWindow *window)
2296 ModestWindowMgr *mgr;
2297 gboolean fullscreen;
2299 g_return_if_fail (MODEST_IS_WINDOW (window));
2301 mgr = modest_runtime_get_window_mgr ();
2302 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2303 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2305 gtk_window_present (GTK_WINDOW (window));
2309 * Used by modest_ui_actions_on_details to call do_headers_action
2312 headers_action_show_details (TnyHeader *header,
2313 ModestWindow *window,
2320 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2323 gtk_widget_show_all (dialog);
2324 gtk_dialog_run (GTK_DIALOG (dialog));
2326 gtk_widget_destroy (dialog);
2330 * Show the folder details in a ModestDetailsDialog widget
2333 show_folder_details (TnyFolder *folder,
2339 dialog = modest_details_dialog_new_with_folder (window, folder);
2342 gtk_widget_show_all (dialog);
2343 gtk_dialog_run (GTK_DIALOG (dialog));
2345 gtk_widget_destroy (dialog);
2349 * Show the header details in a ModestDetailsDialog widget
2352 modest_ui_actions_on_details (GtkAction *action,
2355 TnyList * headers_list;
2359 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2362 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2365 g_object_unref (msg);
2367 headers_list = get_selected_headers (win);
2371 iter = tny_list_create_iterator (headers_list);
2373 header = TNY_HEADER (tny_iterator_get_current (iter));
2374 headers_action_show_details (header, win, NULL);
2375 g_object_unref (header);
2377 g_object_unref (iter);
2378 g_object_unref (headers_list);
2380 } else if (MODEST_IS_MAIN_WINDOW (win)) {
2381 GtkWidget *folder_view, *header_view;
2383 /* Check which widget has the focus */
2384 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2385 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2386 if (gtk_widget_is_focus (folder_view)) {
2389 folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2391 /* Show only when it's a folder */
2392 if (!folder || !TNY_IS_FOLDER (folder))
2395 show_folder_details (folder, GTK_WINDOW (win));
2398 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2399 MODEST_WIDGET_TYPE_HEADER_VIEW);
2400 /* Show details of each header */
2401 do_headers_action (win, headers_action_show_details, header_view);
2407 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2408 ModestMsgEditWindow *window)
2410 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2412 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2416 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2417 ModestMsgEditWindow *window)
2419 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2421 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2425 modest_ui_actions_toggle_folders_view (GtkAction *action,
2426 ModestMainWindow *main_window)
2430 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2432 conf = modest_runtime_get_conf ();
2434 if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2435 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2437 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2441 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
2442 ModestWindow *window)
2444 gboolean active, fullscreen = FALSE;
2445 ModestWindowMgr *mgr;
2447 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2449 /* Check if we want to toggle the toolbar vuew in fullscreen
2451 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
2452 "ViewShowToolbarFullScreen")) {
2456 /* Toggle toolbar */
2457 mgr = modest_runtime_get_window_mgr ();
2458 modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2462 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2463 ModestMsgEditWindow *window)
2465 modest_msg_edit_window_select_font (window);
2469 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2470 const gchar *display_name,
2473 /* Do not change the application name if the widget has not
2474 the focus. This callback could be called even if the folder
2475 view has not the focus, because the handled signal could be
2476 emitted when the folder view is redrawn */
2477 if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2479 gtk_window_set_title (window, display_name);
2481 gtk_window_set_title (window, " ");
2486 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2489 modest_msg_edit_window_select_contacts (window);
2493 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2495 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2496 modest_msg_edit_window_check_names (window);
2501 create_move_to_dialog (ModestWindow *win,
2502 GtkWidget *folder_view,
2503 GtkWidget **tree_view)
2505 GtkWidget *dialog, *scroll;
2507 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2509 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2511 GTK_RESPONSE_ACCEPT,
2513 GTK_RESPONSE_REJECT,
2516 /* Create scrolled window */
2517 scroll = gtk_scrolled_window_new (NULL, NULL);
2518 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
2519 GTK_POLICY_AUTOMATIC,
2520 GTK_POLICY_AUTOMATIC);
2522 /* Create folder view */
2523 *tree_view = modest_folder_view_new (NULL);
2524 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2525 gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2526 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2528 /* Add scroll to dialog */
2529 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
2530 scroll, FALSE, FALSE, 0);
2532 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2538 * Returns TRUE if at least one of the headers of the list belongs to
2539 * a message that has been fully retrieved.
2542 has_retrieved_msgs (TnyList *list)
2545 gboolean found = FALSE;
2547 iter = tny_list_create_iterator (list);
2548 while (tny_iterator_is_done (iter) && !found) {
2550 TnyHeaderFlags flags;
2552 header = TNY_HEADER (tny_iterator_get_current (iter));
2553 flags = tny_header_get_flags (header);
2554 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2558 tny_iterator_next (iter);
2560 g_object_unref (iter);
2566 * Shows a confirmation dialog to the user when we're moving messages
2567 * from a remote server to the local storage. Returns the dialog
2568 * response. If it's other kind of movement the it always returns
2572 msgs_move_to_confirmation (GtkWindow *win,
2573 TnyFolder *dest_folder,
2576 gint response = GTK_RESPONSE_OK;
2578 /* If the destination is a local folder */
2579 if (modest_tny_folder_is_local_folder (dest_folder)) {
2580 TnyFolder *src_folder;
2584 /* Get source folder */
2585 iter = tny_list_create_iterator (headers);
2586 header = TNY_HEADER (tny_iterator_get_current (iter));
2587 src_folder = tny_header_get_folder (header);
2588 g_object_unref (header);
2589 g_object_unref (iter);
2591 /* If the source is a remote folder */
2592 if (!modest_tny_folder_is_local_folder (src_folder)) {
2593 const gchar *message;
2595 if (tny_list_get_length (headers) == 1)
2596 if (has_retrieved_msgs (headers))
2597 message = _("mcen_nc_move_retrieve");
2599 message = _("mcen_nc_move_header");
2601 if (has_retrieved_msgs (headers))
2602 message = _("mcen_nc_move_retrieves");
2604 message = _("mcen_nc_move_headers");
2606 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2607 (const gchar *) message);
2609 g_object_unref (src_folder);
2616 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2618 ModestMsgViewWindow *self = NULL;
2619 gboolean found = FALSE;
2621 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2622 self = MODEST_MSG_VIEW_WINDOW (object);
2624 found = modest_msg_view_window_select_first_message (self);
2625 g_return_if_fail (found);
2629 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
2632 GObject *win = modest_mail_operation_get_source (mail_op);
2634 /* TODO: show error message */
2635 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2636 _("mail_in_ui_folder_move_target_error"));
2640 * UI handler for the "Move to" action when invoked from the
2644 modest_ui_actions_on_main_window_move_to (GtkAction *action,
2645 ModestMainWindow *win)
2647 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2648 GtkWidget *header_view = NULL;
2650 TnyFolderStore *folder_store = NULL;
2651 ModestMailOperation *mail_op = NULL;
2653 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2655 /* Get the folder view */
2656 folder_view = modest_main_window_get_child_widget (win,
2657 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2659 /* Get header view */
2660 header_view = modest_main_window_get_child_widget (win,
2661 MODEST_WIDGET_TYPE_HEADER_VIEW);
2663 /* Create and run the dialog */
2664 dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2665 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
2666 result = gtk_dialog_run (GTK_DIALOG(dialog));
2667 g_object_ref (tree_view);
2669 /* We do this to save an indentation level ;-) */
2670 if (result != GTK_RESPONSE_ACCEPT)
2673 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2675 if (TNY_IS_ACCOUNT (folder_store))
2678 /* Get folder or messages to transfer */
2679 if (gtk_widget_is_focus (folder_view)) {
2680 TnyFolderStore *src_folder;
2681 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2683 /* Clean folder on header view before moving it */
2684 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
2686 if (TNY_IS_FOLDER (src_folder)) {
2688 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
2690 modest_ui_actions_move_folder_error_handler,
2692 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2694 modest_mail_operation_xfer_folder (mail_op,
2695 TNY_FOLDER (src_folder),
2698 /* Unref mail operation */
2699 g_object_unref (G_OBJECT (mail_op));
2703 g_object_unref (G_OBJECT (src_folder));
2705 if (gtk_widget_is_focus (header_view)) {
2709 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2711 /* Ask for user confirmation */
2712 response = msgs_move_to_confirmation (GTK_WINDOW (win),
2713 TNY_FOLDER (folder_store),
2716 /* Transfer messages */
2717 if (response == GTK_RESPONSE_OK) {
2718 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2719 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2722 modest_mail_operation_xfer_msgs (mail_op,
2724 TNY_FOLDER (folder_store),
2729 g_object_unref (G_OBJECT (mail_op));
2731 g_object_unref (headers);
2734 g_object_unref (folder_store);
2736 gtk_widget_destroy (dialog);
2741 * UI handler for the "Move to" action when invoked from the
2742 * ModestMsgViewWindow
2745 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
2746 ModestMsgViewWindow *win)
2748 GtkWidget *dialog, *folder_view, *tree_view = NULL;
2750 ModestMainWindow *main_window;
2754 /* Get the folder view */
2755 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2756 folder_view = modest_main_window_get_child_widget (main_window,
2757 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2759 /* Create and run the dialog */
2760 dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2761 result = gtk_dialog_run (GTK_DIALOG(dialog));
2762 g_object_ref (tree_view);
2764 if (result == GTK_RESPONSE_ACCEPT) {
2765 TnyFolderStore *folder_store;
2768 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2770 /* Create header list */
2771 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
2772 headers = tny_simple_list_new ();
2773 tny_list_prepend (headers, G_OBJECT (header));
2774 g_object_unref (header);
2776 /* Ask user for confirmation. MSG-NOT404 */
2777 response = msgs_move_to_confirmation (GTK_WINDOW (win),
2778 TNY_FOLDER (folder_store),
2781 /* Transfer current msg */
2782 if (response == GTK_RESPONSE_OK) {
2783 ModestMailOperation *mail_op;
2785 /* Create mail op */
2786 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2787 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2790 /* Transfer messages */
2791 modest_mail_operation_xfer_msgs (mail_op,
2793 TNY_FOLDER (folder_store),
2795 tranasfer_msgs_from_viewer_cb,
2797 g_object_unref (G_OBJECT (mail_op));
2799 g_object_unref (headers);
2800 g_object_unref (folder_store);
2802 gtk_widget_destroy (dialog);
2806 modest_ui_actions_on_move_to (GtkAction *action,
2809 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2810 MODEST_IS_MSG_VIEW_WINDOW (win));
2812 if (MODEST_IS_MAIN_WINDOW (win))
2813 modest_ui_actions_on_main_window_move_to (action,
2814 MODEST_MAIN_WINDOW (win));
2816 modest_ui_actions_on_msg_view_window_move_to (action,
2817 MODEST_MSG_VIEW_WINDOW (win));
2821 * Calls #HeadersFunc for each header already selected in the main
2822 * window or the message currently being shown in the msg view window
2825 do_headers_action (ModestWindow *win,
2829 TnyList *headers_list;
2833 headers_list = get_selected_headers (win);
2837 /* Call the function for each header */
2838 iter = tny_list_create_iterator (headers_list);
2839 while (!tny_iterator_is_done (iter)) {
2842 header = TNY_HEADER (tny_iterator_get_current (iter));
2843 func (header, win, user_data);
2844 g_object_unref (header);
2845 tny_iterator_next (iter);
2847 g_object_unref (iter);
2848 g_object_unref (headers_list);
2852 modest_ui_actions_view_attachment (GtkAction *action,
2853 ModestWindow *window)
2855 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2856 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2858 /* not supported window for this action */
2859 g_return_if_reached ();
2864 modest_ui_actions_save_attachments (GtkAction *action,
2865 ModestWindow *window)
2867 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2868 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2870 /* not supported window for this action */
2871 g_return_if_reached ();
2876 modest_ui_actions_remove_attachments (GtkAction *action,
2877 ModestWindow *window)
2879 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2880 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2882 /* not supported window for this action */
2883 g_return_if_reached ();
2888 modest_ui_actions_on_settings (GtkAction *action,
2893 dialog = modest_platform_get_global_settings_dialog ();
2894 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2895 gtk_widget_show (dialog);
2897 gtk_dialog_run (GTK_DIALOG (dialog));
2899 gtk_widget_destroy (dialog);
2903 modest_ui_actions_on_help (GtkAction *action,
2906 const gchar *help_id = NULL;
2908 if (MODEST_IS_MAIN_WINDOW (win)) {
2909 const gchar *action_name;
2910 action_name = gtk_action_get_name (action);
2912 if (!strcmp (action_name, "FolderViewCSMHelp") ||
2913 !strcmp (action_name, "HeaderViewCSMHelp")) {
2914 GtkWidget *folder_view;
2915 TnyFolderStore *folder_store;
2916 /* Get selected folder */
2917 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2918 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2919 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2921 /* Switch help_id */
2922 if (TNY_IS_FOLDER (folder_store)) {
2923 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
2924 case TNY_FOLDER_TYPE_NORMAL:
2925 help_id = "applications_email_userfolder";
2927 case TNY_FOLDER_TYPE_INBOX:
2928 help_id = "applications_email_inbox";
2930 case TNY_FOLDER_TYPE_OUTBOX:
2931 help_id = "applications_email_outbox";
2933 case TNY_FOLDER_TYPE_SENT:
2934 help_id = "applications_email_sent";
2936 case TNY_FOLDER_TYPE_DRAFTS:
2937 help_id = "applications_email_drafts";
2939 case TNY_FOLDER_TYPE_ARCHIVE:
2940 help_id = "applications_email_archive";
2947 help_id = "applications_email_mainview";
2949 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2950 help_id = "applications_email_viewer";
2951 } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
2952 help_id = "applications_email_editor";
2954 modest_platform_show_help (GTK_WINDOW (win), help_id);
2958 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2959 ModestWindow *window)
2961 ModestMailOperation *mail_op;
2965 headers = get_selected_headers (window);
2969 /* Create mail operation */
2970 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
2972 modest_ui_actions_get_msgs_full_error_handler,
2974 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2975 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2978 g_object_unref (headers);
2979 g_object_unref (mail_op);
2983 modest_ui_actions_on_email_menu_activated (GtkAction *action,
2984 ModestWindow *window)
2986 g_return_if_fail (MODEST_IS_WINDOW (window));
2989 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
2993 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
2994 ModestWindow *window)
2996 g_return_if_fail (MODEST_IS_WINDOW (window));
2999 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
3003 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3004 ModestWindow *window)
3006 g_return_if_fail (MODEST_IS_WINDOW (window));
3009 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
3013 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3014 ModestWindow *window)
3016 g_return_if_fail (MODEST_IS_WINDOW (window));
3019 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
3023 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3024 ModestWindow *window)
3026 g_return_if_fail (MODEST_IS_WINDOW (window));
3029 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
3033 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3035 g_return_if_fail (MODEST_IS_WINDOW (window));
3038 modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");
3042 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3044 g_return_if_fail (MODEST_IS_WINDOW (window));
3046 modest_platform_show_search_messages (GTK_WINDOW (window));
3050 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3052 g_return_if_fail (MODEST_IS_WINDOW (win));
3053 modest_platform_show_addressbook (GTK_WINDOW (win));
3058 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3059 ModestWindow *window)
3061 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3063 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3067 _on_send_receive_progress_changed (ModestMailOperation *mail_op,
3068 ModestMailOperationState *state,
3071 g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3073 /* Set send/receive operation finished */
3074 if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3075 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));