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)
179 gchar *icon_name = NULL;
182 gchar **icon_names, **cursor;
184 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
185 content_type = g_content_type_guess (name, NULL, 0, NULL);
187 content_type = g_content_type_from_mime_type (mime_type);
191 content_type = g_content_type_from_mime_type ("application/octet-stream");
193 icon = g_content_type_get_icon (content_type);
194 if (!G_THEMED_ICON (icon))
197 g_object_get (G_OBJECT (icon), "names", &icon_names, NULL);
199 for (cursor = icon_names; cursor; ++cursor) {
200 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
201 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
202 icon_name = g_strdup ("stock_message-display");
204 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
205 icon_name = g_strdup (*cursor);
209 g_strfreev (icon_names);
218 modest_platform_activate_uri (const gchar *uri)
220 GAppLaunchContext *al_context;
223 al_context = gdk_app_launch_context_new ();
224 retval = g_app_info_launch_default_for_uri (uri, al_context, NULL);
225 g_object_unref (al_context);
232 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
239 GAppLaunchContext *al_context;
241 content_type = g_content_type_from_mime_type (mime_type);
245 app_info = g_app_info_get_default_for_type (content_type, FALSE);
246 g_free (content_type);
248 content_type = g_content_type_guess (path, NULL, 0, NULL);
252 app_info = g_app_info_get_default_for_type (content_type, FALSE);
253 g_free (content_type);
260 file = g_file_new_for_path (path);
261 list = g_list_prepend (NULL, file);
262 al_context = gdk_app_launch_context_new ();
263 retval = g_app_info_launch (app_info, list, al_context, NULL);
264 g_object_unref (al_context);
267 g_object_unref (file);
273 modest_platform_show_uri_popup (const gchar *uri)
275 g_warning ("Not implemented %s", __FUNCTION__);
282 modest_platform_get_icon (const gchar *name, guint icon_size)
284 return gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
292 modest_platform_get_app_name (void)
294 return _("mcen_ap_name");
298 entry_insert_text (GtkEditable *editable,
307 chars = gtk_editable_get_chars (editable, 0, -1);
308 chars_length = g_utf8_strlen (chars, -1);
311 /* Show WID-INF036 */
312 if (chars_length >= 20) {
313 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
314 _CS_MAXIMUM_CHARACTERS_REACHED);
316 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
320 tmp = g_strndup (folder_name_forbidden_chars,
321 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
322 msg = g_strdup_printf (_CS_ILLEGAL_CHARACTERS_ENTERED, tmp);
323 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)),
329 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
330 _CS_MAXIMUM_CHARACTERS_REACHED);
332 /* Write the text in the entry if it's valid */
333 g_signal_handlers_block_by_func (editable,
334 (gpointer) entry_insert_text, data);
335 gtk_editable_insert_text (editable, text, length, position);
336 g_signal_handlers_unblock_by_func (editable,
337 (gpointer) entry_insert_text, data);
340 /* Do not allow further processing */
341 g_signal_stop_emission_by_name (editable, "insert_text");
345 entry_changed (GtkEditable *editable,
349 GtkWidget *ok_button;
352 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
353 ok_button = GTK_WIDGET (buttons->data);
355 chars = gtk_editable_get_chars (editable, 0, -1);
356 g_return_if_fail (chars != NULL);
359 if (g_utf8_strlen (chars,-1) >= 20) {
360 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
361 _CS_MAXIMUM_CHARACTERS_REACHED);
363 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
366 g_list_free (buttons);
373 on_response (GtkDialog *dialog,
377 GtkWidget *entry, *picker;
378 TnyFolderStore *parent;
379 const gchar *new_name;
382 if (response != GTK_RESPONSE_ACCEPT)
386 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
387 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
389 parent = TNY_FOLDER_STORE (user_data);
390 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
394 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
396 /* Look for another folder with the same name */
397 if (!TNY_IS_MERGE_FOLDER (parent) &&
398 modest_tny_folder_has_subfolder_with_name (parent, new_name, TRUE))
402 if (TNY_IS_ACCOUNT (parent) &&
403 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
404 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
412 modest_platform_information_banner (gtk_widget_get_parent (GTK_WIDGET (dialog)),
413 NULL, _CS_FOLDER_ALREADY_EXISTS);
414 /* Select the text */
415 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
416 gtk_widget_grab_focus (entry);
417 /* Do not close the dialog */
418 g_signal_stop_emission_by_name (dialog, "response");
422 typedef struct _FolderChooserData {
423 TnyFolderStore *store;
428 folder_chooser_activated (ModestFolderView *folder_view,
429 TnyFolderStore *folder,
430 FolderChooserData *userdata)
432 userdata->store = folder;
433 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
436 static TnyFolderStore *
437 folder_chooser_dialog_run (ModestFolderView *original,
438 TnyFolderStore *current,
441 GtkWidget *folder_view;
442 FolderChooserData userdata = {NULL, NULL};
443 GtkWidget *scrollable;
444 const gchar *visible_id = NULL;
446 userdata.dialog = gtk_dialog_new ();
448 gtk_widget_set_size_request (GTK_WIDGET (userdata.dialog),
449 MODEST_DIALOG_WINDOW_MAX_WIDTH,
450 MODEST_DIALOG_WINDOW_MAX_HEIGHT);
452 gtk_dialog_add_button (GTK_DIALOG (userdata.dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
454 scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
455 folder_view = modest_platform_create_folder_view (NULL);
457 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM_CHANGE_FOLDER);
459 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
460 MODEST_FOLDER_VIEW (folder_view));
462 if (TNY_IS_ACCOUNT (current)) {
463 /* Local folders and MMC account are always shown
464 along with the currently visible server account */
465 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (current)) ||
466 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (current)))
467 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
469 visible_id = tny_account_get_id (TNY_ACCOUNT (current));
470 } else if (TNY_IS_FOLDER (current)) {
472 account = modest_tny_folder_get_account ((TnyFolder *) current);
474 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (account)) ||
475 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (account))) {
476 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
478 visible_id = tny_account_get_id (account);
480 g_object_unref (account);
484 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
487 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
490 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), scrollable);
491 gtk_container_add (GTK_CONTAINER (scrollable), folder_view);
492 gtk_widget_set_size_request (scrollable, -1, 320);
494 gtk_widget_show (folder_view);
495 gtk_widget_show (scrollable);
496 gtk_widget_show (userdata.dialog);
497 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
498 G_CALLBACK (folder_chooser_activated),
499 (gpointer) &userdata);
501 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
502 gtk_widget_destroy (userdata.dialog);
504 return userdata.store;
508 folder_store_get_display_name (TnyFolderStore *store)
510 if (TNY_IS_ACCOUNT (store)) {
511 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
512 return modest_conf_get_string (modest_runtime_get_conf(),
513 MODEST_CONF_DEVICE_NAME, NULL);
515 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
518 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
520 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
521 type = tny_folder_get_folder_type (TNY_FOLDER (store));
522 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
523 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
524 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
525 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
527 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
530 /* Sometimes an special folder is reported by the server as
531 NORMAL, like some versions of Dovecot */
532 if (type == TNY_FOLDER_TYPE_NORMAL ||
533 type == TNY_FOLDER_TYPE_UNKNOWN) {
534 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
538 if (type == TNY_FOLDER_TYPE_INBOX) {
540 fname = g_strdup (_("mcen_me_folder_inbox"));
547 get_image_for_folder_store (TnyFolderStore *store,
551 const gchar *icon_name = NULL;
552 GtkWidget *image = NULL;
554 if (TNY_IS_ACCOUNT (store)) {
555 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
556 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
557 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
558 icon_name = MODEST_FOLDER_ICON_MMC;
560 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
562 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
563 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
565 case TNY_FOLDER_TYPE_INBOX:
566 icon_name = MODEST_FOLDER_ICON_INBOX;
569 icon_name = MODEST_FOLDER_ICON_REMOTE_FOLDER;
571 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
573 case TNY_FOLDER_TYPE_OUTBOX:
574 icon_name = MODEST_FOLDER_ICON_OUTBOX;
576 case TNY_FOLDER_TYPE_DRAFTS:
577 icon_name = MODEST_FOLDER_ICON_DRAFTS;
579 case TNY_FOLDER_TYPE_SENT:
580 icon_name = MODEST_FOLDER_ICON_SENT;
583 icon_name = MODEST_FOLDER_ICON_NORMAL;
585 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
586 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
591 pixbuf = modest_platform_get_icon (icon_name, size);
594 image = gtk_image_new_from_pixbuf (pixbuf);
595 g_object_unref (pixbuf);
602 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
607 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
611 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
612 g_object_ref (store),
613 (GDestroyNotify) g_object_unref);
614 name = folder_store_get_display_name (store);
615 gtk_button_set_label (GTK_BUTTON (button), name);
619 image = get_image_for_folder_store (store, MODEST_ICON_SIZE_SMALL);
621 gtk_button_set_image (GTK_BUTTON (button), image);
625 /* Always returns DUPs so you must free the returned value */
627 get_next_folder_name (const gchar *suggested_name,
628 TnyFolderStore *suggested_folder)
630 const gchar *default_name = _FM_NEW_FOLDER_NAME_STUB;
632 gchar *real_suggested_name;
634 if (suggested_name !=NULL) {
635 return g_strdup (suggested_name);
638 for(i = 0; i < 100; ++ i) {
639 gboolean exists = FALSE;
642 real_suggested_name = g_strdup (default_name);
644 real_suggested_name = g_strdup_printf ("%s(%d)",
645 _FM_NEW_FOLDER_NAME_STUB,
647 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
654 g_free (real_suggested_name);
657 /* Didn't find a free number */
659 real_suggested_name = g_strdup (default_name);
661 return real_suggested_name;
665 ModestFolderView *folder_view;
667 } FolderPickerHelper;
670 folder_picker_clicked (GtkButton *button,
671 FolderPickerHelper *helper)
673 TnyFolderStore *store, *current;
675 current = g_object_get_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER);
677 store = folder_chooser_dialog_run (helper->folder_view, current, button);
679 const gchar *current_name;
680 gboolean exists = FALSE;
682 folder_picker_set_store (GTK_BUTTON (button), store);
684 /* Update the name of the folder */
685 current_name = gtk_entry_get_text (helper->entry);
687 if (TNY_IS_FOLDER_STORE (store))
688 exists = modest_tny_folder_has_subfolder_with_name (store,
692 gchar *new_name = get_next_folder_name (NULL, store);
693 gtk_entry_set_text (helper->entry, new_name);
700 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
703 const gchar *acc_id = NULL;
705 button = gtk_button_new ();
707 gtk_misc_set_alignment (GTK_MISC (button), 0.0, 0.5);
711 folder_picker_set_store (GTK_BUTTON (button), suggested);
713 if (TNY_IS_ACCOUNT (suggested)) {
714 if (!modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (suggested)) &&
715 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (suggested)))
716 acc_id = tny_account_get_id ((TnyAccount *) suggested);
718 TnyAccount *account = modest_tny_folder_get_account ((TnyFolder *) suggested);
720 acc_id = tny_account_get_id ((TnyAccount *) account);
721 g_object_unref (account);
727 acc_id = modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(helper->folder_view));
729 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_ORIGINAL_ACCOUNT,
730 g_strdup (acc_id), (GDestroyNotify) g_free);
733 g_signal_connect (G_OBJECT (button), "clicked",
734 G_CALLBACK (folder_picker_clicked),
742 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
743 TnyFolderStore *suggested_parent,
744 const gchar *dialog_title,
745 const gchar *label_text,
746 const gchar *suggested_name,
748 gboolean show_parent,
750 TnyFolderStore **parent)
752 GtkWidget *accept_btn = NULL;
753 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
754 GtkWidget *account_picker = NULL;
755 GList *buttons = NULL;
757 GtkSizeGroup *sizegroup;
758 ModestFolderView *folder_view;
759 ModestWindow *folder_window;
760 ModestWindowMgr *window_mgr;
761 FolderPickerHelper *helper = NULL;
762 GtkWidget *top_vbox, *top_align;
764 window_mgr = modest_runtime_get_window_mgr ();
765 folder_window = modest_window_mgr_get_folder_window (window_mgr);
766 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
768 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
770 top_vbox = gtk_vbox_new (FALSE, 0);
771 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
772 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
774 /* Ask the user for the folder name */
775 dialog = gtk_dialog_new_with_buttons (dialog_title,
777 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
780 _FM_NEW_FOLDER_DIALOG_OK,
784 /* Add accept button (with unsensitive handler) */
785 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
786 accept_btn = GTK_WIDGET (buttons->data);
788 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
791 label_entry = gtk_label_new (label_text);
792 entry = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
793 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
795 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
796 gtk_size_group_add_widget (sizegroup, label_entry);
799 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
801 gtk_entry_set_text (GTK_ENTRY (entry), _FM_NEW_FOLDER_NAME_STUB);
802 gtk_entry_set_width_chars (GTK_ENTRY (entry),
803 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
804 g_utf8_strlen (_FM_NEW_FOLDER_NAME_STUB, -1)));
805 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
810 label_location = gtk_label_new (_FM_NEW_FOLDER_LOCATION);
812 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
813 gtk_size_group_add_widget (sizegroup, label_location);
815 helper = g_slice_new0 (FolderPickerHelper);
816 helper->folder_view = folder_view;
817 helper->entry = (GtkEntry *) entry;
819 account_picker = folder_picker_new (suggested_parent, helper);
822 g_object_unref (sizegroup);
824 /* Connect to the response method to avoid closing the dialog
825 when an invalid name is selected*/
826 g_signal_connect (dialog,
828 G_CALLBACK (on_response),
832 /* Track entry changes */
833 g_signal_connect (entry,
835 G_CALLBACK (entry_insert_text),
837 g_signal_connect (entry,
839 G_CALLBACK (entry_changed),
844 /* Some locales like pt_BR need this to get the full window
846 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
848 /* Create the hbox */
850 hbox = gtk_hbox_new (FALSE, 12);
851 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
852 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
854 /* Add hbox to dialog */
855 gtk_box_pack_start (GTK_BOX (top_vbox),
856 hbox, FALSE, FALSE, 0);
857 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
861 hbox = gtk_hbox_new (FALSE, 12);
862 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
863 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
865 /* Add hbox to dialog */
866 gtk_box_pack_start (GTK_BOX (top_vbox),
867 hbox, FALSE, FALSE, 0);
868 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
870 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
871 GTK_WINDOW (dialog), parent_window);
873 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
874 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
876 gtk_widget_show_all (GTK_WIDGET(dialog));
878 result = gtk_dialog_run (GTK_DIALOG(dialog));
879 if (result == GTK_RESPONSE_ACCEPT) {
881 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
883 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
885 g_object_ref (*parent);
889 gtk_widget_destroy (dialog);
892 g_slice_free (FolderPickerHelper, helper);
894 while (gtk_events_pending ())
895 gtk_main_iteration ();
901 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
902 TnyFolderStore *suggested_folder,
903 gchar *suggested_name,
905 TnyFolderStore **parent_folder)
907 gchar *real_suggested_name = NULL;
909 ModestTnyAccountStore *acc_store;
911 gboolean do_free = FALSE;
913 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
916 /* In hildon 2.2 we always suggest the archive folder as parent */
917 if (!suggested_folder) {
918 acc_store = modest_runtime_get_account_store ();
919 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
921 suggested_folder = (TnyFolderStore *)
922 modest_tny_account_get_special_folder (account,
923 TNY_FOLDER_TYPE_ARCHIVE);
924 g_object_unref (account);
929 /* If there is not archive folder then fallback to local folders account */
930 if (!suggested_folder) {
932 suggested_folder = (TnyFolderStore *)
933 modest_tny_account_store_get_local_folders_account (acc_store);
936 result = modest_platform_run_folder_common_dialog (parent_window,
938 _HL_TITLE_NEW_FOLDER,
947 g_object_unref (suggested_folder);
949 g_free(real_suggested_name);
955 modest_platform_run_rename_folder_dialog (ModestWindow *parent_window,
956 TnyFolderStore *parent_folder,
957 const gchar *suggested_name,
962 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
964 toplevel = (GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (parent_window));
965 return modest_platform_run_folder_common_dialog (toplevel,
967 _HL_TITLE_RENAME_FOLDER,
979 on_destroy_dialog (GtkWidget *dialog)
981 /* This could happen when the dialogs get programatically
982 hidden or destroyed (for example when closing the
983 application while a dialog is being shown) */
984 if (!GTK_IS_WIDGET (dialog))
987 gtk_widget_destroy (dialog);
989 if (gtk_events_pending ())
990 gtk_main_iteration ();
994 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
995 const gchar *message)
1000 dialog = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1001 GTK_MESSAGE_QUESTION,
1002 GTK_BUTTONS_OK_CANCEL,
1004 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1005 GTK_WINDOW (dialog), parent_window);
1007 response = gtk_dialog_run (GTK_DIALOG (dialog));
1009 on_destroy_dialog (dialog);
1015 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1016 const gchar *message,
1017 const gchar *button_accept,
1018 const gchar *button_cancel)
1023 dialog = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1024 GTK_MESSAGE_QUESTION,
1027 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
1028 button_accept, GTK_RESPONSE_ACCEPT,
1029 button_cancel, GTK_RESPONSE_CANCEL,
1032 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1033 GTK_WINDOW (dialog), parent_window);
1035 response = gtk_dialog_run (GTK_DIALOG (dialog));
1037 on_destroy_dialog (dialog);
1043 modest_platform_run_information_dialog (GtkWindow *parent_window,
1044 const gchar *message,
1049 note = gtk_message_dialog_new (parent_window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1054 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1055 GTK_WINDOW (note), parent_window);
1058 gtk_dialog_run (GTK_DIALOG (note));
1060 on_destroy_dialog (note);
1062 g_signal_connect_swapped (note,
1064 G_CALLBACK (on_destroy_dialog),
1067 gtk_widget_show_all (note);
1071 typedef struct _ConnectAndWaitData {
1073 GMainLoop *wait_loop;
1074 gboolean has_callback;
1076 } ConnectAndWaitData;
1080 modest_platform_connect_and_wait (GtkWindow *parent_window,
1081 TnyAccount *account)
1083 gboolean device_online;
1085 TnyConnectionStatus conn_status;
1086 gboolean user_requested;
1088 device = modest_runtime_get_device();
1089 device_online = tny_device_is_online (device);
1091 /* Whether the connection is user requested or automatically
1092 requested, for example via D-Bus */
1093 user_requested = (parent_window) ? TRUE : FALSE;
1095 /* If there is no account check only the device status */
1100 /* TODO: should show connection dialog through gnome device */
1104 /* Return if the account is already connected */
1105 conn_status = tny_account_get_connection_status (account);
1106 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1113 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1115 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1116 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1117 /* This must be a maildir account, which does not require a connection: */
1122 return modest_platform_connect_and_wait (parent_window, account);
1126 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1129 return TRUE; /* Maybe it is something local. */
1131 gboolean result = TRUE;
1132 if (TNY_IS_FOLDER (folder_store)) {
1133 /* Get the folder's parent account: */
1134 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1135 if (account != NULL) {
1136 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1137 g_object_unref (account);
1139 } else if (TNY_IS_ACCOUNT (folder_store)) {
1140 /* Use the folder store as an account: */
1141 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1148 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1156 modest_platform_set_update_interval (guint minutes)
1162 modest_platform_push_email_notification(void)
1168 modest_platform_on_new_headers_received (GList *URI_list,
1169 gboolean show_visual)
1175 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1183 modest_platform_get_global_settings_dialog ()
1185 return modest_default_global_settings_dialog_new ();
1189 modest_platform_show_help (GtkWindow *parent_window,
1190 const gchar *help_id)
1196 modest_platform_show_search_messages (GtkWindow *parent_window)
1202 modest_platform_show_addressbook (GtkWindow *parent_window)
1208 modest_platform_create_folder_view_full (TnyFolderStoreQuery *query, gboolean do_refresh)
1210 GtkWidget *widget = modest_folder_view_new_full (query, do_refresh);
1212 /* Show one account by default */
1213 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1214 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1220 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1222 return modest_platform_create_folder_view_full (query, TRUE);
1226 banner_finish (gpointer data, GObject *object)
1228 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1229 modest_window_mgr_unregister_banner (mgr);
1230 g_object_unref (mgr);
1234 modest_platform_information_banner (GtkWidget *parent,
1235 const gchar *icon_name,
1240 banner = modest_shell_banner_new (parent);
1241 modest_shell_banner_set_icon (MODEST_SHELL_BANNER (banner), icon_name);
1242 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1248 modest_platform_system_banner (GtkWidget *parent,
1249 const gchar *icon_name,
1252 modest_platform_information_banner (parent, icon_name, text);
1256 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1257 const gchar *icon_name,
1263 banner = modest_shell_banner_new_with_timeout (parent, timeout);
1264 modest_shell_banner_set_icon (MODEST_SHELL_BANNER (banner), icon_name);
1265 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1271 modest_platform_animation_banner (GtkWidget *parent,
1272 const gchar *animation_name,
1277 banner = modest_shell_banner_new_with_timeout (parent, 0);
1278 modest_shell_banner_set_animation (MODEST_SHELL_BANNER (banner), animation_name);
1279 modest_shell_banner_set_text (MODEST_SHELL_BANNER (banner), text);
1287 TnyAccount *account;
1290 } CheckAccountIdleData;
1292 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1295 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1297 gboolean stop_trying = FALSE;
1298 g_return_val_if_fail (data && data->account, FALSE);
1300 if (data && data->account &&
1301 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1302 * after which the account is likely to be usable, or never likely to be usable soon: */
1303 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1305 data->is_online = TRUE;
1309 /* Give up if we have tried too many times: */
1310 if (data->count_tries >= NUMBER_OF_TRIES) {
1313 /* Wait for another timeout: */
1314 ++(data->count_tries);
1319 /* Allow the function that requested this idle callback to continue: */
1321 g_main_loop_quit (data->loop);
1324 g_object_unref (data->account);
1326 return FALSE; /* Don't call this again. */
1328 return TRUE; /* Call this timeout callback again. */
1332 /* Return TRUE immediately if the account is already online,
1333 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1334 * soon as the account is online, or FALSE if the account does
1335 * not become online in the NUMBER_OF_TRIES seconds.
1336 * This is useful when the D-Bus method was run immediately after
1337 * the application was started (when using D-Bus activation),
1338 * because the account usually takes a short time to go online.
1339 * The return value is maybe not very useful.
1342 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1346 g_return_val_if_fail (account, FALSE);
1348 if (!tny_device_is_online (modest_runtime_get_device())) {
1349 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1353 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1354 * so we avoid wait unnecessarily: */
1355 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1358 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1359 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1360 * we want to avoid. */
1361 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1364 /* This blocks on the result: */
1365 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1366 data->is_online = FALSE;
1367 data->account = account;
1368 g_object_ref (data->account);
1369 data->count_tries = 0;
1371 GMainContext *context = NULL; /* g_main_context_new (); */
1372 data->loop = g_main_loop_new (context, FALSE /* not running */);
1374 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1376 /* This main loop will run until the idle handler has stopped it: */
1377 g_main_loop_run (data->loop);
1379 g_main_loop_unref (data->loop);
1380 /* g_main_context_unref (context); */
1382 is_online = data->is_online;
1383 g_slice_free (CheckAccountIdleData, data);
1391 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1393 /* GTK_RESPONSE_HELP means we need to show the certificate */
1394 if (response_id == GTK_RESPONSE_APPLY) {
1397 /* Do not close the dialog */
1398 g_signal_stop_emission_by_name (dialog, "response");
1400 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1401 modest_platform_run_information_dialog (NULL, msg, TRUE);
1407 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1408 const gchar *certificate)
1414 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1417 /* We use GTK_RESPONSE_APPLY because we want the button in the
1418 middle of OK and CANCEL the same as the browser does for
1419 example. With GTK_RESPONSE_HELP the view button is aligned
1420 to the left while the other two to the right */
1421 note = gtk_message_dialog_new (
1423 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1424 GTK_MESSAGE_QUESTION,
1427 gtk_dialog_add_buttons (GTK_DIALOG (note),
1428 _HL_YES, GTK_RESPONSE_OK,
1429 _HL_VIEW, GTK_RESPONSE_APPLY, /* abusing this... */
1430 _HL_NO, GTK_RESPONSE_CANCEL,
1433 g_signal_connect (G_OBJECT(note), "response",
1434 G_CALLBACK(on_cert_dialog_response),
1435 (gpointer) certificate);
1437 response = gtk_dialog_run(GTK_DIALOG(note));
1439 on_destroy_dialog (note);
1442 return response == GTK_RESPONSE_OK;
1446 modest_platform_run_alert_dialog (const gchar* prompt,
1447 gboolean is_question)
1450 gboolean retval = TRUE;
1453 /* The Tinymail documentation says that we should show Yes and No buttons,
1454 * when it is a question.
1455 * Obviously, we need tinymail to use more specific error codes instead,
1456 * so we know what buttons to show. */
1457 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1458 GTK_MESSAGE_QUESTION,
1462 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1463 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1465 on_destroy_dialog (dialog);
1467 /* Just show the error text and use the default response: */
1468 modest_platform_run_information_dialog (NULL,
1476 ModestWindow *parent_window;
1477 ModestConnectedPerformer callback;
1478 TnyAccount *account;
1485 on_went_online_info_free (OnWentOnlineInfo *info)
1487 /* And if we cleanup, we DO cleanup :-) */
1490 g_object_unref (info->device);
1493 if (info->parent_window)
1494 g_object_unref (info->parent_window);
1496 g_object_unref (info->account);
1498 g_slice_free (OnWentOnlineInfo, info);
1500 /* We're done ... */
1506 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1508 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1510 /* Now it's really time to callback to the caller. If going online didn't succeed,
1511 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1512 * canceled will be set. Etcetera etcetera. */
1514 if (info->callback) {
1515 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1518 /* This is our last call, we must cleanup here if we didn't yet do that */
1519 on_went_online_info_free (info);
1525 modest_platform_connect_and_perform (ModestWindow *parent_window,
1527 TnyAccount *account,
1528 ModestConnectedPerformer callback,
1531 gboolean device_online;
1533 TnyConnectionStatus conn_status;
1535 device = modest_runtime_get_device();
1536 device_online = tny_device_is_online (device);
1538 /* If there is no account check only the device status */
1541 if (device_online) {
1543 /* We promise to instantly perform the callback, so ... */
1545 callback (FALSE, NULL, parent_window, account, user_data);
1552 /* The other code has no more reason to run. This is all that we can do for the
1553 * caller (he should have given us a nice and clean account instance!). We
1554 * can't do magic, we don't know what account he intends to bring online. So
1555 * we'll just bring the device online (and await his false bug report). */
1561 /* Return if the account is already connected */
1563 conn_status = tny_account_get_connection_status (account);
1564 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
1566 /* We promise to instantly perform the callback, so ... */
1568 callback (FALSE, NULL, parent_window, account, user_data);
1574 if (!device_online) {
1575 OnWentOnlineInfo *info = NULL;
1577 info = g_slice_new0 (OnWentOnlineInfo);
1579 info->device = NULL;
1581 info->account = TNY_ACCOUNT (g_object_ref (account));
1584 info->parent_window = (ModestWindow *) g_object_ref (parent_window);
1586 info->parent_window = NULL;
1588 /* So we'll put the callback away for later ... */
1589 info->user_data = user_data;
1590 info->callback = callback;
1592 /* If the device is online, we'll just connect the account */
1593 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1594 on_account_went_online, info);
1597 /* The info gets freed by on_account_went_online or on_conic_device_went_online
1598 * in both situations, go look if you don't believe me! */
1602 modest_platform_connect_if_remote_and_perform (ModestWindow *parent_window,
1604 TnyFolderStore *folder_store,
1605 ModestConnectedPerformer callback,
1608 TnyAccount *account = NULL;
1610 if (!folder_store ||
1611 (TNY_IS_MERGE_FOLDER (folder_store) &&
1612 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
1614 /* We promise to instantly perform the callback, so ... */
1616 GError *error = NULL;
1617 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
1618 "Unable to move or not found folder");
1619 callback (FALSE, error, parent_window, NULL, user_data);
1620 g_error_free (error);
1624 } else if (TNY_IS_FOLDER (folder_store)) {
1625 /* Get the folder's parent account: */
1626 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1627 } else if (TNY_IS_ACCOUNT (folder_store)) {
1628 /* Use the folder store as an account: */
1629 account = TNY_ACCOUNT (g_object_ref (folder_store));
1632 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
1633 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1634 /* No need to connect a local account */
1636 callback (FALSE, NULL, parent_window, account, user_data);
1641 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
1645 g_object_unref (account);
1649 src_account_connect_performer (gboolean canceled,
1651 ModestWindow *parent_window,
1652 TnyAccount *src_account,
1655 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
1657 if (canceled || err) {
1658 /* If there was any error call the user callback */
1659 info->callback (canceled, err, parent_window, src_account, info->data);
1661 /* Connect the destination account */
1662 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
1663 TNY_FOLDER_STORE (info->dst_account),
1664 info->callback, info->data);
1667 /* Free the info object */
1668 g_object_unref (info->dst_account);
1669 g_slice_free (DoubleConnectionInfo, info);
1674 modest_platform_double_connect_and_perform (ModestWindow *parent_window,
1676 TnyFolderStore *folder_store,
1677 DoubleConnectionInfo *connect_info)
1679 modest_platform_connect_if_remote_and_perform(parent_window,
1682 src_account_connect_performer,
1687 modest_platform_get_account_settings_wizard (void)
1689 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
1691 return GTK_WIDGET (dialog);
1695 modest_platform_get_current_connection (void)
1697 TnyDevice *device = NULL;
1698 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
1700 device = modest_runtime_get_device ();
1702 if (!tny_device_is_online (device))
1703 return MODEST_CONNECTED_VIA_ANY;
1705 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
1712 modest_platform_check_memory_low (ModestWindow *win,
1720 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
1726 dialog = modest_toolkit_factory_create_details_dialog_with_folder (modest_runtime_get_toolkit_factory (),
1727 parent_window, folder);
1730 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1731 GTK_WINDOW (dialog),
1733 gtk_widget_show_all (dialog);
1735 g_signal_connect_swapped (dialog, "response",
1736 G_CALLBACK (gtk_widget_destroy),
1740 typedef struct _HeaderDetailsGetSizeInfo {
1744 } HeaderDetailsGetSizeInfo;
1747 header_details_dialog_destroy (gpointer userdata,
1750 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1752 info->dialog = NULL;
1756 idle_get_mime_part_size_cb (gpointer userdata)
1758 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
1759 gdk_threads_enter ();
1761 if (info->dialog && GTK_WIDGET_VISIBLE (info->dialog)) {
1762 modest_details_dialog_set_message_size (MODEST_DETAILS_DIALOG (info->dialog),
1767 g_object_weak_unref (G_OBJECT (info->dialog), header_details_dialog_destroy, info);
1768 info->dialog = NULL;
1770 g_object_unref (info->part);
1771 g_slice_free (HeaderDetailsGetSizeInfo, info);
1773 gdk_threads_leave ();
1779 get_mime_part_size_thread (gpointer thr_user_data)
1781 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) thr_user_data;
1783 TnyStream *count_stream;
1785 count_stream = modest_count_stream_new ();
1786 result = tny_mime_part_decode_to_stream (info->part, count_stream, NULL);
1787 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1788 if (info->total == 0) {
1789 modest_count_stream_reset_count(MODEST_COUNT_STREAM (count_stream));
1790 result = tny_mime_part_write_to_stream (info->part, count_stream, NULL);
1791 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
1794 /* if there was an error, don't set the size (this is pretty uncommon) */
1796 g_warning ("%s: error while writing mime part to stream\n", __FUNCTION__);
1798 g_idle_add (idle_get_mime_part_size_cb, info);
1804 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
1806 gboolean async_get_size,
1812 dialog = modest_toolkit_factory_create_details_dialog_with_header (modest_runtime_get_toolkit_factory (),
1813 parent_window, header, !async_get_size);
1815 if (async_get_size && msg && TNY_IS_MSG (msg)) {
1816 HeaderDetailsGetSizeInfo *info;
1817 info = g_slice_new (HeaderDetailsGetSizeInfo);
1818 info->dialog = dialog;
1820 info->part = TNY_MIME_PART (g_object_ref (msg));
1822 g_object_weak_ref (G_OBJECT (dialog), header_details_dialog_destroy, info);
1823 g_thread_create (get_mime_part_size_thread, info, FALSE, NULL);
1827 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1828 GTK_WINDOW (dialog),
1830 gtk_widget_show_all (dialog);
1832 g_signal_connect_swapped (dialog, "response",
1833 G_CALLBACK (gtk_widget_destroy),
1837 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
1838 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
1839 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
1840 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
1841 #define MOVE_TO_DIALOG_SCROLLABLE "scrollable"
1842 #define MOVE_TO_FOLDER_SEPARATOR "/"
1845 translate_path (gchar **path)
1850 gboolean add_separator;
1852 parts = g_strsplit (*path, MOVE_TO_FOLDER_SEPARATOR, 0);
1856 output = g_string_new ("");
1857 add_separator = FALSE;
1859 while (*current != NULL) {
1860 TnyFolderType folder_type;
1863 if (add_separator) {
1864 output = g_string_append (output, MOVE_TO_FOLDER_SEPARATOR);
1866 add_separator = TRUE;
1869 downcase = g_ascii_strdown (*current, -1);
1870 folder_type = modest_local_folder_info_get_type (downcase);
1871 if (strcmp (downcase, "inbox") == 0) {
1872 output = g_string_append (output, _("mcen_me_folder_inbox"));
1873 } else if (folder_type == TNY_FOLDER_TYPE_ARCHIVE ||
1874 folder_type == TNY_FOLDER_TYPE_DRAFTS ||
1875 folder_type == TNY_FOLDER_TYPE_SENT ||
1876 folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1877 output = g_string_append (output, modest_local_folder_info_get_type_display_name (folder_type));
1879 output = g_string_append (output, *current);
1887 *path = g_string_free (output, FALSE);
1891 move_to_dialog_set_selected_folder_store (GtkWidget *dialog,
1892 TnyFolderStore *folder_store)
1894 GtkWidget *action_button;
1895 GtkWidget *image = NULL;
1896 TnyAccount *account;
1897 gchar *account_name = NULL, *short_name = NULL;
1899 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1901 /* Get account name */
1902 if (TNY_IS_FOLDER (folder_store))
1903 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1905 account = g_object_ref (folder_store);
1907 if (modest_tny_account_is_virtual_local_folders (account))
1908 account_name = modest_conf_get_string (modest_runtime_get_conf(),
1909 MODEST_CONF_DEVICE_NAME, NULL);
1912 account_name = g_strdup (tny_account_get_name (account));
1914 g_object_unref (account);
1916 /* Set title of button: account or folder name */
1917 if (TNY_IS_FOLDER (folder_store))
1918 short_name = folder_store_get_display_name (folder_store);
1920 short_name = g_strdup (account_name);
1922 gtk_button_set_label (GTK_BUTTON (action_button), short_name);
1924 /* Set value of button, folder full name */
1925 if (TNY_IS_CAMEL_FOLDER (folder_store)) {
1926 const gchar *camel_full_name;
1927 gchar *last_slash, *full_name;
1929 camel_full_name = tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store));
1930 last_slash = g_strrstr (camel_full_name, "/");
1932 gchar *prefix = g_strndup (camel_full_name, last_slash - camel_full_name + 1);
1933 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR, prefix, short_name, NULL);
1936 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR,
1940 translate_path (&full_name);
1941 gtk_button_set_label (GTK_BUTTON (action_button), full_name);
1944 g_free (account_name);
1945 g_free (short_name);
1947 /* Set image for the button */
1948 image = get_image_for_folder_store (folder_store, MODEST_ICON_SIZE_BIG);
1950 gtk_button_set_image (GTK_BUTTON (action_button), image);
1954 move_to_dialog_show_accounts (GtkWidget *dialog)
1956 GtkWidget *back_button;
1957 GtkWidget *folder_view;
1958 GtkWidget *scrollable;
1959 GtkWidget *action_button;
1961 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
1962 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
1963 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
1964 scrollable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
1966 gtk_widget_set_sensitive (back_button, FALSE);
1967 gtk_widget_set_sensitive (action_button, FALSE);
1969 /* Need to set this here, otherwise callbacks called because
1970 of filtering won't perform correctly */
1971 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
1973 /* Reset action button */
1974 gtk_button_set_label (GTK_BUTTON (action_button), NULL);
1975 gtk_button_set_image (GTK_BUTTON (action_button), NULL);
1977 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
1978 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
1979 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
1980 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1981 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
1982 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1983 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
1984 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
1985 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
1986 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
1987 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
1988 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
1992 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
1994 GtkWidget *back_button;
1995 GtkWidget *folder_view;
1996 TnyAccount *account;
1997 const gchar *account_id;
1998 GtkWidget *scrollable;
1999 GtkWidget *action_button;
2002 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2004 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2006 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2008 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE));
2010 gtk_widget_set_sensitive (back_button, TRUE);
2011 gtk_widget_set_sensitive (action_button, TRUE);
2013 /* Need to set this here, otherwise callbacks called because
2014 of filtering won't perform correctly */
2015 g_object_set_data (G_OBJECT (dialog),
2016 MOVE_TO_DIALOG_SHOWING_FOLDERS,
2017 GINT_TO_POINTER (TRUE));
2019 account = TNY_ACCOUNT (folder_store);
2020 if (modest_tny_account_is_virtual_local_folders (account)) {
2021 account_id = tny_account_get_id (account);
2022 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2023 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2024 } else if (modest_tny_account_is_memory_card_account (account)) {
2025 account_id = tny_account_get_id (account);
2026 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2027 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2029 account_id = tny_account_get_id (account);
2030 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2031 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2032 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2033 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2036 move_to_dialog_set_selected_folder_store (dialog, folder_store);
2037 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2040 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2041 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2042 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2043 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2044 modest_scrollable_jump_to (MODEST_SCROLLABLE (scrollable), 0, 0);
2048 on_move_to_dialog_back_clicked (GtkButton *button,
2051 GtkWidget *dialog = (GtkWidget *) userdata;
2053 /* Back to show accounts */
2054 move_to_dialog_show_accounts (dialog);
2058 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
2060 GtkTreeViewColumn *column,
2063 TnyFolderStore *selected = NULL;
2065 GtkWidget *folder_view;
2066 gboolean showing_folders;
2068 dialog = (GtkWidget *) user_data;
2069 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
2070 MOVE_TO_DIALOG_SHOWING_FOLDERS));
2072 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
2073 MOVE_TO_DIALOG_FOLDER_VIEW));
2075 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2079 if (!showing_folders) {
2080 gboolean valid = TRUE;
2082 if (TNY_IS_ACCOUNT (selected) &&
2083 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2084 ModestProtocolType protocol_type;
2086 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2087 valid = !modest_protocol_registry_protocol_type_has_tag
2088 (modest_runtime_get_protocol_registry (),
2090 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
2093 move_to_dialog_show_folders (dialog, selected);
2095 move_to_dialog_set_selected_folder_store (dialog, selected);
2097 g_object_unref (selected);
2101 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2104 gboolean showing_folders;
2107 dialog = (GtkWidget *) user_data;
2108 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2109 if (showing_folders) {
2110 TnyFolderStore *selected;
2111 GtkWidget *folder_view;
2113 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2114 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2117 move_to_dialog_set_selected_folder_store (dialog, selected);
2118 g_object_unref (selected);
2124 on_move_to_dialog_action_clicked (GtkButton *selection,
2128 gboolean showing_folders;
2130 dialog = (GtkWidget *) user_data;
2131 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2132 if (showing_folders) {
2133 TnyFolderStore *selected;
2134 GtkWidget *folder_view;
2136 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2137 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2140 /* It's not possible to select root folders as
2141 targets unless they're the local account or
2142 the memory card account */
2143 if ((TNY_IS_FOLDER (selected) && !TNY_IS_MERGE_FOLDER (selected)) ||
2144 (TNY_IS_ACCOUNT (selected) &&
2145 (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (selected)) ||
2146 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (selected)))))
2147 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2148 g_object_unref (selected);
2154 move_to_dialog_activity_changed (ModestFolderView *folder_view, gboolean activity, GtkDialog *dialog)
2159 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2160 GtkWidget **folder_view)
2162 GtkWidget *dialog, *folder_view_container;
2164 GtkWidget *buttons_hbox;
2165 GtkWidget *back_button;
2166 GdkPixbuf *back_pixbuf;
2167 GtkWidget *top_vbox;
2168 GtkWidget *action_button;
2169 GtkTreeSelection *selection;
2171 /* Create dialog. We cannot use a touch selector because we
2172 need to use here the folder view widget directly */
2173 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2174 GTK_WINDOW (parent_window),
2175 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2176 GTK_DIALOG_DESTROY_WITH_PARENT,
2177 _FM_CHANGE_FOLDER_NEW_FOLDER,
2178 MODEST_GTK_RESPONSE_NEW_FOLDER,
2181 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2182 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2183 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2185 /* Create folder view */
2186 *folder_view = modest_platform_create_folder_view_full (NULL, FALSE);
2187 g_signal_connect (G_OBJECT (*folder_view), "activity-changed", G_CALLBACK (move_to_dialog_activity_changed),
2190 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2191 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2192 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2194 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2195 (TnyAccountStore *) modest_runtime_get_account_store ());
2197 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2198 back_button = gtk_button_new ();
2199 back_pixbuf = modest_platform_get_icon (_FM_FOLDER_UP, MODEST_ICON_SIZE_BIG);
2201 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2202 g_object_unref (back_pixbuf);
2205 action_button = gtk_button_new ();
2206 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
2208 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2209 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2210 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2211 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2212 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2214 /* Create scrollable and add it to the dialog */
2215 folder_view_container = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
2216 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2217 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2219 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2220 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2222 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2224 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2225 gtk_widget_show (folder_view_container);
2226 gtk_widget_show (align);
2227 gtk_widget_show (top_vbox);
2228 gtk_widget_show (*folder_view);
2229 gtk_widget_show_all (back_button);
2230 gtk_widget_show (action_button);
2231 gtk_widget_show (buttons_hbox);
2232 gtk_widget_show (dialog);
2234 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2235 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2236 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2237 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SCROLLABLE, folder_view_container);
2239 /* Simulate the behaviour of a HildonPickerDialog by emitting
2240 a response when a folder is selected */
2241 g_signal_connect (*folder_view, "row-activated",
2242 G_CALLBACK (on_move_to_dialog_row_activated),
2245 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2246 g_signal_connect (selection, "changed",
2247 G_CALLBACK (on_move_to_dialog_selection_changed),
2250 g_signal_connect (action_button, "clicked",
2251 G_CALLBACK (on_move_to_dialog_action_clicked),
2254 g_signal_connect (back_button, "clicked",
2255 G_CALLBACK (on_move_to_dialog_back_clicked),
2258 move_to_dialog_show_accounts (dialog);
2264 modest_platform_get_list_to_move (ModestWindow *window)
2266 TnyList *list = NULL;
2268 if (MODEST_IS_HEADER_WINDOW (window)) {
2269 ModestHeaderView *header_view;
2271 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2272 list = modest_header_view_get_selected_headers (header_view);
2273 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2274 ModestFolderView *folder_view;
2275 TnyFolderStore *selected_folder;
2277 list = TNY_LIST (tny_simple_list_new ());
2278 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2279 selected_folder = modest_folder_view_get_selected (folder_view);
2280 if (selected_folder) {
2281 tny_list_prepend (list, G_OBJECT (selected_folder));
2282 g_object_unref (selected_folder);
2285 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2288 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2290 list = TNY_LIST (tny_simple_list_new ());
2291 tny_list_prepend (list, G_OBJECT (header));
2292 g_object_unref (header);
2295 g_return_val_if_reached (NULL);