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>
65 #include <modest-gtk-details-dialog.h>
66 #include <modest-default-global-settings-dialog.h>
68 #include "widgets/modest-toolkit-utils.h"
69 #include <modest-shell-banner.h>
71 #define HILDON_OSSO_URI_ACTION "uri-action"
72 #define URI_ACTION_COPY "copy:"
73 #define MODEST_NOTIFICATION_CATEGORY "email-message"
74 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternChatAndEmail"
76 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
77 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
78 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
79 #define FOLDER_PICKER_ORIGINAL_ACCOUNT "original-account"
82 on_modest_conf_update_interval_changed (ModestConf* self,
84 ModestConfEvent event,
85 ModestConfNotificationId id,
88 g_return_if_fail (key);
90 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
91 const guint update_interval_minutes =
92 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
93 modest_platform_set_update_interval (update_interval_minutes);
100 check_required_files (void)
103 FILE *mcc_file = modest_utils_open_mcc_mapping_file ();
106 g_printerr ("modest: check for mcc file (for LANG) failed\n");
112 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
113 access(MODEST_FALLBACK_PROVIDER_DATA_FILE, R_OK) != 0) {
114 g_printerr ("modest: cannot find providers data\n");
122 /* the gpointer here is the osso_context. */
124 modest_platform_init (int argc, char *argv[])
128 if (!check_required_files ()) {
129 g_printerr ("modest: missing required files\n");
133 /* Make sure that the update interval is changed whenever its gconf key
135 /* CAUTION: we're not using here the
136 modest_conf_listen_to_namespace because we know that there
137 are other parts of Modest listening for this namespace, so
138 we'll receive the notifications anyway. We basically do not
139 use it because there is no easy way to do the
140 modest_conf_forget_namespace */
141 ModestConf *conf = modest_runtime_get_conf ();
142 g_signal_connect (G_OBJECT(conf),
144 G_CALLBACK (on_modest_conf_update_interval_changed),
147 /* only force the setting of the default interval, if there are actually
149 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
151 /* Get the initial update interval from gconf: */
152 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
153 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
154 modest_account_mgr_free_account_names (acc_names);
161 modest_platform_uninit (void)
170 modest_platform_get_new_device (void)
172 return TNY_DEVICE (tny_gnome_device_new ());
176 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
177 gchar **effective_mime_type)
180 g_warning ("Not implemented %s", __FUNCTION__);
189 modest_platform_activate_uri (const gchar *uri)
191 g_warning ("Not implemented %s", __FUNCTION__);
198 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
200 g_warning ("Not implemented %s", __FUNCTION__);
206 modest_platform_show_uri_popup (const gchar *uri)
208 g_warning ("Not implemented %s", __FUNCTION__);
215 modest_platform_get_icon (const gchar *name, guint icon_size)
217 return gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
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_TITLE_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 (ModestWindow *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 (gtk_widget_get_toplevel (GTK_WIDGET (parent_window)),
888 _HL_TITLE_RENAME_FOLDER,
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 modest_platform_connect_and_wait (GtkWindow *parent_window,
1002 TnyAccount *account)
1004 gboolean device_online;
1006 TnyConnectionStatus conn_status;
1007 gboolean user_requested;
1009 device = modest_runtime_get_device();
1010 device_online = tny_device_is_online (device);
1012 /* Whether the connection is user requested or automatically
1013 requested, for example via D-Bus */
1014 user_requested = (parent_window) ? TRUE : FALSE;
1016 /* If there is no account check only the device status */
1021 /* TODO: should show connection dialog through gnome device */
1025 /* Return if the account is already connected */
1026 conn_status = tny_account_get_connection_status (account);
1027 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1034 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1036 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1037 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1038 /* This must be a maildir account, which does not require a connection: */
1043 return modest_platform_connect_and_wait (parent_window, account);
1047 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1050 return TRUE; /* Maybe it is something local. */
1052 gboolean result = TRUE;
1053 if (TNY_IS_FOLDER (folder_store)) {
1054 /* Get the folder's parent account: */
1055 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1056 if (account != NULL) {
1057 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1058 g_object_unref (account);
1060 } else if (TNY_IS_ACCOUNT (folder_store)) {
1061 /* Use the folder store as an account: */
1062 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1069 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1077 modest_platform_set_update_interval (guint minutes)
1083 modest_platform_push_email_notification(void)
1089 modest_platform_on_new_headers_received (GList *URI_list,
1090 gboolean show_visual)
1096 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1104 modest_platform_get_global_settings_dialog ()
1106 return modest_default_global_settings_dialog_new ();
1110 modest_platform_show_help (GtkWindow *parent_window,
1111 const gchar *help_id)
1117 modest_platform_show_search_messages (GtkWindow *parent_window)
1123 modest_platform_show_addressbook (GtkWindow *parent_window)
1129 modest_platform_create_folder_view_full (TnyFolderStoreQuery *query, gboolean do_refresh)
1131 GtkWidget *widget = modest_folder_view_new_full (query, do_refresh);
1133 /* Show one account by default */
1134 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1135 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1141 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1143 return modest_platform_create_folder_view_full (query, TRUE);
1147 banner_finish (gpointer data, GObject *object)
1149 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1150 modest_window_mgr_unregister_banner (mgr);
1151 g_object_unref (mgr);
1155 modest_platform_information_banner (GtkWidget *parent,
1156 const gchar *icon_name,
1161 banner = modest_shell_banner_new (parent);
1162 modest_shell_banner_set_icon (MODEST_SHELL_BANNER (banner), icon_name);
1163 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1169 modest_platform_system_banner (GtkWidget *parent,
1170 const gchar *icon_name,
1173 modest_platform_information_banner (parent, icon_name, text);
1177 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1178 const gchar *icon_name,
1184 banner = modest_shell_banner_new_with_timeout (parent, timeout);
1185 modest_shell_banner_set_icon (MODEST_SHELL_BANNER (banner), icon_name);
1186 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1192 modest_platform_animation_banner (GtkWidget *parent,
1193 const gchar *animation_name,
1198 banner = modest_shell_banner_new_with_timeout (parent, 0);
1199 modest_shell_banner_set_animation (MODEST_SHELL_BANNER (banner), animation_name);
1200 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1208 TnyAccount *account;
1211 } CheckAccountIdleData;
1213 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1216 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1218 gboolean stop_trying = FALSE;
1219 g_return_val_if_fail (data && data->account, FALSE);
1221 if (data && data->account &&
1222 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1223 * after which the account is likely to be usable, or never likely to be usable soon: */
1224 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1226 data->is_online = TRUE;
1230 /* Give up if we have tried too many times: */
1231 if (data->count_tries >= NUMBER_OF_TRIES) {
1234 /* Wait for another timeout: */
1235 ++(data->count_tries);
1240 /* Allow the function that requested this idle callback to continue: */
1242 g_main_loop_quit (data->loop);
1245 g_object_unref (data->account);
1247 return FALSE; /* Don't call this again. */
1249 return TRUE; /* Call this timeout callback again. */
1253 /* Return TRUE immediately if the account is already online,
1254 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1255 * soon as the account is online, or FALSE if the account does
1256 * not become online in the NUMBER_OF_TRIES seconds.
1257 * This is useful when the D-Bus method was run immediately after
1258 * the application was started (when using D-Bus activation),
1259 * because the account usually takes a short time to go online.
1260 * The return value is maybe not very useful.
1263 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1267 g_return_val_if_fail (account, FALSE);
1269 if (!tny_device_is_online (modest_runtime_get_device())) {
1270 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1274 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1275 * so we avoid wait unnecessarily: */
1276 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1279 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1280 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1281 * we want to avoid. */
1282 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1285 /* This blocks on the result: */
1286 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1287 data->is_online = FALSE;
1288 data->account = account;
1289 g_object_ref (data->account);
1290 data->count_tries = 0;
1292 GMainContext *context = NULL; /* g_main_context_new (); */
1293 data->loop = g_main_loop_new (context, FALSE /* not running */);
1295 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1297 /* This main loop will run until the idle handler has stopped it: */
1298 g_main_loop_run (data->loop);
1300 g_main_loop_unref (data->loop);
1301 /* g_main_context_unref (context); */
1303 is_online = data->is_online;
1304 g_slice_free (CheckAccountIdleData, data);
1312 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1314 /* GTK_RESPONSE_HELP means we need to show the certificate */
1315 if (response_id == GTK_RESPONSE_APPLY) {
1318 /* Do not close the dialog */
1319 g_signal_stop_emission_by_name (dialog, "response");
1321 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1322 modest_platform_run_information_dialog (NULL, msg, TRUE);
1328 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1329 const gchar *certificate)
1335 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1338 /* We use GTK_RESPONSE_APPLY because we want the button in the
1339 middle of OK and CANCEL the same as the browser does for
1340 example. With GTK_RESPONSE_HELP the view button is aligned
1341 to the left while the other two to the right */
1342 note = gtk_message_dialog_new (
1344 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1345 GTK_MESSAGE_QUESTION,
1348 gtk_dialog_add_buttons (GTK_DIALOG (note),
1349 _HL_YES, GTK_RESPONSE_OK,
1350 _HL_VIEW, GTK_RESPONSE_APPLY, /* abusing this... */
1351 _HL_NO, GTK_RESPONSE_CANCEL,
1354 g_signal_connect (G_OBJECT(note), "response",
1355 G_CALLBACK(on_cert_dialog_response),
1356 (gpointer) certificate);
1358 response = gtk_dialog_run(GTK_DIALOG(note));
1360 on_destroy_dialog (note);
1363 return response == GTK_RESPONSE_OK;
1367 modest_platform_run_alert_dialog (const gchar* prompt,
1368 gboolean is_question)
1371 gboolean retval = TRUE;
1374 /* The Tinymail documentation says that we should show Yes and No buttons,
1375 * when it is a question.
1376 * Obviously, we need tinymail to use more specific error codes instead,
1377 * so we know what buttons to show. */
1378 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1379 GTK_MESSAGE_QUESTION,
1383 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1384 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1386 on_destroy_dialog (dialog);
1388 /* Just show the error text and use the default response: */
1389 modest_platform_run_information_dialog (NULL,
1397 GtkWindow *parent_window;
1398 ModestConnectedPerformer callback;
1399 TnyAccount *account;
1406 on_went_online_info_free (OnWentOnlineInfo *info)
1408 /* And if we cleanup, we DO cleanup :-) */
1411 g_object_unref (info->device);
1414 if (info->parent_window)
1415 g_object_unref (info->parent_window);
1417 g_object_unref (info->account);
1419 g_slice_free (OnWentOnlineInfo, info);
1421 /* We're done ... */
1427 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1429 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1431 /* Now it's really time to callback to the caller. If going online didn't succeed,
1432 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1433 * canceled will be set. Etcetera etcetera. */
1435 if (info->callback) {
1436 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1439 /* This is our last call, we must cleanup here if we didn't yet do that */
1440 on_went_online_info_free (info);
1446 modest_platform_connect_and_perform (GtkWindow *parent_window,
1448 TnyAccount *account,
1449 ModestConnectedPerformer callback,
1452 gboolean device_online;
1454 TnyConnectionStatus conn_status;
1456 device = modest_runtime_get_device();
1457 device_online = tny_device_is_online (device);
1459 /* If there is no account check only the device status */
1462 if (device_online) {
1464 /* We promise to instantly perform the callback, so ... */
1466 callback (FALSE, NULL, parent_window, account, user_data);
1473 /* The other code has no more reason to run. This is all that we can do for the
1474 * caller (he should have given us a nice and clean account instance!). We
1475 * can't do magic, we don't know what account he intends to bring online. So
1476 * we'll just bring the device online (and await his false bug report). */
1482 /* Return if the account is already connected */
1484 conn_status = tny_account_get_connection_status (account);
1485 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
1487 /* We promise to instantly perform the callback, so ... */
1489 callback (FALSE, NULL, parent_window, account, user_data);
1495 if (!device_online) {
1496 OnWentOnlineInfo *info = NULL;
1498 info = g_slice_new0 (OnWentOnlineInfo);
1500 info->device = NULL;
1502 info->account = TNY_ACCOUNT (g_object_ref (account));
1505 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
1507 info->parent_window = NULL;
1509 /* So we'll put the callback away for later ... */
1510 info->user_data = user_data;
1511 info->callback = callback;
1513 /* If the device is online, we'll just connect the account */
1514 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1515 on_account_went_online, info);
1518 /* The info gets freed by on_account_went_online or on_conic_device_went_online
1519 * in both situations, go look if you don't believe me! */
1523 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
1525 TnyFolderStore *folder_store,
1526 ModestConnectedPerformer callback,
1529 TnyAccount *account = NULL;
1531 if (!folder_store ||
1532 (TNY_IS_MERGE_FOLDER (folder_store) &&
1533 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
1535 /* We promise to instantly perform the callback, so ... */
1537 GError *error = NULL;
1538 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
1539 "Unable to move or not found folder");
1540 callback (FALSE, error, parent_window, NULL, user_data);
1541 g_error_free (error);
1545 } else if (TNY_IS_FOLDER (folder_store)) {
1546 /* Get the folder's parent account: */
1547 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1548 } else if (TNY_IS_ACCOUNT (folder_store)) {
1549 /* Use the folder store as an account: */
1550 account = TNY_ACCOUNT (g_object_ref (folder_store));
1553 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
1554 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1555 /* No need to connect a local account */
1557 callback (FALSE, NULL, parent_window, account, user_data);
1562 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
1566 g_object_unref (account);
1570 src_account_connect_performer (gboolean canceled,
1572 GtkWindow *parent_window,
1573 TnyAccount *src_account,
1576 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
1578 if (canceled || err) {
1579 /* If there was any error call the user callback */
1580 info->callback (canceled, err, parent_window, src_account, info->data);
1582 /* Connect the destination account */
1583 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
1584 TNY_FOLDER_STORE (info->dst_account),
1585 info->callback, info->data);
1588 /* Free the info object */
1589 g_object_unref (info->dst_account);
1590 g_slice_free (DoubleConnectionInfo, info);
1595 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
1597 TnyFolderStore *folder_store,
1598 DoubleConnectionInfo *connect_info)
1600 modest_platform_connect_if_remote_and_perform(parent_window,
1603 src_account_connect_performer,
1608 modest_platform_get_account_settings_wizard (void)
1610 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
1612 return GTK_WIDGET (dialog);
1616 modest_platform_get_current_connection (void)
1618 TnyDevice *device = NULL;
1619 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
1621 device = modest_runtime_get_device ();
1623 if (!tny_device_is_online (device))
1624 return MODEST_CONNECTED_VIA_ANY;
1626 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
1633 modest_platform_check_memory_low (ModestWindow *win,
1641 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
1647 dialog = modest_toolkit_factory_create_details_dialog_with_folder (modest_runtime_get_toolkit_factory (),
1648 parent_window, folder);
1651 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1652 GTK_WINDOW (dialog),
1654 gtk_widget_show_all (dialog);
1656 g_signal_connect_swapped (dialog, "response",
1657 G_CALLBACK (gtk_widget_destroy),
1661 typedef struct _HeaderDetailsGetSizeInfo {
1665 } HeaderDetailsGetSizeInfo;
1668 header_details_dialog_destroy (gpointer userdata,
1671 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1673 info->dialog = NULL;
1677 idle_get_mime_part_size_cb (gpointer userdata)
1679 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1680 gdk_threads_enter ();
1682 if (info->dialog && GTK_WIDGET_VISIBLE (info->dialog)) {
1683 modest_details_dialog_set_message_size (MODEST_DETAILS_DIALOG (info->dialog),
1688 g_object_weak_unref (G_OBJECT (info->dialog), header_details_dialog_destroy, info);
1689 info->dialog = NULL;
1691 g_object_unref (info->part);
1692 g_slice_free (HeaderDetailsGetSizeInfo, info);
1694 gdk_threads_leave ();
1700 get_mime_part_size_thread (gpointer thr_user_data)
1702 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) thr_user_data;
1704 TnyStream *count_stream;
1706 count_stream = modest_count_stream_new ();
1707 result = tny_mime_part_decode_to_stream (info->part, count_stream, NULL);
1708 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1709 if (info->total == 0) {
1710 modest_count_stream_reset_count(MODEST_COUNT_STREAM (count_stream));
1711 result = tny_mime_part_write_to_stream (info->part, count_stream, NULL);
1712 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1715 /* if there was an error, don't set the size (this is pretty uncommon) */
1717 g_warning ("%s: error while writing mime part to stream\n", __FUNCTION__);
1719 g_idle_add (idle_get_mime_part_size_cb, info);
1725 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
1727 gboolean async_get_size,
1733 dialog = modest_toolkit_factory_create_details_dialog_with_header (modest_runtime_get_toolkit_factory (),
1734 parent_window, header, !async_get_size);
1736 if (async_get_size && msg && TNY_IS_MSG (msg)) {
1737 HeaderDetailsGetSizeInfo *info;
1738 info = g_slice_new (HeaderDetailsGetSizeInfo);
1739 info->dialog = dialog;
1741 info->part = TNY_MIME_PART (g_object_ref (msg));
1743 g_object_weak_ref (G_OBJECT (dialog), header_details_dialog_destroy, info);
1744 g_thread_create (get_mime_part_size_thread, info, FALSE, NULL);
1748 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1749 GTK_WINDOW (dialog),
1751 gtk_widget_show_all (dialog);
1753 g_signal_connect_swapped (dialog, "response",
1754 G_CALLBACK (gtk_widget_destroy),
1758 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
1759 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
1760 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
1761 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
1762 #define MOVE_TO_DIALOG_SCROLLABLE "scrollable"
1763 #define MOVE_TO_FOLDER_SEPARATOR "/"
1766 translate_path (gchar **path)
1771 gboolean add_separator;
1773 parts = g_strsplit (*path, MOVE_TO_FOLDER_SEPARATOR, 0);
1777 output = g_string_new ("");
1778 add_separator = FALSE;
1780 while (*current != NULL) {
1781 TnyFolderType folder_type;
1784 if (add_separator) {
1785 output = g_string_append (output, MOVE_TO_FOLDER_SEPARATOR);
1787 add_separator = TRUE;
1790 downcase = g_ascii_strdown (*current, -1);
1791 folder_type = modest_local_folder_info_get_type (downcase);
1792 if (strcmp (downcase, "inbox") == 0) {
1793 output = g_string_append (output, _("mcen_me_folder_inbox"));
1794 } else if (folder_type == TNY_FOLDER_TYPE_ARCHIVE ||
1795 folder_type == TNY_FOLDER_TYPE_DRAFTS ||
1796 folder_type == TNY_FOLDER_TYPE_SENT ||
1797 folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1798 output = g_string_append (output, modest_local_folder_info_get_type_display_name (folder_type));
1800 output = g_string_append (output, *current);
1808 *path = g_string_free (output, FALSE);
1812 move_to_dialog_set_selected_folder_store (GtkWidget *dialog,
1813 TnyFolderStore *folder_store)
1815 GtkWidget *action_button;
1816 GtkWidget *image = NULL;
1817 TnyAccount *account;
1818 gchar *account_name = NULL, *short_name = NULL;
1820 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1822 /* Get account name */
1823 if (TNY_IS_FOLDER (folder_store))
1824 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1826 account = g_object_ref (folder_store);
1828 if (modest_tny_account_is_virtual_local_folders (account))
1829 account_name = modest_conf_get_string (modest_runtime_get_conf(),
1830 MODEST_CONF_DEVICE_NAME, NULL);
1833 account_name = g_strdup (tny_account_get_name (account));
1835 g_object_unref (account);
1837 /* Set title of button: account or folder name */
1838 if (TNY_IS_FOLDER (folder_store))
1839 short_name = folder_store_get_display_name (folder_store);
1841 short_name = g_strdup (account_name);
1843 gtk_button_set_label (GTK_BUTTON (action_button), short_name);
1845 /* Set value of button, folder full name */
1846 if (TNY_IS_CAMEL_FOLDER (folder_store)) {
1847 const gchar *camel_full_name;
1848 gchar *last_slash, *full_name;
1850 camel_full_name = tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store));
1851 last_slash = g_strrstr (camel_full_name, "/");
1853 gchar *prefix = g_strndup (camel_full_name, last_slash - camel_full_name + 1);
1854 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR, prefix, short_name, NULL);
1857 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR,
1861 translate_path (&full_name);
1862 gtk_button_set_label (GTK_BUTTON (action_button), full_name);
1865 g_free (account_name);
1866 g_free (short_name);
1868 /* Set image for the button */
1869 image = get_image_for_folder_store (folder_store, MODEST_ICON_SIZE_BIG);
1871 gtk_button_set_image (GTK_BUTTON (action_button), image);
1875 move_to_dialog_show_accounts (GtkWidget *dialog)
1877 GtkWidget *back_button;
1878 GtkWidget *folder_view;
1879 GtkWidget *scrollable;
1880 GtkWidget *action_button;
1882 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
1883 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1884 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
1885 scrollable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
1887 gtk_widget_set_sensitive (back_button, FALSE);
1888 gtk_widget_set_sensitive (action_button, FALSE);
1890 /* Need to set this here, otherwise callbacks called because
1891 of filtering won't perform correctly */
1892 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
1894 /* Reset action button */
1895 gtk_button_set_label (GTK_BUTTON (action_button), NULL);
1896 gtk_button_set_image (GTK_BUTTON (action_button), NULL);
1898 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
1899 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
1900 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
1901 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1902 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1903 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1904 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1905 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1906 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
1907 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1908 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
1909 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
1913 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
1915 GtkWidget *back_button;
1916 GtkWidget *folder_view;
1917 TnyAccount *account;
1918 const gchar *account_id;
1919 GtkWidget *scrollable;
1920 GtkWidget *action_button;
1923 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
1925 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1927 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
1929 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
1931 gtk_widget_set_sensitive (back_button, TRUE);
1932 gtk_widget_set_sensitive (action_button, TRUE);
1934 /* Need to set this here, otherwise callbacks called because
1935 of filtering won't perform correctly */
1936 g_object_set_data (G_OBJECT (dialog),
1937 MOVE_TO_DIALOG_SHOWING_FOLDERS,
1938 GINT_TO_POINTER (TRUE));
1940 account = TNY_ACCOUNT (folder_store);
1941 if (modest_tny_account_is_virtual_local_folders (account)) {
1942 account_id = tny_account_get_id (account);
1943 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1944 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1945 } else if (modest_tny_account_is_memory_card_account (account)) {
1946 account_id = tny_account_get_id (account);
1947 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1948 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1950 account_id = tny_account_get_id (account);
1951 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1952 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1953 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1954 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1957 move_to_dialog_set_selected_folder_store (dialog, folder_store);
1958 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
1961 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
1962 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1963 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
1964 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
1965 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
1969 on_move_to_dialog_back_clicked (GtkButton *button,
1972 GtkWidget *dialog = (GtkWidget *) userdata;
1974 /* Back to show accounts */
1975 move_to_dialog_show_accounts (dialog);
1979 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
1981 GtkTreeViewColumn *column,
1984 TnyFolderStore *selected = NULL;
1986 GtkWidget *folder_view;
1987 gboolean showing_folders;
1989 dialog = (GtkWidget *) user_data;
1990 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
1991 MOVE_TO_DIALOG_SHOWING_FOLDERS));
1993 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
1994 MOVE_TO_DIALOG_FOLDER_VIEW));
1996 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2000 if (!showing_folders) {
2001 gboolean valid = TRUE;
2003 if (TNY_IS_ACCOUNT (selected) &&
2004 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2005 ModestProtocolType protocol_type;
2007 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2008 valid = !modest_protocol_registry_protocol_type_has_tag
2009 (modest_runtime_get_protocol_registry (),
2011 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
2014 move_to_dialog_show_folders (dialog, selected);
2016 move_to_dialog_set_selected_folder_store (dialog, selected);
2018 g_object_unref (selected);
2022 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2025 gboolean showing_folders;
2028 dialog = (GtkWidget *) user_data;
2029 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2030 if (showing_folders) {
2031 TnyFolderStore *selected;
2032 GtkWidget *folder_view;
2034 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2035 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2038 move_to_dialog_set_selected_folder_store (dialog, selected);
2039 g_object_unref (selected);
2045 on_move_to_dialog_action_clicked (GtkButton *selection,
2049 gboolean showing_folders;
2051 dialog = (GtkWidget *) user_data;
2052 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2053 if (showing_folders) {
2054 TnyFolderStore *selected;
2055 GtkWidget *folder_view;
2057 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2058 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2061 /* It's not possible to select root folders as
2062 targets unless they're the local account or
2063 the memory card account */
2064 if ((TNY_IS_FOLDER (selected) && !TNY_IS_MERGE_FOLDER (selected)) ||
2065 (TNY_IS_ACCOUNT (selected) &&
2066 (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (selected)) ||
2067 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (selected)))))
2068 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2069 g_object_unref (selected);
2075 move_to_dialog_activity_changed (ModestFolderView *folder_view, gboolean activity, GtkDialog *dialog)
2080 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2081 GtkWidget **folder_view)
2083 GtkWidget *dialog, *folder_view_container;
2085 GtkWidget *buttons_hbox;
2086 GtkWidget *back_button;
2087 GdkPixbuf *back_pixbuf;
2088 GtkWidget *top_vbox;
2089 GtkWidget *action_button;
2090 GtkTreeSelection *selection;
2092 /* Create dialog. We cannot use a touch selector because we
2093 need to use here the folder view widget directly */
2094 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2095 GTK_WINDOW (parent_window),
2096 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2097 GTK_DIALOG_DESTROY_WITH_PARENT,
2098 _FM ("ckdg_bd_change_folder_new_folder"),
2099 MODEST_GTK_RESPONSE_NEW_FOLDER,
2102 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2103 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2104 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2106 /* Create folder view */
2107 *folder_view = modest_platform_create_folder_view_full (NULL, FALSE);
2108 g_signal_connect (G_OBJECT (*folder_view), "activity-changed", G_CALLBACK (move_to_dialog_activity_changed),
2111 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2112 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2113 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2115 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2116 (TnyAccountStore *) modest_runtime_get_account_store ());
2118 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2119 back_button = gtk_button_new ();
2120 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2122 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2123 g_object_unref (back_pixbuf);
2126 action_button = gtk_button_new ();
2127 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
2129 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2130 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2131 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2132 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2133 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2135 /* Create scrollable and add it to the dialog */
2136 folder_view_container = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
2137 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2138 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2140 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2141 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2143 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2145 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2146 gtk_widget_show (folder_view_container);
2147 gtk_widget_show (align);
2148 gtk_widget_show (top_vbox);
2149 gtk_widget_show (*folder_view);
2150 gtk_widget_show_all (back_button);
2151 gtk_widget_show (action_button);
2152 gtk_widget_show (buttons_hbox);
2153 gtk_widget_show (dialog);
2155 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2156 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2157 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2158 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE, folder_view_container);
2160 /* Simulate the behaviour of a HildonPickerDialog by emitting
2161 a response when a folder is selected */
2162 g_signal_connect (*folder_view, "row-activated",
2163 G_CALLBACK (on_move_to_dialog_row_activated),
2166 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2167 g_signal_connect (selection, "changed",
2168 G_CALLBACK (on_move_to_dialog_selection_changed),
2171 g_signal_connect (action_button, "clicked",
2172 G_CALLBACK (on_move_to_dialog_action_clicked),
2175 g_signal_connect (back_button, "clicked",
2176 G_CALLBACK (on_move_to_dialog_back_clicked),
2179 move_to_dialog_show_accounts (dialog);
2185 modest_platform_get_list_to_move (ModestWindow *window)
2187 TnyList *list = NULL;
2189 if (MODEST_IS_HEADER_WINDOW (window)) {
2190 ModestHeaderView *header_view;
2192 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2193 list = modest_header_view_get_selected_headers (header_view);
2194 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2195 ModestFolderView *folder_view;
2196 TnyFolderStore *selected_folder;
2198 list = TNY_LIST (tny_simple_list_new ());
2199 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2200 selected_folder = modest_folder_view_get_selected (folder_view);
2201 if (selected_folder) {
2202 tny_list_prepend (list, G_OBJECT (selected_folder));
2203 g_object_unref (selected_folder);
2206 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2209 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2211 list = TNY_LIST (tny_simple_list_new ());
2212 tny_list_prepend (list, G_OBJECT (header));
2213 g_object_unref (header);
2216 g_return_val_if_reached (NULL);