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.
31 #include <glib/gi18n.h>
33 #include <modest-platform.h>
34 #include <modest-defs.h>
35 #include <modest-scrollable.h>
36 #include <modest-runtime.h>
37 #include <modest-main-window.h>
38 #include <modest-header-view.h>
39 #include "modest-widget-memory.h"
40 #include <modest-utils.h>
41 #include <tny-camel-folder.h>
42 #include <tny-simple-list.h>
43 #include <tny-merge-folder.h>
44 #include <tny-error.h>
45 #include <tny-folder.h>
46 #include <tny-account-store-view.h>
47 #include <tny-gnome-device.h>
49 #include <modest-text-utils.h>
50 #include "modest-tny-folder.h"
51 #include "modest-tny-account.h"
53 #include <libgnomevfs/gnome-vfs-mime-utils.h>
54 #include <modest-account-settings-dialog.h>
55 #include <modest-easysetup-wizard-dialog.h>
56 #include "widgets/modest-window-mgr.h"
57 #include <modest-datetime-formatter.h>
58 #include "modest-header-window.h"
59 #include <modest-folder-window.h>
60 #include <modest-account-mgr.h>
61 #include <modest-account-mgr-helpers.h>
62 #include <modest-ui-constants.h>
63 #include <modest-icon-names.h>
64 #include <modest-count-stream.h>
68 #define HILDON_OSSO_URI_ACTION "uri-action"
69 #define URI_ACTION_COPY "copy:"
70 #define MODEST_NOTIFICATION_CATEGORY "email-message"
71 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternChatAndEmail"
73 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
74 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
75 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
76 #define FOLDER_PICKER_ORIGINAL_ACCOUNT "original-account"
78 static gboolean ca_con_opened = FALSE;
81 static void modest_platform_play_email_tone (void);
85 on_modest_conf_update_interval_changed (ModestConf* self,
87 ModestConfEvent event,
88 ModestConfNotificationId id,
91 g_return_if_fail (key);
93 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
94 const guint update_interval_minutes =
95 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
96 modest_platform_set_update_interval (update_interval_minutes);
103 check_required_files (void)
105 FILE *mcc_file = modest_utils_open_mcc_mapping_file ();
108 g_printerr ("modest: check for mcc file (for LANG) failed\n");
114 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
115 access(MODEST_FALLBACK_PROVIDER_DATA_FILE, R_OK) != 0) {
116 g_printerr ("modest: cannot find providers data\n");
124 /* the gpointer here is the osso_context. */
126 modest_platform_init (int argc, char *argv[])
130 if (!check_required_files ()) {
131 g_printerr ("modest: missing required files\n");
135 /* Make sure that the update interval is changed whenever its gconf key
137 /* CAUTION: we're not using here the
138 modest_conf_listen_to_namespace because we know that there
139 are other parts of Modest listening for this namespace, so
140 we'll receive the notifications anyway. We basically do not
141 use it because there is no easy way to do the
142 modest_conf_forget_namespace */
143 ModestConf *conf = modest_runtime_get_conf ();
144 g_signal_connect (G_OBJECT(conf),
146 G_CALLBACK (on_modest_conf_update_interval_changed),
149 /* only force the setting of the default interval, if there are actually
151 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
153 /* Get the initial update interval from gconf: */
154 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
155 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
156 modest_account_mgr_free_account_names (acc_names);
163 modest_platform_uninit (void)
172 modest_platform_get_new_device (void)
174 return TNY_DEVICE (tny_gnome_device_new ());
178 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
179 gchar **effective_mime_type)
182 g_warning ("Not implemented %s", __FUNCTION__);
191 modest_platform_activate_uri (const gchar *uri)
193 g_warning ("Not implemented %s", __FUNCTION__);
200 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
202 g_warning ("Not implemented %s", __FUNCTION__);
208 modest_platform_show_uri_popup (const gchar *uri)
210 g_warning ("Not implemented %s", __FUNCTION__);
217 modest_platform_get_icon (const gchar *name, guint icon_size)
219 g_warning ("Not implemented %s", __FUNCTION__);
225 modest_platform_get_app_name (void)
227 return _("mcen_ap_name");
231 entry_insert_text (GtkEditable *editable,
240 chars = gtk_editable_get_chars (editable, 0, -1);
241 chars_length = g_utf8_strlen (chars, -1);
244 /* Show WID-INF036 */
245 if (chars_length >= 20) {
246 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
247 _CS("ckdg_ib_maximum_characters_reached"));
249 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
253 tmp = g_strndup (folder_name_forbidden_chars,
254 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
255 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
256 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)),
262 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
263 _CS("ckdg_ib_maximum_characters_reached"));
265 /* Write the text in the entry if it's valid */
266 g_signal_handlers_block_by_func (editable,
267 (gpointer) entry_insert_text, data);
268 gtk_editable_insert_text (editable, text, length, position);
269 g_signal_handlers_unblock_by_func (editable,
270 (gpointer) entry_insert_text, data);
273 /* Do not allow further processing */
274 g_signal_stop_emission_by_name (editable, "insert_text");
278 entry_changed (GtkEditable *editable,
282 GtkWidget *ok_button;
285 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
286 ok_button = GTK_WIDGET (buttons->data);
288 chars = gtk_editable_get_chars (editable, 0, -1);
289 g_return_if_fail (chars != NULL);
292 if (g_utf8_strlen (chars,-1) >= 20) {
293 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
294 _CS("ckdg_ib_maximum_characters_reached"));
296 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
299 g_list_free (buttons);
306 on_response (GtkDialog *dialog,
310 GtkWidget *entry, *picker;
311 TnyFolderStore *parent;
312 const gchar *new_name;
315 if (response != GTK_RESPONSE_ACCEPT)
319 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
320 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
322 parent = TNY_FOLDER_STORE (user_data);
323 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
327 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
329 /* Look for another folder with the same name */
330 if (!TNY_IS_MERGE_FOLDER (parent) &&
331 modest_tny_folder_has_subfolder_with_name (parent, new_name, TRUE))
335 if (TNY_IS_ACCOUNT (parent) &&
336 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
337 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
345 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (dialog)),
346 NULL, _CS("ckdg_ib_folder_already_exists"));
347 /* Select the text */
348 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
349 gtk_widget_grab_focus (entry);
350 /* Do not close the dialog */
351 g_signal_stop_emission_by_name (dialog, "response");
355 typedef struct _FolderChooserData {
356 TnyFolderStore *store;
361 folder_chooser_activated (ModestFolderView *folder_view,
362 TnyFolderStore *folder,
363 FolderChooserData *userdata)
365 userdata->store = folder;
366 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
369 static TnyFolderStore *
370 folder_chooser_dialog_run (ModestFolderView *original,
371 TnyFolderStore *current,
374 GtkWidget *folder_view;
375 FolderChooserData userdata = {NULL, NULL};
376 GtkWidget *scrollable;
377 const gchar *visible_id = NULL;
379 userdata.dialog = gtk_dialog_new ();
380 scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
381 folder_view = modest_platform_create_folder_view (NULL);
383 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
385 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
386 MODEST_FOLDER_VIEW (folder_view));
388 if (TNY_IS_ACCOUNT (current)) {
389 /* Local folders and MMC account are always shown
390 along with the currently visible server account */
391 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (current)) ||
392 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (current)))
393 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
395 visible_id = tny_account_get_id (TNY_ACCOUNT (current));
396 } else if (TNY_IS_FOLDER (current)) {
398 account = modest_tny_folder_get_account ((TnyFolder *) current);
400 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (account)) ||
401 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (account))) {
402 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
404 visible_id = tny_account_get_id (account);
406 g_object_unref (account);
410 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
413 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
416 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), scrollable);
417 gtk_container_add (GTK_CONTAINER (scrollable), folder_view);
418 gtk_widget_set_size_request (scrollable, -1, 320);
420 gtk_widget_show (folder_view);
421 gtk_widget_show (scrollable);
422 gtk_widget_show (userdata.dialog);
423 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
424 G_CALLBACK (folder_chooser_activated),
425 (gpointer) &userdata);
427 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
428 gtk_widget_destroy (userdata.dialog);
430 return userdata.store;
434 folder_store_get_display_name (TnyFolderStore *store)
436 if (TNY_IS_ACCOUNT (store)) {
437 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
438 return modest_conf_get_string (modest_runtime_get_conf(),
439 MODEST_CONF_DEVICE_NAME, NULL);
441 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
444 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
446 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
447 type = tny_folder_get_folder_type (TNY_FOLDER (store));
448 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
449 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
450 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
451 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
453 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
456 /* Sometimes an special folder is reported by the server as
457 NORMAL, like some versions of Dovecot */
458 if (type == TNY_FOLDER_TYPE_NORMAL ||
459 type == TNY_FOLDER_TYPE_UNKNOWN) {
460 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
464 if (type == TNY_FOLDER_TYPE_INBOX) {
466 fname = g_strdup (_("mcen_me_folder_inbox"));
473 get_image_for_folder_store (TnyFolderStore *store,
477 const gchar *icon_name = NULL;
478 GtkWidget *image = NULL;
480 if (TNY_IS_ACCOUNT (store)) {
481 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
482 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
483 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
484 icon_name = MODEST_FOLDER_ICON_MMC;
486 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
488 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
489 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
491 case TNY_FOLDER_TYPE_INBOX:
492 icon_name = MODEST_FOLDER_ICON_INBOX;
495 icon_name = MODEST_FOLDER_ICON_REMOTE_FOLDER;
497 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
499 case TNY_FOLDER_TYPE_OUTBOX:
500 icon_name = MODEST_FOLDER_ICON_OUTBOX;
502 case TNY_FOLDER_TYPE_DRAFTS:
503 icon_name = MODEST_FOLDER_ICON_DRAFTS;
505 case TNY_FOLDER_TYPE_SENT:
506 icon_name = MODEST_FOLDER_ICON_SENT;
509 icon_name = MODEST_FOLDER_ICON_NORMAL;
511 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
512 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
517 pixbuf = modest_platform_get_icon (icon_name, size);
520 image = gtk_image_new_from_pixbuf (pixbuf);
521 g_object_unref (pixbuf);
528 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
533 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
537 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
538 g_object_ref (store),
539 (GDestroyNotify) g_object_unref);
540 name = folder_store_get_display_name (store);
541 gtk_button_set_label (GTK_BUTTON (button), name);
545 image = get_image_for_folder_store (store, MODEST_ICON_SIZE_SMALL);
547 gtk_button_set_image (GTK_BUTTON (button), image);
551 /* Always returns DUPs so you must free the returned value */
553 get_next_folder_name (const gchar *suggested_name,
554 TnyFolderStore *suggested_folder)
556 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
558 gchar *real_suggested_name;
560 if (suggested_name !=NULL) {
561 return g_strdup (suggested_name);
564 for(i = 0; i < 100; ++ i) {
565 gboolean exists = FALSE;
568 real_suggested_name = g_strdup (default_name);
570 real_suggested_name = g_strdup_printf ("%s(%d)",
571 _FM("ckdg_va_new_folder_name_stub"),
573 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
580 g_free (real_suggested_name);
583 /* Didn't find a free number */
585 real_suggested_name = g_strdup (default_name);
587 return real_suggested_name;
591 ModestFolderView *folder_view;
593 } FolderPickerHelper;
596 folder_picker_clicked (GtkButton *button,
597 FolderPickerHelper *helper)
599 TnyFolderStore *store, *current;
601 current = g_object_get_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER);
603 store = folder_chooser_dialog_run (helper->folder_view, current, button);
605 const gchar *current_name;
606 gboolean exists = FALSE;
608 folder_picker_set_store (GTK_BUTTON (button), store);
610 /* Update the name of the folder */
611 current_name = gtk_entry_get_text (helper->entry);
613 if (TNY_IS_FOLDER_STORE (store))
614 exists = modest_tny_folder_has_subfolder_with_name (store,
618 gchar *new_name = get_next_folder_name (NULL, store);
619 gtk_entry_set_text (helper->entry, new_name);
626 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
629 const gchar *acc_id = NULL;
631 button = gtk_button_new ();
633 gtk_misc_set_alignment (GTK_MISC (button), 0.0, 0.5);
637 folder_picker_set_store (GTK_BUTTON (button), suggested);
639 if (TNY_IS_ACCOUNT (suggested)) {
640 if (!modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (suggested)) &&
641 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (suggested)))
642 acc_id = tny_account_get_id ((TnyAccount *) suggested);
644 TnyAccount *account = modest_tny_folder_get_account ((TnyFolder *) suggested);
646 acc_id = tny_account_get_id ((TnyAccount *) account);
647 g_object_unref (account);
653 acc_id = modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(helper->folder_view));
655 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_ORIGINAL_ACCOUNT,
656 g_strdup (acc_id), (GDestroyNotify) g_free);
659 g_signal_connect (G_OBJECT (button), "clicked",
660 G_CALLBACK (folder_picker_clicked),
668 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
669 TnyFolderStore *suggested_parent,
670 const gchar *dialog_title,
671 const gchar *label_text,
672 const gchar *suggested_name,
674 gboolean show_parent,
676 TnyFolderStore **parent)
678 GtkWidget *accept_btn = NULL;
679 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
680 GtkWidget *account_picker = NULL;
681 GList *buttons = NULL;
683 GtkSizeGroup *sizegroup;
684 ModestFolderView *folder_view;
685 ModestWindow *folder_window;
686 ModestWindowMgr *window_mgr;
687 FolderPickerHelper *helper = NULL;
688 GtkWidget *top_vbox, *top_align;
690 window_mgr = modest_runtime_get_window_mgr ();
691 folder_window = modest_window_mgr_get_folder_window (window_mgr);
692 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
694 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
696 top_vbox = gtk_vbox_new (FALSE, 0);
697 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
698 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
700 /* Ask the user for the folder name */
701 dialog = gtk_dialog_new_with_buttons (dialog_title,
703 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
704 _FM("ckdg_bd_new_folder_dialog_ok"),
708 /* Add accept button (with unsensitive handler) */
709 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
710 accept_btn = GTK_WIDGET (buttons->data);
712 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
715 label_entry = gtk_label_new (label_text);
716 entry = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
717 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
719 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
720 gtk_size_group_add_widget (sizegroup, label_entry);
723 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
725 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
726 gtk_entry_set_width_chars (GTK_ENTRY (entry),
727 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
728 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
729 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
734 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
736 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
737 gtk_size_group_add_widget (sizegroup, label_location);
739 helper = g_slice_new0 (FolderPickerHelper);
740 helper->folder_view = folder_view;
741 helper->entry = (GtkEntry *) entry;
743 account_picker = folder_picker_new (suggested_parent, helper);
746 g_object_unref (sizegroup);
748 /* Connect to the response method to avoid closing the dialog
749 when an invalid name is selected*/
750 g_signal_connect (dialog,
752 G_CALLBACK (on_response),
756 /* Track entry changes */
757 g_signal_connect (entry,
759 G_CALLBACK (entry_insert_text),
761 g_signal_connect (entry,
763 G_CALLBACK (entry_changed),
768 /* Some locales like pt_BR need this to get the full window
770 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
772 /* Create the hbox */
774 hbox = gtk_hbox_new (FALSE, 12);
775 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
776 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
778 /* Add hbox to dialog */
779 gtk_box_pack_start (GTK_BOX (top_vbox),
780 hbox, FALSE, FALSE, 0);
781 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
785 hbox = gtk_hbox_new (FALSE, 12);
786 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
787 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
789 /* Add hbox to dialog */
790 gtk_box_pack_start (GTK_BOX (top_vbox),
791 hbox, FALSE, FALSE, 0);
792 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
794 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
795 GTK_WINDOW (dialog), parent_window);
797 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
798 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
800 gtk_widget_show_all (GTK_WIDGET(dialog));
802 result = gtk_dialog_run (GTK_DIALOG(dialog));
803 if (result == GTK_RESPONSE_ACCEPT) {
805 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
807 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
809 g_object_ref (*parent);
813 gtk_widget_destroy (dialog);
816 g_slice_free (FolderPickerHelper, helper);
818 while (gtk_events_pending ())
819 gtk_main_iteration ();
825 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
826 TnyFolderStore *suggested_folder,
827 gchar *suggested_name,
829 TnyFolderStore **parent_folder)
831 gchar *real_suggested_name = NULL;
833 ModestTnyAccountStore *acc_store;
835 gboolean do_free = FALSE;
837 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
840 /* In hildon 2.2 we always suggest the archive folder as parent */
841 if (!suggested_folder) {
842 acc_store = modest_runtime_get_account_store ();
843 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
845 suggested_folder = (TnyFolderStore *)
846 modest_tny_account_get_special_folder (account,
847 TNY_FOLDER_TYPE_ARCHIVE);
848 g_object_unref (account);
853 /* If there is not archive folder then fallback to local folders account */
854 if (!suggested_folder) {
856 suggested_folder = (TnyFolderStore *)
857 modest_tny_account_store_get_local_folders_account (acc_store);
860 result = modest_platform_run_folder_common_dialog (parent_window,
862 _HL("ckdg_ti_new_folder"),
863 _FM("ckdg_fi_new_folder_name"),
871 g_object_unref (suggested_folder);
873 g_free(real_suggested_name);
879 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
880 TnyFolderStore *parent_folder,
881 const gchar *suggested_name,
884 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
886 return modest_platform_run_folder_common_dialog (parent_window,
888 _HL("ckdg_ti_rename_folder"),
889 _HL("ckdg_fi_rename_name"),
900 on_destroy_dialog (GtkWidget *dialog)
902 /* This could happen when the dialogs get programatically
903 hidden or destroyed (for example when closing the
904 application while a dialog is being shown) */
905 if (!GTK_IS_WIDGET (dialog))
908 gtk_widget_destroy (dialog);
910 if (gtk_events_pending ())
911 gtk_main_iteration ();
915 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
916 const gchar *message)
921 dialog = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
922 GTK_MESSAGE_QUESTION,
923 GTK_BUTTONS_OK_CANCEL,
925 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
926 GTK_WINDOW (dialog), parent_window);
928 response = gtk_dialog_run (GTK_DIALOG (dialog));
930 on_destroy_dialog (dialog);
936 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
937 const gchar *message,
938 const gchar *button_accept,
939 const gchar *button_cancel)
944 dialog = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
945 GTK_MESSAGE_QUESTION,
948 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
949 button_accept, GTK_RESPONSE_ACCEPT,
950 button_cancel, GTK_RESPONSE_CANCEL,
953 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
954 GTK_WINDOW (dialog), parent_window);
956 response = gtk_dialog_run (GTK_DIALOG (dialog));
958 on_destroy_dialog (dialog);
964 modest_platform_run_information_dialog (GtkWindow *parent_window,
965 const gchar *message,
970 note = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
975 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
976 GTK_WINDOW (note), parent_window);
979 gtk_dialog_run (GTK_DIALOG (note));
981 on_destroy_dialog (note);
983 g_signal_connect_swapped (note,
985 G_CALLBACK (on_destroy_dialog),
988 gtk_widget_show_all (note);
992 typedef struct _ConnectAndWaitData {
994 GMainLoop *wait_loop;
995 gboolean has_callback;
997 } ConnectAndWaitData;
1001 quit_wait_loop (TnyAccount *account,
1002 ConnectAndWaitData *data)
1004 /* Set the has_callback to TRUE (means that the callback was
1005 executed and wake up every code waiting for cond to be
1007 g_mutex_lock (data->mutex);
1008 data->has_callback = TRUE;
1009 if (data->wait_loop)
1010 g_main_loop_quit (data->wait_loop);
1011 g_mutex_unlock (data->mutex);
1015 on_connection_status_changed (TnyAccount *account,
1016 TnyConnectionStatus status,
1019 TnyConnectionStatus conn_status;
1020 ConnectAndWaitData *data;
1022 /* Ignore if reconnecting or disconnected */
1023 conn_status = tny_account_get_connection_status (account);
1024 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1025 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1028 /* Remove the handler */
1029 data = (ConnectAndWaitData *) user_data;
1030 g_signal_handler_disconnect (account, data->handler);
1032 /* Quit from wait loop */
1033 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1037 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1042 /* Quit from wait loop */
1043 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1047 modest_platform_connect_and_wait (GtkWindow *parent_window,
1048 TnyAccount *account)
1050 ConnectAndWaitData *data = NULL;
1051 gboolean device_online;
1053 TnyConnectionStatus conn_status;
1054 gboolean user_requested;
1056 device = modest_runtime_get_device();
1057 device_online = tny_device_is_online (device);
1059 /* Whether the connection is user requested or automatically
1060 requested, for example via D-Bus */
1061 user_requested = (parent_window) ? TRUE : FALSE;
1063 /* If there is no account check only the device status */
1068 /* TODO: should show connection dialog through gnome device */
1072 /* Return if the account is already connected */
1073 conn_status = tny_account_get_connection_status (account);
1074 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1081 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1083 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1084 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1085 /* This must be a maildir account, which does not require a connection: */
1090 return modest_platform_connect_and_wait (parent_window, account);
1094 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1097 return TRUE; /* Maybe it is something local. */
1099 gboolean result = TRUE;
1100 if (TNY_IS_FOLDER (folder_store)) {
1101 /* Get the folder's parent account: */
1102 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1103 if (account != NULL) {
1104 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1105 g_object_unref (account);
1107 } else if (TNY_IS_ACCOUNT (folder_store)) {
1108 /* Use the folder store as an account: */
1109 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1116 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1124 modest_platform_set_update_interval (guint minutes)
1130 modest_platform_push_email_notification(void)
1136 modest_platform_on_new_headers_received (GList *URI_list,
1137 gboolean show_visual)
1143 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1151 modest_platform_get_global_settings_dialog ()
1157 modest_platform_show_help (GtkWindow *parent_window,
1158 const gchar *help_id)
1164 modest_platform_show_search_messages (GtkWindow *parent_window)
1170 modest_platform_show_addressbook (GtkWindow *parent_window)
1176 modest_platform_create_folder_view_full (TnyFolderStoreQuery *query, gboolean do_refresh)
1178 GtkWidget *widget = modest_folder_view_new_full (query, do_refresh);
1180 /* Show one account by default */
1181 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1182 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1188 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1190 return modest_platform_create_folder_view_full (query, TRUE);
1194 banner_finish (gpointer data, GObject *object)
1196 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1197 modest_window_mgr_unregister_banner (mgr);
1198 g_object_unref (mgr);
1202 modest_platform_information_banner (GtkWidget *parent,
1203 const gchar *icon_name,
1210 modest_platform_system_banner (GtkWidget *parent,
1211 const gchar *icon_name,
1218 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1219 const gchar *icon_name,
1227 modest_platform_animation_banner (GtkWidget *parent,
1228 const gchar *animation_name,
1237 TnyAccount *account;
1240 } CheckAccountIdleData;
1242 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1245 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1247 gboolean stop_trying = FALSE;
1248 g_return_val_if_fail (data && data->account, FALSE);
1250 if (data && data->account &&
1251 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1252 * after which the account is likely to be usable, or never likely to be usable soon: */
1253 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1255 data->is_online = TRUE;
1259 /* Give up if we have tried too many times: */
1260 if (data->count_tries >= NUMBER_OF_TRIES) {
1263 /* Wait for another timeout: */
1264 ++(data->count_tries);
1269 /* Allow the function that requested this idle callback to continue: */
1271 g_main_loop_quit (data->loop);
1274 g_object_unref (data->account);
1276 return FALSE; /* Don't call this again. */
1278 return TRUE; /* Call this timeout callback again. */
1282 /* Return TRUE immediately if the account is already online,
1283 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1284 * soon as the account is online, or FALSE if the account does
1285 * not become online in the NUMBER_OF_TRIES seconds.
1286 * This is useful when the D-Bus method was run immediately after
1287 * the application was started (when using D-Bus activation),
1288 * because the account usually takes a short time to go online.
1289 * The return value is maybe not very useful.
1292 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1296 g_return_val_if_fail (account, FALSE);
1298 if (!tny_device_is_online (modest_runtime_get_device())) {
1299 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1303 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1304 * so we avoid wait unnecessarily: */
1305 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1308 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1309 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1310 * we want to avoid. */
1311 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1314 /* This blocks on the result: */
1315 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1316 data->is_online = FALSE;
1317 data->account = account;
1318 g_object_ref (data->account);
1319 data->count_tries = 0;
1321 GMainContext *context = NULL; /* g_main_context_new (); */
1322 data->loop = g_main_loop_new (context, FALSE /* not running */);
1324 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1326 /* This main loop will run until the idle handler has stopped it: */
1327 g_main_loop_run (data->loop);
1329 g_main_loop_unref (data->loop);
1330 /* g_main_context_unref (context); */
1332 is_online = data->is_online;
1333 g_slice_free (CheckAccountIdleData, data);
1341 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1343 /* GTK_RESPONSE_HELP means we need to show the certificate */
1344 if (response_id == GTK_RESPONSE_APPLY) {
1348 /* Do not close the dialog */
1349 g_signal_stop_emission_by_name (dialog, "response");
1351 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1352 note = modest_platform_information_banner (NULL, NULL, msg);
1353 gtk_dialog_run (GTK_DIALOG(note));
1354 gtk_widget_destroy (note);
1360 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1361 const gchar *certificate)
1367 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1370 /* We use GTK_RESPONSE_APPLY because we want the button in the
1371 middle of OK and CANCEL the same as the browser does for
1372 example. With GTK_RESPONSE_HELP the view button is aligned
1373 to the left while the other two to the right */
1374 note = gtk_message_dialog_new (
1376 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1377 GTK_MESSAGE_QUESTION,
1380 gtk_dialog_add_buttons (GTK_DIALOG (note),
1381 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1382 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1383 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1386 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1387 (GtkWindow *) note, (GtkWindow *) win);
1389 g_signal_connect (G_OBJECT(note), "response",
1390 G_CALLBACK(on_cert_dialog_response),
1391 (gpointer) certificate);
1393 response = gtk_dialog_run(GTK_DIALOG(note));
1395 on_destroy_dialog (note);
1398 return response == GTK_RESPONSE_OK;
1402 modest_platform_run_alert_dialog (const gchar* prompt,
1403 gboolean is_question)
1406 gboolean retval = TRUE;
1408 /* The Tinymail documentation says that we should show Yes and No buttons,
1409 * when it is a question.
1410 * Obviously, we need tinymail to use more specific error codes instead,
1411 * so we know what buttons to show. */
1412 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1413 GTK_MESSAGE_QUESTION,
1417 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1418 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1420 on_destroy_dialog (dialog);
1422 /* Just show the error text and use the default response: */
1423 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1431 GtkWindow *parent_window;
1432 ModestConnectedPerformer callback;
1433 TnyAccount *account;
1440 on_went_online_info_free (OnWentOnlineInfo *info)
1442 /* And if we cleanup, we DO cleanup :-) */
1445 g_object_unref (info->device);
1448 if (info->parent_window)
1449 g_object_unref (info->parent_window);
1451 g_object_unref (info->account);
1453 g_slice_free (OnWentOnlineInfo, info);
1455 /* We're done ... */
1461 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1463 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1465 /* Now it's really time to callback to the caller. If going online didn't succeed,
1466 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1467 * canceled will be set. Etcetera etcetera. */
1469 if (info->callback) {
1470 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1473 /* This is our last call, we must cleanup here if we didn't yet do that */
1474 on_went_online_info_free (info);
1480 modest_platform_connect_and_perform (GtkWindow *parent_window,
1482 TnyAccount *account,
1483 ModestConnectedPerformer callback,
1486 gboolean device_online;
1488 TnyConnectionStatus conn_status;
1489 OnWentOnlineInfo *info;
1491 device = modest_runtime_get_device();
1492 device_online = tny_device_is_online (device);
1494 /* If there is no account check only the device status */
1497 if (device_online) {
1499 /* We promise to instantly perform the callback, so ... */
1501 callback (FALSE, NULL, parent_window, account, user_data);
1508 /* The other code has no more reason to run. This is all that we can do for the
1509 * caller (he should have given us a nice and clean account instance!). We
1510 * can't do magic, we don't know what account he intends to bring online. So
1511 * we'll just bring the device online (and await his false bug report). */
1517 /* Return if the account is already connected */
1519 conn_status = tny_account_get_connection_status (account);
1520 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
1522 /* We promise to instantly perform the callback, so ... */
1524 callback (FALSE, NULL, parent_window, account, user_data);
1530 if (device_online) {
1533 /* If the device is online, we'll just connect the account */
1535 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1536 on_account_went_online, info);
1539 /* The info gets freed by on_account_went_online or on_conic_device_went_online
1540 * in both situations, go look if you don't believe me! */
1546 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
1548 TnyFolderStore *folder_store,
1549 ModestConnectedPerformer callback,
1552 TnyAccount *account = NULL;
1554 if (!folder_store ||
1555 (TNY_IS_MERGE_FOLDER (folder_store) &&
1556 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
1558 /* We promise to instantly perform the callback, so ... */
1560 GError *error = NULL;
1561 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
1562 "Unable to move or not found folder");
1563 callback (FALSE, error, parent_window, NULL, user_data);
1564 g_error_free (error);
1568 } else if (TNY_IS_FOLDER (folder_store)) {
1569 /* Get the folder's parent account: */
1570 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1571 } else if (TNY_IS_ACCOUNT (folder_store)) {
1572 /* Use the folder store as an account: */
1573 account = TNY_ACCOUNT (g_object_ref (folder_store));
1576 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
1577 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1578 /* No need to connect a local account */
1580 callback (FALSE, NULL, parent_window, account, user_data);
1585 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
1589 g_object_unref (account);
1593 src_account_connect_performer (gboolean canceled,
1595 GtkWindow *parent_window,
1596 TnyAccount *src_account,
1599 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
1601 if (canceled || err) {
1602 /* If there was any error call the user callback */
1603 info->callback (canceled, err, parent_window, src_account, info->data);
1605 /* Connect the destination account */
1606 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
1607 TNY_FOLDER_STORE (info->dst_account),
1608 info->callback, info->data);
1611 /* Free the info object */
1612 g_object_unref (info->dst_account);
1613 g_slice_free (DoubleConnectionInfo, info);
1618 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
1620 TnyFolderStore *folder_store,
1621 DoubleConnectionInfo *connect_info)
1623 modest_platform_connect_if_remote_and_perform(parent_window,
1626 src_account_connect_performer,
1631 modest_platform_get_account_settings_wizard (void)
1633 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
1635 return GTK_WIDGET (dialog);
1639 modest_platform_get_current_connection (void)
1641 TnyDevice *device = NULL;
1642 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
1644 device = modest_runtime_get_device ();
1646 if (!tny_device_is_online (device))
1647 return MODEST_CONNECTED_VIA_ANY;
1649 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
1656 modest_platform_check_memory_low (ModestWindow *win,
1664 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
1670 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
1673 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1674 GTK_WINDOW (dialog),
1676 gtk_widget_show_all (dialog);
1678 g_signal_connect_swapped (dialog, "response",
1679 G_CALLBACK (gtk_widget_destroy),
1683 typedef struct _HeaderDetailsGetSizeInfo {
1687 } HeaderDetailsGetSizeInfo;
1690 header_details_dialog_destroy (gpointer userdata,
1693 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1695 info->dialog = NULL;
1699 idle_get_mime_part_size_cb (gpointer userdata)
1701 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1702 gdk_threads_enter ();
1704 if (info->dialog && GTK_WIDGET_VISIBLE (info->dialog)) {
1705 modest_details_dialog_set_message_size (MODEST_DETAILS_DIALOG (info->dialog),
1710 g_object_weak_unref (G_OBJECT (info->dialog), header_details_dialog_destroy, info);
1711 info->dialog = NULL;
1713 g_object_unref (info->part);
1714 g_slice_free (HeaderDetailsGetSizeInfo, info);
1716 gdk_threads_leave ();
1722 get_mime_part_size_thread (gpointer thr_user_data)
1724 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) thr_user_data;
1726 TnyStream *count_stream;
1728 count_stream = modest_count_stream_new ();
1729 result = tny_mime_part_decode_to_stream (info->part, count_stream, NULL);
1730 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1731 if (info->total == 0) {
1732 modest_count_stream_reset_count(MODEST_COUNT_STREAM (count_stream));
1733 result = tny_mime_part_write_to_stream (info->part, count_stream, NULL);
1734 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1737 /* if there was an error, don't set the size (this is pretty uncommon) */
1739 g_warning ("%s: error while writing mime part to stream\n", __FUNCTION__);
1741 g_idle_add (idle_get_mime_part_size_cb, info);
1747 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
1749 gboolean async_get_size,
1755 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header, !async_get_size);
1757 if (async_get_size && msg && TNY_IS_MSG (msg)) {
1758 HeaderDetailsGetSizeInfo *info;
1759 info = g_slice_new (HeaderDetailsGetSizeInfo);
1760 info->dialog = dialog;
1762 info->part = TNY_MIME_PART (g_object_ref (msg));
1764 g_object_weak_ref (G_OBJECT (dialog), header_details_dialog_destroy, info);
1765 g_thread_create (get_mime_part_size_thread, info, FALSE, NULL);
1769 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1770 GTK_WINDOW (dialog),
1772 gtk_widget_show_all (dialog);
1774 g_signal_connect_swapped (dialog, "response",
1775 G_CALLBACK (gtk_widget_destroy),
1780 modest_platform_play_email_tone (void)
1785 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
1786 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
1787 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
1788 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
1789 #define MOVE_TO_DIALOG_SCROLLABLE "scrollable"
1790 #define MOVE_TO_FOLDER_SEPARATOR "/"
1793 translate_path (gchar **path)
1798 gboolean add_separator;
1800 parts = g_strsplit (*path, MOVE_TO_FOLDER_SEPARATOR, 0);
1804 output = g_string_new ("");
1805 add_separator = FALSE;
1807 while (*current != NULL) {
1808 TnyFolderType folder_type;
1811 if (add_separator) {
1812 output = g_string_append (output, MOVE_TO_FOLDER_SEPARATOR);
1814 add_separator = TRUE;
1817 downcase = g_ascii_strdown (*current, -1);
1818 folder_type = modest_local_folder_info_get_type (downcase);
1819 if (strcmp (downcase, "inbox") == 0) {
1820 output = g_string_append (output, _("mcen_me_folder_inbox"));
1821 } else if (folder_type == TNY_FOLDER_TYPE_ARCHIVE ||
1822 folder_type == TNY_FOLDER_TYPE_DRAFTS ||
1823 folder_type == TNY_FOLDER_TYPE_SENT ||
1824 folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1825 output = g_string_append (output, modest_local_folder_info_get_type_display_name (folder_type));
1827 output = g_string_append (output, *current);
1835 *path = g_string_free (output, FALSE);
1839 move_to_dialog_set_selected_folder_store (GtkWidget *dialog,
1840 TnyFolderStore *folder_store)
1842 GtkWidget *action_button;
1843 GtkWidget *image = NULL;
1844 TnyAccount *account;
1845 gchar *account_name = NULL, *short_name = NULL;
1847 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1849 /* Get account name */
1850 if (TNY_IS_FOLDER (folder_store))
1851 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1853 account = g_object_ref (folder_store);
1855 if (modest_tny_account_is_virtual_local_folders (account))
1856 account_name = modest_conf_get_string (modest_runtime_get_conf(),
1857 MODEST_CONF_DEVICE_NAME, NULL);
1860 account_name = g_strdup (tny_account_get_name (account));
1862 g_object_unref (account);
1864 /* Set title of button: account or folder name */
1865 if (TNY_IS_FOLDER (folder_store))
1866 short_name = folder_store_get_display_name (folder_store);
1868 short_name = g_strdup (account_name);
1870 gtk_button_set_label (GTK_BUTTON (action_button), short_name);
1872 /* Set value of button, folder full name */
1873 if (TNY_IS_CAMEL_FOLDER (folder_store)) {
1874 const gchar *camel_full_name;
1875 gchar *last_slash, *full_name;
1877 camel_full_name = tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store));
1878 last_slash = g_strrstr (camel_full_name, "/");
1880 gchar *prefix = g_strndup (camel_full_name, last_slash - camel_full_name + 1);
1881 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR, prefix, short_name, NULL);
1884 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR,
1888 translate_path (&full_name);
1889 gtk_button_set_label (GTK_BUTTON (action_button), full_name);
1892 g_free (account_name);
1893 g_free (short_name);
1895 /* Set image for the button */
1896 image = get_image_for_folder_store (folder_store, MODEST_ICON_SIZE_BIG);
1898 gtk_button_set_image (GTK_BUTTON (action_button), image);
1902 move_to_dialog_show_accounts (GtkWidget *dialog)
1904 GtkWidget *back_button;
1905 GtkWidget *folder_view;
1906 GtkWidget *scrollable;
1907 GtkWidget *action_button;
1909 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
1910 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1911 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
1912 scrollable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
1914 gtk_widget_set_sensitive (back_button, FALSE);
1915 gtk_widget_set_sensitive (action_button, FALSE);
1917 /* Need to set this here, otherwise callbacks called because
1918 of filtering won't perform correctly */
1919 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
1921 /* Reset action button */
1922 gtk_button_set_label (GTK_BUTTON (action_button), NULL);
1923 gtk_button_set_image (GTK_BUTTON (action_button), NULL);
1925 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
1926 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
1927 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
1928 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1929 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1930 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1931 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1932 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1933 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
1934 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1935 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
1936 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
1940 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
1942 GtkWidget *back_button;
1943 GtkWidget *folder_view;
1944 TnyAccount *account;
1945 const gchar *account_id;
1946 GtkWidget *scrollable;
1947 GtkWidget *action_button;
1950 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
1952 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1954 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
1956 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
1958 gtk_widget_set_sensitive (back_button, TRUE);
1959 gtk_widget_set_sensitive (action_button, TRUE);
1961 /* Need to set this here, otherwise callbacks called because
1962 of filtering won't perform correctly */
1963 g_object_set_data (G_OBJECT (dialog),
1964 MOVE_TO_DIALOG_SHOWING_FOLDERS,
1965 GINT_TO_POINTER (TRUE));
1967 account = TNY_ACCOUNT (folder_store);
1968 if (modest_tny_account_is_virtual_local_folders (account)) {
1969 account_id = tny_account_get_id (account);
1970 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1971 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1972 } else if (modest_tny_account_is_memory_card_account (account)) {
1973 account_id = tny_account_get_id (account);
1974 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1975 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1977 account_id = tny_account_get_id (account);
1978 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1979 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1980 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1981 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1984 move_to_dialog_set_selected_folder_store (dialog, folder_store);
1985 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
1988 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
1989 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1990 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
1991 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
1992 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
1996 on_move_to_dialog_back_clicked (GtkButton *button,
1999 GtkWidget *dialog = (GtkWidget *) userdata;
2001 /* Back to show accounts */
2002 move_to_dialog_show_accounts (dialog);
2006 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
2008 GtkTreeViewColumn *column,
2011 TnyFolderStore *selected = NULL;
2013 GtkWidget *folder_view;
2014 gboolean showing_folders;
2016 dialog = (GtkWidget *) user_data;
2017 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
2018 MOVE_TO_DIALOG_SHOWING_FOLDERS));
2020 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
2021 MOVE_TO_DIALOG_FOLDER_VIEW));
2023 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2027 if (!showing_folders) {
2028 gboolean valid = TRUE;
2030 if (TNY_IS_ACCOUNT (selected) &&
2031 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2032 ModestProtocolType protocol_type;
2034 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2035 valid = !modest_protocol_registry_protocol_type_has_tag
2036 (modest_runtime_get_protocol_registry (),
2038 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
2041 move_to_dialog_show_folders (dialog, selected);
2043 move_to_dialog_set_selected_folder_store (dialog, selected);
2045 g_object_unref (selected);
2049 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2052 gboolean showing_folders;
2055 dialog = (GtkWidget *) user_data;
2056 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2057 if (showing_folders) {
2058 TnyFolderStore *selected;
2059 GtkWidget *folder_view;
2061 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2062 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2065 move_to_dialog_set_selected_folder_store (dialog, selected);
2066 g_object_unref (selected);
2072 on_move_to_dialog_action_clicked (GtkButton *selection,
2076 gboolean showing_folders;
2078 dialog = (GtkWidget *) user_data;
2079 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2080 if (showing_folders) {
2081 TnyFolderStore *selected;
2082 GtkWidget *folder_view;
2084 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2085 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2088 /* It's not possible to select root folders as
2089 targets unless they're the local account or
2090 the memory card account */
2091 if ((TNY_IS_FOLDER (selected) && !TNY_IS_MERGE_FOLDER (selected)) ||
2092 (TNY_IS_ACCOUNT (selected) &&
2093 (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (selected)) ||
2094 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (selected)))))
2095 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2096 g_object_unref (selected);
2102 move_to_dialog_activity_changed (ModestFolderView *folder_view, gboolean activity, GtkDialog *dialog)
2107 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2108 GtkWidget **folder_view)
2110 GtkWidget *dialog, *folder_view_container;
2112 GtkWidget *buttons_hbox;
2113 GtkWidget *back_button;
2114 GdkPixbuf *back_pixbuf;
2115 GtkWidget *top_vbox;
2116 GtkWidget *action_button;
2117 GtkTreeSelection *selection;
2119 /* Create dialog. We cannot use a touch selector because we
2120 need to use here the folder view widget directly */
2121 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2122 GTK_WINDOW (parent_window),
2123 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2124 GTK_DIALOG_DESTROY_WITH_PARENT,
2125 _FM ("ckdg_bd_change_folder_new_folder"),
2126 MODEST_GTK_RESPONSE_NEW_FOLDER,
2129 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2130 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2131 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2133 /* Create folder view */
2134 *folder_view = modest_platform_create_folder_view_full (NULL, FALSE);
2135 g_signal_connect (G_OBJECT (*folder_view), "activity-changed", G_CALLBACK (move_to_dialog_activity_changed),
2138 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2139 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2140 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2142 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2143 (TnyAccountStore *) modest_runtime_get_account_store ());
2145 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2146 back_button = gtk_button_new ();
2147 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2149 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2150 g_object_unref (back_pixbuf);
2153 action_button = gtk_button_new ();
2154 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
2156 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2157 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2158 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2159 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2160 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2162 /* Create scrollable and add it to the dialog */
2163 folder_view_container = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
2164 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2165 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2167 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2168 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2170 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2172 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2173 gtk_widget_show (folder_view_container);
2174 gtk_widget_show (align);
2175 gtk_widget_show (top_vbox);
2176 gtk_widget_show (*folder_view);
2177 gtk_widget_show_all (back_button);
2178 gtk_widget_show (action_button);
2179 gtk_widget_show (buttons_hbox);
2180 gtk_widget_show (dialog);
2182 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2183 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2184 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2185 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE, folder_view_container);
2187 /* Simulate the behaviour of a HildonPickerDialog by emitting
2188 a response when a folder is selected */
2189 g_signal_connect (*folder_view, "row-activated",
2190 G_CALLBACK (on_move_to_dialog_row_activated),
2193 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2194 g_signal_connect (selection, "changed",
2195 G_CALLBACK (on_move_to_dialog_selection_changed),
2198 g_signal_connect (action_button, "clicked",
2199 G_CALLBACK (on_move_to_dialog_action_clicked),
2202 g_signal_connect (back_button, "clicked",
2203 G_CALLBACK (on_move_to_dialog_back_clicked),
2206 move_to_dialog_show_accounts (dialog);
2212 modest_platform_get_list_to_move (ModestWindow *window)
2214 TnyList *list = NULL;
2216 if (MODEST_IS_HEADER_WINDOW (window)) {
2217 ModestHeaderView *header_view;
2219 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2220 list = modest_header_view_get_selected_headers (header_view);
2221 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2222 ModestFolderView *folder_view;
2223 TnyFolderStore *selected_folder;
2225 list = TNY_LIST (tny_simple_list_new ());
2226 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2227 selected_folder = modest_folder_view_get_selected (folder_view);
2228 if (selected_folder) {
2229 tny_list_prepend (list, G_OBJECT (selected_folder));
2230 g_object_unref (selected_folder);
2233 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2236 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2238 list = TNY_LIST (tny_simple_list_new ());
2239 tny_list_prepend (list, G_OBJECT (header));
2240 g_object_unref (header);
2243 g_return_val_if_reached (NULL);