* Added hildon2 directory, with a copy of the contents of maemo
authorJose Dapena Paz <jdapena@igalia.com>
Tue, 30 Sep 2008 17:10:22 +0000 (17:10 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Tue, 30 Sep 2008 17:10:22 +0000 (17:10 +0000)
  directory.
* For hildon2, we removed the easysetup directory to have all the
  hildon2 ui in the same place.
* Modified libalarm, to use the new API in fremantle.

pmo-trunk-r5823

59 files changed:
configure.ac
libmodest-dbus-client/Makefile.am
src/Makefile.am
src/hildon2/Makefile.am [new file with mode: 0644]
src/hildon2/com.nokia.modest.service.in [new file with mode: 0644]
src/hildon2/maemo-provider-data.keyfile [new file with mode: 0644]
src/hildon2/mcc_mapping [new file with mode: 0644]
src/hildon2/mcc_mapping.en_GB [new file with mode: 0644]
src/hildon2/modest-account-view-window.c [new file with mode: 0644]
src/hildon2/modest-address-book.c [new file with mode: 0644]
src/hildon2/modest-connection-specific-smtp-edit-window.c [new file with mode: 0644]
src/hildon2/modest-connection-specific-smtp-edit-window.h [new file with mode: 0644]
src/hildon2/modest-connection-specific-smtp-window.c [new file with mode: 0644]
src/hildon2/modest-connection-specific-smtp-window.h [new file with mode: 0644]
src/hildon2/modest-default-account-settings-dialog.c [new file with mode: 0644]
src/hildon2/modest-easysetup-country-combo-box.c [new file with mode: 0644]
src/hildon2/modest-easysetup-country-combo-box.h [new file with mode: 0644]
src/hildon2/modest-easysetup-provider-combo-box.c [new file with mode: 0644]
src/hildon2/modest-easysetup-provider-combo-box.h [new file with mode: 0644]
src/hildon2/modest-easysetup-servertype-combo-box.c [new file with mode: 0644]
src/hildon2/modest-easysetup-servertype-combo-box.h [new file with mode: 0644]
src/hildon2/modest-easysetup-wizard-dialog.c [new file with mode: 0644]
src/hildon2/modest-easysetup-wizard-dialog.h [new file with mode: 0644]
src/hildon2/modest-hildon-includes.h [new file with mode: 0644]
src/hildon2/modest-hildon-sort-dialog.c [new file with mode: 0644]
src/hildon2/modest-hildon-sort-dialog.h [new file with mode: 0644]
src/hildon2/modest-icon-names.h [new file with mode: 0644]
src/hildon2/modest-maemo-global-settings-dialog.c [new file with mode: 0644]
src/hildon2/modest-maemo-global-settings-dialog.h [new file with mode: 0644]
src/hildon2/modest-maemo-security-options-view.c [new file with mode: 0644]
src/hildon2/modest-maemo-security-options-view.h [new file with mode: 0644]
src/hildon2/modest-maemo-utils.c [new file with mode: 0644]
src/hildon2/modest-maemo-utils.h [new file with mode: 0644]
src/hildon2/modest-main-window-ui-dimming.h [new file with mode: 0644]
src/hildon2/modest-main-window-ui.h [new file with mode: 0644]
src/hildon2/modest-main-window.c [new file with mode: 0644]
src/hildon2/modest-msg-edit-window-ui-dimming.h [new file with mode: 0644]
src/hildon2/modest-msg-edit-window.c [new file with mode: 0644]
src/hildon2/modest-msg-view-window-ui-dimming.h [new file with mode: 0644]
src/hildon2/modest-msg-view-window.c [new file with mode: 0644]
src/hildon2/modest-osso-autosave-callbacks.c [new file with mode: 0644]
src/hildon2/modest-osso-autosave-callbacks.h [new file with mode: 0644]
src/hildon2/modest-osso-state-saving.c [new file with mode: 0644]
src/hildon2/modest-osso-state-saving.h [new file with mode: 0644]
src/hildon2/modest-platform.c [new file with mode: 0644]
src/hildon2/modest-presets.c [new file with mode: 0644]
src/hildon2/modest-presets.h [new file with mode: 0644]
src/hildon2/modest-signature-editor-dialog.c [new file with mode: 0644]
src/hildon2/modest-signature-editor-dialog.h [new file with mode: 0644]
src/hildon2/modest.conf [new file with mode: 0644]
src/hildon2/modest.desktop.in [new file with mode: 0644]
src/hildon2/pixmaps/modest-icon.png [new file with mode: 0644]
src/hildon2/ui/modest-main-window-ui.xml [new file with mode: 0644]
src/hildon2/ui/modest-msg-edit-window-ui.xml [new file with mode: 0644]
src/hildon2/ui/modest-msg-view-window-ui.xml [new file with mode: 0644]
src/modest-ui-actions.c
src/widgets/Makefile.am
tests/Makefile.am
tests/dbus_api/Makefile.am

index cf443cd..8efe412 100644 (file)
@@ -247,7 +247,7 @@ else
    PKG_CHECK_MODULES(MODEST_TOOLKIT,$hildonpkgs)
    if test "$with_toolkit" = "hildon2"; then
       AC_DEFINE_UNQUOTED(MODEST_TOOLKIT_HILDON2, 1, ["Whether modest is being build for the hildon2 toolkit."])
-      MODEST_TOOLKIT_DIR=maemo
+      MODEST_TOOLKIT_DIR=hildon2
    else
       AC_DEFINE_UNQUOTED(MODEST_TOOLKIT_HILDON1, 1, ["Whether modest is being build for the hildon2 toolkit."])
       MODEST_TOOLKIT_DIR=maemo
@@ -296,15 +296,15 @@ fi
 # check libalarm
 #
 if test "x$with_platform" == "xmaemo"; then  
-PKG_CHECK_MODULES(MODEST_LIBALARM,libalarm,have_libalarm=true,have_libalarm=false)
-if test "x$have_libalarm" == "xtrue"; then
-   libalarm="libalarm" 
-   AC_DEFINE_UNQUOTED(MODEST_HAVE_LIBALARM, 1, ["Whether libalarm is used."])          
-   AC_SUBST(MODEST_LIBALARM_CFLAGS)
-   AC_SUBST(MODEST_LIBALARM_LIBS)
-else
-   libalarm=""
-fi
+   PKG_CHECK_MODULES(MODEST_LIBALARM,libalarm,have_libalarm=true,have_libalarm=false)
+   if test "x$have_libalarm" == "xfalse"; then
+      PKG_CHECK_MODULES(MODEST_LIBALARM, alarm, have_libalarm=true,have_libalarm=false)
+   fi
+   if test "x$have_libalarm" == "xtrue"; then
+      AC_DEFINE_UNQUOTED(MODEST_HAVE_LIBALARM, 1, ["Whether libalarm is used."])               
+      AC_SUBST(MODEST_LIBALARM_CFLAGS)
+      AC_SUBST(MODEST_LIBALARM_LIBS)
+   fi
 fi
 
 #
@@ -560,6 +560,7 @@ src/dbus_api/Makefile
 src/gnome/Makefile
 src/maemo/Makefile
 src/maemo/easysetup/Makefile
+src/hildon2/Makefile
 src/widgets/Makefile
 docs/Makefile
 docs/reference/Makefile
@@ -567,6 +568,8 @@ tests/Makefile
 tests/dbus_api/Makefile
 src/maemo/modest.desktop
 src/maemo/com.nokia.modest.service
+src/hildon2/modest.desktop
+src/hildon2/com.nokia.modest.service
 libmodest-dbus-client/Makefile
 libmodest-dbus-client/libmodest-dbus-client-1.0.pc
 ])
index 2fe3606..141bfc4 100644 (file)
@@ -31,7 +31,7 @@ INCLUDES=\
        $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \
        $(MODEST_LIBTINYMAIL_MAEMO_CFLAGS) \
        $(MODEST_PLATFORM_CFLAGS) \
-       -I$(MODEST_PLATFORM) \
+       -I$(MODEST_TOOLKIT_DIR) \
        -I$(top_srcdir)/src \
        -DPREFIX=\"@prefix@\" \
        -DMODEST_LOCALEDIR=\"$(MODEST_LOCALEDIR)\" \
index 379915e..993d1ba 100644 (file)
@@ -3,7 +3,7 @@
 # Time-stamp: <2008-01-06 10:18:49 (djcb)>
 
 SUBDIRS= $(MODEST_TOOLKIT_DIR) widgets $(dbus_api)
-DIST_SUBDIRS = widgets gnome maemo dbus_api
+DIST_SUBDIRS = widgets gnome maemo hildon2 dbus_api
 
 INCLUDES=\
        $(MODEST_GSTUFF_CFLAGS)                                 \
@@ -15,11 +15,12 @@ INCLUDES=\
        $(MODEST_HILDON_NOTIFY_CFLAGS)                          \
        $(MODEST_MOZEMBED_CFLAGS)                               \
        -fPIC \
-       -I$(MODEST_PLATFORM)                                    \
+       -I$(MODEST_TOOLKIT_DIR)                                 \
        -DPREFIX=\"@prefix@\"                                   \
        -DMAEMO_CHANGES                                         \
        -DMODEST_LOCALEDIR=\"$(MODEST_LOCALEDIR)\"              \
        -DMODEST_PLATFORM=\"$(MODEST_PLATFORM)\"                \
+       -DMODEST_TOOLKIT=\"$(MODEST_TOOLKIT)\"          \
        -DPIXMAP_PREFIX=\"${datadir}/pixmaps/modest/\"          \
        -DMODEST_UIDIR=\"$(datadir)/modest/ui/\"                \
        -DMODEST_MAILPLUGINDIR=\"$(libdir)/modest/mail-plugins\"
@@ -169,7 +170,7 @@ libmodest_la_LIBADD =                                               \
        $(MODEST_OGS_LIBS)                              \
        ${easysetupmaybe} \
        widgets/libmodest-widgets.la                    \
-       $(MODEST_PLATFORM)/libmodest-ui.la              
+       $(MODEST_TOOLKIT_DIR)/libmodest-ui.la           
 libmodest_la_LDFLAGS = -rdynamic -export-dynamic -no-undefined -Wl,--version-script=export.map
 
 if MODEST_HAVE_DBUS_API
diff --git a/src/hildon2/Makefile.am b/src/hildon2/Makefile.am
new file mode 100644 (file)
index 0000000..d35d0c4
--- /dev/null
@@ -0,0 +1,142 @@
+# Copyright (c) 2006,2007 Nokia Corporation
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# 
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# * Neither the name of the Nokia Corporation nor the names of its
+#   contributors may be used to endorse or promote products derived from
+#   this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+INCLUDES=\
+       $(MODEST_GSTUFF_CFLAGS)             \
+       $(MODEST_WPEDITOR_CFLAGS)           \
+       $(MODEST_PLATFORM_CFLAGS)           \
+       $(MODEST_TOOLKIT_CFLAGS)           \
+       $(MODEST_ABOOK_CFLAGS)              \
+       $(MODEST_HILDON_HELP_CFLAGS)        \
+       $(MODEST_LIBCONIC_CFLAGS)           \
+       $(MODEST_HILDON_MIME_CFLAGS)        \
+       $(MODEST_HILDON_NOTIFY_CFLAGS)      \
+       $(MODEST_LIBALARM_CFLAGS)           \
+       -I ${top_srcdir}/src/widgets        \
+       -I ${top_srcdir}/src                \
+       -DPREFIX=\"@prefix@\"               \
+       -DMAEMO_CHANGES                     \
+       -DPIXMAP_PREFIX=\"${datadir}/pixmaps/modest/\" \
+       -DMODEST_UIDIR=\""$(datadir)/modest/ui/"\" \
+       -Wall
+
+noinst_LTLIBRARIES=\
+       libmodest-ui.la
+
+libmodest_ui_la_SOURCES=              \
+       modest-account-view-window.c  \
+       modest-default-account-settings-dialog.c \
+       modest-easysetup-wizard-dialog.h modest-easysetup-wizard-dialog.c \
+       modest-easysetup-country-combo-box.h modest-easysetup-country-combo-box.c \
+       modest-easysetup-provider-combo-box.h modest-easysetup-provider-combo-box.c \
+       modest-easysetup-servertype-combo-box.h modest-easysetup-servertype-combo-box.c \
+       modest-icon-names.h           \
+       modest-maemo-global-settings-dialog.c \
+       modest-maemo-global-settings-dialog.h \
+       modest-maemo-security-options-view.c \
+       modest-main-window.c          \
+       modest-main-window-ui.h       \
+       modest-hildon-includes.h      \
+       modest-hildon-sort-dialog.c   \
+       modest-hildon-sort-dialog.h   \
+       modest-platform.c             \
+       modest-signature-editor-dialog.c         \
+       modest-signature-editor-dialog.h         \
+       modest-msg-view-window.c      \
+       modest-msg-edit-window.c      \
+       modest-maemo-utils.c          \
+       modest-connection-specific-smtp-window.h \
+       modest-connection-specific-smtp-window.c \
+       modest-connection-specific-smtp-edit-window.h \
+       modest-connection-specific-smtp-edit-window.c \
+       modest-osso-autosave-callbacks.c \
+       modest-osso-autosave-callbacks.h \
+       modest-osso-state-saving.c \
+       modest-osso-state-saving.h   \
+       modest-presets.h modest-presets.c
+
+if MODEST_USE_DUMMY_ADDRESS_BOOK
+#       nothing 
+else
+libmodest_ui_la_SOURCES += modest-address-book.c
+endif 
+
+
+libmodest_ui_la_LIBADD = \
+       $(MODEST_GSTUFF_LIBS) \
+       $(MODEST_ABOOK_LIBS) \
+       $(MODEST_PLATFORM_LIBS) \
+       $(MODEST_TOOLKIT_LIBS) \
+       $(MODEST_WPEDITOR_LIBS) \
+       $(MODEST_HILDON_MIME_LIBS) \
+       $(MODEST_LIBCONIC_LIBS) \
+       $(MODEST_HILDON_HELP_LIBS) \
+       $(MODEST_LIBALARM_LIBS)   \
+       $(MODEST_HILDON_NOTIFY_LIBS)
+
+PIXMAP_FILES=\
+       pixmaps/*.png 
+
+pixmapdir = $(datadir)/pixmaps/modest
+pixmap_DATA = $(PIXMAP_FILES)
+
+
+
+UI_FILES=\
+       ui/modest-main-window-ui.xml \
+       ui/modest-msg-edit-window-ui.xml \
+       ui/modest-msg-view-window-ui.xml
+
+uidir = $(datadir)/modest/ui
+ui_DATA = $(UI_FILES)
+
+serviceentry_DATA   = com.nokia.modest.service
+desktopentry_DATA   = modest.desktop
+backupsettings_DATA = modest.conf
+
+icon_26x26_DATA     = pixmaps/modest-icon.png
+
+# mcc_mapping may be provided by the operator-wizard-settings package:
+# the one here is a copy, as that package is not available in chinook
+MMC_MAPPING_FILE=mcc_mapping
+mmccmappingdir=$(datadir)/modest/provider-data
+mmccmapping_DATA = $(MMC_MAPPING_FILE)
+
+PROVIDER_DATA_FILE=maemo-provider-data.keyfile
+providerdatadir=$(datadir)/modest/provider-data
+providerdata_DATA = $(PROVIDER_DATA_FILE)
+
+EXTRA_DIST=\
+       $(UI_FILES) \
+       $(PIXMAP_FILES) \
+       $(serviceentry_DATA) \
+       $(desktopentry_DATA) \
+       $(backupsettings_DATA) \
+       $(icon_26x26_DATA)     \
+       $(MMC_MAPPING_FILE)    \
+       $(PROVIDER_DATA_FILE)
diff --git a/src/hildon2/com.nokia.modest.service.in b/src/hildon2/com.nokia.modest.service.in
new file mode 100644 (file)
index 0000000..7ab396c
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=com.nokia.modest
+Exec=@prefix@/bin/modest
diff --git a/src/hildon2/maemo-provider-data.keyfile b/src/hildon2/maemo-provider-data.keyfile
new file mode 100644 (file)
index 0000000..9152172
--- /dev/null
@@ -0,0 +1,90 @@
+# maemo-provider-data.keyfile -*-mode:sh-*-
+# Time-stamp: <2007-12-01 13:39:11 (djcb)>
+
+# Copyright (c) 2006, Nokia Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# * Neither the name of the Nokia Corporation nor the names of its
+#   contributors may be used to endorse or promote products derived from
+#   this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+[aim.com]
+Name=AIM
+MCC=0
+Domain=aim.com
+OutgoingMailServer=smtp.aim.com
+IncomingMailServer=imap.aim.com
+IncomingSecurity=0
+MailboxType=imap
+[aol.com]
+Name=AOL
+MCC=0
+Domain=aol.com
+OutgoingMailServer=smtp.aol.com
+IncomingMailServer=imap.aol.com
+IncomingSecurity=0
+MailboxType=imap
+[imap.gmail.com]
+Name=Gmail/IMAP
+MCC=0
+Domain=gmail.com
+OutgoingMailServer=smtp.gmail.com
+SecureSmtp=true
+IncomingMailServer=imap.gmail.com
+IncomingSecurity=2
+MailboxType=imap
+[pop.gmail.com]
+Name=Gmail/POP3
+MCC=0
+Domain=gmail.com
+OutgoingMailServer=smtp.gmail.com
+SecureSmtp=true
+IncomingMailServer=pop.gmail.com
+IncomingSecurity=2
+MailboxType=pop
+[lycos.com]
+Name=Lycos Mail
+MCC=0
+Domain=lycos.com
+OutgoingMailServer=smtp.mail.lycos.com
+IncomingMailServer=pop.mail.lycos.com
+IncomingSecurity=0
+MailboxType=pop
+[yahoo.com]
+Name=Yahoo Mail Plus
+MCC=0
+Domain=yahoo.com
+OutgoingMailServer=smtp.mail.yahoo.com
+IncomingMailServer=pop.mail.yahoo.com
+IncomingSecurity=0
+MailboxType=pop
+[Tinymail]
+Name=Tinymail
+MCC=206
+Domain=tinymail.org
+IncomingMailServer=imap1.tinymail.org
+IncomingSecurity=0
+MailboxType=imap
+
diff --git a/src/hildon2/mcc_mapping b/src/hildon2/mcc_mapping
new file mode 100644 (file)
index 0000000..6b984d1
--- /dev/null
@@ -0,0 +1,230 @@
+412    osso_db_country_afghanistan\r
+276    osso_db_country_albania\r
+603    osso_db_country_algeria\r
+544    osso_db_country_american_samoa\r
+213    osso_db_country_andorra\r
+631    osso_db_country_angola\r
+365    osso_db_country_anguilla\r
+344    osso_db_country_antigua_and_barbuda\r
+722    osso_db_country_argentina\r
+283    osso_db_country_armenia\r
+363    osso_db_country_aruba\r
+505    osso_db_country_australia\r
+232    osso_db_country_austria\r
+400    osso_db_country_azerbaijani_republic\r
+364    osso_db_country_bahamas\r
+426    osso_db_country_bahrain\r
+470    osso_db_country_bangladesh\r
+342    osso_db_country_barbados\r
+257    osso_db_country_belarus\r
+206    osso_db_country_belgium\r
+702    osso_db_country_belize\r
+616    osso_db_country_benin\r
+350    osso_db_country_bermuda\r
+402    osso_db_country_bhutan\r
+736    osso_db_country_bolivia\r
+218    osso_db_country_bosnia_and_herzegovina\r
+652    osso_db_country_botswana\r
+724    osso_db_country_brazil\r
+348    osso_db_country_british_virgin_islands\r
+528    osso_db_country_brunei_darussalam\r
+284    osso_db_country_bulgaria\r
+613    osso_db_country_burkina_faso\r
+642    osso_db_country_burundi\r
+456    osso_db_country_cambodia\r
+624    osso_db_country_cameroon\r
+302    osso_db_country_canada\r
+625    osso_db_country_cape_verde\r
+346    osso_db_country_cayman_islands\r
+623    osso_db_country_central_african_republic\r
+622    osso_db_country_chad\r
+730    osso_db_country_chile\r
+461    osso_db_country_china\r
+460    osso_db_country_china\r
+732    osso_db_country_colombia\r
+654    osso_db_country_comoros\r
+629    osso_db_country_republic_of_the_congo\r
+548    osso_db_country_cook_islands\r
+712    osso_db_country_costa_rica\r
+612    osso_db_country_cote_dlvoire\r
+219    osso_db_country_croatia\r
+368    osso_db_country_cuba\r
+280    osso_db_country_cyprus\r
+230    osso_db_country_czech_republic\r
+630    osso_db_country_democratic_republic_of_the_congo\r
+238    osso_db_country_denmark\r
+638    osso_db_country_djibouti\r
+366    osso_db_country_dominica\r
+370    osso_db_country_dominican_republic\r
+514    osso_db_country_east_timor\r
+740    osso_db_country_ecuador\r
+602    osso_db_country_egypt\r
+706    osso_db_country_el_salvador\r
+627    osso_db_country_equatorial_guinea\r
+657    osso_db_country_eritrea\r
+248    osso_db_country_estonia\r
+636    osso_db_country_ethiopia\r
+288    osso_db_country_faroe_islands\r
+542    osso_db_country_fiji\r
+244    osso_db_country_finland\r
+208    osso_db_country_france\r
+742    osso_db_country_french_guiana\r
+547    osso_db_country_french_polynesia\r
+628    osso_db_country_gobonese_republic\r
+607    osso_db_country_gambia\r
+282    osso_db_country_georgia\r
+262    osso_db_country_germany\r
+620    osso_db_country_ghana\r
+266    osso_db_country_gibraltar\r
+202    osso_db_country_greece\r
+290    osso_db_country_greenland\r
+352    osso_db_country_grenada\r
+340    osso_db_country_guadeloupe\r
+535    osso_db_country_guam\r
+704    osso_db_country_guatemala\r
+611    osso_db_country_guinea\r
+632    osso_db_country_guinea_bissaus\r
+738    osso_db_country_guyana\r
+372    osso_db_country_haiti\r
+708    osso_db_country_honduras\r
+454    osso_db_country_hong_kong\r
+216    osso_db_country_hungary\r
+274    osso_db_country_iceland\r
+404    osso_db_country_india\r
+510    osso_db_country_indonesia\r
+432    osso_db_country_iran\r
+418    osso_db_country_iraq\r
+272    osso_db_country_republic_of_ireland\r
+425    osso_db_country_israel\r
+222    osso_db_country_italy\r
+338    osso_db_country_jamaica\r
+441    osso_db_country_japan\r
+440    osso_db_country_japan\r
+416    osso_db_country_jordan\r
+401    osso_db_country_kazakhstan\r
+639    osso_db_country_kenya\r
+545    osso_db_country_kiribati\r
+467    osso_db_country_korea_north\r
+450    osso_db_country_country_south_korea\r
+419    osso_db_country_kuwait\r
+437    osso_db_country_kyrgyz_republic\r
+457    osso_db_country_laos\r
+247    osso_db_country_latvia\r
+415    osso_db_country_lebanon\r
+651    osso_db_country_lesotho\r
+618    osso_db_country_liberia\r
+606    osso_db_country_libya\r
+295    osso_db_country_liechtenstein\r
+246    osso_db_country_lithuania\r
+270    osso_db_country_luxembourg\r
+455    osso_db_country_macao\r
+294    osso_db_country_the_former_yugoslav_republic_of_macedonia\r
+646    osso_db_country_madagascar\r
+650    osso_db_country_malawi\r
+502    osso_db_country_malaysia\r
+472    osso_db_country_maldives\r
+610    osso_db_country_mali\r
+278    osso_db_country_malta\r
+551    osso_db_country_marshall_islands\r
+340    osso_db_country_martinique\r
+609    osso_db_country_mauritania\r
+617    osso_db_country_mauritius\r
+334    osso_db_country_mexico\r
+550    osso_db_country_micronesia\r
+259    osso_db_country_republic_of_moldova\r
+212    osso_db_country_monaco\r
+428    osso_db_country_mongolia\r
+354    osso_db_country_montserrat\r
+604    osso_db_country_morocco\r
+643    osso_db_country_mozambique\r
+414    osso_db_country_myanmar\r
+649    osso_db_country_namibia\r
+536    osso_db_country_nauru\r
+429    osso_db_country_nepal\r
+204    osso_db_country_netherlands\r
+362    osso_db_country_netherlands_antilles\r
+546    osso_db_country_new_caledonia\r
+530    osso_db_country_new_zealand\r
+710    osso_db_country_nicaraqua\r
+614    osso_db_country_niger\r
+621    osso_db_country_nigeria\r
+534    osso_db_country_northern_mariana_islands\r
+242    osso_db_country_norway\r
+422    osso_db_country_oman\r
+410    osso_db_country_pakistan\r
+552    osso_db_country_palau\r
+714    osso_db_country_panama\r
+537    osso_db_country_papua_new_guinea\r
+744    osso_db_country_paraquay\r
+716    osso_db_country_peru\r
+515    osso_db_country_philippines\r
+260    osso_db_country_poland\r
+268    osso_db_country_portugal\r
+330    osso_db_country_puerto_rico\r
+427    osso_db_country_qatar\r
+647    osso_db_country_reunion\r
+226    osso_db_country_romania\r
+250    osso_db_country_russian_federation\r
+635    osso_db_country_rwandese_republic\r
+356    osso_db_country_saint_kitts_and_nevis\r
+358    osso_db_country_saint_lucia\r
+308    osso_db_country_saint_pierre_and_miquelon\r
+360    osso_db_country_saint_vincent_and_grenadines\r
+549    osso_db_country_samoa\r
+292    osso_db_country_san_marino\r
+626    osso_db_country_sao_tome_and_principe\r
+420    osso_db_country_saudi_arabia\r
+608    osso_db_country_senegal\r
+220    osso_db_country_serbia_and_montenegro\r
+633    osso_db_country_seychelles\r
+619    osso_db_country_sierra_leone\r
+525    osso_db_country_singapore\r
+231    osso_db_country_slovakia\r
+293    osso_db_country_slovenia\r
+540    osso_db_country_solomon_islands\r
+637    osso_db_country_somalia\r
+655    osso_db_country_south_africa\r
+214    osso_db_country_spain\r
+413    osso_db_country_sri_lanka\r
+634    osso_db_country_sudan\r
+746    osso_db_country_suriname\r
+653    osso_db_country_swaziland\r
+240    osso_db_country_sweden\r
+228    osso_db_country_switzerland\r
+417    osso_db_country_syrian_arab_republic\r
+466    osso_db_country_taiwan\r
+436    osso_db_country_tajikistan\r
+640    osso_db_country_united_republic_of_tanzania\r
+520    osso_db_country_thailand\r
+615    osso_db_country_togolese_republic\r
+539    osso_db_country_tonga\r
+374    osso_db_country_trinidad_and_tobago\r
+605    osso_db_country_tunisia\r
+286    osso_db_country_turkey\r
+438    osso_db_country_turkmenistan\r
+376    osso_db_country_turks_and_caicos_islands\r
+641    osso_db_country_uganda\r
+255    osso_db_country_ukraine\r
+424    osso_db_country_united_arab_emirates\r
+430    osso_db_country_united_arab_emirates_abu_dhabi\r
+431    osso_db_country_united_arab_emirates_dubai\r
+235    osso_db_country_united_kingdom_of_great_britain_and_northern_ireland\r
+234    osso_db_country_united_kingdom_of_great_britain_and_northern_ireland\r
+310    osso_db_country_united_states_of_america\r
+316    osso_db_country_united_states_of_america\r
+311    osso_db_country_united_states_of_america\r
+312    osso_db_country_united_states_of_america\r
+313    osso_db_country_united_states_of_america\r
+314    osso_db_country_united_states_of_america\r
+315    osso_db_country_united_states_of_america\r
+332    osso_db_country_unites_states_virgin_islands\r
+748    osso_db_country_uruguay\r
+434    osso_db_country_uzbekistan\r
+541    osso_db_country_vanuatu\r
+225    osso_db_country_the_vatican\r
+734    osso_db_country_venezuela\r
+452    osso_db_country_viet_nam\r
+543    osso_db_country_wallis_and_futuna\r
+421    osso_db_country_yemen\r
+645    osso_db_country_zambia\r
+648    osso_db_country_zimbabwe\r
diff --git a/src/hildon2/mcc_mapping.en_GB b/src/hildon2/mcc_mapping.en_GB
new file mode 100644 (file)
index 0000000..491e504
--- /dev/null
@@ -0,0 +1,107 @@
+276    Albania\r
+213    Andorra\r
+722    Argentina\r
+363    Aruba\r
+505    Australia\r
+232    Austria\r
+400    Azerbaijan\r
+426    Bahrain\r
+470    Bangladesh\r
+257    Belarus\r
+206    Belgium\r
+736    Bolivia\r
+218    Bosnia and Herzegovina\r
+652    Botswana\r
+724    Brazil\r
+528    Brunei Darussalam\r
+284    Bulgaria\r
+456    Cambodia\r
+302    Canada\r
+730    Chile\r
+460    China\r
+732    Colombia\r
+219    Croatia\r
+280    Cyprus\r
+230    Czech Republic\r
+238    Denmark\r
+370    Dominican Republic\r
+740    Ecuador\r
+602    Egypt\r
+706    El Salvador\r
+248    Estonia\r
+244    Finland\r
+208    France\r
+282    Georgia\r
+262    Germany\r
+620    Ghana\r
+266    Gibraltar\r
+202    Greece\r
+340    Guadeloupe\r
+704    Guatemala\r
+708    Honduras\r
+454    Hong Kong, China\r
+216    Hungary\r
+274    Iceland\r
+404    India\r
+510    Indonesia\r
+272    Ireland\r
+425    Israel\r
+222    Italy\r
+338    Jamaica\r
+440    Japan\r
+416    Jordan\r
+401    Kazakhstan\r
+639    Kenya\r
+419    Kuwait\r
+247    Latvia\r
+415    Lebanon\r
+295    Liechtenstein\r
+246    Lithuania\r
+270    Luxembourg\r
+455    Macao, China\r
+294    Macedonia\r
+502    Malaysia\r
+472    Maldives\r
+278    Malta\r
+340    Martinique\r
+334    Mexico\r
+259    Moldova\r
+212    Monaco\r
+428    Mongolia\r
+220    Montenegro\r
+604    Morocco\r
+204    Netherlands\r
+530    New Zealand\r
+621    Nigeria\r
+242    Norway\r
+422    Oman\r
+410    Pakistan\r
+714    Panama\r
+744    Paraguay\r
+716    Peru\r
+515    Philippines\r
+260    Poland\r
+268    Portugal\r
+427    Qatar\r
+226    Romania\r
+250    Russian Federation\r
+420    Saudi Arabia\r
+220    Serbia\r
+525    Singapore\r
+231    Slovakia\r
+293    Slovenia\r
+655    South Africa\r
+214    Spain\r
+413    Sri Lanka\r
+240    Sweden\r
+228    Switzerland\r
+417    Syria\r
+466    Taiwan\r
+520    Thailand\r
+374    Trinidad and Tobago\r
+286    Turkey\r
+255    Ukraine\r
+234    United Kingdom\r
+748    Uruguay\r
+310    USA\r
+734    Venezuela\r
diff --git a/src/hildon2/modest-account-view-window.c b/src/hildon2/modest-account-view-window.c
new file mode 100644 (file)
index 0000000..8c7e36c
--- /dev/null
@@ -0,0 +1,540 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <widgets/modest-account-view-window.h>
+#include <widgets/modest-account-view.h>
+
+#include <modest-runtime.h>
+#include "modest-platform.h"
+#include "modest-account-protocol.h"
+#include <modest-account-mgr-helpers.h>
+#include <string.h>
+#include "modest-tny-platform-factory.h"
+#include "modest-easysetup-wizard-dialog.h"
+#include "modest-account-settings-dialog.h"
+#include <modest-utils.h>
+#include "widgets/modest-ui-constants.h"
+
+/* 'private'/'protected' functions */
+static void                            modest_account_view_window_class_init   (ModestAccountViewWindowClass *klass);
+static void                            modest_account_view_window_init         (ModestAccountViewWindow *obj);
+static void                            modest_account_view_window_finalize     (GObject *obj);
+
+/* list my signals */
+enum {
+       /* MY_SIGNAL_1, */
+       /* MY_SIGNAL_2, */
+       LAST_SIGNAL
+};
+
+typedef struct _ModestAccountViewWindowPrivate ModestAccountViewWindowPrivate;
+struct _ModestAccountViewWindowPrivate {
+       GtkWidget           *new_button;
+       GtkWidget           *edit_button;
+       GtkWidget           *delete_button;
+       GtkWidget           *close_button;
+       ModestAccountView   *account_view;
+       guint acc_removed_handler;
+};
+#define MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                        MODEST_TYPE_ACCOUNT_VIEW_WINDOW, \
+                                                        ModestAccountViewWindowPrivate))
+/* globals */
+static GtkDialogClass *parent_class = NULL;
+
+/* uncomment the following if you have defined any signals */
+/* static guint signals[LAST_SIGNAL] = {0}; */
+
+GType
+modest_account_view_window_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestAccountViewWindowClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_account_view_window_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestAccountViewWindow),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_account_view_window_init,
+                       NULL
+               };
+               my_type = g_type_register_static (GTK_TYPE_DIALOG,
+                                                 "ModestAccountViewWindow",
+                                                 &my_info, 0);
+       }
+       return my_type;
+}
+
+static void
+modest_account_view_window_class_init (ModestAccountViewWindowClass *klass)
+{
+       GObjectClass *gobject_class;
+       gobject_class = (GObjectClass*) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_account_view_window_finalize;
+
+       g_type_class_add_private (gobject_class, sizeof(ModestAccountViewWindowPrivate));
+}
+
+static void
+modest_account_view_window_finalize (GObject *self)
+{
+       ModestAccountViewWindowPrivate *priv;
+       ModestAccountMgr *mgr;
+       
+       priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE (self);
+       mgr = modest_runtime_get_account_mgr ();
+
+       if (g_signal_handler_is_connected (mgr, priv->acc_removed_handler))
+               g_signal_handler_disconnect (mgr, priv->acc_removed_handler);
+       priv->acc_removed_handler = 0;
+
+       G_OBJECT_CLASS(parent_class)->finalize (self);
+}
+
+
+static void
+on_selection_changed (GtkTreeSelection *sel, ModestAccountViewWindow *self)
+{
+       ModestAccountViewWindowPrivate *priv;
+       GtkTreeModel                   *model;
+       GtkTreeIter                     iter;
+       gboolean                        has_selection;
+       
+       priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+
+       has_selection =
+               gtk_tree_selection_get_selected (sel, &model, &iter);
+
+       /* Set the status of the buttons */
+       gtk_widget_set_sensitive (priv->edit_button, has_selection);
+       gtk_widget_set_sensitive (priv->delete_button, has_selection);
+}
+
+/** Check whether any connections are active, and cancel them if 
+ * the user wishes.
+ * Returns TRUE is there was no problem, 
+ * or if an operation was cancelled so we can continue.
+ * Returns FALSE if the user chose to cancel his request instead.
+ */
+static gboolean
+check_for_active_account (ModestAccountViewWindow *self, const gchar* account_name)
+{
+       ModestTnySendQueue *send_queue;
+       ModestTnyAccountStore *acc_store;
+       ModestMailOperationQueue* queue;
+       TnyConnectionStatus store_conn_status;
+       TnyAccount *store_account = NULL, *transport_account = NULL;
+       gboolean retval = TRUE, sending = FALSE;
+
+       acc_store = modest_runtime_get_account_store ();
+       queue = modest_runtime_get_mail_operation_queue ();
+
+       store_account = 
+               modest_tny_account_store_get_server_account (acc_store,
+                                                            account_name,
+                                                            TNY_ACCOUNT_TYPE_STORE);
+
+       /* This could happen if the account was deleted before the
+          call to this function */
+       if (!store_account)
+               return FALSE;
+
+       transport_account = 
+               modest_tny_account_store_get_server_account (acc_store,
+                                                            account_name,
+                                                            TNY_ACCOUNT_TYPE_TRANSPORT);
+
+       /* This could happen if the account was deleted before the
+          call to this function */
+       if (!transport_account) {
+               g_object_unref (store_account);
+               return FALSE;
+       }
+
+       /* If the transport account was not used yet, then the send
+          queue could not exist (it's created on demand) */
+       send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
+       if (TNY_IS_SEND_QUEUE (send_queue))
+               sending = modest_tny_send_queue_sending_in_progress (send_queue);
+
+       store_conn_status = tny_account_get_connection_status (store_account);
+       if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
+               gint response;
+
+               response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
+                                                               _("emev_nc_disconnect_account"));
+               if (response == GTK_RESPONSE_OK) {
+                       retval = TRUE;
+               } else {
+                       retval = FALSE;
+               }
+       }
+
+       if (retval) {
+
+               /* FIXME: We should only cancel those of this account */
+               modest_mail_operation_queue_cancel_all (queue);
+
+               /* Also disconnect the account */
+               if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
+                   (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
+                       tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
+                                                     FALSE, NULL, NULL);
+               }
+               if (sending) {
+                       tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
+                                                     FALSE, NULL, NULL);
+               }
+       }
+               
+       /* Frees */
+       g_object_unref (store_account);
+       g_object_unref (transport_account);
+       
+       return retval;
+}
+
+static void
+on_delete_button_clicked (GtkWidget *button, ModestAccountViewWindow *self)
+{
+       ModestAccountViewWindowPrivate *priv;
+       ModestAccountMgr *account_mgr;
+       gchar *account_title = NULL, *account_name = NULL;
+       
+       priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+
+       account_mgr = modest_runtime_get_account_mgr(); 
+       account_name = modest_account_view_get_selected_account (priv->account_view);
+       if(!account_name)
+               return;
+
+       account_title = modest_account_mgr_get_display_name(account_mgr, account_name);
+       /* This could happen if the account is being deleted */
+       if (!account_title)
+               return;
+       
+       if (check_for_active_account (self, account_name)) {
+               /* The warning text depends on the account type: */
+               gchar *txt = NULL;      
+               gint response;
+               ModestProtocol *protocol;
+
+               protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
+                                                                         modest_account_mgr_get_store_protocol (account_mgr, account_name));
+               txt = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX, account_title);
+               if (txt == NULL) {
+                       txt = g_strdup_printf (_("emev_nc_delete_mailbox"), 
+                                              account_title);
+               }
+               
+               response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), txt);
+               g_free (txt);
+               txt = NULL;
+               
+               if (response == GTK_RESPONSE_OK) {
+                       /* Remove account. If it succeeds then it also removes
+                          the account from the ModestAccountView: */                             
+                       gboolean is_default = FALSE;
+                       gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
+                       if (default_account_name && (strcmp (default_account_name, account_name) == 0))
+                               is_default = TRUE;
+                       g_free (default_account_name);
+                       
+                               gboolean removed = modest_account_mgr_remove_account (account_mgr, account_name);
+                               if (!removed) {
+                                       g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
+                               }
+
+               }
+               g_free (account_title);
+       }               
+       g_free (account_name);
+}
+
+static void
+on_account_settings_dialog_response (GtkDialog *dialog,
+                                    gint response,
+                                    gpointer user_data)
+{
+       TnyAccount *store_account = NULL;
+       gchar* account_name = NULL;
+       ModestAccountViewWindowPrivate *priv = NULL;
+
+       priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE (user_data);
+       account_name = modest_account_view_get_selected_account (priv->account_view);
+       store_account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
+                                                                    account_name,
+                                                                    TNY_ACCOUNT_TYPE_STORE);
+       
+       /* Reconnect the store account, no need to reconnect the
+          transport account because it will connect when needed */
+       if (tny_account_get_connection_status (store_account) == 
+           TNY_CONNECTION_STATUS_DISCONNECTED)
+               tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
+                                             TRUE, NULL, NULL);
+
+       /* Disconnect this handler */
+       g_signal_handlers_disconnect_by_func (dialog, on_account_settings_dialog_response, user_data);
+
+       /* Free */
+       g_free (account_name);
+       g_object_unref (store_account);
+}
+
+static void
+on_edit_button_clicked (GtkWidget *button, ModestAccountViewWindow *self)
+{
+       ModestAccountViewWindowPrivate *priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE (self);
+       
+       gchar* account_name = modest_account_view_get_selected_account (priv->account_view);
+       if (!account_name)
+               return;
+               
+       /* Check whether any connections are active, and cancel them if 
+        * the user wishes.
+        */
+       if (check_for_active_account (self, account_name)) {
+               ModestAccountProtocol *proto;
+               ModestProtocolType proto_type;
+
+               /* Get proto */
+               proto_type = modest_account_mgr_get_store_protocol (modest_runtime_get_account_mgr (), 
+                                                                   account_name);
+               proto = (ModestAccountProtocol *)
+                       modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), 
+                                                                      proto_type);
+
+               /* Create and show the dialog */
+               if (proto && MODEST_IS_ACCOUNT_PROTOCOL (proto)) {
+                       ModestAccountSettingsDialog *dialog =
+                               modest_account_protocol_get_account_settings_dialog (proto, account_name);
+                       gtk_widget_show (GTK_WIDGET (dialog));
+               }
+       }
+       g_free (account_name);
+}
+
+static void
+on_wizard_response (GtkDialog *dialog, 
+                   gint response, 
+                   gpointer user_data)
+{      
+       /* The response has already been handled by the wizard dialog itself,
+        * creating the new account.
+        */      
+       if (dialog)
+               gtk_widget_destroy (GTK_WIDGET (dialog));
+
+       /* Re-focus the account list view widget */
+       if (MODEST_IS_ACCOUNT_VIEW_WINDOW (user_data)) {
+               ModestAccountViewWindowPrivate *priv;
+               priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE (user_data);
+               gtk_widget_grab_focus (GTK_WIDGET (priv->account_view));
+       }
+}
+
+static void
+on_new_button_clicked (GtkWidget *button, ModestAccountViewWindow *self)
+{
+       GtkDialog *wizard;
+       GtkWindow *dialog;
+
+       /* Show the easy-setup wizard: */       
+       dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
+       if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) {
+               /* old wizard is active already; 
+                */
+               gtk_window_present (dialog);
+               return;
+       }
+       
+       /* there is no such wizard yet */
+       wizard = GTK_DIALOG (modest_easysetup_wizard_dialog_new ());
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), 
+                                    GTK_WINDOW (wizard));
+
+       /* if there is already another modal dialog, make it non-modal */
+       if (dialog)
+               gtk_window_set_modal (GTK_WINDOW(dialog), FALSE);
+       
+       gtk_window_set_modal (GTK_WINDOW (wizard), TRUE);
+       gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (self));
+       /* Destroy the dialog when it is closed: */
+       g_signal_connect (G_OBJECT (wizard), "response", G_CALLBACK
+                         (on_wizard_response), self);
+       gtk_widget_show (GTK_WIDGET (wizard));
+}
+
+static void
+on_close_button_clicked (GtkWidget *button, gpointer user_data)
+{              
+       ModestAccountViewWindow *self = MODEST_ACCOUNT_VIEW_WINDOW (user_data);
+
+       gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+}
+
+static void
+setup_button_box (ModestAccountViewWindow *self, GtkButtonBox *box)
+{
+       ModestAccountViewWindowPrivate *priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+       
+       gtk_button_box_set_spacing (GTK_BUTTON_BOX (box), 6);
+       gtk_button_box_set_layout (GTK_BUTTON_BOX (box), 
+                                  GTK_BUTTONBOX_START);
+       
+       priv->new_button     = gtk_button_new_from_stock(_("mcen_bd_new"));
+       priv->edit_button = gtk_button_new_with_label(_("mcen_bd_edit"));
+       priv->delete_button  = gtk_button_new_from_stock(_("mcen_bd_delete"));
+       priv->close_button    = gtk_button_new_from_stock(_("mcen_bd_close"));
+       
+       g_signal_connect (G_OBJECT(priv->new_button), "clicked",
+                         G_CALLBACK(on_new_button_clicked),
+                         self);
+       g_signal_connect (G_OBJECT(priv->delete_button), "clicked",
+                         G_CALLBACK(on_delete_button_clicked),
+                         self);
+       g_signal_connect (G_OBJECT(priv->edit_button), "clicked",
+                         G_CALLBACK(on_edit_button_clicked),
+                         self);
+       g_signal_connect (G_OBJECT(priv->close_button), "clicked",
+                         G_CALLBACK(on_close_button_clicked),
+                         self);
+
+       gtk_box_pack_start (GTK_BOX(box), priv->new_button, FALSE, FALSE,2);
+       gtk_box_pack_start (GTK_BOX(box), priv->edit_button, FALSE, FALSE,2);
+       gtk_box_pack_start (GTK_BOX(box), priv->delete_button, FALSE, FALSE,2);
+       gtk_box_pack_start (GTK_BOX(box), priv->close_button, FALSE, FALSE,2);
+
+       /* Should has been created by window_vbox_new */
+       if (priv->account_view) {
+               GtkTreeSelection *sel;
+               sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->account_view));
+               if (gtk_tree_selection_count_selected_rows (sel) == 0) {
+                       gtk_widget_set_sensitive (priv->edit_button, FALSE);
+                       gtk_widget_set_sensitive (priv->delete_button, FALSE);  
+               }
+       }
+
+       gtk_widget_show_all (GTK_WIDGET (box));
+}
+
+static GtkWidget*
+window_vbox_new (ModestAccountViewWindow *self)
+{
+       ModestAccountViewWindowPrivate *priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+
+       GtkWidget *main_vbox     = gtk_vbox_new (FALSE, 6);
+       GtkWidget *main_hbox     = gtk_hbox_new (FALSE, 6);
+       
+       priv->account_view = modest_account_view_new (modest_runtime_get_account_mgr());
+
+       /* Only force the height, the width of the widget will depend
+          on the size of the column titles */
+       gtk_widget_set_size_request (GTK_WIDGET(priv->account_view), -1, 400);
+       gtk_widget_show (GTK_WIDGET (priv->account_view));
+
+       GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->account_view));
+       g_signal_connect (G_OBJECT(sel), "changed",  G_CALLBACK(on_selection_changed),
+                         self);
+                         
+       GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), MODEST_MARGIN_DEFAULT);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, 
+               GTK_POLICY_AUTOMATIC);
+       gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (priv->account_view));
+       gtk_widget_show (GTK_WIDGET (scrolled_window));
+       
+       gtk_box_pack_start (GTK_BOX(main_hbox), GTK_WIDGET(scrolled_window), TRUE, TRUE, 2);
+       
+       gtk_box_pack_start (GTK_BOX(main_vbox), main_hbox, TRUE, TRUE, 2);
+       gtk_widget_show (GTK_WIDGET (main_hbox));
+       gtk_widget_show (GTK_WIDGET (main_vbox));
+
+       return main_vbox;
+}
+
+
+static void
+modest_account_view_window_init (ModestAccountViewWindow *self)
+{
+       ModestAccountViewWindowPrivate *priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+
+       priv->acc_removed_handler = 0;
+}
+
+static void
+on_account_removed (ModestAccountMgr *acc_mgr, 
+                   const gchar *account,
+                   gpointer user_data)
+{
+       ModestAccountViewWindowPrivate *priv;
+
+       /* If there is no account left then close the window */
+       if (!modest_account_mgr_has_accounts (acc_mgr, TRUE)) {
+               gboolean ret_value;
+               g_signal_emit_by_name (G_OBJECT (user_data), "delete-event", NULL, &ret_value);
+       } else {                
+               /* Re-focus the account list view widget */
+               priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE (user_data);
+               gtk_widget_grab_focus (GTK_WIDGET (priv->account_view));
+       }
+}
+
+GtkWidget*
+modest_account_view_window_new (void)
+{
+       GObject *self = g_object_new(MODEST_TYPE_ACCOUNT_VIEW_WINDOW, NULL);
+       ModestAccountViewWindowPrivate *priv;
+       ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr ();
+
+       /* Add widgets */
+       gtk_box_pack_start (GTK_BOX((GTK_DIALOG (self)->vbox)), 
+                           window_vbox_new (MODEST_ACCOUNT_VIEW_WINDOW (self)), 
+                           TRUE, TRUE, 2);
+       
+       setup_button_box (MODEST_ACCOUNT_VIEW_WINDOW (self), GTK_BUTTON_BOX (GTK_DIALOG (self)->action_area));
+
+       gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_emailsetup_accounts"));
+
+       /* Connect signals */
+       priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
+       priv->acc_removed_handler = g_signal_connect (G_OBJECT(account_mgr), "account_removed",
+                                                     G_CALLBACK (on_account_removed), self);
+       
+       return GTK_WIDGET (self);
+}
diff --git a/src/hildon2/modest-address-book.c b/src/hildon2/modest-address-book.c
new file mode 100644 (file)
index 0000000..b636c6e
--- /dev/null
@@ -0,0 +1,996 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* modest-address-book.c */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <modest-address-book.h>
+#include <modest-text-utils.h>
+#include <libebook/e-book.h>
+#include <libebook/e-book-view.h>
+#include <libosso-abook/osso-abook.h>
+#include "modest-hildon-includes.h"
+#include "modest-platform.h"
+#include "modest-runtime.h"
+#include "widgets/modest-window-mgr.h"
+#include <string.h>
+#include <gtk/gtksizegroup.h>
+#include <gtk/gtkbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtktreeselection.h>
+#include <gtk/gtkentry.h>
+
+static OssoABookContactModel *contact_model =  NULL;
+static EBook *book = NULL;
+static EBookView * book_view = NULL;
+
+static GSList *get_recipients_for_given_contact(EContact * contact);
+static void commit_contact(EContact * contact, gboolean is_new);
+static gchar *get_email_addr_from_user(const gchar * given_name);
+static gchar *ui_get_formatted_email_id(gchar * current_given_name,
+                                       gchar * current_sur_name, gchar * current_email_id);
+static gchar *run_add_email_addr_to_contact_dlg(const gchar * contact_name);
+static GSList *select_email_addrs_for_contact(GList * email_addr_list);
+static gboolean resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id);
+static gchar *unquote_string (const gchar *str);
+
+
+static void
+unref_gobject (GObject *obj)
+{
+       if (obj)
+               g_object_unref (obj);
+}
+       
+
+static void
+get_book_view_cb (EBook *book, EBookStatus status, EBookView *bookview, gpointer data)
+{
+       if (status != E_BOOK_ERROR_OK) {
+               g_object_unref (book);
+               book = NULL;
+               return;
+       }
+       book_view = bookview;
+
+       if (contact_model)
+#if MODEST_ABOOK_API < 4
+               osso_abook_tree_model_set_book_view (OSSO_ABOOK_TREE_MODEL (contact_model),
+                                                    book_view);
+#else /* MODEST_ABOOK_API < 4 */
+               osso_abook_list_store_set_book_view (OSSO_ABOOK_LIST_STORE (contact_model),
+                                                    book_view);
+#endif /* MODEST_ABOOK_API < 4 */
+
+       e_book_view_start (book_view);
+}
+
+static void
+book_open_cb (EBook *view, EBookStatus status, gpointer data)
+{
+       EBookQuery *query = NULL;
+
+       if (status != E_BOOK_ERROR_OK) {
+               g_object_unref (book);
+               book = NULL;
+               return;
+       }
+       query = e_book_query_any_field_contains ("");
+       e_book_async_get_book_view (book, query, NULL, -1, get_book_view_cb, NULL);
+       e_book_query_unref (query);
+}
+
+static gboolean 
+open_addressbook ()
+{
+       book = e_book_new_system_addressbook (NULL);
+       if (!book)
+               return FALSE;
+
+       e_book_async_open (book, FALSE, book_open_cb, NULL);
+
+       return TRUE; /* FIXME */        
+}
+
+static gboolean
+open_addressbook_sync ()
+{
+       book = e_book_new_system_addressbook (NULL);
+       if (!book)
+               return FALSE;
+
+       e_book_open (book, FALSE, NULL);
+
+       return TRUE;
+}
+
+void
+modest_address_book_add_address (const gchar *address)
+{
+       OssoABookAccount *account = NULL;
+       GtkWidget *dialog = NULL;
+       gchar *email_address = NULL;
+
+       contact_model = osso_abook_contact_model_new ();
+       if (!open_addressbook ()) {
+               if (contact_model) {
+                       g_object_unref (contact_model);
+                       contact_model = NULL;
+               }
+               return;
+       }
+
+       email_address = modest_text_utils_get_email_address (address);
+       
+       account = osso_abook_account_get (EVC_EMAIL, NULL, email_address);
+       g_free (email_address);
+       if (account)
+       {
+               dialog = osso_abook_add_to_contacts_dialog_new (contact_model, account);
+               g_object_unref (account);
+               gtk_dialog_run (GTK_DIALOG (dialog));
+
+               if (contact_model) {
+                       g_object_unref (contact_model);
+                       contact_model = NULL;
+               }
+
+               gtk_widget_destroy (dialog);
+       }
+
+}
+
+void
+modest_address_book_select_addresses (ModestRecptEditor *recpt_editor)
+{
+#if MODEST_ABOOK_API < 4
+       GtkWidget *contact_view = NULL;
+       GtkWidget *contact_dialog;
+#else /* MODEST_ABOOK_API < 4 */
+       OssoABookContactChooser *contact_chooser = NULL;
+#endif /* MODEST_ABOOK_API < 4 */
+
+       GList *contacts_list = NULL;
+       GSList *email_addrs_per_contact = NULL;
+       gchar *econtact_id;
+       gboolean focus_recpt_editor = FALSE;
+
+       g_return_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor));
+
+#if MODEST_ABOOK_API < 4
+       if (!open_addressbook ()) {
+               if (contact_model) {
+                       g_object_unref (contact_model);
+                       contact_model = NULL;
+               }
+               return;
+       }
+       contact_model = osso_abook_contact_model_new ();
+
+       contact_view = osso_abook_contact_selector_new_basic (contact_model);
+       osso_abook_contact_selector_set_minimum_selection (OSSO_ABOOK_CONTACT_SELECTOR (contact_view), 1);
+
+       contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view));
+       gtk_window_set_title (GTK_WINDOW (contact_dialog), _("mcen_ti_select_recipients"));
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (contact_dialog));
+
+       gtk_widget_show (contact_dialog);
+
+       if (gtk_dialog_run (GTK_DIALOG (contact_dialog)) == GTK_RESPONSE_OK) {
+               contacts_list = 
+                       osso_abook_contact_selector_get_extended_selection (OSSO_ABOOK_CONTACT_SELECTOR
+                                                                            (contact_view));
+       }
+#else /* MODEST_ABOOK_API < 4 */
+       /* TODO: figure out how to make the contact chooser modal */
+       contact_chooser = osso_abook_contact_chooser_new
+               ("title", _("mcen_ti_select_recipients"),
+                "help-topic", "",
+                "minimum-selection", 1, NULL);
+
+       if (osso_abook_contact_chooser_run (contact_chooser) == GTK_RESPONSE_OK)
+               contacts_list = osso_abook_contact_chooser_get_selection (contact_chooser);
+
+       g_object_unref (contact_chooser);
+#endif
+       
+       if (contacts_list) {
+               GList *node;
+
+               for (node = contacts_list; node != NULL; node = g_list_next (node)) {
+                       EContact *contact = (EContact *) node->data;
+
+                       email_addrs_per_contact = get_recipients_for_given_contact (contact);
+                       if (email_addrs_per_contact) {
+                               econtact_id = (gchar *) e_contact_get_const (contact, E_CONTACT_UID);
+                               modest_recpt_editor_add_resolved_recipient (MODEST_RECPT_EDITOR (recpt_editor), 
+                                                                           email_addrs_per_contact, econtact_id);
+                               g_slist_foreach (email_addrs_per_contact, (GFunc) g_free, NULL);
+                               g_slist_free (email_addrs_per_contact);
+                               email_addrs_per_contact = NULL;
+                               focus_recpt_editor = TRUE;
+                       }
+               }
+               g_list_free (contacts_list);
+       }
+
+#if MODEST_ABOOK_API < 4
+       if (contact_model) {
+               g_object_unref (contact_model);
+               contact_model = NULL;
+       }
+
+       gtk_widget_destroy (contact_dialog);
+#endif
+
+       if (focus_recpt_editor)
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (recpt_editor));
+
+}
+
+/**
+ * This function returns the resolved recipients for a given EContact.
+ * If no e-mail address is defined, it launches 'Add e-mail address to contact'
+ * dialog to obtain one. If multiple e-mail addresses are found, it launches
+ * 'Select e-mail address' dialog to allow user to select one or more e-mail
+ * addresses for that contact.
+ *
+ * @param  Contact of type #EContact
+ * @return List of resolved recipient strings, to be freed by calling function.
+ */
+static GSList *get_recipients_for_given_contact(EContact * contact)
+{
+       gchar *givenname = NULL;
+       gchar *familyname = NULL;
+       gchar *nickname = NULL;
+       gchar *emailid = NULL;
+       const gchar *display_name = NULL;
+       GList *list = NULL;
+       gchar *formatted_string = NULL;
+       gboolean email_not_present = FALSE;
+       GSList *formattedlist = NULL, *selected_email_addr_list = NULL, *node = NULL;
+
+       if (!contact) {
+               return NULL;
+       }
+
+       givenname = (gchar *) e_contact_get_const(contact, E_CONTACT_GIVEN_NAME);
+       familyname = (gchar *) e_contact_get_const(contact, E_CONTACT_FAMILY_NAME);
+       nickname = (gchar *) e_contact_get_const(contact, E_CONTACT_NICKNAME);
+       if (!nickname)
+               nickname = "";
+       list = (GList *) e_contact_get(contact, E_CONTACT_EMAIL);
+
+       if (!list) {
+               email_not_present = TRUE;
+       }
+
+       if (list && g_list_length(list) == 1) {
+               if (list->data == NULL || g_utf8_strlen(list->data, -1) == 0) {
+                       email_not_present = TRUE;
+               } else {
+                       emailid = g_strstrip(g_strdup(list->data));
+                       if (g_utf8_strlen(emailid, -1) == 0) {
+                               g_free(emailid);
+                               email_not_present = TRUE;
+                       }
+               }
+       }
+
+       /*Launch the 'Add e-mail addr to contact' dialog if required */
+       if (email_not_present) {
+#if MODEST_ABOOK_API < 4
+               display_name = osso_abook_contact_get_display_name(contact);            
+#else
+               OssoABookContact *abook_contact;
+              
+               abook_contact = osso_abook_contact_new_from_template (contact);
+               display_name = osso_abook_contact_get_display_name(abook_contact);
+               g_object_unref (abook_contact);
+#endif
+
+               emailid = get_email_addr_from_user(display_name);
+               if (emailid) {
+                       e_contact_set(contact, E_CONTACT_EMAIL_1, emailid);
+                       commit_contact(contact, FALSE);
+               }
+       }
+
+       if (emailid) {
+               if (givenname || familyname)
+                       formatted_string =
+                           ui_get_formatted_email_id(givenname, familyname, emailid);
+               else
+                       formatted_string = g_strdup(emailid);
+               formattedlist = g_slist_append(formattedlist, formatted_string);
+               g_free(emailid);
+       }
+
+       /*Launch the 'Select e-mail address' dialog if required */
+       if (g_list_length(list) > 1) {
+               selected_email_addr_list = select_email_addrs_for_contact(list);
+               for (node = selected_email_addr_list; node != NULL; node = node->next) {
+                       if (givenname || familyname)
+                               formatted_string =
+                                   ui_get_formatted_email_id(givenname, familyname, node->data);
+                       else
+                               formatted_string = g_strdup(node->data);
+                       formattedlist = g_slist_append(formattedlist, formatted_string);
+               }
+               if (selected_email_addr_list) {
+                       g_slist_foreach(selected_email_addr_list, (GFunc) g_free, NULL);
+                       g_slist_free(selected_email_addr_list);
+               }
+       }
+
+       if (list) {
+               g_list_foreach(list, (GFunc) g_free, NULL);
+               g_list_free(list);
+       }
+
+       return formattedlist;
+}
+
+/**
+ * This is a helper function to commit a EContact to Address_Book application.
+ *
+ * @param  contact  Contact of type #EContact
+ * @return void
+ */
+static void 
+commit_contact(EContact * contact, gboolean is_new)
+{
+       g_return_if_fail (contact);
+       g_return_if_fail (book);
+       
+       if (!contact || !book)
+               return;
+       
+#if MODEST_ABOOK_API < 2
+       osso_abook_contact_commit(contact, is_new, book);
+#else
+       osso_abook_contact_commit(contact, is_new, book, NULL);
+#endif /* MODEST_ABOOK_API < 2 */
+}
+
+/**
+ * This is a helper function used to launch 'Add e-mail address to contact' dialog
+ * after showing appropriate notification, when there is no e-mail address defined
+ * for a selected contact.
+ *
+ * @param  given_name  Given name of the contact
+ * @param  family_name  Family name of the contact
+ * @return E-mail address string entered by user, to be freed by calling function.
+ */
+static gchar *
+get_email_addr_from_user(const gchar * given_name)
+{
+       gchar *notification = NULL;
+       gchar *email_addr = NULL;
+       GtkWidget *note;
+       gboolean note_response;
+
+
+       notification = g_strdup_printf(_("mcen_nc_email_address_not_defined"), given_name);
+
+       note = hildon_note_new_confirmation (NULL, notification);
+       note_response = gtk_dialog_run (GTK_DIALOG(note));
+       gtk_widget_destroy (note);
+       g_free(notification);
+
+       if (note_response == GTK_RESPONSE_OK) {
+               email_addr = run_add_email_addr_to_contact_dlg(given_name);
+       }
+
+       return email_addr;
+}
+
+/**
+This function is used to get the formated email id with given name and sur name
+in the format "GIVENNAME SURNAME <EMAIL ADDRESS>".
+@param current_given_name    to hold the given name
+@param current_sur_name      to hold the sur name
+@param current_email_id      to hold the email id. 
+@return gchar* string to be freed by calling function
+*/
+static gchar *
+ui_get_formatted_email_id(gchar * current_given_name,
+                         gchar * current_sur_name, gchar * current_email_id)
+{
+       GString *email_id_str = NULL;
+
+       email_id_str = g_string_new(NULL);
+
+       if ((current_given_name != NULL) && ((strlen(current_given_name) != 0))
+           && (current_sur_name != NULL) && ((strlen(current_sur_name) != 0))) {
+               g_string_append_printf(email_id_str, "%s %s", current_given_name, current_sur_name);
+       } else if ((current_given_name != NULL) && (strlen(current_given_name) != 0)) {
+               g_string_append_printf(email_id_str, "%s", current_given_name);
+       } else if ((current_sur_name != NULL) && (strlen(current_sur_name) != 0)) {
+               g_string_append_printf(email_id_str, "%s", current_sur_name);
+       }
+       if (g_utf8_strchr (email_id_str->str, -1, ' ')) {
+               g_string_prepend_c (email_id_str, '\"');
+               g_string_append_c (email_id_str, '\"');
+       }
+       g_string_append_printf (email_id_str, " %c%s%c", '<', current_email_id, '>');
+       return g_string_free (email_id_str, FALSE);
+}
+
+/**
+ * This is a helper function used to create & run 'Add e-mail address to contact' dialog.
+ * It allows user to enter an e-mail address, and shows appropriate infonote if the
+ * entered string is not a valid e-mail address.
+ *
+ * @param  contact_name  Full name of the contact
+ * @return E-mail address string entered by user, to be freed by calling function.
+ */
+static gchar *
+run_add_email_addr_to_contact_dlg(const gchar * contact_name)
+{
+       GtkWidget *add_email_addr_to_contact_dlg = NULL;
+       GtkSizeGroup *size_group = NULL;
+       GtkWidget *cptn_cntrl = NULL;
+       GtkWidget *name_label = NULL;
+       GtkWidget *email_entry = NULL;
+       gint result = -1;
+       gchar *new_email_addr = NULL;
+       gboolean run_dialog = TRUE;
+
+       add_email_addr_to_contact_dlg =
+           gtk_dialog_new_with_buttons(_("mcen_ti_add_email_title"), NULL,
+                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT,
+                                       _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT, NULL);
+       gtk_dialog_set_has_separator(GTK_DIALOG(add_email_addr_to_contact_dlg), FALSE);
+       /*Set app_name & state_save related tags to the window */
+
+       size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+       name_label = gtk_label_new(contact_name);
+       gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0);
+       cptn_cntrl =
+           hildon_caption_new(size_group, _("mcen_ia_add_email_name"), name_label, NULL,
+                              HILDON_CAPTION_OPTIONAL);
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(add_email_addr_to_contact_dlg)->vbox), cptn_cntrl,
+                          FALSE, FALSE, 0);
+
+       email_entry = gtk_entry_new();
+       cptn_cntrl =
+           hildon_caption_new(size_group, _("mcen_fi_add_email_name"), email_entry, NULL,
+                              HILDON_CAPTION_OPTIONAL);
+       hildon_gtk_entry_set_input_mode(GTK_ENTRY(email_entry), HILDON_GTK_INPUT_MODE_FULL);
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(add_email_addr_to_contact_dlg)->vbox), cptn_cntrl,
+                          TRUE, TRUE, 0);
+
+       gtk_widget_show_all(add_email_addr_to_contact_dlg);
+
+       while (run_dialog) {
+               run_dialog = FALSE;
+               gtk_widget_grab_focus(email_entry);
+               result = gtk_dialog_run(GTK_DIALOG(add_email_addr_to_contact_dlg));
+
+               if (result == GTK_RESPONSE_ACCEPT) {
+                       const gchar *invalid_char_offset = NULL;
+                       new_email_addr = g_strdup(gtk_entry_get_text(GTK_ENTRY(email_entry)));
+                       new_email_addr = g_strstrip(new_email_addr);
+                       if (!modest_text_utils_validate_email_address (new_email_addr, &invalid_char_offset)) {
+                               gtk_widget_grab_focus(email_entry);
+                               if ((invalid_char_offset != NULL)&&(*invalid_char_offset != '\0')) {
+                                       gchar *char_in_string = g_strdup_printf ("%c", *invalid_char_offset);
+                                       gchar *message = g_strdup_printf(
+                                               dgettext("hildon-common-strings", "ckdg_ib_illegal_characters_entered"), 
+                                               char_in_string);
+                                       hildon_banner_show_information (
+                                               add_email_addr_to_contact_dlg, NULL, message );
+                                       g_free (message);
+                               } else {
+                                       hildon_banner_show_information (add_email_addr_to_contact_dlg, NULL, _("mcen_ib_invalid_email"));
+                                       run_dialog = TRUE;
+                               }
+                               gtk_editable_select_region((GtkEditable *) email_entry, 0, -1);
+                               g_free(new_email_addr);
+                               new_email_addr = NULL;
+                       }
+               }
+       }
+
+       gtk_widget_destroy(add_email_addr_to_contact_dlg);
+
+       return new_email_addr;
+}
+
+/**
+ * This is helper function to create & run 'Select e-mail address' dialog, used when
+ * multiple e-mail addresses are found for a selected contact. It allows user to select
+ * one or more e-mail addresses for that contact.
+ *
+ * @param  email_addr_list  List of e-mail addresses for that contact
+ * @return List of user selected e-mail addresses, to be freed by calling function.
+ */
+static GSList *
+select_email_addrs_for_contact(GList * email_addr_list)
+{
+       GtkWidget *select_email_addr_dlg = NULL;
+       GtkWidget *view = NULL, *scrolledwindow = NULL;
+       GtkTreeSelection *selection = NULL;
+       GtkCellRenderer *renderer = NULL;
+       GtkTreeViewColumn *col = NULL;
+       GtkListStore *list_store = NULL;
+       GtkTreeModel *model = NULL;
+       GtkTreeIter iter;
+       GList *pathslist = NULL, *node = NULL;
+       gint result = -1;
+       gchar *email_addr = NULL;
+       GSList *selected_email_addr_list = NULL;
+
+       if (!email_addr_list)
+               return NULL;
+
+       select_email_addr_dlg =
+           gtk_dialog_new_with_buttons(_("mcen_ti_select_email_title"),
+                                       NULL,
+                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT,
+                                       _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT, NULL);
+       gtk_dialog_set_has_separator(GTK_DIALOG(select_email_addr_dlg), FALSE);
+
+       /* Make the window approximately big enough, because it doesn't resize to be big enough 
+        * for the window title text: */
+       gtk_window_set_default_size (GTK_WINDOW (select_email_addr_dlg), 400, -1);
+
+       scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(select_email_addr_dlg)->vbox), scrolledwindow, TRUE,
+                          TRUE, 0);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+
+       view = gtk_tree_view_new();
+       col = gtk_tree_view_column_new();
+       renderer = gtk_cell_renderer_text_new();
+       gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
+       gtk_tree_view_column_pack_start(col, renderer, TRUE);
+       gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+       gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+       gtk_container_add(GTK_CONTAINER(scrolledwindow), view);
+
+       list_store = gtk_list_store_new(1, G_TYPE_STRING);
+       model = GTK_TREE_MODEL(list_store);
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
+
+       for (node = email_addr_list; node != NULL && node->data != NULL; node = node->next) {
+               email_addr = g_strstrip(g_strdup(node->data));
+               gtk_list_store_append(list_store, &iter);
+               gtk_list_store_set(list_store, &iter, 0, email_addr, -1);
+               g_free(email_addr);
+       }
+       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter);
+       gtk_tree_selection_select_iter (selection, &iter);
+
+       gtk_widget_show_all(select_email_addr_dlg);
+       result = gtk_dialog_run(GTK_DIALOG(select_email_addr_dlg));
+
+       if (result == GTK_RESPONSE_ACCEPT) {
+               pathslist = gtk_tree_selection_get_selected_rows(selection, NULL);
+               for (node = pathslist; node != NULL; node = node->next) {
+                       if (gtk_tree_model_get_iter(model, &iter, (GtkTreePath *) node->data)) {
+                               gtk_tree_model_get(model, &iter, 0, &email_addr, -1);
+                               selected_email_addr_list =
+                                   g_slist_append(selected_email_addr_list, g_strdup(email_addr));
+                               g_free(email_addr);
+                       }
+               }
+       }
+
+       gtk_list_store_clear(list_store);
+       gtk_widget_destroy(select_email_addr_dlg);
+       return selected_email_addr_list;
+}
+
+
+static gboolean /* make this public? */
+add_to_address_book (const gchar* address)
+{
+       EBookQuery *query;
+       GList *contacts = NULL;
+       GError *err = NULL;
+       gchar *email;
+       
+       g_return_val_if_fail (address, FALSE);
+       
+       if (!book)
+               open_addressbook ();
+       
+       g_return_val_if_fail (book, FALSE);
+
+       email = modest_text_utils_get_email_address (address);
+       
+       query = e_book_query_field_test (E_CONTACT_EMAIL, E_BOOK_QUERY_IS, email);
+       if (!e_book_get_contacts (book, query, &contacts, &err)) {
+               g_printerr ("modest: failed to get contacts: %s",
+                           err ? err->message : "<unknown>");
+               if (err)
+                       g_error_free (err);
+               return FALSE;
+       }
+       e_book_query_unref (query);
+       
+       /*  we need to 'commit' it, even if we already found the email
+        * address in the addressbook; thus, it will show up in the 'recent list' */
+       if (contacts)  {                
+               g_debug ("%s already in the address book", address);
+               commit_contact ((EContact*)contacts->data, FALSE);
+               
+               g_list_foreach (contacts, (GFunc)unref_gobject, NULL);
+               g_list_free (contacts);
+
+       } else {
+               /* it's not yet in the addressbook, add it now! */
+               EContact *new_contact = e_contact_new ();
+               gchar *display_address;
+               display_address = g_strdup (address);
+               if (display_address) {
+                       modest_text_utils_get_display_address (display_address);
+                       if ((display_address[0] != '\0') && (strlen (display_address) != strlen (address)))
+                               e_contact_set (new_contact, E_CONTACT_FULL_NAME, (const gpointer)display_address);
+               }
+               e_contact_set (new_contact, E_CONTACT_EMAIL_1, (const gpointer)email);
+               g_free (display_address);
+               commit_contact (new_contact, TRUE);
+               g_debug ("%s added to address book", address);
+               g_object_unref (new_contact);
+       }
+
+       g_free (email);
+
+       return TRUE;
+}
+
+static gboolean
+show_check_names_banner (gpointer userdata)
+{
+       GtkWidget **banner = (GtkWidget **) userdata;
+
+       gdk_threads_enter ();
+       *banner = modest_platform_animation_banner (NULL, NULL, _("mail_ib_checking_names"));
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+static void
+hide_check_names_banner (GtkWidget **banner, guint banner_timeout)
+{
+       if (*banner != NULL) {
+               gtk_widget_destroy (*banner);
+               *banner = NULL;
+       } else {
+               g_source_remove (banner_timeout);
+       }
+
+}
+
+gboolean
+modest_address_book_check_names (ModestRecptEditor *recpt_editor, gboolean update_addressbook)
+{
+       const gchar *recipients = NULL;
+       GSList *start_indexes = NULL, *end_indexes = NULL;
+       GSList *current_start, *current_end;
+       gboolean result = TRUE;
+       GtkTextBuffer *buffer;
+       gint offset_delta = 0;
+       gint last_length;
+       GtkTextIter start_iter, end_iter;
+
+       g_return_val_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor), FALSE);
+
+       recipients = modest_recpt_editor_get_recipients (recpt_editor);
+       last_length = g_utf8_strlen (recipients, -1);
+       modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
+
+       if (start_indexes == NULL) {
+               if (last_length != 0) {
+                       hildon_banner_show_information (NULL, NULL, _("mcen_nc_no_matching_contacts"));
+                       return FALSE;
+               } else {
+                       return TRUE;
+               }
+       }
+
+       current_start = start_indexes;
+       current_end = end_indexes;
+       buffer = modest_recpt_editor_get_buffer (recpt_editor);
+
+       while (current_start != NULL) {
+               gchar *address;
+               gchar *start_ptr, *end_ptr;
+               gint start_pos, end_pos;
+               const gchar *invalid_char_position = NULL;
+               gboolean store_address = FALSE;
+
+               start_pos = (*((gint*) current_start->data)) + offset_delta;
+               end_pos = (*((gint*) current_end->data)) + offset_delta;
+              
+               start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
+               end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
+
+               address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
+               gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_pos);
+               gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end_pos);
+               gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+
+               if (!modest_text_utils_validate_recipient (address, &invalid_char_position)) {
+                       if ((invalid_char_position != NULL) && (*invalid_char_position != '\0')) {
+                               gchar *char_in_string = g_strdup_printf("%c", *invalid_char_position);
+                               gchar *message = g_strdup_printf(
+                                       dgettext("hildon-common-strings", "ckdg_ib_illegal_characters_entered"), 
+                                       char_in_string);
+                               g_free (char_in_string);
+                               hildon_banner_show_information (NULL, NULL, message );
+                               g_free (message);                               
+                               result = FALSE;
+                       } else if (strstr (address, "@") == NULL) {
+                               /* here goes searching in addressbook */
+                               gchar *contact_id = NULL;
+                               GSList *resolved_addresses = NULL;
+
+                               result = resolve_address (address, &resolved_addresses, &contact_id);
+
+                               if (result) {
+                                       gint new_length;
+                                       /* replace string */
+                                       modest_recpt_editor_replace_with_resolved_recipient (recpt_editor,
+                                                                                            &start_iter, &end_iter,
+                                                                                            resolved_addresses, 
+                                                                                            contact_id);
+                                       g_free (contact_id);
+                                       g_slist_foreach (resolved_addresses, (GFunc) g_free, NULL);
+                                       g_slist_free (resolved_addresses);
+
+                                       /* update offset delta */
+                                       recipients = modest_recpt_editor_get_recipients (recpt_editor);
+                                       new_length = g_utf8_strlen (recipients, -1);
+                                       offset_delta = offset_delta + new_length - last_length;
+                                       last_length = new_length;                                       
+                               }
+                       } else {
+                               /* this address is not valid, select it and return control to user showing banner */
+                               hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_email"));
+                               result = FALSE;
+                       }
+               } else {
+                       GSList *tags, *node;
+                       gboolean has_recipient = FALSE;
+
+                       tags = gtk_text_iter_get_tags (&start_iter);
+                       for (node = tags; node != NULL; node = g_slist_next (node)) {
+                               GtkTextTag *tag = GTK_TEXT_TAG (node->data);
+                               if (g_object_get_data (G_OBJECT (tag), "recipient-tag-id") != NULL) {
+                                       has_recipient = TRUE;
+                                       break;
+                               }
+                       }
+                       g_slist_free (tags);
+                       if (!has_recipient) {
+                               GSList * address_list = NULL;
+
+                               address_list = g_slist_prepend (address_list, address);
+                               modest_recpt_editor_replace_with_resolved_recipient (recpt_editor,
+                                                                                    &start_iter, &end_iter,
+                                                                                    address_list, 
+                                                                                    "");
+                               g_slist_free (address_list);
+                               store_address = TRUE;
+                       }
+               }
+
+               /* so, it seems a valid address */
+               /* note: adding it the to the addressbook if it did not exist yet,
+                * and adding it to the recent_list */
+               if (result && update_addressbook && store_address)
+                       add_to_address_book (address);
+
+               g_free (address);
+               if (result == FALSE)
+                       break;
+
+               current_start = g_slist_next (current_start);
+               current_end = g_slist_next (current_end);
+       }
+
+       if (current_start == NULL) {
+               gtk_text_buffer_get_end_iter (buffer, &end_iter);
+               gtk_text_buffer_place_cursor (buffer, &end_iter);
+       }
+
+       g_slist_foreach (start_indexes, (GFunc) g_free, NULL);
+       g_slist_foreach (end_indexes, (GFunc) g_free, NULL);
+       g_slist_free (start_indexes);
+       g_slist_free (end_indexes);
+
+       return result;
+
+}
+
+static GList *
+get_contacts_for_name (const gchar *name)
+{
+       EBookQuery *full_name_book_query = NULL;
+       GList *result;
+       gchar *unquoted;
+
+       if (name == NULL)
+               return NULL;
+
+       unquoted = unquote_string (name);
+       full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted);
+       g_free (unquoted);
+
+       e_book_get_contacts (book, full_name_book_query, &result, NULL);
+       e_book_query_unref (full_name_book_query);
+
+       return result;
+}
+
+static GList *
+select_contacts_for_name_dialog (const gchar *name)
+{
+       EBookQuery *full_name_book_query = NULL;
+       EBookView *book_view = NULL;
+       GList *result = NULL;
+       gchar *unquoted;
+
+       unquoted = unquote_string (name);
+       full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted);
+       g_free (unquoted);
+       e_book_get_book_view (book, full_name_book_query, NULL, -1, &book_view, NULL);
+       e_book_query_unref (full_name_book_query);
+
+       if (book_view) {
+               GtkWidget *contact_view = NULL;
+               GtkWidget *contact_dialog = NULL;
+#if MODEST_ABOOK_API < 4
+               osso_abook_tree_model_set_book_view (OSSO_ABOOK_TREE_MODEL (contact_model), book_view);
+#else /* MODEST_ABOOK_API < 4 */
+               osso_abook_list_store_set_book_view (OSSO_ABOOK_LIST_STORE (contact_model), book_view);
+#endif /* MODEST_ABOOK_API < 4 */
+               e_book_view_start (book_view);
+               
+               contact_view = osso_abook_contact_selector_new_basic (contact_model);
+               contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view));
+               gtk_window_set_title (GTK_WINDOW (contact_dialog), _("mcen_ti_select_recipients"));
+
+               if (gtk_dialog_run (GTK_DIALOG (contact_dialog)) == GTK_RESPONSE_OK) {
+                       result = osso_abook_contact_view_get_selection (OSSO_ABOOK_CONTACT_VIEW (contact_view));
+               }
+               e_book_view_stop (book_view);
+               g_object_unref (book_view);
+               gtk_widget_destroy (contact_dialog);
+       }
+
+       return result;
+}
+
+static gboolean
+resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id)
+{
+       GList *resolved_contacts;
+       guint banner_timeout;
+       GtkWidget *banner = NULL;
+       
+       banner_timeout = g_timeout_add (500, show_check_names_banner, &banner);
+
+       contact_model = osso_abook_contact_model_new ();
+       if (!open_addressbook_sync ()) {
+               if (contact_model) {
+                       g_object_unref (contact_model);
+                       contact_model = NULL;
+               }
+               return FALSE;
+       }
+
+       resolved_contacts = get_contacts_for_name (address);
+
+       if (resolved_contacts == NULL) {
+               /* no matching contacts for the search string */
+               modest_platform_run_information_dialog (NULL, _("mcen_nc_no_matching_contacts"), FALSE);
+               hide_check_names_banner (&banner, banner_timeout);
+     
+               return FALSE;
+       }
+
+       if (g_list_length (resolved_contacts) > 1) {
+               /* show a dialog to select the contact from the resolved ones */
+               g_list_free (resolved_contacts);
+
+               hide_check_names_banner (&banner, banner_timeout);     
+               resolved_contacts = select_contacts_for_name_dialog (address);
+               banner_timeout = g_timeout_add (500, show_check_names_banner, &banner);
+
+       }
+       
+       /* get the resolved contacts (can be no contact) */
+       if (resolved_contacts) {
+               gboolean found;
+               EContact *contact = (EContact *) resolved_contacts->data;
+
+               *resolved_addresses = get_recipients_for_given_contact (contact);
+               hide_check_names_banner (&banner, banner_timeout);     
+               if (*resolved_addresses) {
+                       *contact_id = g_strdup (e_contact_get_const (contact, E_CONTACT_UID));
+                       found = TRUE;
+               } else {
+                       found = FALSE;
+               }
+
+               g_list_foreach (resolved_contacts, (GFunc)unref_gobject, NULL);
+               g_list_free (resolved_contacts);
+
+               return found;
+       } else {
+               /* cancelled dialog to select more than one contact or
+                * selected no contact */
+               hide_check_names_banner (&banner, banner_timeout);     
+               return FALSE;
+       }
+
+}
+
+static gchar *
+unquote_string (const gchar *str)
+{
+       GString *buffer;
+       gchar *p;
+
+       if (str == NULL)
+               return NULL;
+
+       buffer = g_string_new_len (NULL, strlen (str));
+       for (p = (gchar *) str; *p != '\0'; p = g_utf8_next_char (p)) {
+               if (*p == '"') {
+                       p = g_utf8_next_char (p);
+                       while ((*p != '\0')&&(*p != '"')) {
+                               if (*p == '\\') {
+                                       g_string_append_unichar (buffer, g_utf8_get_char (p));
+                                       p = g_utf8_next_char (p);
+                                       
+                               }
+                               g_string_append_unichar (buffer, g_utf8_get_char (p));
+                               p = g_utf8_next_char (p);
+                       }
+               } else {
+                       g_string_append_unichar (buffer, g_utf8_get_char (p));
+               }
+       }
+
+       return g_string_free (buffer, FALSE);
+
+}
diff --git a/src/hildon2/modest-connection-specific-smtp-edit-window.c b/src/hildon2/modest-connection-specific-smtp-edit-window.c
new file mode 100644 (file)
index 0000000..37886bc
--- /dev/null
@@ -0,0 +1,525 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-connection-specific-smtp-edit-window.h"
+#include "widgets/modest-ui-constants.h"
+#include "modest-hildon-includes.h"
+#include "modest-runtime.h"
+
+#include "widgets/modest-serversecurity-combo-box.h"
+#include "widgets/modest-secureauth-combo-box.h"
+#include "widgets/modest-validating-entry.h"
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkstock.h>
+#include "modest-text-utils.h"
+#include "modest-maemo-utils.h"
+
+#include <glib/gi18n.h>
+
+#define PORT_RANGE_MIN 1
+#define PORT_RANGE_MAX 65535
+
+G_DEFINE_TYPE (ModestConnectionSpecificSmtpEditWindow, modest_connection_specific_smtp_edit_window, GTK_TYPE_DIALOG);
+
+#define CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW, ModestConnectionSpecificSmtpEditWindowPrivate))
+
+static void on_response (GtkDialog *dialog,
+                        gint arg1,
+                        gpointer user_data);
+
+typedef struct _ModestConnectionSpecificSmtpEditWindowPrivate ModestConnectionSpecificSmtpEditWindowPrivate;
+
+struct _ModestConnectionSpecificSmtpEditWindowPrivate
+{
+       GtkWidget *entry_outgoingserver;
+       GtkWidget *combo_outgoing_auth;
+       GtkWidget *entry_user_username;
+       GtkWidget *entry_user_password;
+       GtkWidget *combo_outgoing_security;
+       GtkWidget *entry_port;
+       
+       GtkWidget *button_ok;
+       GtkWidget *button_cancel;
+
+       gchar     *account_name;
+       
+       gboolean is_dirty;
+       gboolean range_error_occured;
+       guint range_error_banner_timeout;
+};
+
+static void
+modest_connection_specific_smtp_edit_window_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_connection_specific_smtp_edit_window_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_connection_specific_smtp_edit_window_dispose (GObject *object)
+{
+
+       
+       if (G_OBJECT_CLASS (modest_connection_specific_smtp_edit_window_parent_class)->dispose)
+               G_OBJECT_CLASS (modest_connection_specific_smtp_edit_window_parent_class)->dispose (object);
+}
+
+static void
+modest_connection_specific_smtp_edit_window_finalize (GObject *object)
+{
+       ModestConnectionSpecificSmtpEditWindow *self = (ModestConnectionSpecificSmtpEditWindow *) object;
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+
+       if (priv->range_error_banner_timeout > 0) {
+               g_source_remove (priv->range_error_banner_timeout);
+               priv->range_error_banner_timeout = 0;
+       }
+       if (priv->account_name) {
+               g_free (priv->account_name);
+               priv->account_name = NULL;
+       }
+       G_OBJECT_CLASS (modest_connection_specific_smtp_edit_window_parent_class)->finalize (object);
+}
+
+static void
+modest_connection_specific_smtp_edit_window_class_init (ModestConnectionSpecificSmtpEditWindowClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (ModestConnectionSpecificSmtpEditWindowPrivate));
+
+       object_class->get_property = modest_connection_specific_smtp_edit_window_get_property;
+       object_class->set_property = modest_connection_specific_smtp_edit_window_set_property;
+       object_class->dispose = modest_connection_specific_smtp_edit_window_dispose;
+       object_class->finalize = modest_connection_specific_smtp_edit_window_finalize;
+}
+
+enum MODEL_COLS {
+       MODEL_COL_NAME = 0,
+       MODEL_COL_SERVER_NAME = 1,
+       MODEL_COL_ID = 2
+};
+
+static void
+on_change(GtkWidget* widget, ModestConnectionSpecificSmtpEditWindow *self)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+       priv->is_dirty = TRUE;
+}
+
+static void
+on_value_changed(GtkWidget* widget, GValue* value, ModestConnectionSpecificSmtpEditWindow *self)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+
+       priv->range_error_occured = FALSE;
+       on_change(widget, self);
+}
+
+gboolean
+show_banner_handler (gpointer userdata)
+{
+       ModestConnectionSpecificSmtpEditWindow *self = userdata;
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+       gchar *msg;
+
+       msg = g_strdup_printf (dgettext("hildon-libs", "ckct_ib_set_a_value_within_range"), PORT_RANGE_MIN, PORT_RANGE_MAX);
+
+       hildon_banner_show_information (NULL, NULL, msg);
+       g_free (msg);
+
+       priv->range_error_banner_timeout = 0;
+       return FALSE;
+}
+
+static gboolean
+on_range_error (GtkWidget *widget, HildonNumberEditorErrorType type, gpointer user_data)
+{
+       ModestConnectionSpecificSmtpEditWindow *self = user_data;
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+
+       /* We want to prevent the closure of the dialog when a range error occured. The problem is that
+        * the hildon number editor already resets the value to the default value, so we have to
+        * remember that such an error occured. */
+       priv->range_error_occured = TRUE;
+       if (priv->range_error_banner_timeout == 0)
+               priv->range_error_banner_timeout = g_timeout_add (200, show_banner_handler, self);
+
+       /* Show error message by not returning TRUE */
+       return TRUE;
+}
+
+static void
+on_response (GtkDialog *dialog, int response_id, gpointer user_data)
+{
+       const gchar *hostname;
+       ModestConnectionSpecificSmtpEditWindow *self = user_data;
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+
+       hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
+
+       if ((response_id == GTK_RESPONSE_CANCEL) &&
+           (priv->range_error_banner_timeout > 0)) {
+               g_source_remove (priv->range_error_banner_timeout);
+               priv->range_error_banner_timeout = 0;
+       }
+
+       /* Don't close the dialog if a range error occured */
+       if(response_id == GTK_RESPONSE_OK && priv->range_error_occured)
+       {
+               priv->range_error_occured = FALSE;
+               g_signal_stop_emission_by_name (dialog, "response");
+               gtk_widget_grab_focus (priv->entry_port);
+               return;
+       }
+
+       /* Don't close the dialog if a range error occured */
+       if(response_id == GTK_RESPONSE_OK) {
+               if (hostname && (hostname[0] != '\0') &&
+                   (!modest_text_utils_validate_domain_name (hostname))) { 
+                       g_signal_stop_emission_by_name (dialog, "response");
+                       hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_servername"));
+                       gtk_widget_grab_focus (priv->entry_outgoingserver);
+                       gtk_editable_select_region (GTK_EDITABLE (priv->entry_outgoingserver), 0, -1);
+                       return;
+               }
+       } else {
+               /* Ask user if they want to discard changes */
+               if (priv->is_dirty) {
+                       gint response;
+                       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (user_data), 
+                                                                           _("imum_nc_wizard_confirm_lose_changes"));
+                       if (response == GTK_RESPONSE_CANCEL)
+                               g_signal_stop_emission_by_name (dialog, "response");
+               }
+       }
+}
+
+static void on_set_focus_child (GtkContainer *container, GtkWidget *widget, gpointer user_data)
+{
+       ModestConnectionSpecificSmtpEditWindow *self = user_data;
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv =
+                       CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+
+       /* Another child gained focus. Since the number editor already reset a
+        * possible range error to the default value, we allow closure of the
+        * dialog */
+       priv->range_error_occured = FALSE;
+}
+
+static void
+on_combo_security_changed (GtkComboBox *widget, gpointer user_data)
+{
+       ModestConnectionSpecificSmtpEditWindow *self = 
+               MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW (user_data);
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+       
+       on_change(GTK_WIDGET(widget), self);
+       
+       const gint port_number = 
+               modest_serversecurity_combo_box_get_active_serversecurity_port (
+                       MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security));
+
+       if(port_number != 0) {
+               hildon_number_editor_set_value (
+                       HILDON_NUMBER_EDITOR (priv->entry_port), port_number);
+       }               
+}
+
+static void
+modest_connection_specific_smtp_edit_window_init (ModestConnectionSpecificSmtpEditWindow *self)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv; 
+       GtkWidget *dialog_box;
+       GtkWidget *scrolled_window, *vbox;
+
+       /* The title of this dialog is quite long, so make the window wide enough */
+       gtk_widget_set_size_request (GTK_WIDGET (self), 600, -1);
+
+       priv = CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (self);
+       dialog_box = GTK_DIALOG(self)->vbox; /* gtk_vbox_new (FALSE, MODEST_MARGIN_HALF); */
+       gtk_box_set_spacing (GTK_BOX (dialog_box), MODEST_MARGIN_NONE);
+       gtk_container_set_border_width (GTK_CONTAINER (dialog_box), MODEST_MARGIN_HALF);
+
+       vbox = gtk_vbox_new (FALSE, 0);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The outgoing server widgets: */
+       if (!priv->entry_outgoingserver)
+               priv->entry_outgoingserver = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_outgoingserver), HILDON_GTK_INPUT_MODE_FULL);
+       g_signal_connect(G_OBJECT(priv->entry_outgoingserver), "changed", G_CALLBACK(on_change), self);
+       
+       GtkWidget *caption = hildon_caption_new (sizegroup, 
+               _("mcen_li_emailsetup_smtp"), priv->entry_outgoingserver, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->entry_outgoingserver);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The secure authentication widgets: */
+       if (!priv->combo_outgoing_auth)
+               priv->combo_outgoing_auth = GTK_WIDGET (modest_secureauth_combo_box_new ());
+       caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_authentication"), 
+               priv->combo_outgoing_auth, NULL, HILDON_CAPTION_OPTIONAL);
+       g_signal_connect (G_OBJECT (priv->combo_outgoing_auth), "changed", G_CALLBACK(on_change), self);
+       gtk_widget_show (priv->combo_outgoing_auth);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The username widgets: */     
+       priv->entry_user_username = GTK_WIDGET (modest_validating_entry_new ());
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_username), HILDON_GTK_INPUT_MODE_FULL);
+       caption = hildon_caption_new (sizegroup, _("mail_fi_username"), 
+               priv->entry_user_username, NULL, HILDON_CAPTION_MANDATORY);
+       g_signal_connect(G_OBJECT(priv->entry_user_username), "changed", G_CALLBACK(on_change), self);
+       gtk_widget_show (priv->entry_user_username);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the username, 
+        * as required by our UI specification: */
+       modest_validating_entry_set_unallowed_characters_whitespace (
+               MODEST_VALIDATING_ENTRY (priv->entry_user_username));
+       
+       /* Set max length as in the UI spec:
+        * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_username), 64);
+       
+       /* The password widgets: */     
+       priv->entry_user_password = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_password), 
+               HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
+       gtk_entry_set_visibility (GTK_ENTRY (priv->entry_user_password), FALSE);
+       /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_user_password), '*'); */
+       caption = hildon_caption_new (sizegroup, 
+               _("mail_fi_password"), priv->entry_user_password, NULL, HILDON_CAPTION_OPTIONAL);
+       g_signal_connect(G_OBJECT(priv->entry_user_password), "changed", G_CALLBACK(on_change), self);
+       gtk_widget_show (priv->entry_user_password);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The secure connection widgets: */    
+       if (!priv->combo_outgoing_security)
+               priv->combo_outgoing_security = GTK_WIDGET (modest_serversecurity_combo_box_new ());
+       modest_serversecurity_combo_box_fill (
+               MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security), MODEST_PROTOCOLS_TRANSPORT_SMTP);
+       modest_serversecurity_combo_box_set_active_serversecurity (
+               MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security), MODEST_PROTOCOLS_CONNECTION_NONE);
+       caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_connection"), 
+               priv->combo_outgoing_security, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->combo_outgoing_security);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The port number widgets: */
+       if (!priv->entry_port)
+               priv->entry_port = GTK_WIDGET (hildon_number_editor_new (PORT_RANGE_MIN, PORT_RANGE_MAX));
+       caption = hildon_caption_new (sizegroup, 
+               _("mcen_fi_emailsetup_port"), priv->entry_port, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_add_events(GTK_WIDGET(priv->entry_port), GDK_FOCUS_CHANGE_MASK);
+       g_signal_connect(G_OBJECT(priv->entry_port), "range-error", G_CALLBACK(on_range_error), self);
+       g_signal_connect(G_OBJECT(priv->entry_port), "notify::value", G_CALLBACK(on_value_changed), self);
+       gtk_widget_show (priv->entry_port);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Show a default port number when the security method changes, as per the UI spec: */
+       g_signal_connect (G_OBJECT (priv->combo_outgoing_security), "changed", (GCallback)on_combo_security_changed, self);
+       on_combo_security_changed (GTK_COMBO_BOX (priv->combo_outgoing_security), self);
+       
+       /* Add the buttons: */
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK);
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL);
+       
+       priv->is_dirty = FALSE;
+       priv->range_error_occured = FALSE;
+       g_signal_connect(G_OBJECT(self), "response", G_CALLBACK(on_response), self);
+       g_signal_connect(G_OBJECT(vbox), "set-focus-child", G_CALLBACK(on_set_focus_child), self);
+
+       priv->range_error_banner_timeout = 0;
+       priv->account_name = NULL;
+
+       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), vbox);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       gtk_box_pack_start (GTK_BOX (dialog_box), scrolled_window, TRUE, TRUE, 0);
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (vbox), 
+                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
+       
+       gtk_widget_show_all (dialog_box);
+       gtk_window_set_default_size (GTK_WINDOW (self), -1, 220);
+       
+       
+       /* When this window is shown, hibernation should not be possible, 
+        * because there is no sensible way to save the state: */
+       modest_window_mgr_prevent_hibernation_while_window_is_shown (
+               modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
+       
+       hildon_help_dialog_help_enable (GTK_DIALOG(self),
+                                       "applications_email_connectionspecificsmtpconf",
+                                       modest_maemo_utils_get_osso_context());
+}
+
+ModestConnectionSpecificSmtpEditWindow*
+modest_connection_specific_smtp_edit_window_new (void)
+{
+       return g_object_new (MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW, NULL);
+}
+
+void
+modest_connection_specific_smtp_edit_window_set_connection (
+       ModestConnectionSpecificSmtpEditWindow *window, const gchar* iap_id, const gchar* iap_name,
+       ModestServerAccountSettings *server_settings)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (window);
+
+       /* This causes a warning because of the %s in the translation, but not in the original string: */
+       gchar* title = g_strdup_printf (_("mcen_ti_connection_connection_name"), iap_name);
+       gtk_window_set_title (GTK_WINDOW (window), title);
+       g_free (title);
+
+       if (server_settings) 
+       {
+               
+               if (priv->account_name)
+                       g_free (priv->account_name);
+               priv->account_name = g_strdup (modest_server_account_settings_get_account_name (server_settings));
+               gtk_entry_set_text (GTK_ENTRY (priv->entry_outgoingserver), 
+                                   modest_server_account_settings_get_hostname (server_settings));
+               gtk_entry_set_text (GTK_ENTRY (priv->entry_user_username),
+                                   modest_server_account_settings_get_username (server_settings));     
+               gtk_entry_set_text (GTK_ENTRY (priv->entry_user_password), 
+                                   modest_server_account_settings_get_password (server_settings));
+       
+               modest_serversecurity_combo_box_set_active_serversecurity (
+               MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security), 
+               modest_server_account_settings_get_security_protocol (server_settings));
+       
+               modest_secureauth_combo_box_set_active_secureauth (
+               MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth), 
+               modest_server_account_settings_get_auth_protocol (server_settings));
+               
+               /* port: */
+               hildon_number_editor_set_value (
+                       HILDON_NUMBER_EDITOR (priv->entry_port), 
+                       modest_server_account_settings_get_port (server_settings));
+               
+               
+               /* This will cause changed signals so we set dirty back to FALSE */
+               priv->is_dirty = FALSE;
+               if (priv->range_error_banner_timeout > 0) {
+                       g_source_remove (priv->range_error_banner_timeout);
+                       priv->range_error_banner_timeout = 0;
+               }
+       
+       }
+}
+
+ModestServerAccountSettings*
+modest_connection_specific_smtp_edit_window_get_settings (ModestConnectionSpecificSmtpEditWindow *window)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv = NULL;
+       ModestServerAccountSettings *server_settings = NULL;
+       const gchar *outgoing_server = NULL;
+
+       priv =  CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (window);
+       outgoing_server = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
+
+       /* If the outgoing server is NULL, we are removing the connection specific
+        * settings */
+       if ((outgoing_server == NULL) || (outgoing_server[0] == '\0')) {
+               return NULL;
+       }
+       
+       server_settings = modest_server_account_settings_new ();
+       
+       modest_server_account_settings_set_hostname (server_settings, 
+                                                    gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver)));
+       modest_server_account_settings_set_protocol (server_settings,
+                                                    MODEST_PROTOCOLS_TRANSPORT_SMTP);
+       modest_server_account_settings_set_username (server_settings,
+                                                    gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username)));
+       modest_server_account_settings_set_password (server_settings,
+                                                    gtk_entry_get_text (GTK_ENTRY (priv->entry_user_password)));
+       
+       modest_server_account_settings_set_security_protocol (server_settings, 
+                                                    modest_serversecurity_combo_box_get_active_serversecurity (
+                                                    MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security)));
+       modest_server_account_settings_set_auth_protocol (server_settings,
+                                                         modest_secureauth_combo_box_get_active_secureauth (
+                                                         MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth)));
+       modest_server_account_settings_set_account_name (server_settings,
+                                                        priv->account_name);
+       
+       /* port: */
+       modest_server_account_settings_set_port (server_settings,
+                                                hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (priv->entry_port)));
+                       
+       return server_settings;
+}
+
+gboolean 
+modest_connection_specific_smtp_edit_window_is_dirty(ModestConnectionSpecificSmtpEditWindow *window)
+{
+       ModestConnectionSpecificSmtpEditWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       return priv->is_dirty;
+}
diff --git a/src/hildon2/modest-connection-specific-smtp-edit-window.h b/src/hildon2/modest-connection-specific-smtp-edit-window.h
new file mode 100644 (file)
index 0000000..4efcee5
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW
+#define __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW
+
+#include <gtk/gtkdialog.h>
+#include <gtk/gtktreeview.h>
+#include <modest-server-account-settings.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW modest_connection_specific_smtp_edit_window_get_type()
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW, ModestConnectionSpecificSmtpEditWindow))
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW, ModestConnectionSpecificSmtpEditWindowClass))
+
+#define MODEST_IS_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW))
+
+#define MODEST_IS_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW))
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW, ModestConnectionSpecificSmtpEditWindowClass))
+
+typedef struct {
+       GtkDialog parent;
+       
+} ModestConnectionSpecificSmtpEditWindow;
+
+typedef struct {
+       GtkDialogClass parent_class;
+} ModestConnectionSpecificSmtpEditWindowClass;
+
+GType modest_connection_specific_smtp_edit_window_get_type (void);
+
+ModestConnectionSpecificSmtpEditWindow* modest_connection_specific_smtp_edit_window_new (void);
+
+void modest_connection_specific_smtp_edit_window_set_connection (
+       ModestConnectionSpecificSmtpEditWindow *window, const gchar* iap_id, const gchar* iap_name, 
+       ModestServerAccountSettings *server_settings);
+       
+ModestServerAccountSettings* modest_connection_specific_smtp_edit_window_get_settings (
+       ModestConnectionSpecificSmtpEditWindow *window);
+
+gboolean modest_connection_specific_smtp_edit_window_is_dirty(
+       ModestConnectionSpecificSmtpEditWindow *window);
+       
+G_END_DECLS
+
+#endif /* __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_WINDOW */
diff --git a/src/hildon2/modest-connection-specific-smtp-window.c b/src/hildon2/modest-connection-specific-smtp-window.c
new file mode 100644 (file)
index 0000000..3f98ded
--- /dev/null
@@ -0,0 +1,581 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-connection-specific-smtp-window.h"
+#include "modest-connection-specific-smtp-edit-window.h"
+#include <modest-account-mgr-helpers.h>
+#include "widgets/modest-ui-constants.h"
+
+#include <modest-runtime.h>
+#include <tny-maemo-conic-device.h>
+
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkstock.h>
+
+#include "modest-hildon-includes.h"
+#include "modest-platform.h"
+#include "modest-maemo-utils.h"
+
+#include <glib/gi18n.h>
+#include <string.h>
+
+G_DEFINE_TYPE (ModestConnectionSpecificSmtpWindow, modest_connection_specific_smtp_window,
+              GTK_TYPE_DIALOG);
+
+#define CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW, ModestConnectionSpecificSmtpWindowPrivate))
+
+typedef struct _ModestConnectionSpecificSmtpWindowPrivate ModestConnectionSpecificSmtpWindowPrivate;
+
+struct _ModestConnectionSpecificSmtpWindowPrivate
+{
+       GtkTreeView *treeview;
+       GtkTreeModel *model;
+       GtkWidget *button_edit;
+       
+       ModestAccountMgr *account_manager;
+};
+
+static void on_response (GtkDialog *dialog, 
+                        gint response, 
+                        gpointer user_data);
+
+/* static gboolean on_key_pressed (GtkWidget *self, GdkEventKey *event, gpointer user_data); */
+
+static void
+modest_connection_specific_smtp_window_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_connection_specific_smtp_window_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_connection_specific_smtp_window_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (modest_connection_specific_smtp_window_parent_class)->dispose)
+               G_OBJECT_CLASS (modest_connection_specific_smtp_window_parent_class)->dispose (object);
+}
+
+enum MODEL_COLS {
+       MODEL_COL_NAME = 0, /* libconic IAP Name: a string */
+       MODEL_COL_ID = 1, /* libconic IAP ID: a string */
+       MODEL_COL_SERVER_ACCOUNT_NAME = 2, /* a string */
+       MODEL_COL_SERVER_NAME = 3, /* a string */
+       MODEL_COL_SERVER_ACCOUNT_SETTINGS = 4 /* a gpointer */
+};
+
+
+void update_model_server_names (ModestConnectionSpecificSmtpWindow *self);
+
+static void
+modest_connection_specific_smtp_window_finalize (GObject *object)
+{
+       ModestConnectionSpecificSmtpWindowPrivate *priv = CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (object);
+       
+       /* Free all the data items from the treemodel: */
+       GtkTreeIter iter;
+       gboolean valid = gtk_tree_model_get_iter_first (priv->model, &iter);
+       while (valid) {
+               ModestServerAccountSettings *server_settings = NULL;
+               
+               gtk_tree_model_get (priv->model, &iter, 
+                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, &server_settings,
+                                   -1);
+                                
+               if (server_settings)
+                       g_object_unref (server_settings);
+                       
+               /* Get next row: */
+               valid = gtk_tree_model_iter_next (priv->model, &iter);
+       }
+       
+       g_object_unref (G_OBJECT (priv->model));
+       
+       G_OBJECT_CLASS (modest_connection_specific_smtp_window_parent_class)->finalize (object);
+}
+
+static void
+modest_connection_specific_smtp_window_class_init (ModestConnectionSpecificSmtpWindowClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (ModestConnectionSpecificSmtpWindowPrivate));
+
+       object_class->get_property = modest_connection_specific_smtp_window_get_property;
+       object_class->set_property = modest_connection_specific_smtp_window_set_property;
+       object_class->dispose = modest_connection_specific_smtp_window_dispose;
+       object_class->finalize = modest_connection_specific_smtp_window_finalize;
+}
+
+/* libconic does not return a list of connections in scratchbox,
+ * so enable this to put a fake row in the list,
+ * so we can test other parts of the code. */
+/* #define DEBUG_WITHOUT_LIBCONIC 1 */
+
+void
+modest_connection_specific_smtp_window_fill_with_connections (ModestConnectionSpecificSmtpWindow *self,
+                                                             ModestAccountMgr *account_manager)
+{
+#ifdef MODEST_HAVE_CONIC
+       ModestConnectionSpecificSmtpWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+       priv->account_manager = account_manager;
+       
+       GtkListStore *liststore = GTK_LIST_STORE (priv->model);
+       
+       TnyDevice *device = modest_runtime_get_device ();
+       g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
+       
+       /* Get the list of Internet Access Points: */
+       #ifdef DEBUG_WITHOUT_LIBCONIC
+       GSList *list_iaps = g_slist_append(NULL, (gpointer)1);
+       #else
+       TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
+       GSList *list_iaps = tny_maemo_conic_device_get_iap_list (maemo_device);
+       #endif
+       
+       /* printf("debug: list_iaps=%p, list_iaps size = %d\n", list_iaps, g_slist_length(list_iaps)); */
+       
+       GSList* iter = list_iaps;
+       while (iter) {
+               ConIcIap *iap = (ConIcIap*)iter->data;
+               if (iap) {
+                       #ifdef DEBUG_WITHOUT_LIBCONIC
+                       const gchar *connection_name = "debug name";
+                       const gchar *connection_id = "debug id";
+                       #else
+                       const gchar *connection_name = con_ic_iap_get_name (iap);
+                       const gchar *connection_id = con_ic_iap_get_id (iap);
+                       #endif
+                       
+                       printf ("debug: iac name=%s, id=%s\n", connection_name, connection_id);
+                       
+                       /* Get any already-associated connection-specific server account: */
+                       gchar *server_account_name = NULL;
+                       server_account_name = modest_account_mgr_get_connection_specific_smtp (
+                               priv->account_manager, connection_id);
+                                       
+                       /* Add the row to the model: */
+                       GtkTreeIter iter;
+                       gtk_list_store_append (liststore, &iter);
+                       gtk_list_store_set(liststore, &iter, 
+                               MODEL_COL_ID, connection_id, 
+                               MODEL_COL_NAME, connection_name,
+                               MODEL_COL_SERVER_ACCOUNT_NAME, server_account_name,
+                               -1);
+                               
+                       g_free (server_account_name);
+               }
+               
+               iter = g_slist_next (iter);     
+       }
+               
+       #ifndef DEBUG_WITHOUT_LIBCONIC
+       if (list_iaps)
+               tny_maemo_conic_device_free_iap_list (maemo_device, list_iaps);
+       #endif
+               
+       update_model_server_names (self);
+#endif /*MODEST_HAVE_CONIC */
+}
+       
+static void
+on_button_edit (ModestConnectionSpecificSmtpWindow *self)
+{
+       ModestConnectionSpecificSmtpWindowPrivate *priv = CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+       ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
+       
+       gchar *id = NULL;
+       gchar *connection_name = NULL;
+       gchar *server_account_name = NULL;
+       ModestServerAccountSettings *server_settings = NULL;
+       GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+       GtkTreeIter iter;
+       GtkTreeModel *model = 0;
+       if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
+               gtk_tree_model_get (priv->model, &iter,
+                                   MODEL_COL_ID, &id,
+                                   MODEL_COL_NAME, &connection_name,
+                                   MODEL_COL_SERVER_ACCOUNT_NAME, &server_account_name,
+                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, &server_settings,
+                                   -1);
+       
+               /* printf("DEBUG: %s: BEFORE: connection-specific server_account_name=%s\n", __FUNCTION__, server_account_name); */
+               /* TODO: Is 0 an allowed libconic IAP ID?
+                * If not then we should check for it. */
+               
+               /* Get existing server account data if a server account is already specified: */
+               gboolean settings_were_retrieved = FALSE;
+               if (server_account_name && !server_settings) {
+                       server_settings = modest_account_mgr_load_server_settings(mgr, server_account_name, TRUE);
+                       if (server_settings)
+                               settings_were_retrieved = TRUE;
+               }
+               
+               GtkWidget * window = GTK_WIDGET (modest_connection_specific_smtp_edit_window_new ());
+               modest_connection_specific_smtp_edit_window_set_connection (
+                       MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW (window), id, connection_name, server_settings);
+                       
+               /* Delete data, unless it was data from the rowmodel: */
+               if (settings_were_retrieved) {
+                       g_object_unref (server_settings);
+                       server_settings = NULL;
+               }
+                       
+               modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (window));
+               
+               gint response = gtk_dialog_run (GTK_DIALOG (window));
+               if (response == GTK_RESPONSE_OK) {
+
+                       /* Delete any previous data for this row: */
+                       if (server_settings) {
+                               g_object_unref (server_settings);
+                               server_settings = NULL;
+                       }
+                       
+                       /* Get the new account data and save it in the row for later:
+                        * We free this in finalize(),
+                        * and save it to our configuration in
+                        * modest_connection_specific_smtp_window_save_server_accounts(). */
+                       server_settings = modest_connection_specific_smtp_edit_window_get_settings (
+                                                                                                   MODEST_CONNECTION_SPECIFIC_SMTP_EDIT_WINDOW (window));
+                       
+                       if (server_settings) {
+                               gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+                                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, server_settings,
+                                                   MODEL_COL_SERVER_NAME, modest_server_account_settings_get_hostname (server_settings),
+                                                   -1);
+                       } else {
+                               gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+                                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, NULL,
+                                                   MODEL_COL_SERVER_NAME, NULL,
+                                                   MODEL_COL_SERVER_ACCOUNT_NAME, NULL,
+                                                   -1);
+                       }
+               }
+               gtk_widget_destroy (window);
+       }
+       g_free (connection_name);
+       g_free (id);
+       g_free (server_account_name);
+       update_model_server_names (self);
+}
+
+static void
+on_selection_changed (GtkTreeSelection *sel, ModestConnectionSpecificSmtpWindow *self)
+{
+       ModestConnectionSpecificSmtpWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+
+       GtkTreeModel *model = NULL;
+       GtkTreeIter iter;
+       const gboolean has_selection =
+               gtk_tree_selection_get_selected (sel, &model, &iter);
+
+       gtk_widget_set_sensitive (priv->button_edit, has_selection);
+}
+
+static void
+modest_connection_specific_smtp_window_init (ModestConnectionSpecificSmtpWindow *self)
+{
+       ModestWindowMgr *mgr;
+
+       /* Specify a default size, because the GtkTreeView's default requested size  
+        * is not big enough: */
+       gtk_window_set_default_size (GTK_WINDOW (self), 500, 300);
+       
+       /* This seems to be necessary to make the window show at the front with decoration.
+        * If we use property type=GTK_WINDOW_TOPLEVEL instead of the default GTK_WINDOW_POPUP+decoration, 
+        * then the window will be below the others. */
+       gtk_window_set_type_hint (GTK_WINDOW (self),
+                           GDK_WINDOW_TYPE_HINT_DIALOG);
+                           
+       ModestConnectionSpecificSmtpWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+
+       /* Create a tree model for the tree view:
+        * with a string for the name, a string for the server name, and an int for the ID.
+        * This must match our MODEL_COLS enum constants.
+        */
+       priv->model = GTK_TREE_MODEL (gtk_list_store_new (5, 
+               G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
+
+       /* Setup the tree view: */
+       priv->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (priv->model));
+
+       /* Show the column headers,
+        * which does not seem to be the default on Maemo.
+        */
+       gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(priv->treeview), TRUE);
+       
+       /* name column:
+        * The ID model column in not shown in the view. */
+       GtkTreeViewColumn *view_column = gtk_tree_view_column_new ();
+       GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_column_pack_start(view_column, renderer, TRUE);
+       gtk_tree_view_column_set_attributes (view_column, renderer, 
+       "text", MODEL_COL_NAME, NULL);
+       gtk_tree_view_column_set_title (view_column, _("mcen_ia_optionalsmtp_connection_name"));
+       gtk_tree_view_append_column (priv->treeview, view_column);
+
+       
+       /* server name column: */
+       view_column = gtk_tree_view_column_new ();
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_column_pack_start(view_column, renderer, TRUE);
+       gtk_tree_view_column_set_attributes (view_column, renderer, 
+       "text", MODEL_COL_SERVER_NAME, NULL);
+       gtk_tree_view_column_set_title (view_column, _("mcen_ia_optionalsmtp_servername"));
+       gtk_tree_view_append_column (priv->treeview, view_column);
+       
+       /* The application must call modest_connection_specific_smtp_window_fill_with_connections(). */
+       
+       GtkWidget *vbox = GTK_DIALOG(self)->vbox;
+       //gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
+
+       /* Introductory note: */
+       /* TODO: For some reason this label does not wrap. It is truncated. */
+       GtkWidget *label = gtk_label_new(_("mcen_ia_optionalsmtp_note"));
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       /* So that it is shown without being truncated: */
+       gtk_label_set_max_width_chars (GTK_LABEL (label), 20);
+       /* The documentation for gtk_label_set_line_wrap() says that we must 
+        * call gtk_widget_set_size_request() with a hard-coded width, 
+        * though I wonder why gtk_label_set_max_width_chars() isn't enough. */
+       gtk_widget_set_size_request (label, 400, -1);
+       gtk_widget_show (label);
+       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, MODEST_MARGIN_HALF);
+       
+       /* Put the treeview in a scrolled window and add it to the box: */
+       GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), MODEST_MARGIN_DEFAULT);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, 
+               GTK_POLICY_AUTOMATIC);
+       gtk_widget_show (scrolled_window);
+       gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (priv->treeview));
+       gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (scrolled_window), TRUE, TRUE, MODEST_MARGIN_HALF);
+       gtk_widget_show (GTK_WIDGET (priv->treeview));
+       gtk_widget_show (vbox);
+       
+       /* Hack: we use the response apply to identify the click on the edit button */
+       priv->button_edit = gtk_dialog_add_button (GTK_DIALOG(self), _("mcen_bd_edit"), GTK_RESPONSE_APPLY);
+       gtk_dialog_add_button (GTK_DIALOG(self), _("mcen_bd_close"), GTK_RESPONSE_CLOSE);
+       
+       /* Disable the Edit button when nothing is selected: */
+       GtkTreeSelection *sel = gtk_tree_view_get_selection (priv->treeview);
+       g_signal_connect (sel, "changed",
+                         G_CALLBACK(on_selection_changed), self);
+       on_selection_changed (sel, self);
+       
+       /* When this window is shown, hibernation should not be possible, 
+        * because there is no sensible way to save the state: */
+       mgr = modest_runtime_get_window_mgr ();
+       modest_window_mgr_prevent_hibernation_while_window_is_shown (mgr, 
+                                                                    GTK_WINDOW (self)); 
+
+       /* Set window title */
+       gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_optionalsmtp_servers"));
+
+       g_signal_connect (self, "response", G_CALLBACK (on_response), NULL);
+       
+       hildon_help_dialog_help_enable (GTK_DIALOG(self),
+                                       "email_connectionsspecificsmtpconf",
+                                       modest_maemo_utils_get_osso_context());
+}
+
+ModestConnectionSpecificSmtpWindow*
+modest_connection_specific_smtp_window_new (void)
+{
+       return g_object_new (MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW, NULL);
+}
+
+/** The application should call this when the user changes should be saved.
+ */
+gboolean
+modest_connection_specific_smtp_window_save_server_accounts (ModestConnectionSpecificSmtpWindow *self)
+{
+       ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
+       ModestConnectionSpecificSmtpWindowPrivate *priv = 
+               CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+       
+       
+       /* Get the first iter in the list */
+       GtkTreeIter iter;
+       gboolean valid = gtk_tree_model_get_iter_first (priv->model, &iter);
+
+       /* Walk through the list, reading each row */
+       while (valid) {
+               gchar *id = NULL;
+               gchar *connection_name = NULL;
+               gchar *server_account_name = NULL;
+               gchar *server_name = NULL;
+               ModestServerAccountSettings *server_settings = NULL;
+               
+               gtk_tree_model_get (priv->model, &iter, 
+                                   MODEL_COL_ID, &id, 
+                                   MODEL_COL_NAME, &connection_name, 
+                                   MODEL_COL_SERVER_NAME, &server_name,
+                                   MODEL_COL_SERVER_ACCOUNT_NAME, &server_account_name,
+                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, &server_settings,
+                                   -1);
+                                
+               gboolean success = TRUE;   
+               if (id && server_settings) { /* The presence of data suggests that there is something to save. */
+                       if (!server_account_name) {
+                               /* Add a new server account, building a (non-human-visible) name: */
+                               gchar *name_start = g_strdup_printf("specific_%s", connection_name);
+                               server_account_name = modest_account_mgr_get_unused_account_name (
+                                       priv->account_manager, name_start, TRUE /* server account. */);
+                               g_assert (server_account_name);
+                               g_free (name_start);
+                               
+                               modest_server_account_settings_set_account_name (server_settings, server_account_name);
+                               success = modest_account_mgr_save_server_settings (mgr, server_settings);
+                               if (success) {
+                                       TnyAccount *account = TNY_ACCOUNT (modest_tny_account_store_new_connection_specific_transport_account 
+                                                                          (modest_runtime_get_account_store (),
+                                                                           server_account_name));
+                                       if (account)
+                                               g_object_unref (account);
+                               }
+                               
+                               /* associate the specific server account with this connection for this account: */
+                               success = success && modest_account_mgr_set_connection_specific_smtp (
+                                       priv->account_manager, id, server_account_name);
+                               
+                               /* Save the new name in the treemodel, so it can be edited again later: */
+                               gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter, 
+                                       MODEL_COL_SERVER_ACCOUNT_NAME, server_account_name, -1);
+                               
+                       } else {
+                               modest_account_mgr_save_server_settings (mgr, server_settings);
+                       }
+               } else if (id && server_name && 
+                          !strcmp (server_name, _("mcen_ia_optionalsmtp_notdefined"))) {
+                       modest_account_mgr_remove_connection_specific_smtp (priv->account_manager, 
+                                                                           id);
+                       gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter, 
+                                           MODEL_COL_SERVER_ACCOUNT_NAME, NULL, -1);
+               }
+               
+               g_free (connection_name);
+               g_free (id);
+               g_free (server_account_name);
+               g_free (server_name);
+               
+               if (!success)
+                       return FALSE;
+                       
+               /* Get next row: */
+               valid = gtk_tree_model_iter_next (priv->model, &iter);
+       }
+       
+       update_model_server_names (self);
+       
+       return TRUE;
+}
+
+void update_model_server_names (ModestConnectionSpecificSmtpWindow *self)
+{
+       ModestConnectionSpecificSmtpWindowPrivate *priv = CONNECTION_SPECIFIC_SMTP_WINDOW_GET_PRIVATE (self);
+
+       GtkTreeIter iter;
+       gboolean valid = gtk_tree_model_get_iter_first (priv->model, &iter);
+       while (valid) {
+               
+               gchar *server_account_name = NULL;
+               ModestServerAccountSettings *server_settings = NULL;
+               gtk_tree_model_get (priv->model, &iter, 
+                                   MODEL_COL_SERVER_ACCOUNT_NAME, &server_account_name,
+                                   MODEL_COL_SERVER_ACCOUNT_SETTINGS, &server_settings,
+                                   -1);        
+               if (server_settings && modest_server_account_settings_get_hostname (server_settings)
+                   && (modest_server_account_settings_get_hostname (server_settings) [0] != '\0')) {
+                       gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter, 
+                                           MODEL_COL_SERVER_NAME, modest_server_account_settings_get_hostname (server_settings),
+                                           -1);
+               } else if (server_account_name) {
+                       
+                       /* Get the server hostname and show it in the treemodel: */     
+                       gchar *hostname = modest_account_mgr_get_server_account_hostname (priv->account_manager, 
+                                                                                         server_account_name);
+                       gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter, 
+                                           MODEL_COL_SERVER_NAME, hostname,
+                                           -1);
+                       g_free (hostname);
+               } else {
+                       gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+                                           MODEL_COL_SERVER_NAME, _("mcen_ia_optionalsmtp_notdefined"),
+                                           -1);
+               }
+                       
+               /* Get next row: */
+               valid = gtk_tree_model_iter_next (priv->model, &iter);
+       }
+}
+
+static void
+on_response (GtkDialog *dialog,
+            gint response,
+            gpointer user_data)
+{
+       switch (response) {
+       case GTK_RESPONSE_APPLY:
+               /* We use it for the edit button */
+               on_button_edit (MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (dialog));
+               g_signal_stop_emission_by_name (dialog, "response");
+               break;
+       case GTK_RESPONSE_CLOSE:
+       case GTK_RESPONSE_NONE:
+       case GTK_RESPONSE_DELETE_EVENT:
+               /* Generated as a response to delete-event, i.e,
+                  pressin Esc, or by pressing the Close button */
+               modest_connection_specific_smtp_window_save_server_accounts (MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (dialog));
+               gtk_widget_destroy (GTK_WIDGET (dialog));
+       }
+}
diff --git a/src/hildon2/modest-connection-specific-smtp-window.h b/src/hildon2/modest-connection-specific-smtp-window.h
new file mode 100644 (file)
index 0000000..279681e
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_WINDOW
+#define __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_WINDOW
+
+#include <modest-account-mgr.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkdialog.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW modest_connection_specific_smtp_window_get_type()
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW, ModestConnectionSpecificSmtpWindow))
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW, ModestConnectionSpecificSmtpWindowClass))
+
+#define MODEST_IS_CONNECTION_SPECIFIC_SMTP_WINDOW(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW))
+
+#define MODEST_IS_CONNECTION_SPECIFIC_SMTP_WINDOW_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW))
+
+#define MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_TYPE_CONNECTION_SPECIFIC_SMTP_WINDOW, ModestConnectionSpecificSmtpWindowClass))
+
+typedef struct {
+       GtkDialog parent;
+       
+} ModestConnectionSpecificSmtpWindow;
+
+typedef struct {
+       GtkDialogClass parent_class;
+} ModestConnectionSpecificSmtpWindowClass;
+
+GType modest_connection_specific_smtp_window_get_type (void);
+
+ModestConnectionSpecificSmtpWindow* modest_connection_specific_smtp_window_new (void);
+
+void
+modest_connection_specific_smtp_window_fill_with_connections (ModestConnectionSpecificSmtpWindow *self, 
+       ModestAccountMgr *account_manager);
+
+gboolean
+modest_connection_specific_smtp_window_save_server_accounts (ModestConnectionSpecificSmtpWindow *self);
+
+G_END_DECLS
+
+#endif /* __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_WINDOW */
diff --git a/src/hildon2/modest-default-account-settings-dialog.c b/src/hildon2/modest-default-account-settings-dialog.c
new file mode 100644 (file)
index 0000000..bdfb231
--- /dev/null
@@ -0,0 +1,1566 @@
+/* Copyright (c) 2008, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <glib/gi18n.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include "modest-hildon-includes.h"
+#include "modest-default-account-settings-dialog.h"
+#include "modest-account-mgr.h"
+#include "widgets/modest-serversecurity-combo-box.h"
+#include "widgets/modest-secureauth-combo-box.h"
+#include "widgets/modest-validating-entry.h"
+#include "widgets/modest-retrieve-combo-box.h"
+#include "widgets/modest-limit-retrieve-combo-box.h"
+#include "modest-text-utils.h"
+#include "modest-account-mgr.h"
+#include "modest-account-mgr-helpers.h" /* For modest_account_mgr_get_account_data(). */
+#include <modest-server-account-settings.h>
+#include "modest-runtime.h" /* For modest_runtime_get_account_mgr(). */
+#include "maemo/modest-connection-specific-smtp-window.h"
+#include "maemo/modest-signature-editor-dialog.h"
+#include <modest-utils.h>
+#include <modest-defs.h>
+#include "maemo/modest-maemo-utils.h"
+#include "maemo/modest-maemo-security-options-view.h"
+#include "widgets/modest-ui-constants.h"
+#include <tny-account.h>
+#include <tny-status.h>
+
+#include <gconf/gconf-client.h>
+#include <string.h> /* For strlen(). */
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define PORT_MIN 1
+#define PORT_MAX 65535
+
+static void modest_account_settings_dialog_init (gpointer g, gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED (ModestDefaultAccountSettingsDialog, 
+                        modest_default_account_settings_dialog, 
+                        GTK_TYPE_DIALOG,
+                        0, 
+                        G_IMPLEMENT_INTERFACE (MODEST_TYPE_ACCOUNT_SETTINGS_DIALOG, 
+                                               modest_account_settings_dialog_init));
+
+#define MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_DEFAULT_ACCOUNT_SETTINGS_DIALOG, ModestDefaultAccountSettingsDialogPrivate))
+
+typedef struct _ModestDefaultAccountSettingsDialogPrivate ModestDefaultAccountSettingsDialogPrivate;
+
+struct _ModestDefaultAccountSettingsDialogPrivate
+{
+       /* Used by derived widgets to query existing accounts,
+        * and to create new accounts: */
+       ModestAccountMgr *account_manager;
+       ModestAccountSettings *settings;
+       
+       gboolean modified;
+       gchar * account_name; /* This may not change. It is not user visible. */
+       ModestProtocolType incoming_protocol; /* This may not change. */
+       ModestProtocolType outgoing_protocol; /* This may not change. */
+       gchar * original_account_title;
+
+       ModestProtocolType protocol_authentication_incoming;
+       
+       GtkNotebook *notebook;
+       
+       GtkWidget *page_account_details;
+       GtkWidget *entry_account_title;
+       GtkWidget *combo_retrieve;
+       GtkWidget *combo_limit_retrieve;
+       GtkWidget *caption_leave_messages;
+       GtkWidget *checkbox_leave_messages;
+       
+       GtkWidget *page_user_details;
+       GtkWidget *entry_user_name;
+       GtkWidget *entry_user_username;
+       GtkWidget *entry_user_password;
+       GtkWidget *entry_user_email;
+/*     GtkWidget *entry_incoming_port; */
+       GtkWidget *button_signature;
+       
+       GtkWidget *page_complete_easysetup;
+       
+       GtkWidget *page_incoming;
+       GtkWidget *caption_incoming;
+       GtkWidget *entry_incomingserver;
+/*     GtkWidget *combo_incoming_security; */
+/*     GtkWidget *checkbox_incoming_auth; */
+
+       GtkWidget *page_outgoing;
+       GtkWidget *entry_outgoingserver;
+/*     GtkWidget *caption_outgoing_username; */
+/*     GtkWidget *entry_outgoing_username; */
+/*     GtkWidget *caption_outgoing_password; */
+/*     GtkWidget *entry_outgoing_password; */
+/*     GtkWidget *combo_outgoing_security; */
+/*     GtkWidget *combo_outgoing_auth; */
+/*     GtkWidget *entry_outgoing_port; */
+       GtkWidget *checkbox_outgoing_smtp_specific;
+       GtkWidget *button_outgoing_smtp_servers;
+       
+       GtkWidget *signature_dialog;
+
+       GtkWidget *incoming_security;
+       GtkWidget *outgoing_security;
+};
+
+static void
+enable_buttons (ModestDefaultAccountSettingsDialog *self);
+
+static gboolean
+save_configuration (ModestDefaultAccountSettingsDialog *dialog);
+
+static const gchar * null_means_empty (const gchar * str);
+
+static const gchar *
+null_means_empty (const gchar * str)
+{
+       return str ? str : "";
+}
+
+static void
+modest_default_account_settings_dialog_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->dispose)
+               G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->dispose (object);
+}
+
+static void
+modest_default_account_settings_dialog_finalize (GObject *object)
+{
+       ModestDefaultAccountSettingsDialog *self;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (object);
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       
+       if (priv->account_name)
+               g_free (priv->account_name);
+               
+       if (priv->original_account_title)
+               g_free (priv->original_account_title);
+               
+       if (priv->account_manager)
+               g_object_unref (G_OBJECT (priv->account_manager));
+               
+       if (priv->signature_dialog)
+               gtk_widget_destroy (priv->signature_dialog);
+
+       if (priv->settings) {
+               g_object_unref (priv->settings);
+               priv->settings = NULL;
+       }
+       
+       G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->finalize (object);
+}
+
+static void 
+set_modified (ModestDefaultAccountSettingsDialog *self, gboolean modified)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       priv->modified = modified;
+}
+
+static void
+on_modified_combobox_changed (GtkComboBox *widget, gpointer user_data)
+{
+       set_modified (MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data), TRUE);
+}
+
+static void
+on_modified_entry_changed (GtkEditable *editable, gpointer user_data)
+{
+       set_modified (MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data), TRUE);
+}
+
+static void
+on_modified_checkbox_toggled (GtkToggleButton *togglebutton, gpointer user_data)
+{
+       set_modified (MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data), TRUE);
+}
+
+static void
+on_modified_number_editor_changed (HildonNumberEditor *number_editor, gint new_value, gpointer user_data)
+{
+       set_modified (MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data), TRUE);
+}
+
+static void       
+on_number_editor_notify (HildonNumberEditor *editor, GParamSpec *arg1, gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog *dialog = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data);
+       gint value = hildon_number_editor_get_value (editor);
+
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, value > 0);
+}
+
+/* Set a modified boolean whenever the widget is changed, 
+ * so we can check for it later.
+ */
+static void
+connect_for_modified (ModestDefaultAccountSettingsDialog *self, GtkWidget *widget)
+{
+       if (HILDON_IS_NUMBER_EDITOR (widget)) {
+               g_signal_connect (G_OBJECT (widget), "notify::value",
+                       G_CALLBACK (on_modified_number_editor_changed), self);
+               g_signal_connect (G_OBJECT (widget), "notify", G_CALLBACK (on_number_editor_notify), self);
+       }
+       else if (GTK_IS_ENTRY (widget)) {
+               g_signal_connect (G_OBJECT (widget), "changed",
+                       G_CALLBACK (on_modified_entry_changed), self);
+       } else if (GTK_IS_COMBO_BOX (widget)) {
+               g_signal_connect (G_OBJECT (widget), "changed",
+                       G_CALLBACK (on_modified_combobox_changed), self);       
+       } else if (GTK_IS_TOGGLE_BUTTON (widget)) {
+               g_signal_connect (G_OBJECT (widget), "toggled",
+                       G_CALLBACK (on_modified_checkbox_toggled), self);
+       }
+}
+
+static void
+on_caption_entry_changed (GtkEditable *editable, gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog *self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data);
+       g_assert(self);
+       enable_buttons(self);
+}
+
+static void
+on_caption_combobox_changed (GtkComboBox *widget, gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog *self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data);
+       g_assert(self);
+       enable_buttons(self);
+}
+
+/** This is a convenience function to create a caption containing a mandatory widget.
+ * When the widget is edited, the enable_buttons() vfunc will be called.
+ */
+static GtkWidget* 
+create_caption_new_with_asterisk(ModestDefaultAccountSettingsDialog *self,
+       GtkSizeGroup *group,
+       const gchar *value,
+       GtkWidget *control,
+       GtkWidget *icon,
+       HildonCaptionStatus flag)
+{
+       GtkWidget *caption = NULL;
+  
+       /* Note: Previously, the translated strings already contained the "*",
+        * Comment out this code if they do again.
+        */
+       /* Add a * character to indicate mandatory fields,
+        * as specified in our "Email UI Specification": */
+       if (flag == HILDON_CAPTION_MANDATORY) {
+               gchar* title = g_strdup_printf("%s*", value);
+               caption = hildon_caption_new (group, title, control, icon, flag);       
+               g_free(title);
+       }       
+       else
+               caption = hildon_caption_new (group, value, control, icon, flag);
+
+       /* Connect to the appropriate changed signal for the widget, 
+        * so we can ask for the prev/next buttons to be enabled/disabled appropriately:
+        */
+       if (GTK_IS_ENTRY (control)) {
+               g_signal_connect (G_OBJECT (control), "changed",
+               G_CALLBACK (on_caption_entry_changed), self);
+               
+       }
+       else if (GTK_IS_COMBO_BOX (control)) {
+               g_signal_connect (G_OBJECT (control), "changed",
+               G_CALLBACK (on_caption_combobox_changed), self);
+       }
+        
+       return caption;
+}
+
+static void
+on_entry_invalid_account_title_character (ModestValidatingEntry *self, const gchar* character, gpointer user_data)
+{
+       gchar *tmp, *msg;
+                       
+       tmp = g_strndup (account_title_forbidden_chars, ACCOUNT_TITLE_FORBIDDEN_CHARS_LENGTH);
+       msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
+
+       modest_platform_information_banner (GTK_WIDGET (self), NULL, msg);
+
+       g_free (msg);
+       g_free (tmp);
+}
+
+static void
+on_entry_invalid_fullname_character (ModestValidatingEntry *self, const gchar* character, gpointer user_data)
+{
+       gchar *tmp, *msg;
+                       
+       tmp = g_strndup (user_name_forbidden_chars, USER_NAME_FORBIDDEN_CHARS_LENGTH);
+       msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
+
+       modest_platform_information_banner (GTK_WIDGET (self), NULL, msg);
+
+       g_free (msg);
+       g_free (tmp);
+}
+
+
+static void
+on_entry_max (ModestValidatingEntry *self, gpointer user_data)
+{
+       modest_platform_information_banner (GTK_WIDGET (self), NULL, 
+                                           _CS("ckdg_ib_maximum_characters_reached"));
+}
+
+static GtkWidget*
+create_page_account_details (ModestDefaultAccountSettingsDialog *self)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       GtkWidget *box;
+       GtkAdjustment *focus_adjustment = NULL;
+       GtkSizeGroup* sizegroup;
+       GtkWidget *scrollwin;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+       scrollwin = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
+                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+           
+       /* The description widgets: */  
+       priv->entry_account_title = GTK_WIDGET (modest_validating_entry_new ());
+       /* Do use auto-capitalization: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_account_title), 
+               HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_account_title"), 
+               priv->entry_account_title, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->entry_account_title);
+       connect_for_modified (self, priv->entry_account_title);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the account title, 
+        * as required by our UI specification: */
+       GList *list_prevent = NULL;
+       list_prevent = g_list_append (list_prevent, "\\");
+       list_prevent = g_list_append (list_prevent, "/");
+       list_prevent = g_list_append (list_prevent, ":");
+       list_prevent = g_list_append (list_prevent, "*");
+       list_prevent = g_list_append (list_prevent, "?");
+       list_prevent = g_list_append (list_prevent, "\"");
+       list_prevent = g_list_append (list_prevent, "<"); 
+       list_prevent = g_list_append (list_prevent, ">"); 
+       list_prevent = g_list_append (list_prevent, "|");
+       list_prevent = g_list_append (list_prevent, "^");       
+       modest_validating_entry_set_unallowed_characters (
+               MODEST_VALIDATING_ENTRY (priv->entry_account_title), list_prevent);
+       g_list_free (list_prevent);
+       modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_account_title),
+                                        on_entry_invalid_account_title_character, self);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_account_title), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_account_title), 
+               on_entry_max, self);
+       
+       /* The retrieve combobox: */
+       priv->combo_retrieve = GTK_WIDGET (modest_retrieve_combo_box_new ());
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_advsetup_retrievetype"), 
+               priv->combo_retrieve, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->combo_retrieve);
+       connect_for_modified (self, priv->combo_retrieve);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The limit-retrieve combobox: */
+       priv->combo_limit_retrieve = GTK_WIDGET (modest_limit_retrieve_combo_box_new ());
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_advsetup_limit_retrieve"), 
+               priv->combo_limit_retrieve, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->combo_limit_retrieve);
+       connect_for_modified (self, priv->combo_limit_retrieve);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+
+       /* The leave-messages widgets: */
+       if(!priv->checkbox_leave_messages)
+               priv->checkbox_leave_messages = gtk_check_button_new ();
+       if (!priv->caption_leave_messages) {
+               priv->caption_leave_messages = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_advsetup_leave_on_server"), 
+                       priv->checkbox_leave_messages, NULL, HILDON_CAPTION_MANDATORY);
+       }
+                       
+       gtk_widget_show (priv->checkbox_leave_messages);
+       connect_for_modified (self, priv->checkbox_leave_messages);
+       gtk_box_pack_start (GTK_BOX (box), priv->caption_leave_messages, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->caption_leave_messages);
+
+       g_object_unref (sizegroup);
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollwin), box);
+       gtk_widget_show (scrollwin);
+
+       focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrollwin));
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (box), focus_adjustment); 
+       
+       return GTK_WIDGET (scrollwin);
+}
+
+static gchar*
+get_entered_account_title (ModestDefaultAccountSettingsDialog *dialog)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       const gchar* account_title;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
+       account_title = gtk_entry_get_text (GTK_ENTRY (priv->entry_account_title));
+
+       if (!account_title || (strlen (account_title) == 0))
+               return NULL;
+       else {
+               /* Strip it of whitespace at the start and end: */
+               gchar *result = g_strdup (account_title);
+               result = g_strstrip (result);
+               
+               if (!result)
+                       return NULL;
+                       
+               if (strlen (result) == 0) {
+                       g_free (result);
+                       return NULL;    
+               }
+               
+               return result;
+       }
+}
+
+
+static void
+on_button_signature (GtkButton *button, gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog *self;
+       gint response;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data);
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       /* Create the window, if necessary: */
+       if (!(priv->signature_dialog)) {
+               priv->signature_dialog = GTK_WIDGET (modest_signature_editor_dialog_new ());
+       
+               gboolean use_signature = modest_account_settings_get_use_signature (priv->settings);
+               const gchar *signature = modest_account_settings_get_signature(priv->settings);
+               gchar* account_title = get_entered_account_title (self);
+               modest_signature_editor_dialog_set_settings (
+                       MODEST_SIGNATURE_EDITOR_DIALOG (priv->signature_dialog), 
+                       use_signature, signature, account_title);
+
+               g_free (account_title);
+               account_title = NULL;
+               signature = NULL;
+       }
+
+       /* Show the window: */  
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
+                                    GTK_WINDOW (priv->signature_dialog));
+
+       response = gtk_dialog_run (GTK_DIALOG (priv->signature_dialog));
+       gtk_widget_hide (priv->signature_dialog);
+       if (response != GTK_RESPONSE_OK) {
+               /* Destroy the widget now, and its data: */
+               gtk_widget_destroy (priv->signature_dialog);
+               priv->signature_dialog = NULL;
+       } else {
+               /* Mark modified, so we use the dialog's data later: */
+               priv->modified = TRUE;  
+       }
+}
+
+static GtkWidget*
+create_page_user_details (ModestDefaultAccountSettingsDialog *self)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       GtkWidget *box;
+       GtkAdjustment *focus_adjustment = NULL;
+       GtkSizeGroup* sizegroup;
+       GtkWidget *scrollwin;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+       scrollwin = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
+                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+        
+       /* The name widgets: */
+       priv->entry_user_name = GTK_WIDGET (modest_validating_entry_new ());
+
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_name), HILDON_GTK_INPUT_MODE_FULL);
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_name), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_name), 
+               on_entry_max, self);
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, 
+               _("mcen_li_emailsetup_name"), priv->entry_user_name, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->entry_user_name);
+       connect_for_modified (self, priv->entry_user_name);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+
+
+       /* Prevent the use of some characters in the name, 
+        * as required by our UI specification: */
+       GList *list_prevent = NULL;
+       list_prevent = g_list_append (list_prevent, "<");
+       list_prevent = g_list_append (list_prevent, ">");
+       modest_validating_entry_set_unallowed_characters (
+               MODEST_VALIDATING_ENTRY (priv->entry_user_name), list_prevent);
+       g_list_free (list_prevent);
+       modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_name),
+                                        on_entry_invalid_fullname_character, self);
+       
+       /* The username widgets: */     
+       priv->entry_user_username = GTK_WIDGET (modest_validating_entry_new ());
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_username), HILDON_GTK_INPUT_MODE_FULL);
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mail_fi_username"), 
+               priv->entry_user_username, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->entry_user_username);
+       connect_for_modified (self, priv->entry_user_username);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the username, 
+        * as required by our UI specification: */
+       modest_validating_entry_set_unallowed_characters_whitespace (
+               MODEST_VALIDATING_ENTRY (priv->entry_user_username));
+       modest_validating_entry_set_func (MODEST_VALIDATING_ENTRY (priv->entry_user_username), 
+                                         modest_utils_on_entry_invalid_character, 
+                                         self);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_username), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_username), 
+               on_entry_max, self);
+       
+       /* The password widgets: */     
+       priv->entry_user_password = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_password), 
+               HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
+       gtk_entry_set_visibility (GTK_ENTRY (priv->entry_user_password), FALSE);
+       /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_user_password), '*'); */
+       caption = create_caption_new_with_asterisk (self, sizegroup, 
+               _("mail_fi_password"), priv->entry_user_password, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->entry_user_password);
+       connect_for_modified (self, priv->entry_user_password);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The email address widgets: */        
+       priv->entry_user_email = GTK_WIDGET (modest_validating_entry_new ());
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_email), HILDON_GTK_INPUT_MODE_FULL);
+       caption = create_caption_new_with_asterisk (self, sizegroup, 
+               _("mcen_li_emailsetup_email_address"), priv->entry_user_email, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_entry_set_text (GTK_ENTRY (priv->entry_user_email), MODEST_EXAMPLE_EMAIL_ADDRESS); /* Default text. */
+       gtk_widget_show (priv->entry_user_email);
+       connect_for_modified (self, priv->entry_user_email);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_email), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_email), 
+               on_entry_max, self);
+       
+       /* Signature button: */
+       if (!priv->button_signature)
+               priv->button_signature = gtk_button_new_with_label (_("mcen_bd_edit"));
+       caption = hildon_caption_new (sizegroup, _("mcen_fi_email_signature"), 
+               priv->button_signature, NULL, HILDON_CAPTION_OPTIONAL);
+       hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
+       gtk_widget_show (priv->button_signature);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+
+       g_object_unref (sizegroup);
+               
+       g_signal_connect (G_OBJECT (priv->button_signature), "clicked",
+               G_CALLBACK (on_button_signature), self);
+               
+       gtk_widget_show (GTK_WIDGET (box));
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollwin), box);
+       gtk_widget_show (scrollwin);
+
+       focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrollwin));
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (box), focus_adjustment); 
+       
+       return GTK_WIDGET (scrollwin);
+}
+
+/* Change the caption title for the incoming server */
+static void
+update_incoming_server_title (ModestDefaultAccountSettingsDialog *self,
+                             ModestProtocolType protocol_type)
+{
+       ModestProtocolRegistry *protocol_registry;
+       ModestProtocol *protocol;
+       const gchar *protocol_display_name;
+       gchar* incomingserver_title;
+       gchar *with_asterisk;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
+       protocol_display_name = modest_protocol_get_display_name (protocol);
+       incomingserver_title = g_strdup_printf(_("mcen_li_emailsetup_servertype"), 
+                                              protocol_display_name);
+       
+       /* This is a mandatory field, so add a *. This is usually done by
+        * create_caption_new_with_asterisk() but we can't use that here. */
+       with_asterisk = g_strconcat (incomingserver_title, "*", NULL);
+       g_free (incomingserver_title);
+       
+       g_object_set (G_OBJECT (priv->caption_incoming), "label", with_asterisk, NULL);
+       g_free (with_asterisk);
+}
+
+/** Change the caption title for the incoming server, 
+ * as specified in the UI spec:
+ */
+/* static void  */
+/* update_incoming_server_security_choices (ModestDefaultAccountSettingsDialog *self,  */
+/*                                      ModestProtocolType protocol) */
+/* { */
+/*     /\* Fill the combo with appropriately titled choices for POP or IMAP. *\/ */
+/*     /\* The choices are the same, but the titles are different, as in the UI spec. *\/ */
+/*     modest_serversecurity_combo_box_fill ( */
+/*             MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security), protocol); */
+/* } */
+           
+static GtkWidget* 
+create_page_incoming (ModestDefaultAccountSettingsDialog *self)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       GtkWidget *box;
+       GtkSizeGroup *sizegroup;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE); 
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The incoming server widgets: */
+       if(!priv->entry_incomingserver)
+               priv->entry_incomingserver = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_incomingserver), HILDON_GTK_INPUT_MODE_FULL);
+
+       if (priv->caption_incoming)
+               gtk_widget_destroy (priv->caption_incoming);
+          
+       /* The caption title will be updated in update_incoming_server_title().
+        * so this default text will never be seen: */
+       /* (Note: Changing the title seems pointless. murrayc) */
+       priv->caption_incoming = create_caption_new_with_asterisk (self, sizegroup, 
+               "Incoming Server", priv->entry_incomingserver, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->entry_incomingserver);
+       connect_for_modified (self, priv->entry_incomingserver);
+       gtk_box_pack_start (GTK_BOX (box), priv->caption_incoming, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->caption_incoming);
+
+       /* Incoming security widgets */
+       priv->incoming_security = 
+               modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_INCOMING,
+                                                       TRUE, sizegroup);
+       gtk_box_pack_start (GTK_BOX (box), priv->incoming_security, 
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       gtk_widget_show (priv->incoming_security);
+
+       g_object_unref (sizegroup);     
+       gtk_widget_show (GTK_WIDGET (box));
+       
+       return GTK_WIDGET (box);
+}
+
+static void
+on_toggle_button_changed (GtkToggleButton *togglebutton, gpointer user_data)
+{
+       GtkWidget *widget = GTK_WIDGET (user_data);
+       
+       /* Enable the widget only if the toggle button is active: */
+       const gboolean enable = gtk_toggle_button_get_active (togglebutton);
+       gtk_widget_set_sensitive (widget, enable);
+}
+
+/* Make the sensitivity of a widget depend on a toggle button.
+ */
+static void
+enable_widget_for_togglebutton (GtkWidget *widget, GtkToggleButton* button)
+{
+       g_signal_connect (G_OBJECT (button), "toggled",
+               G_CALLBACK (on_toggle_button_changed), widget);
+       
+       /* Set the starting sensitivity: */
+       on_toggle_button_changed (button, widget);
+}
+
+static void
+on_button_outgoing_smtp_servers (GtkButton *button, gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog * self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data);
+       ModestConnectionSpecificSmtpWindow *smtp_win;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       /* Create the window if necessary: */
+       smtp_win = modest_connection_specific_smtp_window_new ();
+       modest_connection_specific_smtp_window_fill_with_connections (smtp_win, priv->account_manager);
+
+       /* Show the window: */  
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (smtp_win));
+       gtk_widget_show (GTK_WIDGET (smtp_win));
+       priv->modified = TRUE;
+}
+
+/* static void */
+/* on_combo_outgoing_auth_changed (GtkComboBox *widget, gpointer user_data) */
+/* { */
+/*     ModestDefaultAccountSettingsDialog *self; */
+/*     ModestProtocolRegistry *protocol_registry; */
+/*     ModestProtocolType protocol_security;    */
+/*     gboolean secureauth_used; */
+
+/*     self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data); */
+/*     protocol_registry = modest_runtime_get_protocol_registry (); */
+       
+/*     protocol_security =  */
+/*             modest_secureauth_combo_box_get_active_secureauth ( */
+/*                     MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth)); */
+/*     secureauth_used = modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_security); */
+       
+/*     gtk_widget_set_sensitive (priv->caption_outgoing_username, secureauth_used); */
+/*     gtk_widget_set_sensitive (priv->caption_outgoing_password, secureauth_used); */
+/* } */
+
+/* static void */
+/* on_combo_outgoing_security_changed (GtkComboBox *widget, gpointer user_data) */
+/* { */
+/*     ModestDefaultAccountSettingsDialog *self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (user_data); */
+       
+/*     const gint port_number =  */
+/*             modest_serversecurity_combo_box_get_active_serversecurity_port ( */
+/*                     MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security)); */
+
+/*     if(port_number != 0) { */
+/*             hildon_number_editor_set_value ( */
+/*                     HILDON_NUMBER_EDITOR (priv->entry_outgoing_port), port_number); */
+/*     }                */
+/* } */
+
+static void
+on_missing_mandatory_data (ModestSecurityOptionsView *security_view,
+                          gboolean missing,
+                          gpointer user_data)
+{
+       /* Disable the OK button */
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (user_data),
+                                          GTK_RESPONSE_OK,
+                                          !missing);
+}
+
+static GtkWidget* 
+create_page_outgoing (ModestDefaultAccountSettingsDialog *self)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       GtkAdjustment *focus_adjustment = NULL;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       
+       /* Put it all in a scrolled window, so that all widgets can be 
+        * accessed even when the on-screen keyboard is visible: */
+       GtkWidget *scrollwin = gtk_scrolled_window_new(NULL, NULL);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), 
+               GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The outgoing server widgets: */
+       if (!priv->entry_outgoingserver)
+               priv->entry_outgoingserver = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_outgoingserver), HILDON_GTK_INPUT_MODE_FULL);
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, 
+               _("mcen_li_emailsetup_smtp"), priv->entry_outgoingserver, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->entry_outgoingserver);
+       connect_for_modified (self, priv->entry_outgoingserver);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+
+       /* Outgoing security widgets */
+       priv->outgoing_security = 
+               modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_OUTGOING,
+                                                       TRUE, sizegroup);
+       gtk_box_pack_start (GTK_BOX (box), priv->outgoing_security, 
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->outgoing_security);
+       g_signal_connect (priv->outgoing_security, "missing-mandatory-data",
+                         G_CALLBACK (on_missing_mandatory_data), self);
+
+       GtkWidget *separator = gtk_hseparator_new ();
+       gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (separator);
+       
+       /* connection-specific checkbox: */
+       if (!priv->checkbox_outgoing_smtp_specific) {
+               priv->checkbox_outgoing_smtp_specific = gtk_check_button_new ();
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific), 
+                       FALSE);
+       }
+       caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_connection_smtp"), 
+               priv->checkbox_outgoing_smtp_specific, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->checkbox_outgoing_smtp_specific);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       connect_for_modified (self, priv->checkbox_outgoing_smtp_specific);
+       
+       /* Connection-specific SMTP-Severs Edit button: */
+       if (!priv->button_outgoing_smtp_servers)
+               priv->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_edit"));
+       caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_optional_smtp"), 
+               priv->button_outgoing_smtp_servers, NULL, HILDON_CAPTION_OPTIONAL);
+       hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
+       gtk_widget_show (priv->button_outgoing_smtp_servers);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Only enable the button when the checkbox is checked: */
+       enable_widget_for_togglebutton (priv->button_outgoing_smtp_servers, 
+               GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific));
+
+       g_object_unref (sizegroup);
+               
+       g_signal_connect (G_OBJECT (priv->button_outgoing_smtp_servers), "clicked",
+               G_CALLBACK (on_button_outgoing_smtp_servers), self);
+               
+       gtk_widget_show (GTK_WIDGET (box));
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrollwin), box);
+       gtk_widget_show(scrollwin);
+
+       focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrollwin));
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (box), focus_adjustment);
+       
+       return GTK_WIDGET (scrollwin);
+}
+       
+static gboolean
+check_data (ModestDefaultAccountSettingsDialog *self)
+{
+       gchar* account_title;
+       const gchar* email_address; 
+       const gchar* hostname;
+       const gchar* hostname2;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       /* Check that the title is not already in use: */
+       account_title = get_entered_account_title (self);
+       if (!account_title)
+               return FALSE; /* Should be prevented already anyway. */
+               
+       if (strcmp(account_title, priv->original_account_title) != 0) {
+               gboolean name_in_use; 
+
+               /* Check the changed title: */
+               name_in_use = modest_account_mgr_account_with_display_name_exists (priv->account_manager,
+                                                                                  account_title);
+               
+               if (name_in_use) {
+                       /* Warn the user via a dialog: */
+                       modest_platform_information_banner(NULL, NULL, _("mail_ib_account_name_already_existing"));
+                       
+                       g_free (account_title);
+                       return FALSE;
+               }
+       }
+       
+       g_free (account_title);
+       account_title  = NULL;
+
+       /* Check that the email address is valid: */
+       email_address = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
+       if ((!email_address) || (strlen(email_address) == 0)) {
+               return FALSE;
+       }
+                       
+       if (!modest_text_utils_validate_email_address (email_address, NULL)) {
+               /* Warn the user via a dialog: */
+               modest_platform_information_banner (NULL, NULL, _("mcen_ib_invalid_email"));
+                                         
+               /* Return focus to the email address entry: */
+               gtk_widget_grab_focus (priv->entry_user_email);
+               gtk_editable_select_region (GTK_EDITABLE (priv->entry_user_email), 0, -1);
+               return FALSE;
+       }
+
+       /* make sure the domain name for the incoming server is valid */
+       hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_incomingserver));
+       if ((!hostname) || (strlen(hostname) == 0)) {
+               return FALSE;
+       }
+       
+       if (!modest_text_utils_validate_domain_name (hostname)) {
+               /* Warn the user via a dialog: */
+               modest_platform_information_banner (NULL, NULL, _("mcen_ib_invalid_servername"));
+                                         
+               /* Return focus to the email address entry: */
+               gtk_widget_grab_focus (priv->entry_incomingserver);
+               gtk_editable_select_region (GTK_EDITABLE (priv->entry_incomingserver), 0, -1);
+               return FALSE;
+       }
+
+       /* make sure the domain name for the outgoing server is valid */
+       hostname2 = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
+       if ((!hostname2) || (strlen(hostname2) == 0)) {
+               return FALSE;
+       }
+       
+       if (!modest_text_utils_validate_domain_name (hostname2)) {
+               /* Warn the user via a dialog: */
+               modest_platform_information_banner (priv->entry_outgoingserver, NULL, _("mcen_ib_invalid_servername"));
+
+               /* Return focus to the email address entry: */
+               gtk_widget_grab_focus (priv->entry_outgoingserver);
+               gtk_editable_select_region (GTK_EDITABLE (priv->entry_outgoingserver), 0, -1);
+               return FALSE;
+       }
+       
+/*     /\* Find a suitable authentication method when secure authentication is desired *\/ */
+/*     port_num = hildon_number_editor_get_value ( */
+/*             HILDON_NUMBER_EDITOR (priv->entry_incoming_port)); */
+/*     username = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username)); */
+
+/*     protocol_registry = modest_runtime_get_protocol_registry (); */
+
+/*     protocol_security_incoming = modest_serversecurity_combo_box_get_active_serversecurity ( */
+/*             MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security)); */
+/*     if (!modest_protocol_registry_protocol_type_is_secure(protocol_registry, protocol_security_incoming)) */
+/*     { */
+/*             if (gtk_toggle_button_get_active ( */
+/*                             GTK_TOGGLE_BUTTON (priv->checkbox_incoming_auth))) { */
+/*                     GError *error = NULL; */
+/*                     GList *list_auth_methods; */
+
+/*                     list_auth_methods =  */
+/*                             modest_utils_get_supported_secure_authentication_methods (priv->incoming_protocol,  */
+/*                                                                                       hostname, port_num, username, GTK_WINDOW (self), &error); */
+/*                     if (list_auth_methods) { */
+/*                             GList* method; */
+
+/*                             /\* Use the first supported method. */
+/*                              * TODO: Should we prioritize them, to prefer a particular one? *\/ */
+/*                             for (method = list_auth_methods; method != NULL; method = g_list_next(method)) */
+/*                             { */
+/*                                     ModestProtocolType proto = (ModestProtocolType)(GPOINTER_TO_INT(method->data)); */
+/*                                     // Allow secure methods, e.g MD5 only */
+/*                                     if (modest_protocol_registry_protocol_type_is_secure(protocol_registry, proto)) */
+/*                                     { */
+/*                                             priv->protocol_authentication_incoming = proto; */
+/*                                             break; */
+/*                                     } */
+/*                             } */
+/*                             g_list_free (list_auth_methods); */
+/*                     } */
+
+/*                     if (list_auth_methods == NULL ||  */
+/*                         !modest_protocol_registry_protocol_type_is_secure(protocol_registry, priv->protocol_authentication_incoming)) */
+/*                     { */
+/*                             if(error == NULL || error->domain != modest_utils_get_supported_secure_authentication_error_quark() || */
+/*                                             error->code != MODEST_UTILS_GET_SUPPORTED_SECURE_AUTHENTICATION_ERROR_CANCELED) */
+/*                                     modest_platform_information_banner(GTK_WIDGET (self), NULL,  */
+/*                                                                    _("mcen_ib_unableto_discover_auth_methods")); */
+
+/*                             if(error != NULL) */
+/*                                     g_error_free(error); */
+                                       
+/*                             /\* This is a nasty hack. jschmid. *\/ */
+/*                             /\* Don't let the dialog close *\/ */
+/*                             /\*g_signal_stop_emission_by_name (dialog, "response");*\/ */
+/*                             return FALSE; */
+/*                     } */
+/*             } */
+/*     } */
+       
+       return TRUE;
+}
+
+static void 
+on_response (GtkDialog *wizard_dialog,
+            gint response_id,
+            gpointer user_data)
+{
+       ModestDefaultAccountSettingsDialog *self = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (wizard_dialog);
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       gboolean prevent_response = FALSE, sec_changed;
+       ModestSecurityOptionsView *incoming_sec, *outgoing_sec;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       enable_buttons (self);
+
+       /* Check if security widgets changed */
+       incoming_sec = MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security);
+       outgoing_sec = MODEST_SECURITY_OPTIONS_VIEW (priv->outgoing_security);
+       sec_changed =
+               modest_security_options_view_changed (incoming_sec, priv->settings) ||
+               modest_security_options_view_changed (outgoing_sec, priv->settings);
+
+       /* Warn about unsaved changes: */
+       if (response_id == GTK_RESPONSE_CANCEL && (priv->modified || sec_changed)) {
+               GtkDialog *dialog = GTK_DIALOG (hildon_note_new_confirmation (GTK_WINDOW (self), 
+                       _("imum_nc_wizard_confirm_lose_changes")));
+               /* TODO: These button names will be ambiguous, and not specified in the UI specification. */
+                
+                const gint dialog_response = gtk_dialog_run (dialog);
+                gtk_widget_destroy (GTK_WIDGET (dialog));
+                
+               if (dialog_response != GTK_RESPONSE_OK)
+                       prevent_response = TRUE;
+       }
+       /* Check for invalid input: */
+       else if (response_id != GTK_RESPONSE_CANCEL && !check_data (self)) {
+               prevent_response = TRUE;
+       }
+               
+       if (prevent_response) {
+               /* This is a nasty hack. murrayc. */
+               /* Don't let the dialog close */
+               g_signal_stop_emission_by_name (wizard_dialog, "response");
+               return; 
+       } else {
+               modest_tny_account_store_set_send_mail_blocked (modest_runtime_get_account_store (), FALSE);
+       }
+               
+       if (response_id == GTK_RESPONSE_OK) {
+               /* Try to save the changes if modified (NB #59251): */
+               if (priv->modified || sec_changed) {
+                       if (save_configuration (self)) {
+                               /* Do not show the account-saved dialog if we are just saving this 
+                                * temporarily, because from the user's point of view it will not 
+                                * really be saved (saved + enabled) until later
+                                */
+                               if (modest_account_settings_get_account_name (priv->settings) != NULL) {
+                                       ModestServerAccountSettings *store_settings;
+                                       ModestServerAccountSettings *transport_settings;
+                                       const gchar *store_account_name;
+                                       const gchar *transport_account_name;
+
+
+                                       store_settings = modest_account_settings_get_store_settings (priv->settings);
+                                       transport_settings = modest_account_settings_get_transport_settings (priv->settings);
+                                       store_account_name = modest_server_account_settings_get_account_name (store_settings);
+                                       transport_account_name = modest_server_account_settings_get_account_name (transport_settings);
+                                       
+                                       if (store_account_name) {
+                                               modest_account_mgr_notify_account_update (priv->account_manager, 
+                                                                                         store_account_name);
+                                       }
+                                       if (transport_account_name) {
+                                               modest_account_mgr_notify_account_update (priv->account_manager, 
+                                                                                         transport_account_name);
+                                       }
+                                       g_object_unref (store_settings);
+                                       g_object_unref (transport_settings);
+                                       
+                                       modest_platform_information_banner(NULL, NULL, _("mcen_ib_advsetup_settings_saved"));
+                               }
+                       } else {
+                               modest_platform_information_banner (NULL, NULL, _("mail_ib_setting_failed"));
+                       }
+               }
+       }
+}
+
+static void
+modest_default_account_settings_dialog_init (ModestDefaultAccountSettingsDialog *self)
+{
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE(self);
+
+       priv->incoming_security = NULL;
+       priv->outgoing_security = NULL;
+
+       /* Create the notebook to be used by the GtkDialog base class:
+        * Each page of the notebook will be a page of the wizard: */
+       priv->notebook = GTK_NOTEBOOK (gtk_notebook_new());
+       priv->settings = modest_account_settings_new ();
+
+       /* Get the account manager object, 
+        * so we can check for existing accounts,
+        * and create new accounts: */
+       priv->account_manager = modest_runtime_get_account_mgr ();
+       g_assert (priv->account_manager);
+       g_object_ref (priv->account_manager);
+       
+       priv->protocol_authentication_incoming = MODEST_PROTOCOLS_AUTH_PASSWORD;
+
+    /* Create the common pages, 
+     */
+       priv->page_account_details = create_page_account_details (self);
+       priv->page_user_details = create_page_user_details (self);
+       priv->page_incoming = create_page_incoming (self);
+       priv->page_outgoing = create_page_outgoing (self);
+       
+       /* Add the notebook pages: */
+       gtk_notebook_append_page (priv->notebook, priv->page_account_details, 
+               gtk_label_new (_("mcen_ti_account_settings_account")));
+       gtk_notebook_append_page (priv->notebook, priv->page_user_details, 
+               gtk_label_new (_("mcen_ti_account_settings_userinfo")));
+       gtk_notebook_append_page (priv->notebook, priv->page_incoming,
+               gtk_label_new (_("mcen_ti_advsetup_retrieval")));
+       gtk_notebook_append_page (priv->notebook, priv->page_outgoing,
+               gtk_label_new (_("mcen_ti_advsetup_sending")));
+               
+       GtkDialog *dialog = GTK_DIALOG (self);
+       gtk_container_add (GTK_CONTAINER (dialog->vbox), GTK_WIDGET (priv->notebook));
+       gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), MODEST_MARGIN_HALF);
+       gtk_widget_show (GTK_WIDGET (priv->notebook));
+        
+    /* Add the buttons: */
+    gtk_dialog_add_button (GTK_DIALOG(self), _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK);
+    gtk_dialog_add_button (GTK_DIALOG(self), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL);
+    
+    /* Connect to the dialog's response signal: */
+    /* We use connect-before 
+     * so we can stop the signal emission, 
+     * to stop the default signal handler from closing the dialog.
+     */
+    g_signal_connect (G_OBJECT (self), "response",
+            G_CALLBACK (on_response), self); 
+            
+    priv->modified = FALSE;
+
+    /* When this window is shown, hibernation should not be possible, 
+        * because there is no sensible way to save the state: */
+    modest_window_mgr_prevent_hibernation_while_window_is_shown (
+       modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
+
+    /* Prevent sending mails while editing an account, to avoid hangs on unprotected locks
+     * while sending messages causes an error dialog and we have a lock */
+    modest_tny_account_store_set_send_mail_blocked (modest_runtime_get_account_store (), TRUE);
+
+    hildon_help_dialog_help_enable (GTK_DIALOG(self), "applications_email_accountsettings",
+                                   modest_maemo_utils_get_osso_context());
+}
+
+ModestAccountSettingsDialog*
+modest_default_account_settings_dialog_new (void)
+{
+       return g_object_new (MODEST_TYPE_DEFAULT_ACCOUNT_SETTINGS_DIALOG, NULL);
+}
+
+/** Update the UI with the stored account details, so they can be edited.
+ * @account_name: Name of the account, which should contain incoming and outgoing server accounts.
+ */
+static void 
+modest_default_account_settings_dialog_load_settings (ModestAccountSettingsDialog *dialog, 
+                                                     ModestAccountSettings *settings)
+{
+       ModestServerAccountSettings *incoming_account;
+       ModestServerAccountSettings *outgoing_account;
+       ModestProtocolRegistry *protocol_registry;
+       const gchar *account_name, *server_account_name;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       gint page_num;
+       gboolean username_known;
+
+       g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS_DIALOG (dialog));
+       g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS (settings));
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       incoming_account = modest_account_settings_get_store_settings (settings);
+       outgoing_account = modest_account_settings_get_transport_settings (settings);
+
+       account_name = modest_account_settings_get_account_name (settings);
+               
+       /* Save the account name so we can refer to it later: */
+       if (priv->account_name)
+               g_free (priv->account_name);
+       priv->account_name = g_strdup (account_name);
+
+       if (priv->settings)
+               g_object_unref (priv->settings);
+       priv->settings = g_object_ref (settings);
+       
+       /* Save the account title so we can refer to it if the user changes it: */
+       if (priv->original_account_title)
+               g_free (priv->original_account_title);
+       priv->original_account_title = g_strdup (modest_account_settings_get_display_name (settings));
+       
+       /* Show the account data in the widgets: */
+       
+       /* Note that we never show the non-display name in the UI.
+        * (Though the display name defaults to the non-display name at the start.) */
+       gtk_entry_set_text( GTK_ENTRY (priv->entry_account_title),
+                           null_means_empty (modest_account_settings_get_display_name (settings)));
+       gtk_entry_set_text( GTK_ENTRY (priv->entry_user_name), 
+                           null_means_empty (modest_account_settings_get_fullname (settings)));
+       gtk_entry_set_text( GTK_ENTRY (priv->entry_user_email), 
+                           null_means_empty (modest_account_settings_get_email_address (settings)));
+       modest_retrieve_combo_box_set_active_retrieve_conf (MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve), 
+                                                           modest_account_settings_get_retrieve_type (settings));
+       modest_limit_retrieve_combo_box_set_active_limit_retrieve (
+               MODEST_LIMIT_RETRIEVE_COMBO_BOX (priv->combo_limit_retrieve), 
+               modest_account_settings_get_retrieve_limit (settings));
+       
+       
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_leave_messages), 
+                                     modest_account_settings_get_leave_messages_on_server (settings));
+       
+
+       if (incoming_account) {
+               const gchar *username, *password, *hostname, *proto_str, *account_title;
+               gchar *proto_name, *title;
+               ModestProtocolType incoming_protocol;
+
+               modest_retrieve_combo_box_fill (MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve), modest_server_account_settings_get_protocol (incoming_account));
+               
+               if (!modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry,
+                                                                                modest_server_account_settings_get_protocol (incoming_account))) {
+                       gtk_widget_hide (priv->caption_leave_messages);
+               } else {
+                       gtk_widget_show (priv->caption_leave_messages);
+               }
+
+               /* Remember this for later: */
+               incoming_protocol = modest_server_account_settings_get_protocol (incoming_account);;
+               
+               hostname = modest_server_account_settings_get_hostname (incoming_account);
+               username = modest_server_account_settings_get_username (incoming_account);
+               password = modest_server_account_settings_get_password (incoming_account);
+               gtk_entry_set_text( GTK_ENTRY (priv->entry_user_username),
+                                   null_means_empty (username));
+               gtk_entry_set_text( GTK_ENTRY (priv->entry_user_password), 
+                                   null_means_empty (password));
+                       
+               gtk_entry_set_text( GTK_ENTRY (priv->entry_incomingserver), 
+                                   null_means_empty (hostname));
+
+               /* Load security settings */
+               modest_security_options_view_load_settings (
+                           MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security), 
+                           settings);
+               gtk_widget_show (priv->incoming_security);
+                                       
+               /* Update the incoming label */
+               update_incoming_server_title (MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG (dialog), 
+                                             incoming_protocol);
+               
+               /* Set window title according to account */
+               proto_str = modest_protocol_get_display_name (modest_protocol_registry_get_protocol_by_type (protocol_registry, incoming_protocol));
+               proto_name = g_utf8_strup (proto_str, -1);
+               account_title = modest_account_settings_get_display_name(settings);
+               title = g_strdup_printf(_("mcen_ti_account_settings"), proto_name, account_title);
+               
+               gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+               g_free (proto_name);
+               g_free (title);
+               g_object_unref (incoming_account);
+       }
+       
+       outgoing_account = modest_account_settings_get_transport_settings (settings);
+       if (outgoing_account) {
+               const gchar *hostname;
+               const gchar *username;
+               const gchar *password;
+               ModestProtocolType outgoing_protocol;
+
+               /* Remember this for later: */
+               outgoing_protocol = 
+                       modest_server_account_settings_get_protocol (outgoing_account);
+
+               hostname = modest_server_account_settings_get_hostname (outgoing_account);
+               username = modest_server_account_settings_get_username (outgoing_account);
+               password = modest_server_account_settings_get_password (outgoing_account);
+               gtk_entry_set_text( GTK_ENTRY (priv->entry_outgoingserver), 
+                                   null_means_empty (hostname));
+
+               /* Load security settings */
+               modest_security_options_view_load_settings (
+                           MODEST_SECURITY_OPTIONS_VIEW (priv->outgoing_security), 
+                           settings);
+               gtk_widget_show (priv->outgoing_security);
+
+               const gboolean has_specific = 
+                       modest_account_settings_get_use_connection_specific_smtp (settings);
+               gtk_toggle_button_set_active (
+                       GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific), 
+                       has_specific);
+               g_object_unref (outgoing_account);
+       }
+
+       /* Switch to user page */
+       page_num = gtk_notebook_page_num (priv->notebook,priv->page_user_details);
+       gtk_notebook_set_current_page (priv->notebook, page_num);
+
+       /* Check if we allow changes or not */
+       server_account_name = modest_server_account_settings_get_account_name (incoming_account);
+       username_known = 
+               modest_account_mgr_get_server_account_username_has_succeeded (priv->account_manager,
+                                                                             server_account_name);
+       gtk_widget_set_sensitive (priv->entry_user_username, !username_known);
+       gtk_widget_set_sensitive (priv->entry_incomingserver, !username_known);
+       modest_security_options_view_enable_changes (MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security),
+                                                    !username_known);
+
+
+       /* Unset the modified flag so we can detect changes later: */
+       priv->modified = FALSE;
+}
+
+static gboolean
+save_configuration (ModestDefaultAccountSettingsDialog *dialog)
+{
+       const gchar* user_fullname;
+       const gchar* emailaddress;
+       ModestServerAccountSettings *store_settings;
+       ModestServerAccountSettings *transport_settings;
+       ModestAccountRetrieveType retrieve_type;
+       gint retrieve_limit;
+       gboolean leave_on_server;
+       const gchar* hostname;
+       const gchar* username;
+       const gchar* password;
+       gchar* account_title;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+       const gchar* account_name;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
+       account_name = priv->account_name;
+
+       /* Set the account data from the widgets: */
+       user_fullname = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_name));
+       modest_account_settings_set_fullname (priv->settings, user_fullname);
+       
+       emailaddress = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
+       modest_account_settings_set_email_address (priv->settings, emailaddress);
+               
+       /* Signature: */
+       if (priv->signature_dialog) {
+               gboolean use_signature = FALSE;
+               gchar *signature;
+               signature = modest_signature_editor_dialog_get_settings (MODEST_SIGNATURE_EDITOR_DIALOG (priv->signature_dialog),
+                                                                        &use_signature);
+       
+               modest_account_settings_set_use_signature (priv->settings, use_signature);
+               modest_account_settings_set_signature (priv->settings, signature);
+       }
+       
+       retrieve_type = modest_retrieve_combo_box_get_active_retrieve_conf (
+               MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve));
+       modest_account_settings_set_retrieve_type (priv->settings, retrieve_type);
+       
+       retrieve_limit = modest_limit_retrieve_combo_box_get_active_limit_retrieve (
+               MODEST_LIMIT_RETRIEVE_COMBO_BOX (priv->combo_limit_retrieve));
+       modest_account_settings_set_retrieve_limit (priv->settings, retrieve_limit);
+       
+       leave_on_server = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->checkbox_leave_messages));
+       modest_account_settings_set_leave_messages_on_server (priv->settings, leave_on_server); 
+
+       store_settings = modest_account_settings_get_store_settings (priv->settings);
+                       
+       hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_incomingserver));
+       modest_server_account_settings_set_hostname (store_settings, hostname);
+                               
+       username = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username));
+       modest_server_account_settings_set_username (store_settings, username);
+       
+       password = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_password));
+       modest_server_account_settings_set_password (store_settings, password);
+
+       /* Save security settings */
+       modest_security_options_view_save_settings (MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security), 
+                                                   priv->settings);
+
+       g_object_unref (store_settings);
+       
+       /* Outgoing: */
+       transport_settings = modest_account_settings_get_transport_settings (priv->settings);
+       
+       hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
+       modest_server_account_settings_set_hostname (transport_settings, hostname);
+                       
+       /* Save security settings */
+       modest_security_options_view_save_settings (
+           MODEST_SECURITY_OPTIONS_VIEW (priv->outgoing_security), 
+           priv->settings);
+       
+       /* Set the changed account title last, to simplify the previous code: */
+       account_title = get_entered_account_title (dialog);
+       if (!account_title)
+               return FALSE; /* Should be prevented already anyway. */
+               
+/*     if (strcmp (account_title, account_name) != 0) { */
+       modest_account_settings_set_display_name (priv->settings, account_title);
+/*     } */
+       g_free (account_title);
+       account_title = NULL;
+       
+       /* Save connection-specific SMTP server accounts: */
+       modest_account_settings_set_use_connection_specific_smtp 
+               (priv->settings, 
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox_outgoing_smtp_specific)));
+
+       /* this configuration is not persistent, we should not save */
+       if (account_name != NULL)
+               modest_account_mgr_save_account_settings (priv->account_manager, priv->settings);
+
+       return TRUE;
+}
+
+static gboolean entry_is_empty (GtkWidget *entry)
+{
+       if (!entry)
+               return FALSE;
+               
+       const gchar* text = gtk_entry_get_text (GTK_ENTRY (entry));
+       if ((!text) || (strlen(text) == 0))
+               return TRUE;
+       else {
+               /* Strip it of whitespace at the start and end: */
+               gchar *stripped = g_strdup (text);
+               stripped = g_strstrip (stripped);
+               
+               if (!stripped)
+                       return TRUE;
+                       
+               const gboolean result = (strlen (stripped) == 0);
+               
+               g_free (stripped);
+               return result;
+       }
+}
+
+static void
+enable_buttons (ModestDefaultAccountSettingsDialog *self)
+{
+       gboolean enable_ok = TRUE;
+       ModestProtocolRegistry *protocol_registry;
+       ModestDefaultAccountSettingsDialogPrivate *priv;
+
+       priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
+       
+       /* The account details title is mandatory: */
+       if (entry_is_empty(priv->entry_account_title))
+               enable_ok = FALSE;
+
+       /* The user details username is mandatory: */
+       if (enable_ok && entry_is_empty(priv->entry_user_username))
+               enable_ok = FALSE;
+               
+       /* The user details email address is mandatory: */
+       if (enable_ok && entry_is_empty (priv->entry_user_email))
+               enable_ok = FALSE;
+
+       /* The custom incoming server is mandatory: */
+       if (enable_ok && entry_is_empty(priv->entry_incomingserver))
+               enable_ok = FALSE;
+
+       /* The custom outgoing server is mandatory: */
+       if (enable_ok && entry_is_empty(priv->entry_outgoingserver))
+               enable_ok = FALSE;
+
+       protocol_registry = modest_runtime_get_protocol_registry ();
+                       
+       /* Enable the buttons, 
+        * identifying them via their associated response codes:
+        */
+       GtkDialog *dialog_base = GTK_DIALOG (self);
+       gtk_dialog_set_response_sensitive (dialog_base,
+                                          GTK_RESPONSE_OK,
+                                          enable_ok);
+}
+
+static void
+modest_default_account_settings_dialog_class_init (ModestDefaultAccountSettingsDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       g_type_class_add_private (klass, sizeof (ModestDefaultAccountSettingsDialogPrivate));
+
+       object_class->dispose = modest_default_account_settings_dialog_dispose;
+       object_class->finalize = modest_default_account_settings_dialog_finalize;
+}
+
+static void 
+modest_account_settings_dialog_init (gpointer g_iface, gpointer iface_data)
+{
+       ModestAccountSettingsDialogClass *iface = (ModestAccountSettingsDialogClass *) g_iface;
+
+       iface->load_settings = modest_default_account_settings_dialog_load_settings;
+}
diff --git a/src/hildon2/modest-easysetup-country-combo-box.c b/src/hildon2/modest-easysetup-country-combo-box.c
new file mode 100644 (file)
index 0000000..683c365
--- /dev/null
@@ -0,0 +1,394 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */
+#endif
+
+#include <stdio.h>
+
+#include "modest-maemo-utils.h"
+#include "modest-easysetup-country-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+#include <langinfo.h>
+#include <locale.h>
+#include <libintl.h> /* For dgettext(). */
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MAX_LINE_LEN 128 /* max length of a line in MCC file */
+
+#if MODEST_HILDON_API < 2
+G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, GTK_TYPE_COMBO_BOX);
+#else
+G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, HILDON_TYPE_PICKER_BUTTON);
+#endif
+
+typedef struct
+{
+       gint locale_mcc;
+/*     GtkTreeModel *model; */
+} ModestEasysetupCountryComboBoxPrivate;
+
+#define MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                                       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, \
+                                                       ModestEasysetupCountryComboBoxPrivate))
+
+static void
+easysetup_country_combo_box_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_country_combo_box_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_country_combo_box_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (easysetup_country_combo_box_parent_class)->dispose)
+               G_OBJECT_CLASS (easysetup_country_combo_box_parent_class)->dispose (object);
+}
+
+enum MODEL_COLS {
+       MODEL_COL_NAME = 0, /* string */
+       MODEL_COL_MCC  = 1 /* the 'effective mcc' for this country */
+};
+
+       
+static void
+easysetup_country_combo_box_finalize (GObject *object)
+{
+       G_OBJECT_CLASS (easysetup_country_combo_box_parent_class)->finalize (object);
+}
+
+static void
+easysetup_country_combo_box_class_init (EasysetupCountryComboBoxClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (ModestEasysetupCountryComboBoxPrivate));
+
+       object_class->get_property = easysetup_country_combo_box_get_property;
+       object_class->set_property = easysetup_country_combo_box_set_property;
+       object_class->dispose = easysetup_country_combo_box_dispose;
+       object_class->finalize = easysetup_country_combo_box_finalize;
+}
+
+
+
+
+/* cluster mcc's, based on the list
+ * http://en.wikipedia.org/wiki/Mobile_country_code
+ */
+static int
+effective_mcc (gint mcc)
+{
+       switch (mcc) {
+       case 405: return 404; /* india */
+       case 441: return 440; /* japan */       
+       case 235: return 234; /* united kingdom */
+       case 311:
+       case 312:
+       case 313:
+       case 314:
+       case 315:
+       case 316: return 310; /* united states */
+       default:  return mcc;
+       }
+}
+
+
+/* each line is of the form:
+   xxx    logical_id
+   
+  NOTE: this function is NOT re-entrant, the out-param country
+  are static strings that should NOT be freed. and will change when
+  calling this function again
+
+  also note, this function will return the "effective mcc", which
+  is the normalized mcc for a country - ie. even if the there
+  are multiple entries for the United States with various mccs,
+  this function will always return 310, even if the real mcc parsed
+  would be 314. see the 'effective_mcc' function above.
+*/
+static int
+parse_mcc_mapping_line (const char* line,  char** country)
+{
+       int i, j;
+       char mcc[4];  /* the mcc code, always 3 bytes*/
+       static char my_country[128];
+
+       if (!line) {
+               *country = NULL;
+               return 0;
+       }
+       
+       for (i = 3, j = 0; i < 128; ++i) {
+               char kar = line[i];
+               if (kar == '\0')
+                       break;
+               else if (kar < '_')
+                       continue;
+               else 
+                       my_country [j++] = kar;
+       }
+       my_country[j] = '\0';
+
+       mcc[0] = line[0];
+       mcc[1] = line[1];
+       mcc[2] = line[2];
+       mcc[3] = '\0';
+       
+       *country = my_country;
+
+       return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
+}
+
+/** Note that the mcc_mapping file is installed 
+ * by the operator-wizard-settings package.
+ */
+static void
+load_from_file (EasysetupCountryComboBox *self, GtkListStore *liststore)
+{
+       ModestEasysetupCountryComboBoxPrivate *priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self);
+       
+       char line[MAX_LINE_LEN];
+       guint previous_mcc = 0;
+       gchar *territory, *fallback = NULL;
+       gchar *current_locale;
+
+       /* Get the territory specified for the current locale */
+       territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
+
+       /* Tricky stuff, the translations of the OSSO countries does
+          not always correspond to the country names in locale
+          databases. Add all these cases here. sergio */
+       if (!strcmp (territory, "United Kingdom"))
+               fallback = g_strdup ("UK");
+
+       current_locale = setlocale (LC_ALL ,NULL);
+
+       FILE *file = modest_maemo_open_mcc_mapping_file ();
+       if (!file) {
+               g_warning("Could not open mcc_mapping file");
+               return;
+       }
+
+       while (fgets (line, MAX_LINE_LEN, file) != NULL) { 
+
+               int mcc;
+               char *country = NULL;
+               const gchar *name_translated, *english_translation;
+
+               mcc = parse_mcc_mapping_line (line, &country);
+               if (!country || mcc == 0) {
+                       g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
+                       continue;
+               }
+
+               if (mcc == previous_mcc) {
+                       /* g_warning ("already seen: %s", line); */
+                       continue;
+               }
+               previous_mcc = mcc;
+
+               if (!priv->locale_mcc) {
+                       english_translation = dgettext ("osso-countries", country);
+                       if (!strcmp (english_translation, territory) ||
+                           (fallback && !strcmp (english_translation, fallback)))
+                               priv->locale_mcc = mcc;
+               }
+               name_translated = dgettext ("osso-countries", country);
+               
+               /* Add the row to the model: */
+               GtkTreeIter iter;
+               gtk_list_store_append (liststore, &iter);
+               gtk_list_store_set(liststore, &iter, MODEL_COL_MCC, mcc, MODEL_COL_NAME, name_translated, -1);
+       }       
+       fclose (file);
+
+       /* Sort the items: */
+       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore), 
+                                             MODEL_COL_NAME, GTK_SORT_ASCENDING);
+
+       g_free (fallback);
+}
+
+static void
+easysetup_country_combo_box_init (EasysetupCountryComboBox *self)
+{
+       ModestEasysetupCountryComboBoxPrivate *priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self);
+       priv->locale_mcc = 0;
+}
+
+void
+easysetup_country_combo_box_load_data(EasysetupCountryComboBox *self)
+{
+       GtkListStore *model;
+
+       /* Create a tree model for the combo box,
+        * with a string for the name, and an int for the MCC ID.
+        * This must match our MODEL_COLS enum constants.
+        */
+       model = gtk_list_store_new (2,  G_TYPE_STRING, G_TYPE_INT);
+       
+       /* Country column:
+        * The ID model column in not shown in the view. */
+       GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+       g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+
+#if MODEST_HILDON_API < 2
+       gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (self), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), renderer, 
+                                       "text", MODEL_COL_NAME, NULL);
+#else
+       GtkWidget *selector = hildon_touch_selector_new ();
+       hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (self), HILDON_TOUCH_SELECTOR (selector));
+       hildon_touch_selector_append_column (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (self)),
+                                            GTK_TREE_MODEL (model),
+                                            renderer, "text", MODEL_COL_NAME, NULL);
+#endif
+
+       /* Fill the model with rows: */
+       load_from_file (self, model);
+
+       /* Set this _after_ loading from file, it makes loading faster */
+#if MODEST_HILDON_API < 2
+       gtk_combo_box_set_model (GTK_COMBO_BOX (self), GTK_TREE_MODEL (model));
+#else
+       hildon_touch_selector_set_model (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (self)),
+                                        0, GTK_TREE_MODEL (model));
+#endif
+}
+
+EasysetupCountryComboBox*
+easysetup_country_combo_box_new (void)
+{
+#if MODEST_HILDON_API >= 2
+       return g_object_new (MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, 
+                            "arrangement", HILDON_BUTTON_ARRANGEMENT_VERTICAL,
+                            "size", HILDON_SIZE_AUTO,
+                            NULL);
+#else
+       return g_object_new (MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, 
+                            NULL);
+#endif
+}
+
+/**
+ * Returns the MCC number of the selected country, or 0 if no country was selected. 
+ */
+gint
+easysetup_country_combo_box_get_active_country_mcc (EasysetupCountryComboBox *self)
+{
+       GtkTreeIter active;
+       gboolean found;
+
+#if MODEST_HILDON_API < 2
+       found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &active);
+#else
+       found = hildon_touch_selector_get_selected (hildon_picker_button_get_selector
+                                                   (HILDON_PICKER_BUTTON (self)), 0, &active);
+#endif
+       if (found) {
+               gint mcc = 0;
+#if MODEST_HILDON_API < 2
+               gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (self)), 
+                                   &active, MODEL_COL_MCC, &mcc, -1);
+#else
+               gtk_tree_model_get (hildon_touch_selector_get_model (hildon_picker_button_get_selector
+                                                                    (HILDON_PICKER_BUTTON (self)), 
+                                                                    0), 
+                                   &active, MODEL_COL_MCC, &mcc, -1);
+#endif
+               return mcc;     
+       }
+       return 0; /* Failed. */
+}
+
+
+/**
+ * Selects the MCC number of the selected country.
+ * Specify 0 to select no country. 
+ */
+gboolean
+easysetup_country_combo_box_set_active_country_locale (EasysetupCountryComboBox *self)
+{
+       ModestEasysetupCountryComboBoxPrivate *priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self);
+       GtkTreeIter iter;
+       gint current_mcc;
+       GtkTreeModel *model;
+
+#if MODEST_HILDON_API < 2
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
+       g_message ("HILDON < 2");
+#else
+       model = hildon_touch_selector_get_model (hildon_picker_button_get_selector 
+                                                (HILDON_PICKER_BUTTON (self)), 0);
+       g_message ("HILDON >= 2");
+#endif
+       if (!gtk_tree_model_get_iter_first (model, &iter))
+               return FALSE;
+       do {
+               gtk_tree_model_get (model, &iter, MODEL_COL_MCC, &current_mcc, -1);
+               if (priv->locale_mcc == current_mcc) {
+#if MODEST_HILDON_API < 2
+                       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
+#else
+                       hildon_touch_selector_select_iter (hildon_picker_button_get_selector 
+                                                          (HILDON_PICKER_BUTTON (self)), 0, 
+                                                          &iter, TRUE);
+#endif
+                       return TRUE;
+               }
+       } while (gtk_tree_model_iter_next (model, &iter));
+       
+       return FALSE; /* not found */
+}
+
diff --git a/src/hildon2/modest-easysetup-country-combo-box.h b/src/hildon2/modest-easysetup-country-combo-box.h
new file mode 100644 (file)
index 0000000..56f1741
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MODEST_EASYSETUP_COUNTRY_COMBO_BOX
+#define _MODEST_EASYSETUP_COUNTRY_COMBO_BOX
+
+#if MODEST_HILDON_API < 2
+#include <gtk/gtkcombobox.h>
+#else
+#include <hildon/hildon-picker-button.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX easysetup_country_combo_box_get_type()
+
+#define MODEST_EASYSETUP_COUNTRY_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBox))
+
+#define MODEST_EASYSETUP_COUNTRY_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxClass))
+
+#define MODEST_EASYSETUP_IS_COUNTRY_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX))
+
+#define MODEST_EASYSETUP_IS_COUNTRY_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX))
+
+#define MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxClass))
+
+#if MODEST_HILDON_API < 2
+typedef struct {
+       GtkComboBox parent;
+} EasysetupCountryComboBox;
+
+typedef struct {
+       GtkComboBoxClass parent_class;
+} EasysetupCountryComboBoxClass;
+#else
+typedef struct {
+       HildonPickerButton parent;
+} EasysetupCountryComboBox;
+
+typedef struct {
+       HildonPickerButtonClass parent_class;
+} EasysetupCountryComboBoxClass;
+#endif
+GType easysetup_country_combo_box_get_type (void);
+
+EasysetupCountryComboBox* easysetup_country_combo_box_new (void);
+
+void easysetup_country_combo_box_load_data(EasysetupCountryComboBox *self);
+
+gint easysetup_country_combo_box_get_active_country_mcc (EasysetupCountryComboBox *self);
+
+
+gboolean easysetup_country_combo_box_set_active_country_locale (EasysetupCountryComboBox *self);
+
+G_END_DECLS
+
+#endif /* _MODEST_EASYSETUP_COUNTRY_COMBO_BOX */
diff --git a/src/hildon2/modest-easysetup-provider-combo-box.c b/src/hildon2/modest-easysetup-provider-combo-box.c
new file mode 100644 (file)
index 0000000..1147a1d
--- /dev/null
@@ -0,0 +1,332 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-easysetup-provider-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+#include <modest-text-utils.h>
+#include "modest-protocol-registry.h"
+#include "modest-runtime.h"
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+G_DEFINE_TYPE (EasysetupProviderComboBox, easysetup_provider_combo_box, GTK_TYPE_COMBO_BOX);
+
+#define PROVIDER_COMBO_BOX_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBoxPrivate))
+
+typedef struct _EasysetupProviderComboBoxPrivate EasysetupProviderComboBoxPrivate;
+
+struct _EasysetupProviderComboBoxPrivate
+{
+       GtkTreeModel *model;
+};
+
+static void
+easysetup_provider_combo_box_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_provider_combo_box_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_provider_combo_box_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (easysetup_provider_combo_box_parent_class)->dispose)
+               G_OBJECT_CLASS (easysetup_provider_combo_box_parent_class)->dispose (object);
+}
+
+static void
+easysetup_provider_combo_box_finalize (GObject *object)
+{
+       EasysetupProviderComboBoxPrivate *priv = PROVIDER_COMBO_BOX_GET_PRIVATE (object);
+
+       g_object_unref (G_OBJECT (priv->model));
+
+       G_OBJECT_CLASS (easysetup_provider_combo_box_parent_class)->finalize (object);
+}
+
+static void
+easysetup_provider_combo_box_class_init (EasysetupProviderComboBoxClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (EasysetupProviderComboBoxPrivate));
+
+       object_class->get_property = easysetup_provider_combo_box_get_property;
+       object_class->set_property = easysetup_provider_combo_box_set_property;
+       object_class->dispose = easysetup_provider_combo_box_dispose;
+       object_class->finalize = easysetup_provider_combo_box_finalize;
+}
+
+enum MODEL_COLS {
+       MODEL_COL_ID, /* a string, not an int. */
+       MODEL_COL_NAME,
+       MODEL_COL_ID_TYPE
+};
+
+
+/*
+ * strictly, we should sort providers with mcc=0 after the other ones.... but, we don't have
+ * that info here, so ignoring for now.
+ */
+static gint
+provider_sort_func (GtkTreeModel *model, GtkTreeIter *iter1, GtkTreeIter *iter2, gpointer user_data)
+{
+       gchar *prov1, *prov2;
+       gint retval;
+       
+       gtk_tree_model_get (model, iter1, MODEL_COL_NAME, &prov1, -1);
+       gtk_tree_model_get (model, iter2, MODEL_COL_NAME, &prov2, -1);
+
+       if (strcmp (prov1, prov2) == 0) 
+               retval = 0;
+       else if (strcmp (_("mcen_va_serviceprovider_other"), prov1) == 0)
+               retval = -1;
+       else if (strcmp (_("mcen_va_serviceprovider_other"), prov2) == 0)
+               retval = 1;
+       else
+               retval = modest_text_utils_utf8_strcmp (prov1, prov2, TRUE);
+       
+       g_free (prov1);
+       g_free (prov2);
+
+       return retval;
+}
+
+static void
+easysetup_provider_combo_box_init (EasysetupProviderComboBox *self)
+{
+       EasysetupProviderComboBoxPrivate *priv = PROVIDER_COMBO_BOX_GET_PRIVATE (self);
+
+       /* Create a tree model for the combo box,
+        * with a string for the name, and a string for the ID (e.g. "vodafone.it"), and the mcc
+        * This must match our MODEL_COLS enum constants.
+        */
+       priv->model = GTK_TREE_MODEL (gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT));
+
+       /* Setup the combo box: */
+       GtkComboBox *combobox = GTK_COMBO_BOX (self);
+       gtk_combo_box_set_model (combobox, priv->model);
+
+       /* Provider column:
+        * The ID model column in not shown in the view. */
+       GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combobox), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer,  "text", MODEL_COL_NAME, NULL);
+       
+       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(priv->model),
+                                             MODEL_COL_NAME, GTK_SORT_ASCENDING);
+       gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(priv->model),
+                                         MODEL_COL_NAME,
+                                         (GtkTreeIterCompareFunc)provider_sort_func,
+                                         NULL, NULL);
+}
+
+EasysetupProviderComboBox*
+easysetup_provider_combo_box_new (void)
+{
+       return g_object_new (EASYSETUP_TYPE_PROVIDER_COMBO_BOX, NULL);
+}
+
+void
+easysetup_provider_combo_box_fill (EasysetupProviderComboBox *combobox, 
+                                  ModestPresets *presets,
+                                  gint mcc)
+{      
+       GtkTreeIter other_iter;
+       EasysetupProviderComboBoxPrivate *priv;
+       GtkListStore *liststore;        
+       GSList *provider_ids_used_already = NULL, *provider_protos, *tmp;
+       gchar ** provider_ids = NULL;
+       gchar ** provider_names;        
+       gchar ** iter_provider_names;
+       gchar ** iter_provider_ids;
+       ModestProtocolRegistry *registry;
+
+       g_return_if_fail (EASYSETUP_IS_PROVIDER_COMBO_BOX(combobox));
+
+       priv = PROVIDER_COMBO_BOX_GET_PRIVATE (combobox);
+       liststore = GTK_LIST_STORE (priv->model);
+       gtk_list_store_clear (liststore);
+       provider_names = modest_presets_get_providers (presets, mcc, TRUE, &provider_ids);
+
+       iter_provider_names = provider_names;
+       iter_provider_ids = provider_ids;
+
+       while(iter_provider_names && *iter_provider_names && iter_provider_ids && *iter_provider_ids) {
+               const gchar* provider_name = *iter_provider_names;
+               const gchar* provider_id = *iter_provider_ids;
+
+               /* Prevent duplicate providers: */
+               if (g_slist_find_custom (provider_ids_used_already, 
+                                        provider_id, (GCompareFunc)strcmp) == NULL) {
+                       /* printf("debug: provider_name=%s\n", provider_name); */
+
+                       /* Add the row: */
+                       GtkTreeIter iter;
+                       gtk_list_store_append (liststore, &iter);
+                       
+                       gtk_list_store_set(liststore, &iter, 
+                                          MODEL_COL_ID, provider_id, 
+                                          MODEL_COL_NAME, provider_name, 
+                                          MODEL_COL_ID_TYPE, EASYSETUP_PROVIDER_COMBO_BOX_ID_PROVIDER,
+                                          -1);
+                       
+                       provider_ids_used_already = g_slist_prepend (
+                               provider_ids_used_already, (gpointer)g_strdup (provider_id));
+               }
+               
+               ++iter_provider_names;
+               ++iter_provider_ids;
+       }
+       
+       /* Free the result of modest_presets_get_providers()
+        * as specified by its documentation: */
+       g_strfreev (provider_names);
+       g_strfreev (provider_ids);
+
+       /* Add the provider protocols */
+       registry = modest_runtime_get_protocol_registry ();
+       provider_protos = modest_protocol_registry_get_by_tag (registry, 
+                                                              MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS);
+       tmp = provider_protos;
+       while (tmp) {
+               GtkTreeIter iter;
+               ModestProtocol *proto = MODEST_PROTOCOL (tmp->data);
+               const gchar *name = modest_protocol_get_display_name (proto);
+
+               /* only add store protocols, no need to duplicate them */
+               if (modest_protocol_registry_protocol_type_has_tag (registry, 
+                                                                   modest_protocol_get_type_id (proto),
+                                                                   MODEST_PROTOCOL_REGISTRY_STORE_PROTOCOLS)) {
+                       gtk_list_store_append (liststore, &iter);
+                       gtk_list_store_set (liststore, &iter,
+                                           MODEL_COL_ID, modest_protocol_get_name (proto),
+                                           MODEL_COL_NAME, name,
+                                           MODEL_COL_ID_TYPE, EASYSETUP_PROVIDER_COMBO_BOX_ID_PLUGIN_PROTOCOL,
+                                           -1);
+               }
+               tmp = g_slist_next (tmp);
+       }
+       g_slist_free (provider_protos);
+       
+       /* Add the "Other" item: */
+       /* Note that ID 0 means "Other" for us: */
+       gtk_list_store_prepend (liststore, &other_iter);
+       gtk_list_store_set (liststore, &other_iter,
+                           MODEL_COL_ID, 0,
+                           MODEL_COL_NAME, _("mcen_va_serviceprovider_other"),
+                           MODEL_COL_ID_TYPE, EASYSETUP_PROVIDER_COMBO_BOX_ID_OTHER,
+                           -1);
+
+       /* Select the "Other" item: */
+       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &other_iter);
+       
+       g_slist_foreach (provider_ids_used_already, (GFunc)g_free, NULL);
+       g_slist_free (provider_ids_used_already);
+}
+
+/**
+ * Returns the MCC number of the selected provider, 
+ * or NULL if no provider was selected, or "Other" was selected. 
+ */
+gchar*
+easysetup_provider_combo_box_get_active_provider_id (EasysetupProviderComboBox *combobox)
+{
+       GtkTreeIter active;
+
+       g_return_val_if_fail (EASYSETUP_IS_PROVIDER_COMBO_BOX(combobox), NULL);
+
+       const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active);
+       if (found) {
+               EasysetupProviderComboBoxPrivate *priv = PROVIDER_COMBO_BOX_GET_PRIVATE (combobox);
+
+               gchar *id = NULL;
+               gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &id, -1);
+               return g_strdup(id);    
+       }
+
+       return NULL; /* Failed. */
+}
+
+void 
+easysetup_provider_combo_box_set_others_provider (EasysetupProviderComboBox *combobox)
+{
+       GtkTreeModel *model;
+       GtkTreeIter others_iter;
+
+       g_return_if_fail (EASYSETUP_IS_PROVIDER_COMBO_BOX(combobox));
+       
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));
+       
+       if (gtk_tree_model_get_iter_first (model, &others_iter))
+               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &others_iter);
+}
+
+EasysetupProviderComboBoxIdType 
+easysetup_provider_combo_box_get_active_id_type (EasysetupProviderComboBox *combobox)
+{
+       GtkTreeIter active;
+
+       g_return_val_if_fail (EASYSETUP_IS_PROVIDER_COMBO_BOX (combobox), 
+                             EASYSETUP_PROVIDER_COMBO_BOX_ID_OTHER);
+
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active)) {
+               EasysetupProviderComboBoxPrivate *priv = PROVIDER_COMBO_BOX_GET_PRIVATE (combobox);
+               EasysetupProviderComboBoxIdType id_type;
+
+               gtk_tree_model_get (priv->model, &active, MODEL_COL_ID_TYPE, &id_type, -1);
+               return id_type; 
+       } else {
+               /* Fallback to other */
+               return EASYSETUP_PROVIDER_COMBO_BOX_ID_OTHER;
+       }
+}
diff --git a/src/hildon2/modest-easysetup-provider-combo-box.h b/src/hildon2/modest-easysetup-provider-combo-box.h
new file mode 100644 (file)
index 0000000..d4bc283
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _EASYSETUP_PROVIDER_COMBO_BOX
+#define _EASYSETUP_PROVIDER_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#include "modest-presets.h"
+
+G_BEGIN_DECLS
+
+#define EASYSETUP_TYPE_PROVIDER_COMBO_BOX easysetup_provider_combo_box_get_type()
+
+#define EASYSETUP_PROVIDER_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBox))
+
+#define EASYSETUP_PROVIDER_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBoxClass))
+
+#define EASYSETUP_IS_PROVIDER_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       EASYSETUP_TYPE_PROVIDER_COMBO_BOX))
+
+#define EASYSETUP_IS_PROVIDER_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       EASYSETUP_TYPE_PROVIDER_COMBO_BOX))
+
+#define EASYSETUP_PROVIDER_COMBO_BOX_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBoxClass))
+
+/** The thype of the ID
+ *
+ * this means the value of returned by get_active_provider_id will be
+ * different depending on the value returned by get_active_id_type
+ *
+ * If the selected option is a provider then the ID will be the provider ID
+ * If the selected option is "Other..." the the ID will be 0
+ * If the selected option is a provider protocol () the the ID will be protocol name
+ **/
+typedef enum {
+       EASYSETUP_PROVIDER_COMBO_BOX_ID_PROVIDER,
+       EASYSETUP_PROVIDER_COMBO_BOX_ID_OTHER,
+       EASYSETUP_PROVIDER_COMBO_BOX_ID_PLUGIN_PROTOCOL
+} EasysetupProviderComboBoxIdType;
+
+typedef struct {
+       GtkComboBox parent;
+} EasysetupProviderComboBox;
+
+typedef struct {
+       GtkComboBoxClass parent_class;
+} EasysetupProviderComboBoxClass;
+
+GType easysetup_provider_combo_box_get_type (void);
+
+EasysetupProviderComboBox* easysetup_provider_combo_box_new (void);
+
+void easysetup_provider_combo_box_fill (EasysetupProviderComboBox *combobox, ModestPresets *presets,
+                                       gint mcc);
+
+gchar* easysetup_provider_combo_box_get_active_provider_id (EasysetupProviderComboBox *combobox);
+
+EasysetupProviderComboBoxIdType easysetup_provider_combo_box_get_active_id_type (EasysetupProviderComboBox *combobox);
+
+G_END_DECLS
+
+#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */
diff --git a/src/hildon2/modest-easysetup-servertype-combo-box.c b/src/hildon2/modest-easysetup-servertype-combo-box.c
new file mode 100644 (file)
index 0000000..ab54656
--- /dev/null
@@ -0,0 +1,276 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <modest-runtime.h>
+#include "modest-easysetup-servertype-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+G_DEFINE_TYPE (EasysetupServertypeComboBox, easysetup_servertype_combo_box, GTK_TYPE_COMBO_BOX);
+
+#define SERVERTYPE_COMBO_BOX_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, EasysetupServertypeComboBoxPrivate))
+
+typedef struct _EasysetupServertypeComboBoxPrivate EasysetupServertypeComboBoxPrivate;
+
+struct _EasysetupServertypeComboBoxPrivate
+{
+       GtkTreeModel *model;
+};
+
+static void
+easysetup_servertype_combo_box_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_servertype_combo_box_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+easysetup_servertype_combo_box_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->dispose)
+               G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->dispose (object);
+}
+
+static void
+easysetup_servertype_combo_box_finalize (GObject *object)
+{
+       EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (object);
+
+       g_object_unref (G_OBJECT (priv->model));
+
+       G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->finalize (object);
+}
+
+static void
+easysetup_servertype_combo_box_class_init (EasysetupServertypeComboBoxClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (EasysetupServertypeComboBoxPrivate));
+
+       object_class->get_property = easysetup_servertype_combo_box_get_property;
+       object_class->set_property = easysetup_servertype_combo_box_set_property;
+       object_class->dispose = easysetup_servertype_combo_box_dispose;
+       object_class->finalize = easysetup_servertype_combo_box_finalize;
+}
+
+enum MODEL_COLS {
+       MODEL_COL_NAME = 0, /* a string */
+       MODEL_COL_ID = 1 /* an int. */
+};
+
+static void
+easysetup_servertype_combo_box_init (EasysetupServertypeComboBox *self)
+{
+       EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (self);
+
+       /* Create a tree model for the combo box,
+        * with a string for the name, and an ID for the servertype.
+        * This must match our MODEL_COLS enum constants.
+        */
+       priv->model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
+
+       /* Setup the combo box: */
+       GtkComboBox *combobox = GTK_COMBO_BOX (self);
+       gtk_combo_box_set_model (combobox, priv->model);
+
+       /* Servertype column:
+        * The ID model column in not shown in the view. */
+       GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combobox), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, 
+       "text", MODEL_COL_NAME, NULL);
+}
+
+static void 
+easysetup_servertype_combo_box_fill (EasysetupServertypeComboBox *combobox,
+                                    gboolean filter_providers)
+{      
+       EasysetupServertypeComboBoxPrivate *priv;
+       GtkListStore *liststore;
+       ModestProtocolRegistry *protocol_registry;
+       GSList *remote_protocols, *node;
+       GtkTreeIter iter;
+       
+       /* Remove any existing rows: */
+       priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       remote_protocols = modest_protocol_registry_get_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_REMOTE_STORE_PROTOCOLS);
+
+       liststore = GTK_LIST_STORE (priv->model);
+       gtk_list_store_clear (liststore);
+
+       for (node = remote_protocols; node != NULL; node = g_slist_next (node)) {
+               ModestProtocol* protocol;
+               gboolean add = TRUE;
+
+               protocol = (ModestProtocol *) node->data;
+
+               /* Do not include the protocols that would be listed
+                  in the providers combo */
+               if (filter_providers)
+                       if (modest_protocol_registry_protocol_type_is_provider (protocol_registry,
+                                                                               modest_protocol_get_type_id (protocol))) {
+                               add = FALSE;
+                       }
+               
+               if (add) {
+                       gtk_list_store_append (liststore, &iter);
+                       gtk_list_store_set (liststore, &iter, 
+                                           MODEL_COL_ID, 
+                                           modest_protocol_get_type_id (protocol),
+                                           MODEL_COL_NAME, 
+                                           modest_protocol_get_display_name (protocol),
+                                           -1);
+               }
+       }
+       
+       g_slist_free (remote_protocols);
+}
+
+EasysetupServertypeComboBox*
+easysetup_servertype_combo_box_new (gboolean filter_providers)
+{
+       EasysetupServertypeComboBox *combo;
+
+       combo = g_object_new (EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, NULL);
+
+       /* Fill the combo */    
+       easysetup_servertype_combo_box_fill (combo, filter_providers);
+
+       return combo;
+}
+
+/**
+ * Returns the selected servertype, 
+ * or MODEST_PROTOCOL_REGISTRY_TYPE_INVALID if no servertype was selected.
+ */
+ModestProtocolType
+easysetup_servertype_combo_box_get_active_servertype (EasysetupServertypeComboBox *combobox)
+{
+       GtkTreeIter active;
+       gboolean found;
+
+       found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active);
+       if (found) {
+               EasysetupServertypeComboBoxPrivate *priv;
+               ModestProtocolType servertype;
+
+               priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
+
+               servertype = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+               gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &servertype, -1);
+               return servertype;      
+       }
+
+       return MODEST_PROTOCOL_REGISTRY_TYPE_INVALID; /* Failed. */
+}
+
+/* This allows us to pass more than one piece of data to the signal handler,
+ * and get a result: */
+typedef struct 
+{
+               EasysetupServertypeComboBox* self;
+               ModestProtocolType id;
+               gboolean found;
+} ForEachData;
+
+static gboolean
+on_model_foreach_select_id(GtkTreeModel *model, 
+       GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
+{
+       ModestProtocolType id = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+       ForEachData *state = (ForEachData*)(user_data);
+       
+       /* Select the item if it has the matching ID: */
+       gtk_tree_model_get (model, iter, MODEL_COL_ID, &id, -1); 
+       if(id == state->id) {
+               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (state->self), iter);
+               
+               state->found = TRUE;
+               return TRUE; /* Stop walking the tree. */
+       }
+       
+       return FALSE; /* Keep walking the tree. */
+}
+
+/**
+ * Selects the specified servertype, 
+ * or MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN if no servertype was selected.
+ */
+gboolean
+easysetup_servertype_combo_box_set_active_servertype (EasysetupServertypeComboBox *combobox, ModestProtocolType servertype)
+{
+       EasysetupServertypeComboBoxPrivate *priv;
+       ForEachData *state;
+       gboolean result;
+       
+       priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
+
+       /* Create a state instance so we can send two items of data to the signal handler: */
+       state = g_new0 (ForEachData, 1);
+       state->self = combobox;
+       state->id = servertype;
+       state->found = FALSE;
+       
+       /* Look at each item, and select the one with the correct ID: */
+       gtk_tree_model_foreach (priv->model, &on_model_foreach_select_id, state);
+
+       result = state->found;
+       
+       /* Free the state instance: */
+       g_free(state);
+       
+       return result;
+}
+
diff --git a/src/hildon2/modest-easysetup-servertype-combo-box.h b/src/hildon2/modest-easysetup-servertype-combo-box.h
new file mode 100644 (file)
index 0000000..bb7a6b4
--- /dev/null
@@ -0,0 +1,79 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _EASYSETUP_SERVERTYPE_COMBO_BOX
+#define _EASYSETUP_SERVERTYPE_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#include "modest-protocol-registry.h"
+
+G_BEGIN_DECLS
+
+#define EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX easysetup_servertype_combo_box_get_type()
+
+#define EASYSETUP_SERVERTYPE_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, EasysetupServertypeComboBox))
+
+#define EASYSETUP_SERVERTYPE_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, EasysetupServertypeComboBoxClass))
+
+#define EASYSETUP_IS_SERVERTYPE_COMBO_BOX(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX))
+
+#define EASYSETUP_IS_SERVERTYPE_COMBO_BOX_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX))
+
+#define EASYSETUP_SERVERTYPE_COMBO_BOX_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, EasysetupServertypeComboBoxClass))
+
+typedef struct {
+       GtkComboBox parent;
+} EasysetupServertypeComboBox;
+
+typedef struct {
+       GtkComboBoxClass parent_class;
+} EasysetupServertypeComboBoxClass;
+
+GType easysetup_servertype_combo_box_get_type (void);
+
+EasysetupServertypeComboBox* easysetup_servertype_combo_box_new (gboolean filter_providers);
+
+ModestProtocolType easysetup_servertype_combo_box_get_active_servertype (EasysetupServertypeComboBox *combobox);
+
+gboolean easysetup_servertype_combo_box_set_active_servertype (EasysetupServertypeComboBox *combobox, ModestProtocolType servertype);
+
+
+G_END_DECLS
+
+#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */
diff --git a/src/hildon2/modest-easysetup-wizard-dialog.c b/src/hildon2/modest-easysetup-wizard-dialog.c
new file mode 100644 (file)
index 0000000..9e61d43
--- /dev/null
@@ -0,0 +1,2101 @@
+
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <config.h>
+#include "modest-easysetup-wizard-dialog.h"
+#include <glib/gi18n.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkseparator.h>
+#include "maemo/easysetup/modest-easysetup-country-combo-box.h"
+#include "maemo/easysetup/modest-easysetup-provider-combo-box.h"
+#include "maemo/easysetup/modest-easysetup-servertype-combo-box.h"
+#include "widgets/modest-validating-entry.h"
+#include "modest-text-utils.h"
+#include "modest-conf.h"
+#include "modest-defs.h"
+#include "modest-account-mgr.h"
+#include "modest-signal-mgr.h"
+#include "modest-account-mgr-helpers.h"
+#include "modest-runtime.h" /* For modest_runtime_get_account_mgr(). */
+#include "maemo/modest-connection-specific-smtp-window.h"
+#include "widgets/modest-ui-constants.h"
+#include "widgets/modest-default-account-settings-dialog.h"
+#include "widgets/modest-easysetup-wizard-page.h"
+#include "maemo/modest-maemo-utils.h"
+#include "modest-utils.h"
+#include "maemo/modest-hildon-includes.h"
+#include "maemo/modest-maemo-security-options-view.h"
+#include <modest-account-protocol.h>
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+G_DEFINE_TYPE (ModestEasysetupWizardDialog, modest_easysetup_wizard_dialog, MODEST_TYPE_WIZARD_DIALOG);
+
+#define MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                                   MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, \
+                                                   ModestEasysetupWizardDialogPrivate))
+
+typedef struct _ModestEasysetupWizardDialogPrivate ModestEasysetupWizardDialogPrivate;
+
+
+typedef enum {
+       MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED = 0x01,
+       MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED = 0x02
+} ModestEasysetupWizardDialogServerChanges;
+
+struct _ModestEasysetupWizardDialogPrivate
+{
+       ModestPresets *presets;
+
+       /* Remember what fields the user edited manually to not prefill them
+        * again. */
+       ModestEasysetupWizardDialogServerChanges server_changes;
+       
+       /* Check if the user changes a field to show a confirmation dialog */
+       gboolean dirty;
+
+       /* If we have a pending load of settings or not. */
+       gboolean pending_load_settings;
+       
+       /* Used by derived widgets to query existing accounts,
+        * and to create new accounts: */
+       ModestAccountMgr *account_manager;
+       ModestAccountSettings *settings;
+       
+       /* notebook pages: */
+       GtkWidget *page_welcome;
+       
+       GtkWidget *page_account_details;
+       GtkWidget *combo_account_country;
+       GtkWidget *combo_account_serviceprovider;
+       GtkWidget *entry_account_title;
+       
+       GtkWidget *page_user_details;
+       GtkWidget *entry_user_name;
+       GtkWidget *entry_user_username;
+       GtkWidget *entry_user_password;
+       GtkWidget *entry_user_email;
+       
+       GtkWidget *page_complete_easysetup;
+       
+       GtkWidget *page_custom_incoming;
+       GtkWidget *combo_incoming_servertype;
+       GtkWidget *caption_incoming;
+       GtkWidget *entry_incomingserver;
+
+       /* Security widgets */
+       GtkWidget *incoming_security;
+       GtkWidget *outgoing_security;
+
+       GtkWidget *page_custom_outgoing;
+       GtkWidget *entry_outgoingserver;
+       GtkWidget *combo_outgoing_security;
+       GtkWidget *combo_outgoing_auth;
+       GtkWidget *checkbox_outgoing_smtp_specific;
+       GtkWidget *button_outgoing_smtp_servers;
+       
+       GtkWidget *page_complete_customsetup;
+
+       ModestProtocolType last_plugin_protocol_selected;
+       GSList *missing_data_signals;
+};
+
+static void save_to_settings (ModestEasysetupWizardDialog *self);
+static void real_enable_buttons (ModestWizardDialog *dialog, gboolean enable_next);
+
+static gboolean
+on_delete_event (GtkWidget *widget,
+                GdkEvent *event,
+                ModestEasysetupWizardDialog *wizard)
+{
+       gtk_dialog_response (GTK_DIALOG (wizard), GTK_RESPONSE_CANCEL);
+       return TRUE;
+}
+
+static void
+on_easysetup_changed(GtkWidget* widget, ModestEasysetupWizardDialog* wizard)
+{
+       ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(wizard);
+       g_return_if_fail (priv != NULL);
+       priv->dirty = TRUE;
+}
+
+static void
+modest_easysetup_wizard_dialog_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->dispose)
+               G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->dispose (object);
+}
+
+static void
+modest_easysetup_wizard_dialog_finalize (GObject *object)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (object);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       
+       if (priv->account_manager)
+               g_object_unref (G_OBJECT (priv->account_manager));
+               
+       if (priv->presets)
+               modest_presets_destroy (priv->presets);
+
+       if (priv->settings)
+               g_object_unref (priv->settings);
+
+       if (priv->missing_data_signals) {
+               modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
+               priv->missing_data_signals = NULL;
+       }
+               
+       G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->finalize (object);
+}
+
+static void
+create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self);
+
+static void
+set_default_custom_servernames(ModestEasysetupWizardDialog *dialog);
+
+static void on_combo_servertype_changed(GtkComboBox *combobox, gpointer user_data);
+
+static gint 
+get_port_from_protocol (ModestProtocolType server_type,
+                       gboolean alternate_port)
+{
+       int server_port = 0;
+       ModestProtocol *protocol;
+       ModestProtocolRegistry *protocol_registry;
+
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, server_type);
+
+       if (alternate_port) {
+               server_port = modest_account_protocol_get_alternate_port (MODEST_ACCOUNT_PROTOCOL (protocol));
+       } else {
+               server_port = modest_account_protocol_get_port (MODEST_ACCOUNT_PROTOCOL (protocol));
+       }
+       return server_port;
+}
+
+/* static GList*  */
+/* check_for_supported_auth_methods (ModestEasysetupWizardDialog* self) */
+/* { */
+/*     GError *error = NULL; */
+/*     ModestProtocolType protocol_type; */
+/*     const gchar* hostname; */
+/*     const gchar* username; */
+/*     ModestProtocolType security_protocol_incoming_type; */
+/*     ModestProtocolRegistry *registry; */
+/*     int port_num;  */
+/*     GList *list_auth_methods; */
+/*     ModestEasysetupWizardDialogPrivate *priv; */
+       
+/*     priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self); */
+/*     registry = modest_runtime_get_protocol_registry (); */
+/*     protocol_type = easysetup_servertype_combo_box_get_active_servertype ( */
+/*             EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype)); */
+/*     hostname = gtk_entry_get_text(GTK_ENTRY(priv->entry_incomingserver)); */
+/*     username = gtk_entry_get_text(GTK_ENTRY(priv->entry_user_username)); */
+/*     security_protocol_incoming_type = modest_serversecurity_combo_box_get_active_serversecurity */
+/*             (MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security)); */
+/*     port_num = get_port_from_protocol(protocol_type, FALSE);  */
+/*     list_auth_methods = modest_utils_get_supported_secure_authentication_methods (protocol_type, hostname, port_num,  */
+/*                                                                                   username, GTK_WINDOW (self), &error); */
+
+/*     if (list_auth_methods) { */
+/*             /\* TODO: Select the correct method *\/ */
+/*             GList* list = NULL; */
+/*             GList* method; */
+/*             for (method = list_auth_methods; method != NULL; method = g_list_next(method)) { */
+/*                     ModestProtocolType auth_protocol_type = (ModestProtocolType) (GPOINTER_TO_INT(method->data)); */
+/*                     if (modest_protocol_registry_protocol_type_has_tag (registry, auth_protocol_type, */
+/*                                                                         MODEST_PROTOCOL_REGISTRY_SECURE_PROTOCOLS)) { */
+/*                             list = g_list_append(list, GINT_TO_POINTER(auth_protocol_type)); */
+/*                     } */
+/*             } */
+
+/*             g_list_free(list_auth_methods); */
+
+/*             if (list) */
+/*                     return list; */
+/*     } */
+
+/*     if(error == NULL || error->domain != modest_utils_get_supported_secure_authentication_error_quark() || */
+/*                     error->code != MODEST_UTILS_GET_SUPPORTED_SECURE_AUTHENTICATION_ERROR_CANCELED) */
+/*     { */
+/*             modest_platform_information_banner (GTK_WIDGET(self), NULL, */
+/*                                                 _("mcen_ib_unableto_discover_auth_methods")); */
+/*     } */
+
+/*     if(error != NULL) */
+/*             g_error_free(error); */
+
+/*     return NULL; */
+/* } */
+
+/* static gboolean check_has_supported_auth_methods(ModestEasysetupWizardDialog* self) */
+/* { */
+/*     GList* methods = check_for_supported_auth_methods(self); */
+/*     if (!methods) */
+/*     { */
+/*             return FALSE; */
+/*     } */
+
+/*     g_list_free(methods); */
+/*     return TRUE; */
+/* } */
+
+/* static ModestProtocolType check_first_supported_auth_method(ModestEasysetupWizardDialog* self) */
+/* { */
+/*     ModestProtocolType result; */
+
+/*     result = MODEST_PROTOCOLS_AUTH_PASSWORD; */
+
+/*     GList* methods = check_for_supported_auth_methods(self); */
+/*     if (methods) */
+/*     { */
+/*             /\* Use the first one: *\/ */
+/*             result = (ModestProtocolType) (GPOINTER_TO_INT(methods->data)); */
+/*             g_list_free(methods); */
+/*     } */
+
+/*     return result; */
+/* } */
+
+static void
+invoke_enable_buttons_vfunc (ModestEasysetupWizardDialog *wizard_dialog)
+{
+       ModestWizardDialogClass *klass = MODEST_WIZARD_DIALOG_GET_CLASS (wizard_dialog);
+       
+       /* Call the vfunc, which may be overridden by derived classes: */
+       if (klass->enable_buttons) {
+               GtkNotebook *notebook = NULL;
+               g_object_get (wizard_dialog, "wizard-notebook", &notebook, NULL);
+               
+               const gint current_page_num = gtk_notebook_get_current_page (notebook);
+               if (current_page_num == -1)
+                       return;
+                       
+               GtkWidget* current_page_widget = gtk_notebook_get_nth_page (notebook, current_page_num);
+               (*(klass->enable_buttons))(MODEST_WIZARD_DIALOG (wizard_dialog), current_page_widget);
+       }
+}
+
+static void
+on_caption_entry_changed (GtkEditable *editable, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       g_assert(self);
+       invoke_enable_buttons_vfunc(self);
+}
+
+static void
+on_caption_combobox_changed (GtkComboBox *widget, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       g_assert(self);
+       invoke_enable_buttons_vfunc(self);
+}
+
+/** This is a convenience function to create a caption containing a mandatory widget.
+ * When the widget is edited, the enable_buttons() vfunc will be called.
+ */
+static GtkWidget* 
+create_caption_new_with_asterisk (ModestEasysetupWizardDialog *self,
+                                 GtkSizeGroup *group,
+                                 const gchar *value,
+                                 GtkWidget *control,
+                                 GtkWidget *icon,
+                                 HildonCaptionStatus flag)
+{
+       GtkWidget *caption = NULL;
+  
+       /* Note: Previously, the translated strings already contained the "*",
+        * Comment out this code if they do again.
+        */
+       /* Add a * character to indicate mandatory fields,
+        * as specified in our "Email UI Specification": */
+       if (flag == HILDON_CAPTION_MANDATORY) {
+               gchar* title = g_strdup_printf("%s*", value);
+               caption = hildon_caption_new (group, title, control, icon, flag);       
+               g_free(title);
+       }       
+       else
+               caption = hildon_caption_new (group, value, control, icon, flag);
+
+       /* Connect to the appropriate changed signal for the widget, 
+        * so we can ask for the prev/next buttons to be enabled/disabled appropriately:
+        */
+       if (GTK_IS_ENTRY (control)) {
+               g_signal_connect (G_OBJECT (control), "changed",
+                                 G_CALLBACK (on_caption_entry_changed), self);
+               
+       }
+       else if (GTK_IS_COMBO_BOX (control)) {
+               g_signal_connect (G_OBJECT (control), "changed",
+                                 G_CALLBACK (on_caption_combobox_changed), self);
+       }
+        
+       return caption;
+}
+           
+static GtkWidget*
+create_page_welcome (ModestEasysetupWizardDialog *self)
+{
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_intro"));
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       /* So that it is not truncated: */
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       gtk_widget_show (GTK_WIDGET (box));
+       return GTK_WIDGET (box);
+}
+
+#if MODEST_HILDON_API < 2
+static void
+on_combo_account_country (GtkComboBox *widget, gpointer user_data)
+#else
+static void
+on_combo_account_country (HildonTouchSelector *widget, gint column, gpointer user_data)
+#endif
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       g_assert(self);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       
+       priv->dirty = TRUE;
+       
+       /* Fill the providers combo, based on the selected country: */
+       if (priv->presets != NULL) {
+               gint mcc = easysetup_country_combo_box_get_active_country_mcc (
+                       MODEST_EASYSETUP_COUNTRY_COMBO_BOX (priv->combo_account_country));
+               easysetup_provider_combo_box_fill (
+                       EASYSETUP_PROVIDER_COMBO_BOX (priv->combo_account_serviceprovider), priv->presets, mcc);
+       }
+}
+
+static void
+on_combo_account_serviceprovider (GtkComboBox *widget, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       g_assert(self);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       
+       priv->dirty = TRUE;
+       
+       /* Fill the providers combo, based on the selected country: */
+       gchar* provider_id = easysetup_provider_combo_box_get_active_provider_id (
+               EASYSETUP_PROVIDER_COMBO_BOX (priv->combo_account_serviceprovider));
+       
+       gchar* domain_name = NULL;
+       if(provider_id)
+               domain_name = modest_presets_get_domain (priv->presets, provider_id);
+       
+       if(!domain_name)
+               domain_name = g_strdup (MODEST_EXAMPLE_EMAIL_ADDRESS);
+               
+       if (priv->entry_user_email)
+               gtk_entry_set_text (GTK_ENTRY (priv->entry_user_email), domain_name);
+               
+       g_free (domain_name);
+       
+       g_free (provider_id);
+}
+
+static void
+on_entry_max (ModestValidatingEntry *self, gpointer user_data)
+{
+       modest_platform_information_banner (GTK_WIDGET (self), NULL,
+                                           _CS("ckdg_ib_maximum_characters_reached"));
+}
+
+static GtkWidget*
+create_page_account_details (ModestEasysetupWizardDialog *self)
+{
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       GtkWidget *label = gtk_label_new(_("mcen_ia_accountdetails"));
+       ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (label);
+
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+       /* The country widgets: */
+       priv->combo_account_country = GTK_WIDGET (easysetup_country_combo_box_new ());
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_country"), 
+                                                             priv->combo_account_country, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->combo_account_country);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* connect to country combo's changed signal, so we can fill the provider combo: */
+#if MODEST_HILDON_API < 2
+       g_signal_connect (G_OBJECT (priv->combo_account_country), "changed",
+                         G_CALLBACK (on_combo_account_country), self);
+#else
+       g_signal_connect (G_OBJECT (hildon_picker_button_get_selector 
+                                   (HILDON_PICKER_BUTTON (priv->combo_account_country))),
+                         "changed",
+                         G_CALLBACK (on_combo_account_country), self);
+#endif
+            
+       GtkWidget *separator = gtk_hseparator_new ();
+       gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (separator);
+            
+       /* The service provider widgets: */     
+       priv->combo_account_serviceprovider = GTK_WIDGET (easysetup_provider_combo_box_new ());
+       gtk_widget_set_size_request (priv->combo_account_serviceprovider, 320, -1);
+       
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_serviceprovider"), 
+                                                  priv->combo_account_serviceprovider, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->combo_account_serviceprovider);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* connect to providers combo's changed signal, so we can fill the email address: */
+       g_signal_connect (G_OBJECT (priv->combo_account_serviceprovider), "changed",
+                         G_CALLBACK (on_combo_account_serviceprovider), self);
+       
+       /* The description widgets: */  
+       priv->entry_account_title = GTK_WIDGET (modest_validating_entry_new ());
+       g_signal_connect(G_OBJECT(priv->entry_account_title), "changed",
+                        G_CALLBACK(on_easysetup_changed), self);
+       /* Do use auto-capitalization: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_account_title), 
+                                        HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
+       
+       /* Set a default account title, choosing one that does not already exist: */
+       /* Note that this is irrelevant to the non-user visible name, which we will create later. */
+       gchar* default_account_name_start = g_strdup (_("mcen_ia_emailsetup_defaultname"));
+       gchar* default_account_name = modest_account_mgr_get_unused_account_display_name (
+               priv->account_manager, default_account_name_start);
+       g_free (default_account_name_start);
+       default_account_name_start = NULL;
+       
+       gtk_entry_set_text( GTK_ENTRY (priv->entry_account_title), default_account_name);
+       g_free (default_account_name);
+       default_account_name = NULL;
+
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mcen_fi_account_title"), 
+                                                  priv->entry_account_title, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->entry_account_title);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the account title, 
+        * as required by our UI specification: */
+       GList *list_prevent = NULL;
+       list_prevent = g_list_append (list_prevent, "\\");
+       list_prevent = g_list_append (list_prevent, "/");
+       list_prevent = g_list_append (list_prevent, ":");
+       list_prevent = g_list_append (list_prevent, "*");
+       list_prevent = g_list_append (list_prevent, "?");
+       list_prevent = g_list_append (list_prevent, "\""); /* The UI spec mentions â€œ, but maybe means ", maybe both. */
+       list_prevent = g_list_append (list_prevent, "“");
+       list_prevent = g_list_append (list_prevent, "<"); 
+       list_prevent = g_list_append (list_prevent, ">"); 
+       list_prevent = g_list_append (list_prevent, "|");
+       list_prevent = g_list_append (list_prevent, "^");       
+       modest_validating_entry_set_unallowed_characters (
+               MODEST_VALIDATING_ENTRY (priv->entry_account_title), list_prevent);
+       g_list_free (list_prevent);
+       list_prevent = NULL;
+       modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_account_title),
+                                                                                                                                        modest_utils_on_entry_invalid_character, self);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_account_title), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_account_title), 
+                                             on_entry_max, self);
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       
+       return GTK_WIDGET (box);
+}
+
+static GtkWidget*
+create_page_user_details (ModestEasysetupWizardDialog *self)
+{
+       GtkSizeGroup* sizegroup;
+       GtkWidget *box;
+       ModestEasysetupWizardDialogPrivate *priv;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The name widgets: (use auto cap) */
+       priv->entry_user_name = GTK_WIDGET (modest_validating_entry_new ());
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_name), 
+                                        HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_name), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_name), 
+                                             on_entry_max, self);
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, 
+                                                             _("mcen_li_emailsetup_name"), priv->entry_user_name, NULL, HILDON_CAPTION_OPTIONAL);
+       g_signal_connect(G_OBJECT(priv->entry_user_name), "changed", 
+                        G_CALLBACK(on_easysetup_changed), self);
+       gtk_widget_show (priv->entry_user_name);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the name, 
+        * as required by our UI specification: */
+       GList *list_prevent = NULL;
+       list_prevent = g_list_append (list_prevent, "<");
+       list_prevent = g_list_append (list_prevent, ">");
+       modest_validating_entry_set_unallowed_characters (
+               MODEST_VALIDATING_ENTRY (priv->entry_user_name), list_prevent);
+       modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_name),
+               modest_utils_on_entry_invalid_character, self);
+       g_list_free (list_prevent);
+       
+       /* The username widgets: */     
+       priv->entry_user_username = GTK_WIDGET (modest_validating_entry_new ());
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_username), 
+                                        HILDON_GTK_INPUT_MODE_FULL);
+       caption = create_caption_new_with_asterisk (self, sizegroup, _("mail_fi_username"), 
+                                                  priv->entry_user_username, 
+                                                   NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->entry_user_username);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       g_signal_connect(G_OBJECT(priv->entry_user_username), "changed", 
+                        G_CALLBACK(on_easysetup_changed), self);
+       gtk_widget_show (caption);
+       
+       /* Prevent the use of some characters in the username, 
+        * as required by our UI specification: */
+       modest_validating_entry_set_unallowed_characters_whitespace (
+               MODEST_VALIDATING_ENTRY (priv->entry_user_username));
+       modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_username),
+               modest_utils_on_entry_invalid_character, self);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_username), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_username), 
+                                             on_entry_max, self);
+       
+       /* The password widgets: */     
+       priv->entry_user_password = gtk_entry_new ();
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_password), 
+                                        HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
+       gtk_entry_set_visibility (GTK_ENTRY (priv->entry_user_password), FALSE);
+       /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_user_password), '*'); */
+       caption = create_caption_new_with_asterisk (self, sizegroup, 
+                                                  _("mail_fi_password"), priv->entry_user_password, NULL, HILDON_CAPTION_OPTIONAL);
+       g_signal_connect(G_OBJECT(priv->entry_user_password), "changed", 
+                        G_CALLBACK(on_easysetup_changed), self);
+       gtk_widget_show (priv->entry_user_password);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* The email address widgets: */        
+       priv->entry_user_email = GTK_WIDGET (modest_validating_entry_new ());
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_email), HILDON_GTK_INPUT_MODE_FULL);
+       caption = create_caption_new_with_asterisk (self, sizegroup, 
+                                                  _("mcen_li_emailsetup_email_address"), priv->entry_user_email, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_entry_set_text (GTK_ENTRY (priv->entry_user_email), MODEST_EXAMPLE_EMAIL_ADDRESS); /* Default text. */
+       gtk_widget_show (priv->entry_user_email);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       g_signal_connect(G_OBJECT(priv->entry_user_email), "changed", 
+                        G_CALLBACK(on_easysetup_changed), self);
+       gtk_widget_show (caption);
+       
+       /* Set max length as in the UI spec:
+        * The UI spec seems to want us to show a dialog if we hit the maximum. */
+       gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_email), 64);
+       modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_email), 
+                                             on_entry_max, self);
+       
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       
+       return GTK_WIDGET (box);
+}
+
+static GtkWidget* 
+create_page_complete_easysetup (ModestEasysetupWizardDialog *self)
+{
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       
+       GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete"));
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+       /* The documentation for gtk_label_set_line_wrap() says that we must 
+        * call gtk_widget_set_size_request() with a hard-coded width, 
+        * though I wonder why gtk_label_set_max_width_chars() isn't enough. */
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       
+       label = gtk_label_new (_("mcen_ia_easysetup_complete"));
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_widget_set_size_request (label, 600, -1);
+       
+       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       return GTK_WIDGET (box);
+}
+
+/** Change the caption title for the incoming server, 
+ * as specified in the UI spec:
+ */
+static void 
+update_incoming_server_title (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate* priv; 
+       ModestProtocolType protocol_type; 
+       ModestProtocolRegistry *protocol_registry;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       
+       protocol_type = easysetup_servertype_combo_box_get_active_servertype (
+               EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype));
+
+       /* This could happen when the combo box has still no active iter */
+       if (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
+               gchar* incomingserver_title;
+               const gchar *protocol_display_name; 
+
+               protocol_display_name = modest_protocol_get_display_name (modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type));
+               
+               incomingserver_title = g_strdup_printf(_("mcen_li_emailsetup_servertype"), protocol_display_name);
+               g_object_set (G_OBJECT (priv->caption_incoming), "label", incomingserver_title, NULL);
+               g_free(incomingserver_title);
+       }
+}
+
+/** Change the caption title for the incoming server, 
+ * as specified in the UI spec:
+ */
+static void 
+update_incoming_server_security_choices (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       EasysetupServertypeComboBox *server_type_combo;
+       ModestProtocolType protocol_type;
+       ModestSecurityOptionsView *view;
+
+       server_type_combo = 
+               EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype);
+       protocol_type = 
+               easysetup_servertype_combo_box_get_active_servertype (server_type_combo);
+       
+       /* Fill the combo with appropriately titled choices for all
+          those protocols */
+       view = MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security);
+       modest_security_options_view_set_server_type (view, protocol_type);
+}
+
+static void 
+on_combo_servertype_changed(GtkComboBox *combobox, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       EasysetupServertypeComboBox *combo;
+       ModestProtocolType protocol_type;
+
+       priv->dirty = TRUE;
+       
+       /* Update title */
+       update_incoming_server_title (self);
+
+       /* Update security options if needed */
+       combo = EASYSETUP_SERVERTYPE_COMBO_BOX (combobox);
+       protocol_type = easysetup_servertype_combo_box_get_active_servertype (combo);
+       update_incoming_server_security_choices (self);
+       gtk_widget_show (priv->incoming_security);
+
+       set_default_custom_servernames (self);
+}
+
+static void 
+on_entry_incoming_servername_changed(GtkEntry *entry, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       priv->dirty = TRUE;
+       priv->server_changes |= MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED;
+}
+
+static GtkWidget* 
+create_page_custom_incoming (ModestEasysetupWizardDialog *self)
+{
+       ModestProtocolRegistry *protocol_registry;
+       ModestEasysetupWizardDialogPrivate* priv; 
+       GtkWidget *box; 
+       GtkWidget *scrolled_window;
+       GtkWidget *label;
+       GtkSizeGroup *sizegroup;
+       GtkWidget *caption;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                       GTK_POLICY_NEVER,
+                                       GTK_POLICY_AUTOMATIC);
+
+       /* Show note that account type cannot be changed in future: */
+       label = gtk_label_new (_("mcen_ia_emailsetup_account_type"));
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The incoming server widgets: */
+       priv->combo_incoming_servertype = GTK_WIDGET (easysetup_servertype_combo_box_new (TRUE));
+       caption = create_caption_new_with_asterisk (self, sizegroup, 
+                                                   _("mcen_li_emailsetup_type"), priv->combo_incoming_servertype, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (priv->combo_incoming_servertype);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       priv->entry_incomingserver = gtk_entry_new ();
+       g_signal_connect(G_OBJECT(priv->entry_incomingserver), "changed", G_CALLBACK(on_easysetup_changed), self);
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_incomingserver), HILDON_GTK_INPUT_MODE_FULL);
+       set_default_custom_servernames (self);
+
+       /* The caption title will be updated in update_incoming_server_title().
+        * so this default text will never be seen: */
+       /* (Note: Changing the title seems pointless. murrayc) */
+       priv->caption_incoming = create_caption_new_with_asterisk (self, sizegroup, 
+                                                                 "Incoming Server", 
+                                                                  priv->entry_incomingserver, 
+                                                                  NULL, HILDON_CAPTION_MANDATORY);
+       update_incoming_server_title (self);
+       gtk_widget_show (priv->entry_incomingserver);
+       gtk_box_pack_start (GTK_BOX (box), priv->caption_incoming, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->caption_incoming);
+       
+       /* Change the caption title when the servertype changes, 
+        * as in the UI spec: */
+       g_signal_connect (G_OBJECT (priv->combo_incoming_servertype), "changed",
+                         G_CALLBACK (on_combo_servertype_changed), self);
+
+       /* Remember when the servername was changed manually: */
+       g_signal_connect (G_OBJECT (priv->entry_incomingserver), "changed",
+                         G_CALLBACK (on_entry_incoming_servername_changed), self);
+
+       /* The secure connection widgets. These are only valid for
+          protocols with security */   
+       priv->incoming_security = 
+               modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_INCOMING,
+                                                       FALSE, sizegroup);
+       gtk_box_pack_start (GTK_BOX (box), priv->incoming_security, 
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Set default selection */
+       easysetup_servertype_combo_box_set_active_servertype (
+               EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype), 
+               MODEST_PROTOCOLS_STORE_POP);
+
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box);
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (box),
+                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
+       gtk_widget_show (GTK_WIDGET (box));
+       gtk_widget_show (scrolled_window);
+
+       return GTK_WIDGET (scrolled_window);
+}
+
+static void
+on_toggle_button_changed (GtkToggleButton *togglebutton, gpointer user_data)
+{
+       GtkWidget *widget = GTK_WIDGET (user_data);
+       
+       /* Enable the widget only if the toggle button is active: */
+       const gboolean enable = gtk_toggle_button_get_active (togglebutton);
+       gtk_widget_set_sensitive (widget, enable);
+}
+
+/* Make the sensitivity of a widget depend on a toggle button.
+ */
+static void
+enable_widget_for_togglebutton (GtkWidget *widget, GtkToggleButton* button)
+{
+       g_signal_connect (G_OBJECT (button), "toggled",
+                         G_CALLBACK (on_toggle_button_changed), widget);
+       
+       /* Set the starting sensitivity: */
+       on_toggle_button_changed (button, widget);
+}
+
+static void
+on_button_outgoing_smtp_servers (GtkButton *button, gpointer user_data)
+{
+       ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       GtkWidget *specific_window;
+       
+       /* We set dirty here because setting it depending on the connection specific dialog
+       seems overkill */
+       priv->dirty = TRUE;
+       
+       /* Create the window, if necessary: */
+       specific_window = (GtkWidget *) modest_connection_specific_smtp_window_new ();
+       modest_connection_specific_smtp_window_fill_with_connections (MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), priv->account_manager);
+
+       /* Show the window */
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (specific_window));
+       gtk_widget_show (specific_window);
+}
+
+static void 
+on_entry_outgoing_servername_changed (GtkEntry *entry, gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       priv->server_changes |= MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED;
+}
+
+static GtkWidget* 
+create_page_custom_outgoing (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv;
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+        
+       /* The outgoing server widgets: */
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       priv->entry_outgoingserver = gtk_entry_new ();
+       g_signal_connect (G_OBJECT (priv->entry_outgoingserver), "changed",
+                  G_CALLBACK (on_easysetup_changed), self);
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_outgoingserver), HILDON_GTK_INPUT_MODE_FULL);
+       GtkWidget *caption = create_caption_new_with_asterisk (self, sizegroup, 
+                                                             _("mcen_li_emailsetup_smtp"), priv->entry_outgoingserver, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->entry_outgoingserver);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       set_default_custom_servernames (self);
+
+       /* The secure connection widgets. These are only valid for
+          protocols with security */   
+       priv->outgoing_security = 
+               modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_OUTGOING,
+                                                       FALSE, sizegroup);
+       gtk_box_pack_start (GTK_BOX (box), priv->outgoing_security, 
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->outgoing_security);
+       
+       GtkWidget *separator = gtk_hseparator_new ();
+       gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (separator);
+       
+       /* connection-specific checkbox: */
+       priv->checkbox_outgoing_smtp_specific = gtk_check_button_new ();
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific), 
+                                     FALSE);
+       g_signal_connect (G_OBJECT (priv->checkbox_outgoing_smtp_specific), "toggled",
+                  G_CALLBACK (on_easysetup_changed), self);
+
+       caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_connection_smtp"), 
+                                     priv->checkbox_outgoing_smtp_specific, NULL, HILDON_CAPTION_OPTIONAL);
+       gtk_widget_show (priv->checkbox_outgoing_smtp_specific);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Connection-specific SMTP-Severs Edit button: */
+       priv->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_edit"));
+       caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_optional_smtp"), 
+                                     priv->button_outgoing_smtp_servers, NULL, HILDON_CAPTION_OPTIONAL);
+       hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
+       gtk_widget_show (priv->button_outgoing_smtp_servers);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       /* Only enable the button when the checkbox is checked: */
+       enable_widget_for_togglebutton (priv->button_outgoing_smtp_servers, 
+                                       GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific));
+               
+       g_signal_connect (G_OBJECT (priv->button_outgoing_smtp_servers), "clicked",
+                         G_CALLBACK (on_button_outgoing_smtp_servers), self);
+
+       g_signal_connect (G_OBJECT (priv->entry_outgoingserver), "changed",
+                         G_CALLBACK (on_entry_outgoing_servername_changed), self);
+       
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       
+       return GTK_WIDGET (box);
+}
+
+static gboolean
+show_advanced_edit(gpointer user_data)
+{
+       ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       gint response;
+       
+       /* Show the Account Settings window: */
+       ModestAccountSettingsDialog *dialog = modest_default_account_settings_dialog_new ();
+       if (priv->pending_load_settings) {
+               save_to_settings (self);
+               priv->pending_load_settings = FALSE;
+       }
+       modest_account_settings_dialog_load_settings (dialog, priv->settings);
+       
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
+       
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+       
+       return FALSE; /* Do not call this timeout callback again. */
+}
+
+static void
+on_button_edit_advanced_settings (GtkButton *button, gpointer user_data)
+{
+       ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
+       
+       /* Show the Account Settings window: */
+       show_advanced_edit(self);
+}
+static GtkWidget* 
+create_page_complete_custom (ModestEasysetupWizardDialog *self)
+{
+       GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
+       GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete"));
+       GtkWidget *button_edit = gtk_button_new_with_label (_("mcen_bd_edit"));
+       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       
+       label = gtk_label_new (_("mcen_ia_customsetup_complete"));
+       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+       gtk_widget_set_size_request (label, 600, -1);
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+       gtk_widget_show (label);
+       
+       GtkWidget *caption = hildon_caption_new (NULL, _("mcen_fi_advanced_settings"), 
+                                                button_edit, NULL, HILDON_CAPTION_OPTIONAL);
+       hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
+       gtk_widget_show (button_edit);
+       gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       
+       g_signal_connect (G_OBJECT (button_edit), "clicked", 
+                         G_CALLBACK (on_button_edit_advanced_settings), self);
+       
+       gtk_widget_show (GTK_WIDGET (box));
+       return GTK_WIDGET (box);
+}
+
+
+/*
+ */
+static void 
+on_response (ModestWizardDialog *wizard_dialog,
+            gint response_id,
+            gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (wizard_dialog);
+
+       invoke_enable_buttons_vfunc (self);
+}
+
+static void 
+on_response_before (ModestWizardDialog *wizard_dialog,
+                    gint response_id,
+                    gpointer user_data)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (wizard_dialog);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(wizard_dialog);
+       if (response_id == GTK_RESPONSE_CANCEL) {
+               /* This is mostly copied from
+                * src/maemo/modest-account-settings-dialog.c */
+               if (priv->dirty) {
+                       GtkDialog *dialog = GTK_DIALOG (hildon_note_new_confirmation (GTK_WINDOW (self), 
+                               _("imum_nc_wizard_confirm_lose_changes")));
+                       /* TODO: These button names will be ambiguous, and not
+                        * specified in the UI specification. */
+
+                       const gint dialog_response = gtk_dialog_run (dialog);
+                       gtk_widget_destroy (GTK_WIDGET (dialog));
+
+                       if (dialog_response != GTK_RESPONSE_OK) {
+                               /* Don't let the dialog close */
+                               g_signal_stop_emission_by_name (wizard_dialog, "response");
+                       }
+               }
+       }
+}
+
+typedef struct IdleData {
+       ModestEasysetupWizardDialog *dialog;
+       ModestPresets *presets;
+} IdleData;
+
+static gboolean
+presets_idle (gpointer userdata)
+{
+       IdleData *idle_data = (IdleData *) userdata;
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (idle_data->dialog);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+
+       g_assert (idle_data->presets);
+
+       gdk_threads_enter ();
+
+       priv->presets = idle_data->presets;
+
+       if (MODEST_EASYSETUP_IS_COUNTRY_COMBO_BOX (priv->combo_account_country)) {
+/*             gint mcc = get_default_country_code(); */
+               gint mcc;
+               /* Fill the combo in an idle call, as it takes a lot of time */
+               easysetup_country_combo_box_load_data(
+                       MODEST_EASYSETUP_COUNTRY_COMBO_BOX (priv->combo_account_country));
+/*             easysetup_country_combo_box_set_active_country_mcc ( */
+/*                     MODEST_EASYSETUP_COUNTRY_COMBO_BOX (priv->combo_account_country), mcc); */
+               easysetup_country_combo_box_set_active_country_locale (
+                       MODEST_EASYSETUP_COUNTRY_COMBO_BOX (priv->combo_account_country));
+               mcc = easysetup_country_combo_box_get_active_country_mcc (
+                       MODEST_EASYSETUP_COUNTRY_COMBO_BOX (priv->combo_account_country));
+               easysetup_provider_combo_box_fill (
+                       EASYSETUP_PROVIDER_COMBO_BOX (priv->combo_account_serviceprovider),
+                       priv->presets, mcc);
+       }
+
+       priv->dirty = FALSE;
+
+       g_object_unref (idle_data->dialog);
+       g_free (idle_data);
+
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+static gpointer
+presets_loader (gpointer userdata)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (userdata);
+       ModestPresets *presets = NULL;
+       IdleData *idle_data;
+
+       const gchar* path  = NULL;
+       const gchar* path1 = MODEST_PROVIDER_DATA_FILE;
+       const gchar* path2 = MODEST_MAEMO_PROVIDER_DATA_FILE;
+       
+       if (access(path1, R_OK) == 0) 
+               path = path1;
+       else if (access(path2, R_OK) == 0)
+               path = path2;
+       else {
+               g_warning ("%s: neither '%s' nor '%s' is a readable provider data file",
+                          __FUNCTION__, path1, path2);
+               return NULL;
+       }
+
+       presets = modest_presets_new (path);
+       if (!presets) {
+               g_warning ("%s: failed to parse '%s'", __FUNCTION__, path);
+               return NULL;
+       }
+       
+       idle_data = g_new0 (IdleData, 1);
+       idle_data->dialog = self;
+       idle_data->presets = presets;
+       
+       g_idle_add (presets_idle, idle_data);   
+
+       return NULL;
+}
+
+static void
+modest_easysetup_wizard_dialog_append_page (GtkNotebook *notebook,
+                                           GtkWidget *page,
+                                           const gchar *label)
+{
+       gint index;
+       /* Append page and set attributes */
+       index = gtk_notebook_append_page (notebook, page, gtk_label_new (label));
+       gtk_container_child_set (GTK_CONTAINER (notebook), page,
+                                "tab-expand", TRUE, "tab-fill", TRUE,
+                                NULL);
+       gtk_widget_show (page);
+}
+
+static void
+init_user_page (ModestEasysetupWizardDialogPrivate *priv)
+{
+       priv->page_user_details = NULL;
+       priv->entry_user_name = NULL;
+       priv->entry_user_username = NULL;
+       priv->entry_user_password = NULL;
+       priv->entry_user_email = NULL;
+}
+
+static void
+init_incoming_page (ModestEasysetupWizardDialogPrivate *priv)
+{
+       priv->page_custom_incoming = NULL;
+       priv->combo_incoming_servertype = NULL;
+       priv->caption_incoming = NULL;
+       priv->entry_incomingserver = NULL;
+       priv->entry_user_email = NULL;
+       priv->incoming_security = NULL;
+}
+
+static void
+init_outgoing_page (ModestEasysetupWizardDialogPrivate *priv)
+{
+       priv->page_custom_outgoing = NULL;
+       priv->entry_outgoingserver = NULL;
+       priv->combo_outgoing_security = NULL;
+       priv->combo_outgoing_auth = NULL;
+       priv->checkbox_outgoing_smtp_specific = NULL;
+       priv->button_outgoing_smtp_servers = NULL;
+       priv->outgoing_security = NULL;
+}
+
+static void
+modest_easysetup_wizard_dialog_init (ModestEasysetupWizardDialog *self)
+{
+       gtk_container_set_border_width (GTK_CONTAINER (self), MODEST_MARGIN_HALF);
+       
+       /* Create the notebook to be used by the ModestWizardDialog base class:
+        * Each page of the notebook will be a page of the wizard: */
+       GtkNotebook *notebook = GTK_NOTEBOOK (gtk_notebook_new());
+       
+       /* Set the notebook used by the ModestWizardDialog base class: */
+       g_object_set (G_OBJECT(self), "wizard-notebook", notebook, NULL);
+    
+       /* Set the wizard title:
+        * The actual window title will be a combination of this and the page's tab label title. */
+       g_object_set (G_OBJECT(self), "wizard-name", _("mcen_ti_emailsetup"), NULL);
+
+       /* Read in the information about known service providers: */
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       
+       /* The server fields did not have been manually changed yet */
+       priv->server_changes = 0;
+       priv->pending_load_settings = TRUE;
+
+       /* Get the account manager object, 
+        * so we can check for existing accounts,
+        * and create new accounts: */
+       priv->account_manager = modest_runtime_get_account_mgr ();
+       g_object_ref (priv->account_manager);
+       
+       /* Initialize fields */
+       priv->page_welcome = create_page_welcome (self);
+       priv->page_account_details = create_page_account_details (self);
+
+       init_user_page (priv);
+       init_incoming_page (priv);
+       init_outgoing_page (priv);
+
+       priv->page_complete_easysetup = NULL;       
+       priv->page_complete_customsetup = NULL;
+       priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+       priv->missing_data_signals = NULL;
+
+       /* Add the common pages */
+       modest_easysetup_wizard_dialog_append_page (notebook, priv->page_welcome, 
+                                                   _("mcen_ti_emailsetup_welcome"));
+       modest_easysetup_wizard_dialog_append_page (notebook, priv->page_account_details, 
+                                                   _("mcen_ti_accountdetails"));
+               
+       /* Connect to the dialog's response signal so we can enable/disable buttons 
+        * for the newly-selected page, because the prev/next buttons cause response to be emitted.
+        * Note that we use g_signal_connect_after() instead of g_signal_connect()
+        * so that we can be enable/disable after ModestWizardDialog has done its own 
+        * enabling/disabling of buttons.
+        * 
+        * HOWEVER, this doesn't work because ModestWizardDialog's response signal handler 
+        * does g_signal_stop_emission_by_name(), stopping our signal handler from running.
+        * 
+        * It's not enough to connect to the notebook's switch-page signal, because 
+        * ModestWizardDialog's "response" signal handler enables the buttons itself, 
+        * _after_ switching the page (understandably).
+        * (Note that if we had, if we used g_signal_connect() instead of g_signal_connect_after()
+        * then gtk_notebook_get_current_page() would return an incorrect value.)
+        */
+       g_signal_connect_after (G_OBJECT (self), "response",
+                               G_CALLBACK (on_response), self);
+
+       /* This is to show a confirmation dialog when the user hits cancel */
+       g_signal_connect (G_OBJECT (self), "response",
+                         G_CALLBACK (on_response_before), self);
+
+       g_signal_connect (G_OBJECT (self), "delete-event",
+                         G_CALLBACK (on_delete_event), self);
+
+       /* Reset dirty, because there was no user input until now */
+       priv->dirty = FALSE;
+       
+       /* When this window is shown, hibernation should not be possible, 
+        * because there is no sensible way to save the state: */
+       modest_window_mgr_prevent_hibernation_while_window_is_shown (
+               modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
+
+       /* Load provider presets */
+       g_object_ref (self);
+       g_thread_create (presets_loader, self, FALSE, NULL);
+
+       hildon_help_dialog_help_enable (GTK_DIALOG(self), "applications_email_wizardwelcome",
+                                       modest_maemo_utils_get_osso_context()); 
+
+       priv->settings = modest_account_settings_new ();
+}
+
+ModestEasysetupWizardDialog*
+modest_easysetup_wizard_dialog_new (void)
+{      
+       
+       return g_object_new (MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, NULL);
+}
+
+static void 
+create_subsequent_customsetup_pages (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv;
+       GtkNotebook *notebook = NULL;
+
+       g_object_get (self, "wizard-notebook", &notebook, NULL);
+       g_assert(notebook);
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+
+       if (!priv->page_user_details) {
+               priv->page_user_details = create_page_user_details (self);
+       }                       
+
+       /* Create the custom pages: */
+       if(!(priv->page_custom_incoming)) {
+               priv->page_custom_incoming = create_page_custom_incoming (self);
+       }
+               
+       /* TODO: only if needed */
+       if(!(priv->page_custom_outgoing)) {
+               priv->page_custom_outgoing = create_page_custom_outgoing (self);
+       }
+       
+       if(!(priv->page_complete_customsetup)) {
+               priv->page_complete_customsetup = create_page_complete_custom (self);
+       }
+
+       if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_user_details)))
+               modest_easysetup_wizard_dialog_append_page (notebook, priv->page_user_details,
+                                                           _("mcen_ti_emailsetup_userdetails"));
+
+       if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_custom_incoming)))
+               modest_easysetup_wizard_dialog_append_page (notebook, priv->page_custom_incoming, 
+                                                           _("mcen_ti_emailsetup_incomingdetails"));
+       
+       if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_custom_outgoing)))           
+               modest_easysetup_wizard_dialog_append_page (notebook, priv->page_custom_outgoing, 
+                                                           _("mcen_ti_emailsetup_outgoingdetails"));
+               
+       if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_complete_customsetup)))
+               modest_easysetup_wizard_dialog_append_page (notebook, priv->page_complete_customsetup, 
+                                                           _("mcen_ti_emailsetup_complete"));
+                       
+       /* This is unnecessary with GTK+ 2.10: */
+       modest_wizard_dialog_force_title_update (MODEST_WIZARD_DIALOG(self));
+}
+       
+static void 
+create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv;
+       GtkNotebook *notebook = NULL;
+
+       g_object_get (self, "wizard-notebook", &notebook, NULL);
+       g_assert(notebook);
+       
+       /* Create the easysetup-specific pages: */
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       if(!priv->page_complete_easysetup)
+               priv->page_complete_easysetup = create_page_complete_easysetup (self);
+
+       if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_complete_easysetup)))
+               modest_easysetup_wizard_dialog_append_page (notebook, priv->page_complete_easysetup, 
+                                                           _("mcen_ti_emailsetup_complete"));
+                       
+       /* This is unnecessary with GTK+ 2.10: */
+       modest_wizard_dialog_force_title_update (MODEST_WIZARD_DIALOG(self));
+}
+
+/* */
+static void
+remove_non_common_tabs (GtkNotebook *notebook, 
+                       gboolean remove_user_details) 
+{
+       gint starting_tab;
+       /* The first 2 tabs are the common ones (welcome tab and the
+          providers tab), so we always remove starting from the
+          end */
+
+       starting_tab = (remove_user_details) ? 2 : 3;
+       while (gtk_notebook_get_n_pages (notebook) > starting_tab) 
+               gtk_notebook_remove_page (notebook, -1); 
+}
+
+static void
+on_missing_mandatory_data (ModestAccountProtocol *protocol,
+                          gboolean missing,
+                          gpointer user_data)
+{
+       real_enable_buttons (MODEST_WIZARD_DIALOG (user_data), !missing);
+}
+
+/* After the user details page,
+ * the following pages depend on whether "Other" was chosen 
+ * in the provider combobox on the account page
+ */
+static void 
+create_subsequent_pages (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv;
+       EasysetupProviderComboBox *combo;
+       EasysetupProviderComboBoxIdType id_type;
+       GtkNotebook *notebook;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       combo = EASYSETUP_PROVIDER_COMBO_BOX (priv->combo_account_serviceprovider);
+       id_type = easysetup_provider_combo_box_get_active_id_type (combo);
+       g_object_get (self, "wizard-notebook", &notebook, NULL);
+
+       if (id_type == EASYSETUP_PROVIDER_COMBO_BOX_ID_OTHER) {
+               /* "Other..." was selected: */
+
+               /* If we come from a rollbacked easysetup */
+               if (priv->page_complete_easysetup) {
+                       remove_non_common_tabs (notebook, FALSE);
+                       priv->page_complete_easysetup = NULL;
+               } 
+               
+               /* If we come from a rollbacked plugin protocol setup */
+               if (priv->last_plugin_protocol_selected != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
+                       remove_non_common_tabs (notebook, TRUE);
+                       priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+                       modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
+                       priv->missing_data_signals = NULL;
+               }
+
+               create_subsequent_customsetup_pages (self);
+       } else {
+               /* If we come from a rollbacked custom setup */
+               if (priv->page_custom_incoming) {
+                       remove_non_common_tabs (notebook, TRUE);
+                       init_user_page (priv);
+                       init_incoming_page (priv);
+                       init_outgoing_page (priv);
+                       init_user_page (priv);
+                       priv->page_complete_customsetup = NULL;
+               }
+
+               /* It's a pluggable protocol and not a provider with presets */
+               if (id_type == EASYSETUP_PROVIDER_COMBO_BOX_ID_PLUGIN_PROTOCOL) {
+                       ModestProtocol *protocol;
+                       gchar *proto_name;
+                       ModestProtocolType proto_type;
+
+                       
+                       /* If we come from a rollbacked easy setup */
+                       if (priv->last_plugin_protocol_selected == 
+                           MODEST_PROTOCOL_REGISTRY_TYPE_INVALID &&
+                           priv->page_complete_easysetup) {
+                               remove_non_common_tabs (notebook, TRUE);
+                               init_user_page (priv);
+                               priv->page_complete_easysetup = NULL;
+                       }
+                       
+                       proto_name = easysetup_provider_combo_box_get_active_provider_id (combo);
+                       protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
+                                                                                 MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS,
+                                                                                 proto_name);
+                       proto_type = modest_protocol_get_type_id (protocol);
+
+                       if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol) &&
+                           proto_type != priv->last_plugin_protocol_selected) {
+                               ModestPairList *tabs;
+                               GSList *tmp;
+
+                               /* Remember the last selected plugin protocol */
+                               priv->last_plugin_protocol_selected = proto_type;
+
+                               /* Get tabs */
+                               tabs = modest_account_protocol_get_easysetupwizard_tabs (MODEST_ACCOUNT_PROTOCOL (protocol));
+                               tmp = (GSList *) tabs;
+                               while (tmp) {
+                                       ModestPair *pair = (ModestPair *) tmp->data;
+                                       modest_easysetup_wizard_dialog_append_page (notebook,
+                                                                                   GTK_WIDGET (pair->second),
+                                                                                   (const gchar *) pair->first);
+
+                                       /* Connect signals */
+                                       priv->missing_data_signals = 
+                                               modest_signal_mgr_connect (priv->missing_data_signals, 
+                                                                          G_OBJECT (pair->second), 
+                                                                          "missing-mandatory-data",
+                                                                          G_CALLBACK (on_missing_mandatory_data), 
+                                                                          self);
+
+                                       g_free (pair->first);
+                                       tmp = g_slist_next (tmp);
+                                       /* Critical: if you don't show the page then the dialog will ignore it */
+/*                                     gtk_widget_show (GTK_WIDGET (pair->second)); */
+                               }
+                               modest_pair_list_free (tabs);
+                       }
+                       g_free (proto_name);
+               } else {
+                       if (priv->last_plugin_protocol_selected != 
+                           MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
+                               remove_non_common_tabs (notebook, TRUE);
+                               init_user_page (priv);
+                               priv->page_complete_easysetup = NULL;
+                               priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+                               modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
+                               priv->missing_data_signals = NULL;
+                       }
+                       if (!priv->page_user_details) {
+                               priv->page_user_details = create_page_user_details (self);
+                               modest_easysetup_wizard_dialog_append_page (notebook, 
+                                                                           priv->page_user_details,
+                                                                           _("mcen_ti_emailsetup_userdetails"));
+                       }
+               }
+               
+               /* Create the easysetup pages: */
+               create_subsequent_easysetup_pages (self);
+       }
+}
+
+
+static gchar*
+util_get_default_servername_from_email_address (const gchar* email_address, ModestProtocolType protocol_type)
+{
+       const gchar* hostname = NULL;
+       gchar* at;
+       gchar* domain;
+       ModestProtocolRegistry *protocol_registry;
+       ModestProtocol *protocol;
+
+       if (!email_address)
+               return NULL;
+       
+       at = g_utf8_strchr (email_address, -1, '@');
+       if (!at || (g_utf8_strlen (at, -1) < 2))
+               return NULL;
+               
+       domain = g_utf8_next_char (at);
+       if(!domain)
+               return NULL;
+
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
+               
+       if (modest_protocol_registry_protocol_type_has_tag (protocol_registry, protocol_type, MODEST_PROTOCOL_REGISTRY_REMOTE_STORE_PROTOCOLS) ||
+           modest_protocol_registry_protocol_type_has_tag (protocol_registry, protocol_type, MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS)) {
+               hostname = modest_protocol_get_name (protocol);
+       }
+       
+       if (!hostname)
+               return NULL;
+               
+       return g_strdup_printf ("%s.%s", hostname, domain);
+}
+
+static void 
+set_default_custom_servernames (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+
+       if (!priv->entry_incomingserver)
+               return;
+               
+       /* Set a default domain for the server, based on the email address,
+        * if no server name was already specified.
+        */
+       if (priv->entry_user_email
+           && ((priv->server_changes & MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED) == 0)) {
+               const ModestProtocolType protocol_type = easysetup_servertype_combo_box_get_active_servertype (
+                       EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype));
+
+               /* This could happen when the combo box has still no active iter */
+               if (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
+                       const gchar* email_address = gtk_entry_get_text (GTK_ENTRY(priv->entry_user_email));    
+                       gchar* servername = util_get_default_servername_from_email_address (email_address, 
+                                                                                           protocol_type);
+
+                       /* Do not set the INCOMING_CHANGED flag because of this edit */
+                       g_signal_handlers_block_by_func (G_OBJECT (priv->entry_incomingserver), G_CALLBACK (on_entry_incoming_servername_changed), self);
+                       gtk_entry_set_text (GTK_ENTRY (priv->entry_incomingserver), servername);
+                       g_signal_handlers_unblock_by_func (G_OBJECT (priv->entry_incomingserver), G_CALLBACK (on_entry_incoming_servername_changed), self);
+                       
+                       g_free (servername);
+               }
+       }
+       
+       /* Set a default domain for the server, based on the email address,
+        * if no server name was already specified.
+        */
+       if (!priv->entry_outgoingserver)
+               return;
+               
+       if (priv->entry_user_email
+           && ((priv->server_changes & MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED) == 0)) {
+               const gchar* email_address = gtk_entry_get_text (GTK_ENTRY(priv->entry_user_email));
+               
+               gchar* servername = util_get_default_servername_from_email_address (email_address, MODEST_PROTOCOLS_TRANSPORT_SMTP);
+
+               /* Do not set the OUTGOING_CHANGED flag because of this edit */
+               g_signal_handlers_block_by_func (G_OBJECT (priv->entry_outgoingserver), G_CALLBACK (on_entry_outgoing_servername_changed), self);
+               gtk_entry_set_text (GTK_ENTRY (priv->entry_outgoingserver), servername);
+               g_signal_handlers_unblock_by_func (G_OBJECT (priv->entry_outgoingserver), G_CALLBACK (on_entry_outgoing_servername_changed), self);
+
+               g_free (servername);
+       }
+}
+
+static gchar*
+get_entered_account_title (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv;
+       const gchar* account_title;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
+       account_title = gtk_entry_get_text (GTK_ENTRY (priv->entry_account_title));
+
+       if (!account_title || (g_utf8_strlen (account_title, -1) == 0)) {
+               return NULL;
+       } else {
+               /* Strip it of whitespace at the start and end: */
+               gchar *result = g_strdup (account_title);
+               result = g_strstrip (result);
+               
+               if (!result)
+                       return NULL;
+                       
+               if (g_utf8_strlen (result, -1) == 0) {
+                       g_free (result);
+                       return NULL;    
+               }
+               
+               return result;
+       }
+}
+
+static gboolean
+on_before_next (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       ModestProtocolRegistry *protocol_registry;
+
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       /* if are browsing pages previous to the last one, then we have pending settings in
+        * this wizard */
+       if (next_page != NULL)
+               priv->pending_load_settings = TRUE;
+       
+       /* Do extra validation that couldn't be done for every key press,
+        * either because it was too slow,
+        * or because it requires interaction:
+        */
+       if (current_page == priv->page_account_details) {       
+               /* Check that the title is not already in use: */
+               gchar* account_title = get_entered_account_title (self);
+               if (!account_title)
+                       return FALSE;
+                       
+               /* Aavoid a clash with an existing display name: */
+               const gboolean name_in_use = modest_account_mgr_account_with_display_name_exists (
+                       priv->account_manager, account_title);
+
+               if (name_in_use) {
+                       /* Warn the user via a dialog: */
+                       hildon_banner_show_information(NULL, NULL, _("mail_ib_account_name_already_existing"));
+            
+                       return FALSE;
+               }
+
+               /* Make sure that the subsequent pages are appropriate for the provider choice. */
+               create_subsequent_pages (self);
+
+       } else if (current_page == priv->page_user_details) {
+               /* Check that the email address is valud: */
+               const gchar* email_address = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
+               if ((!email_address) || (g_utf8_strlen (email_address, -1) == 0))
+                       return FALSE;
+                       
+               if (!modest_text_utils_validate_email_address (email_address, NULL)) {
+                       /* Warn the user via a dialog: */
+                       hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_email"));
+                                             
+                       /* Return focus to the email address entry: */
+                       gtk_widget_grab_focus (priv->entry_user_email);
+                       gtk_editable_select_region (GTK_EDITABLE (priv->entry_user_email), 0, -1);
+
+                       return FALSE;
+               }
+       }
+         
+       if (next_page == priv->page_custom_incoming) {
+               set_default_custom_servernames (self);
+       } else if (next_page == priv->page_custom_outgoing) {
+               set_default_custom_servernames (self);
+
+               /* Check if the server supports secure authentication */
+/*             if (modest_security_options_view_auth_check (security_options)) */
+/*                     if (!check_has_supported_auth_methods (self)) */
+/*                             return FALSE; */
+               gtk_widget_show (priv->outgoing_security);
+       }
+       
+       /* If this is the last page, and this is a click on Finish, 
+        * then attempt to create the dialog.
+        */
+       if(!next_page && 
+          current_page != priv->page_account_details) /* This is NULL when this is a click on Finish. */
+       {
+               if (priv->pending_load_settings) {
+                       save_to_settings (self);
+               }
+
+               /* We check if there's already another account with the same configuration */
+               if (modest_account_mgr_check_already_configured_account (priv->account_manager, priv->settings)) {
+                       modest_platform_information_banner (NULL, NULL, _("mail_ib_setting_failed"));
+                       return FALSE;
+               }
+
+               modest_account_mgr_add_account_from_settings (priv->account_manager, priv->settings);
+       }
+       
+       
+       return TRUE;
+}
+
+static gboolean entry_is_empty (GtkWidget *entry)
+{
+       if (!entry)
+               return FALSE;
+               
+       const gchar* text = gtk_entry_get_text (GTK_ENTRY (entry));
+       if ((!text) || (g_utf8_strlen (text, -1) == 0))
+               return TRUE;
+       else {
+               /* Strip it of whitespace at the start and end: */
+               gchar *stripped = g_strdup (text);
+               stripped = g_strstrip (stripped);
+               
+               if (!stripped)
+                       return TRUE;
+                       
+               const gboolean result = (g_utf8_strlen (stripped, -1) == 0);
+               
+               g_free (stripped);
+               return result;
+       }
+}
+
+static void
+real_enable_buttons (ModestWizardDialog *dialog, gboolean enable_next)
+{              
+       GtkNotebook *notebook = NULL;
+       gboolean is_finish_tab;
+       GtkWidget *current;
+       ModestEasysetupWizardDialogPrivate *priv;
+
+       /* Get data */
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (dialog);
+       g_object_get (dialog, "wizard-notebook", &notebook, NULL);
+       
+       /* Disable the Finish button until we are on the last page,
+        * because HildonWizardDialog enables this for all but the
+        * first page */
+       current = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
+       is_finish_tab = ((current == priv->page_complete_easysetup) ||
+                        (current == priv->page_complete_customsetup));
+
+       if (is_finish_tab) {
+               /* Disable Next on the last page no matter what the
+                  argument say */
+               enable_next = FALSE;
+       } else {
+               /* Not the last one */
+               gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+                                                  MODEST_WIZARD_DIALOG_FINISH,
+                                                  FALSE);
+       }
+       
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+                                          MODEST_WIZARD_DIALOG_NEXT,
+                                          enable_next);
+}
+
+static void
+on_enable_buttons (ModestWizardDialog *dialog, GtkWidget *current_page)
+{
+       ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       
+       gboolean enable_next = TRUE;
+       if (current_page == priv->page_welcome) {
+               enable_next = TRUE;
+       } else if (current_page == priv->page_account_details) {
+               /* The account details title is mandatory: */
+               if (entry_is_empty(priv->entry_account_title))
+                       enable_next = FALSE;
+       } else if (current_page == priv->page_user_details) {   
+               /* The user details username is mandatory: */
+               if (entry_is_empty(priv->entry_user_username))
+                       enable_next = FALSE;
+                       
+               /* The user details email address is mandatory: */
+               if (enable_next && entry_is_empty (priv->entry_user_email))
+                       enable_next = FALSE;
+       } else if (current_page == priv->page_custom_incoming) {
+               /* The custom incoming server is mandatory: */
+               if (entry_is_empty(priv->entry_incomingserver))
+                       enable_next = FALSE;
+       } else if (MODEST_IS_EASYSETUP_WIZARD_PAGE (current_page)) {
+               enable_next = !modest_easysetup_wizard_page_validate (
+                      MODEST_EASYSETUP_WIZARD_PAGE (current_page));
+       }
+                       
+       /* Enable/disable buttons */ 
+       real_enable_buttons (dialog, enable_next);
+}
+
+static void
+modest_easysetup_wizard_dialog_class_init (ModestEasysetupWizardDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       g_type_class_add_private (klass, sizeof (ModestEasysetupWizardDialogPrivate));
+
+
+       object_class->dispose = modest_easysetup_wizard_dialog_dispose;
+       object_class->finalize = modest_easysetup_wizard_dialog_finalize;
+       
+       /* Provide a vfunc implementation so we can decide 
+        * when to enable/disable the prev/next buttons.
+        */
+       ModestWizardDialogClass *base_klass = (ModestWizardDialogClass*)(klass);
+       base_klass->before_next = on_before_next;
+       base_klass->enable_buttons = on_enable_buttons;
+}
+
+/**
+ * save_to_settings:
+ * @self: a #ModestEasysetupWizardDialog
+ *
+ * takes information from all the wizard and stores it in settings
+ */
+static void
+save_to_settings (ModestEasysetupWizardDialog *self)
+{
+       ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       guint special_port;
+       gchar *provider_id;
+       gchar* display_name;
+       const gchar *username, *password;
+       gchar *store_hostname, *transport_hostname;
+       guint store_port, transport_port;
+       ModestProtocolRegistry *protocol_registry;
+       ModestProtocolType store_protocol, transport_protocol;
+       ModestProtocolType store_security, transport_security;
+       ModestProtocolType store_auth_protocol, transport_auth_protocol;
+       ModestServerAccountSettings *store_settings, *transport_settings;
+       const gchar *fullname, *email_address;
+       EasysetupProviderComboBox *combo;
+       EasysetupProviderComboBoxIdType id_type;
+
+       priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
+       combo = EASYSETUP_PROVIDER_COMBO_BOX (priv->combo_account_serviceprovider);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       /* Get details from the specified presets: */
+       id_type = easysetup_provider_combo_box_get_active_id_type (combo);
+       provider_id = easysetup_provider_combo_box_get_active_provider_id (combo);
+               
+       /* Let the plugin save the settings. We do a return in order
+          to save an indentation level */
+       if (id_type == EASYSETUP_PROVIDER_COMBO_BOX_ID_PLUGIN_PROTOCOL) {
+               ModestProtocol *protocol;
+
+               protocol = modest_protocol_registry_get_protocol_by_name (
+                      modest_runtime_get_protocol_registry (),
+                      MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS,
+                      provider_id);
+
+               if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
+                       gint n_pages, i = 0;
+                       GtkNotebook *notebook;
+                       GList *wizard_pages = NULL;
+
+                       g_object_get (self, "wizard-notebook", &notebook, NULL);
+                       n_pages = gtk_notebook_get_n_pages (notebook);
+                       for (i = 0; i < n_pages; i++) {
+                               GtkWidget *page = gtk_notebook_get_nth_page (notebook, i);
+                               if (MODEST_IS_EASYSETUP_WIZARD_PAGE (page))
+                                       wizard_pages  = g_list_append (wizard_pages, page);
+                       }
+                       modest_account_protocol_save_wizard_settings (MODEST_ACCOUNT_PROTOCOL (protocol),
+                                                                     wizard_pages,
+                                                                     priv->settings);
+                       g_list_free (wizard_pages);
+               } else {
+                       g_warning ("The selected protocol is a plugin protocol "//
+                                  "but it's not a ModestAccountProtocol");
+               }
+
+               return;
+       }
+
+       /* username and password (for both incoming and outgoing): */
+       username = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username));
+       password = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_password));
+
+       store_settings = modest_account_settings_get_store_settings (priv->settings);
+       transport_settings = modest_account_settings_get_transport_settings (priv->settings);
+
+       /* Incoming server: */
+       /* Note: We need something as default for the transport store protocol values, 
+        * or modest_account_mgr_add_server_account will fail. */
+       store_port = 0;
+       store_protocol = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+       store_security = MODEST_PROTOCOLS_CONNECTION_NONE;
+       store_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
+
+       if (provider_id) {
+               ModestProtocolType store_provider_server_type;
+               gboolean store_provider_use_alternate_port;
+               /* Use presets: */
+               store_hostname = modest_presets_get_server (priv->presets, provider_id, 
+                                                           TRUE /* store */);
+               
+               store_provider_server_type = modest_presets_get_info_server_type (priv->presets,
+                                                                        provider_id, 
+                                                                        TRUE /* store */);
+               store_security  = modest_presets_get_info_server_security (priv->presets,
+                                                                                   provider_id, 
+                                                                                   TRUE /* store */);
+               store_auth_protocol  = modest_presets_get_info_server_auth (priv->presets,
+                                                                                    provider_id, 
+                                                                                    TRUE /* store */);
+               store_provider_use_alternate_port  = modest_presets_get_info_server_use_alternate_port (priv->presets,
+                                                                                                       provider_id, 
+                                                                                                       TRUE /* store */);
+
+               /* We don't check for SMTP here as that is impossible for an incoming server. */
+               if (store_provider_server_type == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID)
+                       store_protocol = MODEST_PROTOCOLS_STORE_POP;
+               else
+                       store_protocol = store_provider_server_type;
+
+               /* we check if there is a *special* port */
+               special_port = modest_presets_get_port (priv->presets, provider_id, TRUE /* incoming */);
+               if (special_port != 0)
+                       store_port = special_port;
+               else 
+                       store_port = get_port_from_protocol(store_provider_server_type, store_security);
+
+               modest_server_account_settings_set_security_protocol (store_settings, 
+                                                                     store_security);
+               modest_server_account_settings_set_auth_protocol (store_settings, 
+                                                                 store_auth_protocol);
+               if (store_port != 0)
+                       modest_server_account_settings_set_port (store_settings, store_port);
+       } else {
+               /* Use custom pages because no preset was specified: */
+               store_hostname = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry_incomingserver) ));               
+               store_protocol = easysetup_servertype_combo_box_get_active_servertype (
+                       EASYSETUP_SERVERTYPE_COMBO_BOX (priv->combo_incoming_servertype));              
+
+               modest_security_options_view_save_settings (
+                                   MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security),
+                                   priv->settings);
+       }
+
+       /* now we store the common store account settings */
+       modest_server_account_settings_set_hostname (store_settings, store_hostname);
+       modest_server_account_settings_set_username (store_settings, username);
+       modest_server_account_settings_set_password (store_settings, password);
+       modest_server_account_settings_set_protocol (store_settings, store_protocol);
+
+       g_object_unref (store_settings);
+       g_free (store_hostname);
+       
+       /* Outgoing server: */
+       transport_hostname = NULL;
+       transport_protocol = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+       transport_security = MODEST_PROTOCOLS_CONNECTION_NONE;
+       transport_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
+       transport_port = 0;
+       
+       if (provider_id) {
+               ModestProtocolType transport_provider_server_type;
+               ModestProtocolType transport_provider_security;
+
+               /* Use presets */
+               transport_hostname = modest_presets_get_server (priv->presets, provider_id, 
+                                                               FALSE /* transport */);
+                       
+               transport_provider_server_type = modest_presets_get_info_server_type (priv->presets,
+                                                                                     provider_id, 
+                                                                                     FALSE /* transport */);           
+               transport_provider_security = modest_presets_get_info_server_security (priv->presets, 
+                                                                                      provider_id, 
+                                                                                      FALSE /* transport */);
+
+               /* Note: We need something as default, or modest_account_mgr_add_server_account will fail. */
+               transport_protocol = transport_provider_server_type;
+               transport_security = transport_provider_security;
+               if (transport_security == MODEST_PROTOCOLS_CONNECTION_SSL) {
+                       /* printf("DEBUG: %s: using secure SMTP\n", __FUNCTION__); */
+                       /* we check if there is a *special* port */
+                       special_port = modest_presets_get_port (priv->presets, provider_id,
+                                                               FALSE /* transport */);
+                       if (special_port != 0)
+                               transport_port = special_port;
+                       else 
+                               transport_port = 465;
+                       transport_auth_protocol = MODEST_PROTOCOLS_AUTH_PASSWORD;
+               } else {
+                       /* printf("DEBUG: %s: using non-secure SMTP\n", __FUNCTION__); */
+                       transport_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
+               }
+
+               modest_server_account_settings_set_security_protocol (transport_settings, 
+                                                                     transport_security);
+               modest_server_account_settings_set_auth_protocol (transport_settings, 
+                                                                 transport_auth_protocol);
+               if (transport_port != 0)
+                       modest_server_account_settings_set_port (transport_settings, 
+                                                                transport_port);
+       } else {
+               ModestProtocolRegistry *registry;
+               ModestProtocol *store_proto;
+
+               registry = modest_runtime_get_protocol_registry ();
+               /* Use custom pages because no preset was specified: */
+               transport_hostname = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver) ));
+
+               store_proto = modest_protocol_registry_get_protocol_by_type (registry, 
+                                                                            store_protocol);
+
+               if (transport_protocol == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
+                       /* fallback to SMTP if none was specified */
+                       g_warning ("No transport protocol was specified for store %d (%s)",
+                                  modest_protocol_get_type_id (store_proto),
+                                  modest_protocol_get_display_name (store_proto));
+                       transport_protocol = MODEST_PROTOCOLS_TRANSPORT_SMTP;
+               }
+
+               modest_security_options_view_save_settings (
+                                   MODEST_SECURITY_OPTIONS_VIEW (priv->outgoing_security),
+                                   priv->settings);
+       }
+
+       /* now we store the common transport account settings */
+       modest_server_account_settings_set_hostname (transport_settings, transport_hostname);
+       modest_server_account_settings_set_username (transport_settings, username);
+       modest_server_account_settings_set_password (transport_settings, password);
+       modest_server_account_settings_set_protocol (transport_settings, transport_protocol);
+
+       g_object_unref (transport_settings);
+       g_free (transport_hostname);
+       
+       fullname = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_name));
+       email_address = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
+       modest_account_settings_set_fullname (priv->settings, fullname);
+       modest_account_settings_set_email_address (priv->settings, email_address);
+       /* we don't set retrieve type to preserve advanced settings if
+          any. By default account settings are set to headers only */
+       
+       /* Save the connection-specific SMTP server accounts. */
+        modest_account_settings_set_use_connection_specific_smtp 
+               (priv->settings, 
+                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox_outgoing_smtp_specific)));
+
+       display_name = get_entered_account_title (self);
+       modest_account_settings_set_display_name (priv->settings, display_name);
+       g_free (display_name);
+}
+
diff --git a/src/hildon2/modest-easysetup-wizard-dialog.h b/src/hildon2/modest-easysetup-wizard-dialog.h
new file mode 100644 (file)
index 0000000..ca075dc
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MODEST_EAYSETUP_WIZARD_DIALOG
+#define _MODEST_EAYSETUP_WIZARD_DIALOG
+
+/* #include <hildon-widgets/hildon-wizard-dialog.h> */
+#include "widgets/modest-wizard-dialog.h" /* We use a copied-and-improved HildonWizardDialog. */
+#include "modest-account-mgr.h"
+#include <config.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+#include <hildon-widgets/hildon-caption.h>
+#else
+#include <hildon/hildon-caption.h>
+#endif /*MODEST_HAVE_HILDON0_WIDGETS*/
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_EASYSETUP_WIZARD_DIALOG modest_easysetup_wizard_dialog_get_type()
+
+#define MODEST_EASYSETUP_WIZARD_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, ModestEasysetupWizardDialog))
+
+#define MODEST_EASYSETUP_WIZARD_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, ModestEasysetupWizardDialogClass))
+
+#define MODEST_IS_EASYSETUP_WIZARD_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                             \
+                                    MODEST_TYPE_EASYSETUP_WIZARD_DIALOG))
+
+#define MODEST_EASYSETUP_IS_WIZARD_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_TYPE_EASYSETUP_WIZARD_DIALOG))
+
+#define MODEST_EASYSETUP_WIZARD_DIALOG_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, ModestEasysetupWizardDialogClass))
+
+typedef struct {
+       ModestWizardDialog parent;
+       
+} ModestEasysetupWizardDialog;
+
+typedef struct {
+       ModestWizardDialogClass parent_class;
+       
+} ModestEasysetupWizardDialogClass;
+
+GType modest_easysetup_wizard_dialog_get_type (void);
+
+/*
+ * NOTE: can be instantiated only once; after that, this function will
+ * return NULL, until the one before is destroyed; if it returns NULL
+ * it will gtk_window_present the existing one.
+ */
+ModestEasysetupWizardDialog* modest_easysetup_wizard_dialog_new (void);
+
+G_END_DECLS
+
+#endif /* _MODEST_EAYSETUP_WIZARD_DIALOG */
diff --git a/src/hildon2/modest-hildon-includes.h b/src/hildon2/modest-hildon-includes.h
new file mode 100644 (file)
index 0000000..6dd1306
--- /dev/null
@@ -0,0 +1,156 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+k * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __MODEST_HILDON_INCLUDES__
+#define __MODEST_HILDON_INCLUDES__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* helplib to use */
+#ifdef MODEST_HAVE_OSSO_HELP
+#include <osso-helplib.h>
+#else
+#ifdef MODEST_HAVE_HILDON_HELP
+#include <hildon/hildon-help.h>
+#endif /*MODEST_HAVE_HILDON_HELP*/
+#endif /*MODEST_HAVE_OSSO_HELP*/
+
+/* mimelib to use */
+#ifdef MODEST_HAVE_OSSO_MIME
+#include <osso-mime.h>
+#include <osso-uri.h>
+#else
+#ifdef MODEST_HAVE_HILDON_MIME
+#include <hildon-mime.h>
+#include <hildon-uri.h>
+#endif /*MODEST_HAVE_HILDON_MIME*/
+#endif /*MODEST_HAVE_OSSO_MIME*/
+
+
+#ifdef MODEST_HAVE_HILDON_NOTIFY
+#include <hildon/hildon-notification.h>
+#endif /*MODEST_HILDON_NOTIFY*/
+
+#if MODEST_HILDON_API == 0
+#include <hildon-widgets/hildon-color-selector.h>
+#include <hildon-widgets/hildon-color-button.h>
+#include <hildon-widgets/hildon-banner.h>
+#include <hildon-widgets/hildon-caption.h>
+#include <hildon-widgets/hildon-number-editor.h>
+#include <hildon-widgets/hildon-note.h>
+#include <hildon-widgets/hildon-file-chooser-dialog.h>
+#include <hildon-widgets/hildon-font-selection-dialog.h>
+#include <hildon-widgets/hildon-find-toolbar.h>
+#include <hildon-widgets/hildon-sort-dialog.h>
+#include <hildon-widgets/hildon-program.h>
+
+#else
+
+#if MODEST_HILDON_API >= 1
+#include <hildon/hildon-helper.h>
+#include <hildon/hildon-file-chooser-dialog.h>
+#include <hildon/hildon-color-chooser.h>
+#include <hildon/hildon-banner.h>
+#include <hildon/hildon-color-button.h>
+#include <hildon/hildon-note.h>
+#include <hildon/hildon-color-button.h>
+#include <hildon/hildon-font-selection-dialog.h>
+#include <hildon/hildon-caption.h>
+#include <hildon/hildon-find-toolbar.h>
+#include <hildon/hildon-sort-dialog.h>
+#include <hildon/hildon-number-editor.h>
+#include <hildon/hildon-program.h>
+
+#endif /*__MODEST_HAVE_HILDON1_WIDGETS*/
+#endif /*__MODEST_HAVE_HILDON0_WIDGETS_*/
+
+
+/* backward compatibility... */
+#ifdef MODEST_HAVE_OSSO_MIME
+#define hildon_mime_open_file_with_mime_type osso_mime_open_file_with_mime_type 
+#define hildon_mime_open_file                osso_mime_open_file                
+
+#define HildonURIAction                      OssoURIAction
+#define hildon_uri_get_scheme_from_uri       osso_uri_get_scheme_from_uri
+#define hildon_uri_get_actions               osso_uri_get_actions
+#define hildon_uri_get_actions_by_uri        osso_uri_get_actions_by_uri
+#define hildon_uri_action_get_translation    osso_uri_action_get_translation   
+#define hildon_uri_is_default_action         osso_uri_is_default_action
+#define hildon_uri_free_actions              osso_uri_free_actions
+
+/* service->name */
+#define hildon_uri_action_get_service        osso_uri_action_get_name
+#define hildon_uri_open                      osso_uri_open
+
+#define hildon_mime_get_icon_names           osso_mime_get_icon_names 
+#endif /*MODEST_HAVE_OSSO_MIME*/
+
+/* helplib to use */
+#ifdef MODEST_HAVE_OSSO_HELP
+#define hildon_help_show               ossohelp_show
+#define hildon_help_dialog_help_enable ossohelp_dialog_help_enable
+#define HILDON_HELP_SHOW_DIALOG        OSSO_HELP_SHOW_DIALOG
+#else
+#ifdef MODEST_HAVE_HILDON_HELP
+/* nothing */
+#endif /*MODEST_HAVE_HILDON_HELP*/
+#endif /*MODEST_HAVE_OSSO_HELP*/
+
+/* some extra #defines, so it will compile with the 'normal' gtk */
+#ifndef MODEST_HAVE_HILDON_GTK
+#define hildon_gtk_entry_set_input_mode(a,b) \
+       g_warning ("%s: hildon_gtk_entry_set_input_mode requires gtk-hildon", __FUNCTION__)
+#define hildon_gtk_text_view_set_input_mode(a,b) \
+       g_warning ("%s: hildon_gtk_text_view_set_input_mode requires gtk-hildon", __FUNCTION__)
+#define gtk_widget_tap_and_hold_setup(a,b,c,d)                         \
+       g_warning ("%s: gtk_widget_tap_and_hold_setup requires gtk-hildon", __FUNCTION__)
+
+typedef enum
+{
+  GTK_INVALID_INPUT_MAX_CHARS_REACHED,
+  GTK_INVALID_INPUT_MODE_RESTRICTION
+} GtkInvalidInputType;
+
+typedef enum
+{
+  HILDON_GTK_INPUT_MODE_ALPHA        = 1 << 0,
+  HILDON_GTK_INPUT_MODE_NUMERIC      = 1 << 1,
+  HILDON_GTK_INPUT_MODE_SPECIAL      = 1 << 2,
+  HILDON_GTK_INPUT_MODE_HEXA         = 1 << 3,
+  HILDON_GTK_INPUT_MODE_TELE         = 1 << 4,
+  HILDON_GTK_INPUT_MODE_FULL         = (HILDON_GTK_INPUT_MODE_ALPHA | HILDON_GTK_INPUT_MODE_NUMERIC | HILDON_GTK_INPUT_MODE_SPECIAL),
+  HILDON_GTK_INPUT_MODE_MULTILINE    = 1 << 28,
+  HILDON_GTK_INPUT_MODE_INVISIBLE    = 1 << 29,
+  HILDON_GTK_INPUT_MODE_AUTOCAP      = 1 << 30,
+  HILDON_GTK_INPUT_MODE_DICTIONARY   = 1 << 31
+} HildonGtkInputMode;
+#endif /* !MODEST_HAVE_HILDON_GTK */
+
+#endif /*__MODEST_HILDON_INCLUDES__*/
diff --git a/src/hildon2/modest-hildon-sort-dialog.c b/src/hildon2/modest-hildon-sort-dialog.c
new file mode 100644 (file)
index 0000000..b2e56da
--- /dev/null
@@ -0,0 +1,133 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-hildon-sort-dialog.h"
+#include "widgets/modest-sort-criterium-view.h"
+
+
+static gint    modest_hildon_sort_dialog_add_sort_key        (ModestSortCriteriumView *self,
+                                                                     const gchar *sort_key);
+static void    modest_hildon_sort_dialog_set_sort_key (ModestSortCriteriumView *self, gint key);
+static void    modest_hildon_sort_dialog_set_sort_order (ModestSortCriteriumView *self, GtkSortType sort_type);
+static gint    modest_hildon_sort_dialog_get_sort_key (ModestSortCriteriumView *self);
+static GtkSortType modest_hildon_sort_dialog_get_sort_order (ModestSortCriteriumView *self);
+static void modest_sort_criterium_view_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED (ModestHildonSortDialog, 
+                       modest_hildon_sort_dialog, 
+                       HILDON_TYPE_SORT_DIALOG,
+                       0,
+                       G_IMPLEMENT_INTERFACE (MODEST_TYPE_SORT_CRITERIUM_VIEW, modest_sort_criterium_view_init));
+
+static void
+modest_hildon_sort_dialog_finalize (GObject *object)
+{
+       G_OBJECT_CLASS (modest_hildon_sort_dialog_parent_class)->finalize (object);
+}
+
+static void
+modest_hildon_sort_dialog_class_init (ModestHildonSortDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = modest_hildon_sort_dialog_finalize;
+
+}
+
+static void
+modest_hildon_sort_dialog_init (ModestHildonSortDialog *self)
+{
+}
+
+static gint
+modest_hildon_sort_dialog_add_sort_key        (ModestSortCriteriumView *self,
+                                              const gchar *sort_key)
+{
+       g_return_val_if_fail (MODEST_IS_HILDON_SORT_DIALOG (self), 0);
+
+       return hildon_sort_dialog_add_sort_key (HILDON_SORT_DIALOG (self), sort_key);
+}
+
+static void
+modest_hildon_sort_dialog_set_sort_key (ModestSortCriteriumView *self, gint key)
+{
+       g_return_if_fail (MODEST_IS_HILDON_SORT_DIALOG (self));
+
+       hildon_sort_dialog_set_sort_key (HILDON_SORT_DIALOG (self), key);
+}
+
+static void
+modest_hildon_sort_dialog_set_sort_order (ModestSortCriteriumView *self, GtkSortType sort_type)
+{
+       g_return_if_fail (MODEST_IS_HILDON_SORT_DIALOG (self));
+
+       hildon_sort_dialog_set_sort_order (HILDON_SORT_DIALOG (self), sort_type);
+}
+
+static gint
+modest_hildon_sort_dialog_get_sort_key (ModestSortCriteriumView *self)
+{
+       g_return_val_if_fail (MODEST_IS_HILDON_SORT_DIALOG (self), 0);
+
+       return hildon_sort_dialog_get_sort_key (HILDON_SORT_DIALOG (self));
+}
+
+static GtkSortType 
+modest_hildon_sort_dialog_get_sort_order (ModestSortCriteriumView *self)
+{
+       g_return_val_if_fail (MODEST_IS_HILDON_SORT_DIALOG (self), GTK_SORT_ASCENDING);
+
+       return hildon_sort_dialog_get_sort_order (HILDON_SORT_DIALOG (self));
+}
+
+static void
+modest_sort_criterium_view_init (gpointer g_iface,
+                                gpointer iface_data)
+{
+       ModestSortCriteriumViewIface *iface = (ModestSortCriteriumViewIface *) g_iface;
+
+       iface->add_sort_key_func = modest_hildon_sort_dialog_add_sort_key;
+       iface->get_sort_key_func = modest_hildon_sort_dialog_get_sort_key;
+       iface->set_sort_key_func = modest_hildon_sort_dialog_set_sort_key;
+       iface->get_sort_order_func = modest_hildon_sort_dialog_get_sort_order;
+       iface->set_sort_order_func = modest_hildon_sort_dialog_set_sort_order;
+}
+
+GtkWidget*
+modest_hildon_sort_dialog_new (GtkWindow *parent)
+{
+       GtkWidget *result = g_object_new (MODEST_TYPE_HILDON_SORT_DIALOG, NULL);
+
+
+       if (parent)
+               gtk_window_set_transient_for(GTK_WINDOW(result), parent);
+
+       return result;
+}
+
diff --git a/src/hildon2/modest-hildon-sort-dialog.h b/src/hildon2/modest-hildon-sort-dialog.h
new file mode 100644 (file)
index 0000000..8fd7227
--- /dev/null
@@ -0,0 +1,77 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_HILDON_SORT_DIALOG
+#define __MODEST_HILDON_SORT_DIALOG
+
+#include <glib.h>
+#include <hildon/hildon-sort-dialog.h>
+#include <widgets/modest-sort-criterium-view.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_HILDON_SORT_DIALOG modest_hildon_sort_dialog_get_type()
+
+#define MODEST_HILDON_SORT_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_TYPE_HILDON_SORT_DIALOG, ModestHildonSortDialog))
+
+#define MODEST_HILDON_SORT_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_TYPE_HILDON_SORT_DIALOG, ModestHildonSortDialogClass))
+
+#define MODEST_IS_HILDON_SORT_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       MODEST_TYPE_HILDON_SORT_DIALOG))
+
+#define MODEST_IS_HILDON_SORT_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_TYPE_HILDON_SORT_DIALOG))
+
+#define MODEST_HILDON_SORT_DIALOG_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_TYPE_HILDON_SORT_DIALOG, ModestHildonSortDialogClass))
+
+typedef struct {
+       HildonSortDialog parent;
+       
+} ModestHildonSortDialog;
+
+typedef struct {
+       HildonSortDialogClass parent_class;
+
+} ModestHildonSortDialogClass;
+
+GType modest_hildon_sort_dialog_get_type (void);
+
+GtkWidget* modest_hildon_sort_dialog_new (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __MODEST_HILDON_SORT_DIALOG */
diff --git a/src/hildon2/modest-icon-names.h b/src/hildon2/modest-icon-names.h
new file mode 100644 (file)
index 0000000..5ab97e1
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* modest-tny-icon-names.h */
+
+
+#ifndef __MODEST_TNY_ICON_NAMES_H__
+#define __MODEST_TNY_ICON_NAMES_H__
+
+/* icons */
+
+#define MODEST_APP_ICON                                "qgn_list_messagin"
+#define MODEST_APP_MSG_VIEW_ICON               "qgn_list_messagin_viewer"
+#define MODEST_APP_MSG_EDIT_ICON               "qgn_list_messagin_editor"
+
+#define MODEST_HEADER_ICON_READ                        "qgn_list_messagin_mail"
+#define MODEST_HEADER_ICON_UNREAD              ""
+#define MODEST_HEADER_ICON_DELETED             "qgn_list_messagin_mail_deleted"
+#define MODEST_HEADER_ICON_ATTACH              "qgn_list_gene_attacpap"
+#define MODEST_HEADER_ICON_HIGH                        "qgn_list_messaging_high"
+#define MODEST_HEADER_ICON_LOW                 "qgn_list_messaging_low"
+
+/*
+ * until we have the custom cell renderer, we use the hacked icons below;
+ * don't remove!!!
+ */ 
+#define MODEST_HEADER_ICON_ATTACH_HIGH_PRIORITY PIXMAP_PREFIX"modest_high_attachment.png"
+#define MODEST_HEADER_ICON_ATTACH_LOW_PRIORITY  PIXMAP_PREFIX"modest_low_attachment.png"
+#define MODEST_HEADER_ICON_ATTACH_NORM_PRIORITY PIXMAP_PREFIX"modest_normal_attachment.png"
+#define MODEST_HEADER_ICON_HIGH_PRIORITY        PIXMAP_PREFIX"modest_high_no_attachment.png"
+#define MODEST_HEADER_ICON_LOW_PRIORITY         PIXMAP_PREFIX"modest_low_no_attachment.png"
+#define MODEST_HEADER_ICON_NORM_PRIORITY        PIXMAP_PREFIX"modest_normal_no_attachment.png"
+/*
+ *
+ */
+
+#define MODEST_FOLDER_ICON_OPEN                        "qgn_list_gene_fldr_opn"
+#define MODEST_FOLDER_ICON_CLOSED              "qgn_list_gene_fldr_cls"
+
+#define MODEST_FOLDER_ICON_ACCOUNT             "qgn_list_browser"
+#define MODEST_FOLDER_ICON_INBOX               "qgn_list_messagin_inbox"
+#define MODEST_FOLDER_ICON_OUTBOX              "qgn_list_messagin_outbox"
+#define MODEST_FOLDER_ICON_SENT                        "qgn_list_messagin_sent"
+#define MODEST_FOLDER_ICON_TRASH               "qgn_toolb_gene_deletebutton"
+#define MODEST_FOLDER_ICON_JUNK                        "qgn_toolb_gene_deletebutton"
+#define MODEST_FOLDER_ICON_DRAFTS              "qgn_list_messagin_drafts"
+#define MODEST_FOLDER_ICON_NORMAL              "qgn_list_gene_fldr_cls"
+#define MODEST_FOLDER_ICON_LOCAL_FOLDERS       "qgn_list_shell_mydevice"
+#define MODEST_FOLDER_ICON_MMC                  "qgn_list_gene_mmc"
+
+
+/* toolbar */
+#define  MODEST_TOOLBAR_ICON_MAIL_SEND         "qgn_toolb_messagin_send"
+#define  MODEST_TOOLBAR_ICON_NEW_MAIL          "qgn_list_messagin_editor"
+#define  MODEST_TOOLBAR_ICON_SEND_RECEIVE      "qgn_toolb_messagin_sendreceive"
+#define  MODEST_TOOLBAR_ICON_REPLY             "qgn_toolb_messagin_reply"
+#define  MODEST_TOOLBAR_ICON_REPLY_ALL         "qgn_toolb_messagin_replytoall"
+#define  MODEST_TOOLBAR_ICON_FORWARD           "qgn_toolb_messagin_forward"
+#define  MODEST_TOOLBAR_ICON_DELETE            "qgn_toolb_gene_deletebutton"
+#define  MODEST_TOOLBAR_ICON_FORMAT_BULLETS     "qgn_list_gene_bullets"
+#define  MODEST_TOOLBAR_ICON_SPLIT_VIEW         "qgn_toolb_rss_fldonoff"
+#define  MODEST_TOOLBAR_ICON_SORT               "qgn_list_sort"
+#define  MODEST_TOOLBAR_ICON_REFRESH            "qgn_toolb_gene_refresh"
+#define  MODEST_TOOLBAR_ICON_MOVE_TO_FOLDER     "qgn_toolb_gene_movetofldr"
+#define  MODEST_TOOLBAR_ICON_BOLD               "qgn_list_gene_bold"
+#define  MODEST_TOOLBAR_ICON_ITALIC             "qgn_list_gene_italic"
+#define  MODEST_TOOLBAR_ICON_NEXT               "qgn_toolb_gene_forward"
+#define  MODEST_TOOLBAR_ICON_PREV               "qgn_toolb_gene_back"
+#define  MODEST_TOOLBAR_ICON_FIND               "qgn_toolb_gene_find"
+
+/* Stock icon names */
+#define  MODEST_STOCK_MAIL_SEND    "modest-stock-mail-send"
+#define  MODEST_STOCK_NEW_MAIL     "modest-stock-new-mail"
+#define  MODEST_STOCK_SEND_RECEIVE "modest-stock-send-receive"
+#define  MODEST_STOCK_REPLY        "modest-stock-reply"
+#define  MODEST_STOCK_REPLY_ALL    "modest-stock-reply-all"
+#define  MODEST_STOCK_FORWARD      "modest-stock-forward"
+#define  MODEST_STOCK_DELETE       "modest-stock-delete"
+#define  MODEST_STOCK_NEXT         "modest-stock-next"
+#define  MODEST_STOCK_PREV         "modest-stock-prev"
+#define  MODEST_STOCK_STOP         "modest-stock-stop"
+#define  MODEST_STOCK_SPLIT_VIEW   "modest-stock-split-view"
+#define  MODEST_STOCK_SORT         "modest-stock-sort"
+#define  MODEST_STOCK_REFRESH      "modest-stock-refresh"
+
+#endif  /*__MODEST_TNY_ICON_NAMES_H__*/
diff --git a/src/hildon2/modest-maemo-global-settings-dialog.c b/src/hildon2/modest-maemo-global-settings-dialog.c
new file mode 100644 (file)
index 0000000..3d192ea
--- /dev/null
@@ -0,0 +1,523 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /*HAVE_CONFIG_H*/
+
+#include <modest-hildon-includes.h>
+#include <modest-maemo-utils.h>
+
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gtk/gtkbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkhseparator.h>
+#include "modest-runtime.h"
+#include "widgets/modest-global-settings-dialog-priv.h"
+#include "widgets/modest-combo-box.h"
+#include "maemo/modest-maemo-global-settings-dialog.h"
+#include "widgets/modest-ui-constants.h"
+#include <tny-account-store.h>
+
+
+#define MSG_SIZE_MAX_VAL 5000
+#define MSG_SIZE_DEF_VAL 1000
+#define MSG_SIZE_MIN_VAL 1
+
+#define DEFAULT_FOCUS_WIDGET "default-focus-widget"
+
+/* 'private'/'protected' functions */
+static void modest_maemo_global_settings_dialog_class_init (ModestMaemoGlobalSettingsDialogClass *klass);
+static void modest_maemo_global_settings_dialog_init       (ModestMaemoGlobalSettingsDialog *obj);
+static void modest_maemo_global_settings_dialog_finalize   (GObject *obj);
+
+static ModestConnectedVia current_connection (void);
+
+/* list my signals  */
+enum {
+       /* MY_SIGNAL_1, */
+       /* MY_SIGNAL_2, */
+       LAST_SIGNAL
+};
+
+static GtkWidget* create_updating_page   (ModestMaemoGlobalSettingsDialog *self);
+static GtkWidget* create_composing_page  (ModestMaemoGlobalSettingsDialog *self);
+
+static gboolean   on_range_error         (HildonNumberEditor *editor, 
+                                         HildonNumberEditorErrorType type,
+                                         gpointer user_data);
+
+static void       on_size_notify         (HildonNumberEditor *editor, 
+                                         GParamSpec *arg1,
+                                         gpointer user_data);
+
+static void       on_auto_update_toggled (GtkToggleButton *togglebutton,
+                                         gpointer user_data);
+
+static gboolean   on_inner_tabs_key_pressed (GtkWidget *widget,
+                                            GdkEventKey *event,
+                                            gpointer user_data);
+
+typedef struct _ModestMaemoGlobalSettingsDialogPrivate ModestMaemoGlobalSettingsDialogPrivate;
+struct _ModestMaemoGlobalSettingsDialogPrivate {
+       ModestPairList *connect_via_list;
+       gint switch_handler;
+};
+#define MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                           MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG, \
+                                                           ModestMaemoGlobalSettingsDialogPrivate))
+/* globals */
+static GtkDialogClass *parent_class = NULL;
+
+/* uncomment the following if you have defined any signals */
+/* static guint signals[LAST_SIGNAL] = {0}; */
+
+GType
+modest_maemo_global_settings_dialog_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestMaemoGlobalSettingsDialogClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_maemo_global_settings_dialog_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestMaemoGlobalSettingsDialog),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_maemo_global_settings_dialog_init,
+                       NULL
+               };
+               my_type = g_type_register_static (MODEST_TYPE_GLOBAL_SETTINGS_DIALOG,
+                                                 "ModestMaemoGlobalSettingsDialog",
+                                                 &my_info, 0);
+       }
+       return my_type;
+}
+
+static void
+modest_maemo_global_settings_dialog_class_init (ModestMaemoGlobalSettingsDialogClass *klass)
+{
+       GObjectClass *gobject_class;
+       gobject_class = (GObjectClass*) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_maemo_global_settings_dialog_finalize;
+
+       g_type_class_add_private (gobject_class, sizeof(ModestMaemoGlobalSettingsDialogPrivate));
+
+       MODEST_GLOBAL_SETTINGS_DIALOG_CLASS (klass)->current_connection_func = current_connection;
+}
+
+typedef struct {
+       ModestMaemoGlobalSettingsDialog *dia;
+       GtkWidget *focus_widget;
+} SwitchPageHelper;
+
+static gboolean
+idle_select_default_focus (gpointer data) 
+{
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       ModestMaemoGlobalSettingsDialogPrivate *priv;
+       SwitchPageHelper *helper;
+
+       helper = (SwitchPageHelper *) data;
+       priv  = MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (helper->dia);
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (helper->dia);
+
+       /* Grab focus, we need to block in order to prevent a
+          recursive call to this callback */
+       g_signal_handler_block (G_OBJECT (ppriv->notebook), priv->switch_handler);
+
+       /* This is a GDK lock because we are an idle callback and
+        * the code below is or does Gtk+ code */
+
+       gdk_threads_enter (); /* CHECKED */
+       gtk_widget_grab_focus (helper->focus_widget);
+       gdk_threads_leave (); /* CHECKED */
+
+       g_signal_handler_unblock (G_OBJECT (ppriv->notebook), priv->switch_handler);
+       g_free (helper);
+
+       return FALSE;
+}
+
+
+static void
+on_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer user_data)
+{
+       /* grab the focus to the default element in the current page */
+       GtkWidget *selected_page = NULL, *focus_item = NULL;
+       SwitchPageHelper *helper;
+
+       selected_page = gtk_notebook_get_nth_page (notebook, page_num);
+       focus_item = GTK_WIDGET(g_object_get_data (G_OBJECT(selected_page), DEFAULT_FOCUS_WIDGET));
+       if (!focus_item) {
+               g_printerr ("modest: cannot get focus item\n");
+               return;
+       }
+
+       /* Create the helper */
+       helper = g_malloc0 (sizeof (SwitchPageHelper));
+       helper->dia = MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG (user_data);
+       helper->focus_widget = focus_item;
+
+       /* Focus the widget in an idle. We need to do this in an idle,
+          because this handler is executed *before* the page was
+          really switched, so the focus is not placed in the right
+          widget */
+       g_idle_add (idle_select_default_focus, helper);
+}
+
+
+static void
+modest_maemo_global_settings_dialog_init (ModestMaemoGlobalSettingsDialog *self)
+{
+       ModestMaemoGlobalSettingsDialogPrivate *priv;
+       ModestGlobalSettingsDialogPrivate *ppriv;
+
+       priv  = MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       ppriv->updating_page = create_updating_page (self);
+       ppriv->composing_page = create_composing_page (self);
+
+       /* Add the buttons: */
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK);
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL);
+
+       /* Set the default focusable widgets */
+       g_object_set_data (G_OBJECT(ppriv->updating_page), DEFAULT_FOCUS_WIDGET,
+                          (gpointer)ppriv->auto_update);
+       g_object_set_data (G_OBJECT(ppriv->composing_page), DEFAULT_FOCUS_WIDGET,
+                          (gpointer)ppriv->msg_format);
+
+       /* Add the notebook pages: */
+       gtk_notebook_append_page (GTK_NOTEBOOK (ppriv->notebook), ppriv->updating_page, 
+                                 gtk_label_new (_("mcen_ti_options_updating")));
+       gtk_notebook_append_page (GTK_NOTEBOOK (ppriv->notebook), ppriv->composing_page, 
+                                 gtk_label_new (_("mcen_ti_options_composing")));
+               
+       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (self)->vbox), ppriv->notebook);
+       gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (self)->vbox), MODEST_MARGIN_HALF);
+
+       gtk_window_set_default_size (GTK_WINDOW (self), 700, 300);
+
+       g_signal_connect (G_OBJECT (self), "key-press-event",
+                         G_CALLBACK (on_inner_tabs_key_pressed), self);
+       priv->switch_handler = g_signal_connect (G_OBJECT(ppriv->notebook), "switch-page",
+                                                G_CALLBACK(on_switch_page), self);
+
+       /* Load current config */
+       _modest_global_settings_dialog_load_conf (MODEST_GLOBAL_SETTINGS_DIALOG (self));
+
+       /* Set first page */
+       gtk_notebook_set_current_page (GTK_NOTEBOOK (ppriv->notebook), 0);
+
+       hildon_help_dialog_help_enable (GTK_DIALOG(self), "applications_email_options_dialog",
+                                       modest_maemo_utils_get_osso_context());
+}
+
+static void
+modest_maemo_global_settings_dialog_finalize (GObject *obj)
+{
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       ModestMaemoGlobalSettingsDialogPrivate *priv;
+
+       priv = MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (obj);
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (obj);
+
+       if (priv->switch_handler && ppriv->notebook) {
+               /* TODO: This causes a g_warning and a valgrind mem error: */
+               /* g_signal_handler_disconnect (G_OBJECT (ppriv->notebook), priv->switch_handler);*/
+               priv->switch_handler = 0;
+       }
+
+/*     free/unref instance resources here */
+       G_OBJECT_CLASS(parent_class)->finalize (obj);
+}
+
+GtkWidget*
+modest_maemo_global_settings_dialog_new (void)
+{
+       return GTK_WIDGET(g_object_new(MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG, NULL));
+}
+
+/*
+ * Creates the updating page
+ */
+static GtkWidget*
+create_updating_page (ModestMaemoGlobalSettingsDialog *self)
+{
+       GtkWidget *vbox, *vbox_update, *vbox_limit, *caption;
+       GtkSizeGroup *size_group;
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       GtkWidget *scrollwin = NULL;
+       GtkAdjustment *focus_adjustment = NULL;
+
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+       scrollwin = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin), 
+                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+       vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
+
+       vbox_update = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+       /* Auto update */
+       ppriv->auto_update = gtk_check_button_new ();
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_options_autoupdate"), 
+                                     ppriv->auto_update, 
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox_update), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       g_signal_connect (ppriv->auto_update, "toggled", G_CALLBACK (on_auto_update_toggled), self);
+
+       /* Connected via */
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->connect_via_list = _modest_global_settings_dialog_get_connected_via ();
+       ppriv->connect_via = modest_combo_box_new (ppriv->connect_via_list, g_int_equal);
+
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_options_connectiontype"),
+                                     ppriv->connect_via, 
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox_update), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Update interval */
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->update_interval_list = _modest_global_settings_dialog_get_update_interval ();
+       ppriv->update_interval = modest_combo_box_new (ppriv->update_interval_list, g_int_equal);
+
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_options_updateinterval"),
+                                     ppriv->update_interval, 
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox_update), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Add to vbox */
+       gtk_box_pack_start (GTK_BOX (vbox), vbox_update, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Separator */
+       gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Limits */
+       vbox_limit = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+       /* Size limit */
+       ppriv->size_limit = hildon_number_editor_new (MSG_SIZE_MIN_VAL, MSG_SIZE_MAX_VAL);
+       hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (ppriv->size_limit), MSG_SIZE_DEF_VAL);
+       g_signal_connect (ppriv->size_limit, "range_error", G_CALLBACK (on_range_error), self);
+       g_signal_connect (ppriv->size_limit, "notify", G_CALLBACK (on_size_notify), self);
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_advsetup_sizelimit"), 
+                                     ppriv->size_limit,
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox_limit), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Play sound */
+       ppriv->play_sound = gtk_check_button_new ();
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_options_playsound"), 
+                                     ppriv->play_sound, 
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox_limit), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Add to vbox */
+       gtk_box_pack_start (GTK_BOX (vbox), vbox_limit, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollwin), vbox);
+       focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrollwin));
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (vbox), focus_adjustment);
+       gtk_widget_show (scrollwin);
+       
+       return scrollwin;
+}
+
+/*
+ * Creates the composing page
+ */
+static GtkWidget* 
+create_composing_page (ModestMaemoGlobalSettingsDialog *self)
+{
+       GtkWidget *vbox;
+       GtkSizeGroup *size_group;
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       GtkWidget *caption;
+
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+       vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
+
+       /* Update interval */
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->msg_format_list = _modest_global_settings_dialog_get_msg_formats ();
+       ppriv->msg_format = modest_combo_box_new (ppriv->msg_format_list, g_int_equal);
+
+       caption = hildon_caption_new (size_group, 
+                                     _("mcen_fi_options_messageformat"),
+                                     ppriv->msg_format, 
+                                     NULL, 
+                                     HILDON_CAPTION_MANDATORY);
+       gtk_box_pack_start (GTK_BOX (vbox), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       return vbox;
+}
+
+static void
+on_auto_update_toggled (GtkToggleButton *togglebutton,
+                       gpointer user_data)
+{
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       GtkWidget *caption1, *caption2;
+
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (user_data);
+       caption1 = gtk_widget_get_ancestor (ppriv->connect_via, HILDON_TYPE_CAPTION);
+       caption2 = gtk_widget_get_ancestor (ppriv->update_interval, HILDON_TYPE_CAPTION);
+
+       if (gtk_toggle_button_get_active (togglebutton)) {
+               gtk_widget_set_sensitive (caption1, TRUE);
+               gtk_widget_set_sensitive (caption2, TRUE);
+       } else {
+               gtk_widget_set_sensitive (caption1, FALSE);
+               gtk_widget_set_sensitive (caption2, FALSE);
+       }
+}
+
+static gboolean
+on_range_error (HildonNumberEditor *editor, 
+               HildonNumberEditorErrorType type,
+               gpointer user_data)
+{
+       gchar *msg;
+       gint new_val;
+
+       switch (type) {
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+       case MAXIMUM_VALUE_EXCEED:
+#else
+       case HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED:
+#endif
+               msg = g_strdup_printf (dgettext("hildon-libs", "ckct_ib_maximum_value"), MSG_SIZE_MAX_VAL);
+               new_val = MSG_SIZE_MAX_VAL;
+               break;
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+       case MINIMUM_VALUE_EXCEED:
+#else
+       case HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED:
+#endif
+               msg = g_strdup_printf (dgettext("hildon-libs", "ckct_ib_minimum_value"), MSG_SIZE_MIN_VAL);
+               new_val = MSG_SIZE_MIN_VAL;
+               break;
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+       case ERRONEOUS_VALUE:
+#else
+       case HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE:
+#endif
+               msg = g_strdup_printf (dgettext("hildon-libs", "ckct_ib_set_a_value_within_range"), 
+                                      MSG_SIZE_MIN_VAL, 
+                                      MSG_SIZE_MAX_VAL);
+               /* FIXME: use the previous */
+               new_val = MSG_SIZE_DEF_VAL;
+               break;
+       default:
+               g_return_val_if_reached (FALSE);
+       }
+
+       /* Restore value */
+       hildon_number_editor_set_value (editor, new_val);
+
+       /* Show error */
+       hildon_banner_show_information (GTK_WIDGET (user_data), NULL, msg);
+
+       /* Free */
+       g_free (msg);
+
+       return TRUE;
+}
+
+static void       
+on_size_notify         (HildonNumberEditor *editor, 
+                       GParamSpec *arg1,
+                       gpointer user_data)
+{
+       ModestMaemoGlobalSettingsDialog *dialog = MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG (user_data);
+       gint value = hildon_number_editor_get_value (editor);
+
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, value > 0);
+}
+
+static ModestConnectedVia
+current_connection (void)
+{
+       return modest_platform_get_current_connection ();
+}
+
+static gboolean
+on_inner_tabs_key_pressed (GtkWidget *widget,
+                          GdkEventKey *event,
+                          gpointer user_data)
+{
+       ModestGlobalSettingsDialogPrivate *ppriv;
+       gboolean retval = FALSE;
+
+       ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (user_data);
+
+       if (widget == ppriv->notebook) {
+               if (event->keyval == GDK_Right) {
+                       gtk_notebook_next_page (GTK_NOTEBOOK (ppriv->notebook));
+                       retval = TRUE;
+               } else if (event->keyval == GDK_Left) {
+                       gtk_notebook_prev_page (GTK_NOTEBOOK (ppriv->notebook));
+                       retval = TRUE;
+               }
+       }
+
+       return retval;
+}
diff --git a/src/hildon2/modest-maemo-global-settings-dialog.h b/src/hildon2/modest-maemo-global-settings-dialog.h
new file mode 100644 (file)
index 0000000..351807d
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_H__
+#define __MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_H__
+
+#include "widgets/modest-global-settings-dialog.h"
+
+G_BEGIN_DECLS
+
+/* convenience macros */
+#define MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG             (modest_maemo_global_settings_dialog_get_type())
+#define MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG,ModestMaemoGlobalSettingsDialog))
+#define MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG,ModestMaemoGlobalSettingsDialogClass))
+#define MODEST_IS_MAEMO_GLOBAL_SETTINGS_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG))
+#define MODEST_IS_MAEMO_GLOBAL_SETTINGS_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG))
+#define MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG,ModestMaemoGlobalSettingsDialogClass))
+
+typedef struct _ModestMaemoGlobalSettingsDialog      ModestMaemoGlobalSettingsDialog;
+typedef struct _ModestMaemoGlobalSettingsDialogClass ModestMaemoGlobalSettingsDialogClass;
+
+struct _ModestMaemoGlobalSettingsDialog {
+        ModestGlobalSettingsDialog parent;
+};
+
+struct _ModestMaemoGlobalSettingsDialogClass {
+       ModestGlobalSettingsDialogClass parent_class;
+};
+
+/* member functions */
+GType        modest_maemo_global_settings_dialog_get_type    (void) G_GNUC_CONST;
+
+GtkWidget*   modest_maemo_global_settings_dialog_new         (void);
+
+G_END_DECLS
+
+#endif /* __MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_H__ */
+
diff --git a/src/hildon2/modest-maemo-security-options-view.c b/src/hildon2/modest-maemo-security-options-view.c
new file mode 100644 (file)
index 0000000..8593897
--- /dev/null
@@ -0,0 +1,488 @@
+/* Copyright (c) 2008, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-runtime.h"
+#include "modest-security-options-view-priv.h"
+#include "modest-maemo-security-options-view.h"
+#include "modest-text-utils.h"
+#include "modest-platform.h"
+#include "modest-account-protocol.h"
+#include "widgets/modest-ui-constants.h"
+#include "widgets/modest-validating-entry.h"
+#include "widgets/modest-serversecurity-combo-box.h"
+#include "widgets/modest-secureauth-combo-box.h"
+#include "maemo/easysetup/modest-easysetup-servertype-combo-box.h"
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+#include <hildon-widgets/hildon-caption.h>
+#include <hildon-widgets/hildon-number-editor.h>
+#else
+#include <hildon/hildon-caption.h>
+#include <hildon/hildon-number-editor.h>
+#endif /*MODEST_HAVE_HILDON0_WIDGETS*/
+
+#define PORT_MIN 1
+#define PORT_MAX 65535
+
+typedef struct _ModestMaemoSecurityOptionsViewPrivate ModestMaemoSecurityOptionsViewPrivate;
+struct _ModestMaemoSecurityOptionsViewPrivate {
+};
+
+#define MODEST_MAEMO_SECURITY_OPTIONS_VIEW_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                    MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW, \
+                                    ModestMaemoSecurityOptionsViewPrivate))
+
+static void modest_maemo_security_options_view_init (ModestMaemoSecurityOptionsView *obj);
+static void modest_maemo_security_options_view_finalize (GObject *obj);
+static void modest_maemo_security_options_view_class_init (ModestMaemoSecurityOptionsViewClass *klass);
+
+G_DEFINE_TYPE (ModestMaemoSecurityOptionsView, 
+              modest_maemo_security_options_view, 
+              MODEST_TYPE_SECURITY_OPTIONS_VIEW);
+
+static void on_entry_changed (GtkEditable *editable, gpointer user_data);
+
+/* Tracks changes in the incoming security combo box */
+static void
+on_security_changed (GtkWidget *widget, 
+                    ModestMaemoSecurityOptionsView *self)
+{
+       ModestSecurityOptionsViewPrivate* ppriv;
+       ModestServersecurityComboBox *combo;
+       ModestProtocolType proto_type;
+       ModestProtocolRegistry *proto_registry;
+       gboolean is_secure;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+
+       proto_registry = modest_runtime_get_protocol_registry ();
+       combo = MODEST_SERVERSECURITY_COMBO_BOX (ppriv->security_view);
+       proto_type = modest_serversecurity_combo_box_get_active_serversecurity (combo);
+
+       is_secure = modest_protocol_registry_protocol_type_has_tag (proto_registry, proto_type, 
+                                                                   MODEST_PROTOCOL_REGISTRY_SECURE_PROTOCOLS);
+
+       if (MODEST_SECURITY_OPTIONS_VIEW (self)->type == MODEST_SECURITY_OPTIONS_INCOMING) {
+               /* Activate and dim checkbutton if it's secure */
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ppriv->auth_view), 
+                                             is_secure);
+               gtk_widget_set_sensitive (ppriv->auth_view, !is_secure);
+       } else {
+
+       }
+
+       if (ppriv->full) {
+               gint port_number = 
+                       modest_serversecurity_combo_box_get_active_serversecurity_port (MODEST_SERVERSECURITY_COMBO_BOX (ppriv->security_view));
+               
+               if(port_number) {
+                       hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (ppriv->port_view), 
+                                                       port_number);
+               }
+       }
+}
+
+static void
+on_auth_changed (GtkWidget *widget, 
+                ModestMaemoSecurityOptionsView *self)
+{
+       ModestSecurityOptionsViewPrivate* ppriv;
+       ModestSecureauthComboBox *combo;
+       ModestProtocolRegistry *protocol_registry;
+       ModestProtocolType auth_proto;
+       gboolean secureauth_used;
+       GtkWidget *user_caption, *pwd_caption;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+       combo = MODEST_SECUREAUTH_COMBO_BOX (ppriv->auth_view);
+
+       auth_proto = modest_secureauth_combo_box_get_active_secureauth (combo);
+       secureauth_used = modest_protocol_registry_protocol_type_is_secure (protocol_registry, 
+                                                                           auth_proto);
+
+       /* Get captions, well dimm the whole widget */
+       user_caption = gtk_widget_get_parent (ppriv->user_entry);
+       pwd_caption = gtk_widget_get_parent (ppriv->pwd_entry);
+       
+       /* Enable / disable */
+       gtk_widget_set_sensitive (user_caption, secureauth_used);
+       gtk_widget_set_sensitive (pwd_caption, secureauth_used);
+
+       /* Check if mandatory data is missing */
+       on_entry_changed (GTK_EDITABLE (ppriv->user_entry), (gpointer) self);
+}
+
+static void
+create_incoming_security (ModestSecurityOptionsView* self,
+                         GtkSizeGroup *size_group)
+{
+       ModestSecurityOptionsViewPrivate *ppriv;
+       GtkWidget *combo_caption, *check_caption, *entry_caption = NULL;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+
+       /* Create widgets for incoming security */
+       ppriv->security_view = GTK_WIDGET (modest_serversecurity_combo_box_new ());
+       combo_caption = hildon_caption_new (size_group, _("mcen_li_emailsetup_secure_connection"),
+                                           ppriv->security_view, NULL, 
+                                           HILDON_CAPTION_OPTIONAL);
+
+       if (ppriv->full) {              
+               ppriv->port_view = GTK_WIDGET (hildon_number_editor_new (PORT_MIN, PORT_MAX));
+               entry_caption = hildon_caption_new (size_group, _("mcen_fi_emailsetup_port"), 
+                                                   ppriv->port_view, NULL, 
+                                                   HILDON_CAPTION_OPTIONAL);
+       }
+
+       ppriv->auth_view = gtk_check_button_new ();
+       check_caption = 
+               hildon_caption_new (size_group, _("mcen_li_emailsetup_secure_authentication"),
+                                   ppriv->auth_view, NULL, HILDON_CAPTION_OPTIONAL);
+
+       /* Track changes in UI */       
+       g_signal_connect (G_OBJECT (ppriv->security_view), "changed",
+                         G_CALLBACK (on_security_changed), self);
+
+       /* Pack into container */
+       gtk_box_pack_start (GTK_BOX (self), combo_caption,
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+       if (ppriv->full)
+               gtk_box_pack_start (GTK_BOX (self), entry_caption, 
+                                   FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_box_pack_start (GTK_BOX (self), check_caption,
+                           FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       /* Show widgets */
+       if (ppriv->full) {
+               gtk_widget_show (ppriv->port_view);
+               gtk_widget_show (entry_caption);
+       }
+       gtk_widget_show (ppriv->security_view);
+       gtk_widget_show (ppriv->auth_view);
+       gtk_widget_show (combo_caption);
+       gtk_widget_show (check_caption);
+}
+
+static void
+on_entry_max (ModestValidatingEntry *self, 
+             gpointer user_data)
+{
+       modest_platform_information_banner (GTK_WIDGET (self), NULL, 
+                                           _CS("ckdg_ib_maximum_characters_reached"));
+}
+
+/*
+ * TODO: call this whenever the auth combo changes. If we set it
+ * explicitely at the beggining to a value then there is no need to
+ * call this handler directly at the beginning
+ */
+static void
+on_entry_changed (GtkEditable *editable, 
+                 gpointer user_data)
+{
+       ModestSecurityOptionsView* self;
+       ModestSecurityOptionsViewPrivate *ppriv;
+       ModestProtocolType auth_proto;
+       ModestSecureauthComboBox *combo;
+       gboolean is_secure, missing;
+       ModestProtocolRegistry *protocol_registry;
+
+       self = MODEST_SECURITY_OPTIONS_VIEW (user_data);
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       /* Outgoing username is mandatory if outgoing auth is secure */
+       combo = MODEST_SECUREAUTH_COMBO_BOX (ppriv->auth_view);
+       auth_proto = modest_secureauth_combo_box_get_active_secureauth (combo);
+       is_secure = modest_protocol_registry_protocol_type_is_secure (protocol_registry, 
+                                                                     auth_proto);
+
+       if (is_secure && 
+           !g_ascii_strcasecmp (gtk_entry_get_text (GTK_ENTRY (ppriv->user_entry)), "")) {
+               missing = TRUE;
+       } else {
+               missing = FALSE;
+       }
+       
+       /* Emit a signal to notify if mandatory data is missing */
+       g_signal_emit_by_name (G_OBJECT (self), "missing_mandatory_data", 
+                              missing, NULL);
+}
+
+static void
+create_outgoing_security (ModestSecurityOptionsView* self,
+                         GtkSizeGroup *size_group)
+{
+       ModestSecurityOptionsViewPrivate *ppriv;
+       GtkWidget *sec_caption, *auth_caption, *user_caption = NULL;
+       GtkWidget *pwd_caption = NULL, *port_caption = NULL;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+       
+       /* The secure connection widgets */
+       ppriv->security_view = GTK_WIDGET (modest_serversecurity_combo_box_new ());
+       modest_serversecurity_combo_box_fill (MODEST_SERVERSECURITY_COMBO_BOX (ppriv->security_view), 
+                                             MODEST_PROTOCOLS_TRANSPORT_SMTP);
+       sec_caption = hildon_caption_new (size_group, _("mcen_li_emailsetup_secure_connection"),
+                                     ppriv->security_view, NULL, HILDON_CAPTION_OPTIONAL);
+       
+       /* The secure authentication widgets */
+       ppriv->auth_view = GTK_WIDGET (modest_secureauth_combo_box_new ());
+       auth_caption = hildon_caption_new (size_group, _("mcen_li_emailsetup_secure_authentication"),
+                                          ppriv->auth_view, NULL, HILDON_CAPTION_OPTIONAL);
+
+       if (ppriv->full) {
+               gchar *user_label;
+
+               /* Username widgets */
+               ppriv->user_entry = GTK_WIDGET (modest_validating_entry_new ());
+
+               /* Auto-capitalization is the default, so let's turn it off: */
+               hildon_gtk_entry_set_input_mode (GTK_ENTRY (ppriv->user_entry), 
+                                                HILDON_GTK_INPUT_MODE_FULL);
+
+               user_label = g_strdup_printf("%s*", _("mail_fi_username"));
+               user_caption = hildon_caption_new (size_group, user_label, 
+                                                  ppriv->user_entry, NULL, 
+                                                  HILDON_CAPTION_MANDATORY);
+               g_free (user_label);
+       
+               /* Prevent the use of some characters. Limit the max
+                  length as well */
+               modest_validating_entry_set_unallowed_characters_whitespace (
+                    MODEST_VALIDATING_ENTRY (ppriv->user_entry));      
+               gtk_entry_set_max_length (GTK_ENTRY (ppriv->user_entry), 64);
+               modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (ppriv->user_entry),
+                                                     on_entry_max, self);
+               
+               /* Password widgets */
+               ppriv->pwd_entry = gtk_entry_new ();
+
+               /* Auto-capitalization is the default, so let's turn it off */
+               hildon_gtk_entry_set_input_mode (GTK_ENTRY (ppriv->pwd_entry),
+                                                HILDON_GTK_INPUT_MODE_FULL | 
+                                                HILDON_GTK_INPUT_MODE_INVISIBLE);
+               gtk_entry_set_visibility (GTK_ENTRY (ppriv->pwd_entry), FALSE);
+
+               pwd_caption = hildon_caption_new (size_group, _("mail_fi_password"), 
+                                                 ppriv->pwd_entry, NULL, 
+                                                 HILDON_CAPTION_OPTIONAL);
+
+               ppriv->port_view = GTK_WIDGET (hildon_number_editor_new (PORT_MIN, PORT_MAX));
+               port_caption = hildon_caption_new (size_group, _("mcen_fi_emailsetup_port"), 
+                                                   ppriv->port_view, NULL, 
+                                                   HILDON_CAPTION_OPTIONAL);
+       }
+
+       /* Track changes in UI */       
+       g_signal_connect (G_OBJECT (ppriv->security_view), "changed",
+                         G_CALLBACK (on_security_changed), self);
+       if (ppriv->full) {
+               g_signal_connect (G_OBJECT (ppriv->auth_view), "changed",
+                                 G_CALLBACK (on_auth_changed), self);
+               g_signal_connect (G_OBJECT (ppriv->user_entry), "changed",
+                                 G_CALLBACK (on_entry_changed), self);
+       }
+
+       /* Initialize widgets */
+       modest_serversecurity_combo_box_set_active_serversecurity (
+               MODEST_SERVERSECURITY_COMBO_BOX (ppriv->security_view), 
+               MODEST_PROTOCOLS_CONNECTION_NONE);
+       modest_secureauth_combo_box_set_active_secureauth (
+          MODEST_SECUREAUTH_COMBO_BOX (ppriv->auth_view),
+          MODEST_PROTOCOLS_AUTH_NONE);
+
+       /* Pack into container */
+       if (ppriv->full) {
+               gtk_box_pack_start (GTK_BOX (self), auth_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+               gtk_box_pack_start (GTK_BOX (self), user_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+               gtk_box_pack_start (GTK_BOX (self), pwd_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+               gtk_box_pack_start (GTK_BOX (self), sec_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+               gtk_box_pack_start (GTK_BOX (self), port_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       } else {
+               /* The order is different */
+               gtk_box_pack_start (GTK_BOX (self), sec_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+               gtk_box_pack_start (GTK_BOX (self), auth_caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+       }
+
+       /* Show widgets */
+       if (ppriv->full) {
+               gtk_widget_show (ppriv->pwd_entry);
+               gtk_widget_show (ppriv->user_entry);
+               gtk_widget_show (ppriv->port_view);
+               gtk_widget_show (pwd_caption);
+               gtk_widget_show (user_caption);
+               gtk_widget_show (port_caption);
+       }
+       gtk_widget_show (ppriv->security_view);
+       gtk_widget_show (ppriv->auth_view);
+       gtk_widget_show (sec_caption);
+       gtk_widget_show (auth_caption);
+}
+
+GtkWidget *    
+modest_maemo_security_options_view_new  (ModestSecurityOptionsType type,
+                                        gboolean full,
+                                        GtkSizeGroup *size_group)
+{
+       ModestSecurityOptionsView* self;
+       ModestSecurityOptionsViewPrivate *ppriv;
+
+       self = (ModestSecurityOptionsView *)
+               g_object_new (MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW, NULL);
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+
+       ppriv->full = full;
+       self->type = type;
+       if (self->type == MODEST_SECURITY_OPTIONS_INCOMING)
+               create_incoming_security (self, size_group);
+       else
+               create_outgoing_security (self, size_group);
+
+       return (GtkWidget *) self;
+}
+
+static void 
+modest_maemo_security_options_view_load_settings (ModestSecurityOptionsView* self, 
+                                                 ModestAccountSettings *settings)
+{
+       ModestSecurityOptionsViewPrivate *ppriv;
+       ModestServerAccountSettings *server_settings;
+       gint port_number;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+
+       if (self->type == MODEST_SECURITY_OPTIONS_INCOMING)
+               server_settings = modest_account_settings_get_store_settings (settings);
+       else
+               server_settings = modest_account_settings_get_transport_settings (settings);
+       port_number = modest_server_account_settings_get_port (server_settings);
+
+       if (port_number == 0) {
+               /* Show the appropriate port number */
+               on_security_changed (ppriv->security_view, 
+                                    MODEST_MAEMO_SECURITY_OPTIONS_VIEW (self));
+       } else if (ppriv->full) {
+               /* Keep the user-entered port-number, or the
+                * already-appropriate automatic port number */
+               hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (ppriv->port_view), 
+                                               port_number);
+       }
+       /* Frees */
+       g_object_unref (server_settings);
+}
+
+static void
+modest_maemo_security_options_view_save_settings (ModestSecurityOptionsView* self, 
+                                                 ModestAccountSettings *settings)
+{
+       ModestServerAccountSettings *server_settings;
+       ModestSecurityOptionsViewPrivate *ppriv;
+       gint server_port;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+
+       if (self->type == MODEST_SECURITY_OPTIONS_INCOMING)
+               server_settings = modest_account_settings_get_store_settings (settings);
+       else
+               server_settings = modest_account_settings_get_transport_settings (settings);
+
+       if (ppriv->full) {
+               server_port = hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (ppriv->port_view));
+       } else {
+               server_port = modest_serversecurity_combo_box_get_active_serversecurity_port (MODEST_SERVERSECURITY_COMBO_BOX (ppriv->security_view));
+       }
+
+       modest_server_account_settings_set_port (server_settings, server_port);
+
+       /* Frees */
+       g_object_unref (server_settings);
+}
+
+static gboolean 
+modest_maemo_security_options_view_changed (ModestSecurityOptionsView* self,
+                                           ModestAccountSettings *settings)
+{
+       ModestServerAccountSettings *server_settings;
+       ModestSecurityOptionsViewPrivate *ppriv;
+       gint server_port;
+
+       ppriv = MODEST_SECURITY_OPTIONS_VIEW_GET_PRIVATE (self);
+       
+       /* If we're not showing the port number then it never changes */
+       if (!ppriv->full)
+               return FALSE;
+
+       if (self->type == MODEST_SECURITY_OPTIONS_INCOMING)
+               server_settings = modest_account_settings_get_store_settings (settings);
+       else
+               server_settings = modest_account_settings_get_transport_settings (settings);
+       
+       server_port = 
+               hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (ppriv->port_view));
+
+       /* Frees */
+       g_object_unref (server_settings);
+
+       if (server_port != ppriv->initial_state.port)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+static void
+modest_maemo_security_options_view_init (ModestMaemoSecurityOptionsView *obj)
+{
+}
+
+static void
+modest_maemo_security_options_view_finalize (GObject *obj)
+{
+       G_OBJECT_CLASS (modest_maemo_security_options_view_parent_class)->finalize (obj);
+}
+
+
+static void     
+modest_maemo_security_options_view_class_init (ModestMaemoSecurityOptionsViewClass *klass)
+{
+       GObjectClass *gobject_class = (GObjectClass*) klass;
+
+       modest_maemo_security_options_view_parent_class = g_type_class_peek_parent (klass);
+
+       g_type_class_add_private (gobject_class, sizeof (ModestMaemoSecurityOptionsViewPrivate));
+       gobject_class->finalize = modest_maemo_security_options_view_finalize;
+
+       MODEST_SECURITY_OPTIONS_VIEW_CLASS (klass)->load_settings = 
+               modest_maemo_security_options_view_load_settings;
+       MODEST_SECURITY_OPTIONS_VIEW_CLASS (klass)->save_settings = 
+               modest_maemo_security_options_view_save_settings;
+       MODEST_SECURITY_OPTIONS_VIEW_CLASS (klass)->changed = 
+               modest_maemo_security_options_view_changed;
+}
diff --git a/src/hildon2/modest-maemo-security-options-view.h b/src/hildon2/modest-maemo-security-options-view.h
new file mode 100644 (file)
index 0000000..9511c5c
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2008, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAEMO_SECURITY_OPTIONS_VIEW_H__
+#define __MODEST_MAEMO_SECURITY_OPTIONS_VIEW_H__
+
+#include <glib-object.h>
+#include "modest-security-options-view.h"
+#include <gtk/gtkbox.h>
+#include <gtk/gtksizegroup.h>
+
+G_BEGIN_DECLS
+
+/* convenience macros */
+#define MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW             (modest_maemo_security_options_view_get_type())
+#define MODEST_MAEMO_SECURITY_OPTIONS_VIEW(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW,ModestMaemoSecurityOptionsView))
+#define MODEST_MAEMO_SECURITY_OPTIONS_VIEW_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW,GObject))
+#define MODEST_IS_MAEMO_SECURITY_OPTIONS_VIEW(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW))
+#define MODEST_IS_MAEMO_SECURITY_OPTIONS_VIEW_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW))
+#define MODEST_MAEMO_SECURITY_OPTIONS_VIEW_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_MAEMO_SECURITY_OPTIONS_VIEW,ModestMaemoSecurityOptionsViewClass))
+
+typedef struct _ModestMaemoSecurityOptionsView      ModestMaemoSecurityOptionsView;
+typedef struct _ModestMaemoSecurityOptionsViewClass ModestMaemoSecurityOptionsViewClass;
+
+struct _ModestMaemoSecurityOptionsView {
+        ModestSecurityOptionsView parent;
+};
+
+struct _ModestMaemoSecurityOptionsViewClass {
+       ModestSecurityOptionsViewClass parent_class;
+};
+
+/* member functions */
+GType        modest_maemo_security_options_view_get_type    (void) G_GNUC_CONST;
+
+GtkWidget* modest_maemo_security_options_view_new (ModestSecurityOptionsType type,
+                                                  gboolean full,
+                                                  GtkSizeGroup *size_group);
+
+G_END_DECLS
+
+#endif /* __MODEST_MAEMO_SECURITY_OPTIONS_VIEW_H__ */
+
diff --git a/src/hildon2/modest-maemo-utils.c b/src/hildon2/modest-maemo-utils.c
new file mode 100644 (file)
index 0000000..d1a10c7
--- /dev/null
@@ -0,0 +1,290 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DBUS_API_SUBJECT_TO_CHANGE
+#define DBUS_API_SUBJECT_TO_CHANGE
+#endif /*DBUS_API_SUBJECT_TO_CHANGE*/
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <string.h> /* for strlen */
+#include <modest-runtime.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <tny-fs-stream.h>
+#include <tny-camel-account.h>
+#include <tny-status.h>
+#include <tny-camel-transport-account.h>
+#include <tny-camel-imap-store-account.h>
+#include <tny-camel-pop-store-account.h>
+#include "modest-hildon-includes.h"
+
+#include <modest-defs.h>
+#include "modest-maemo-utils.h"
+#include "modest-text-utils.h"
+#include "modest-platform.h"
+
+/*
+ * For getting and tracking the Bluetooth name
+ */
+#define BTNAME_SERVICE                  "org.bluez"
+#define BTNAME_REQUEST_IF               "org.bluez.Adapter"
+#define BTNAME_SIGNAL_IF                "org.bluez.Adapter"
+#define BTNAME_REQUEST_PATH             "/org/bluez/hci0"
+#define BTNAME_SIGNAL_PATH              "/org/bluez/hci0"
+
+#define BTNAME_REQ_GET                  "GetName"
+#define BTNAME_SIG_CHANGED              "NameChanged"
+
+#define BTNAME_MATCH_RULE "type='signal',interface='" BTNAME_SIGNAL_IF \
+                          "',member='" BTNAME_SIG_CHANGED "'"
+
+
+static osso_context_t *__osso_context = NULL; /* urgh global */
+
+osso_context_t *
+modest_maemo_utils_get_osso_context (void)
+{
+       if (!__osso_context) 
+               g_warning ("%s: __osso_context == NULL", __FUNCTION__);
+       
+       return __osso_context;
+}
+
+void
+modest_maemo_utils_set_osso_context (osso_context_t *osso_context)
+{
+       g_return_if_fail (osso_context);
+       __osso_context = osso_context;
+}
+
+static void
+update_device_name_from_msg (DBusMessage *message)
+{
+       DBusError error;
+       DBusMessageIter iter;
+
+       dbus_error_init (&error);
+
+       if (dbus_set_error_from_message (&error, message)) {
+               g_printerr ("modest: failed to get bluetooth name: %s\n", error.message);
+               dbus_error_free (&error);
+       } else {
+               const gchar *device_name;
+               if (!dbus_message_iter_init (message, &iter)) {
+                       g_printerr ("modest: message did not have argument\n");
+                       return;
+               }
+               dbus_message_iter_get_basic (&iter, &device_name);
+               modest_conf_set_string (modest_runtime_get_conf(),
+                                       MODEST_CONF_DEVICE_NAME, device_name,
+                                       NULL);
+       }
+}
+
+
+static void
+on_device_name_received (DBusPendingCall *call, void *user_data)
+{
+       DBusMessage *message;
+       
+       g_return_if_fail (dbus_pending_call_get_completed (call));
+       
+       message = dbus_pending_call_steal_reply (call);
+       if (!message) {
+               g_printerr ("modest: no reply on device name query\n");
+               return;
+       }
+
+       update_device_name_from_msg (message);
+       dbus_message_unref (message);
+}
+
+
+static DBusHandlerResult
+handle_dbus_signal (DBusConnection *conn, DBusMessage *msg, gpointer data)
+{
+       if (dbus_message_is_signal(msg, BTNAME_SIGNAL_IF, BTNAME_SIG_CHANGED))
+               update_device_name_from_msg (msg);
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static void
+get_device_name_from_dbus ()
+{
+       static DBusConnection *conn = NULL;
+       DBusMessage *request;
+       DBusError error;
+       DBusPendingCall *call = NULL;
+       
+       dbus_error_init (&error);
+       if (!conn) {
+               conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+               if (!conn) {
+                       g_printerr ("modest: cannot get on the dbus: %s: %s\n",
+                                   error.name, error.message);
+                       dbus_error_free (&error);
+                       return;
+               }
+       }
+       
+       request = dbus_message_new_method_call (BTNAME_SERVICE, BTNAME_REQUEST_PATH,
+                                               BTNAME_REQUEST_IF, BTNAME_REQ_GET);
+       if (!request) {
+               /* should we free the connection? */
+               g_printerr ("modest: dbus_message_new_method_call failed\n");
+               return;
+       }
+       dbus_message_set_auto_start (request, TRUE);
+       if (dbus_connection_send_with_reply (conn, request, &call, -1)) {
+               dbus_pending_call_set_notify (call, on_device_name_received,
+                                             NULL, NULL);
+               dbus_pending_call_unref (call);
+       }
+       dbus_message_unref (request);
+       
+       dbus_connection_setup_with_g_main (conn, NULL);
+       dbus_bus_add_match (conn, BTNAME_MATCH_RULE, &error);
+       if (dbus_error_is_set(&error)) {
+               g_printerr ("modest: dbus_bus_add_match failed: %s\n", error.message);
+               dbus_error_free (&error);
+       }
+
+       if (!dbus_connection_add_filter(conn, handle_dbus_signal, NULL, NULL))
+               g_printerr ("modest: dbus_connection_add_filter failed\n");
+}
+
+
+void
+modest_maemo_utils_get_device_name (void)
+{
+       get_device_name_from_dbus ();
+}
+
+void
+modest_maemo_utils_setup_images_filechooser (GtkFileChooser *chooser)
+{
+       gchar *images_folder;
+       GtkFileFilter *file_filter;
+       GList *image_mimetypes_list;
+       GList *node;
+
+       g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
+
+       /* Set the default folder to images folder */
+       images_folder = g_build_filename (g_get_home_dir (), 
+                                         MODEST_MAEMO_UTILS_MYDOCS_FOLDER,
+                                         MODEST_MAEMO_UTILS_DEFAULT_IMAGE_FOLDER, NULL);
+       gtk_file_chooser_set_current_folder (chooser, images_folder);
+       g_free (images_folder);
+
+       /* Set the images mime filter */
+       file_filter = gtk_file_filter_new ();
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+       image_mimetypes_list = osso_mime_get_mime_types_for_category (OSSO_MIME_CATEGORY_IMAGES);
+#else
+       image_mimetypes_list = hildon_mime_get_mime_types_for_category (HILDON_MIME_CATEGORY_IMAGES);
+#endif
+       for (node = image_mimetypes_list; node != NULL; node = g_list_next (node)) {
+               gtk_file_filter_add_mime_type (file_filter, node->data);
+       }
+       gtk_file_chooser_set_filter (chooser, file_filter);
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+       osso_mime_types_list_free (image_mimetypes_list);
+#else
+       hildon_mime_types_list_free (image_mimetypes_list);
+#endif
+
+}
+
+void
+modest_maemo_set_thumbable_scrollbar (GtkScrolledWindow *win, 
+                                     gboolean thumbable)
+{
+       g_return_if_fail (GTK_IS_SCROLLED_WINDOW(win));
+#ifdef MODEST_HAVE_HILDON1_WIDGETS             
+       hildon_helper_set_thumb_scrollbar (win, thumbable);
+#endif /* MODEST_HAVE_HILDON1_WIDGETS */
+}
+
+FILE*
+modest_maemo_open_mcc_mapping_file (void)
+{
+       FILE* result;
+       
+       const gchar* path;
+       const gchar* path1 = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
+       const gchar* path2 = MODEST_MCC_MAPPING;
+       
+       if (access(path1, R_OK) == 0) 
+               path = path1;
+       else if (access(path2, R_OK) == 0)
+               path = path2;
+       else {
+               g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
+                          __FUNCTION__, path1, path2);
+               return NULL;
+       }
+       
+       result = fopen (path, "r");
+       if (!result) {
+               g_warning ("%s: error opening mapping file '%s': %s",
+                          __FUNCTION__, path, strerror(errno));
+               return NULL;
+       }
+       return result;
+}
+
+GtkWidget *
+modest_maemo_utils_get_manager_menubar_as_menu (GtkUIManager *manager,
+                                               const gchar *item_name)
+{
+       GtkWidget *new_menu;
+       GtkWidget *menubar;
+       GList *children, *iter;
+
+       menubar = gtk_ui_manager_get_widget (manager, item_name);
+       new_menu = gtk_menu_new ();
+
+       children = gtk_container_get_children (GTK_CONTAINER (menubar));
+       for (iter = children; iter != NULL; iter = g_list_next (iter)) {
+               GtkWidget *menu;
+
+               menu = GTK_WIDGET (iter->data);
+               gtk_widget_reparent (menu, new_menu);
+       }
+       
+       g_list_free (children);
+
+       return new_menu;
+}
diff --git a/src/hildon2/modest-maemo-utils.h b/src/hildon2/modest-maemo-utils.h
new file mode 100644 (file)
index 0000000..c9b889b
--- /dev/null
@@ -0,0 +1,126 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MODEST_MAEMO_UTILS_H__
+#define __MODEST_MAEMO_UTILS_H__
+
+#include <gtk/gtk.h>
+#include <stdio.h> /* for FILE* */
+#include <tny-fs-stream.h>
+#include <libosso.h>
+#include "widgets/modest-global-settings-dialog.h"
+#include "widgets/modest-validating-entry.h"
+
+#define MODEST_MAEMO_UTILS_MYDOCS_FOLDER "MyDocs"
+#define MODEST_MAEMO_UTILS_DEFAULT_IMAGE_FOLDER ".images"
+
+
+/**
+ * modest_maemo_utils_get_device_name
+ *
+ * get the name for this device. Note: this queries the bluetooth
+ * name over DBUS, and may block. The result will be available in
+ * MODEST_CONF_DEVICE_NAME in ModestConf; it will be updated when it
+ * changes
+ * 
+ */
+void modest_maemo_utils_get_device_name (void);
+
+
+/**
+ * modest_maemo_utils_setup_images_filechooser:
+ * @chooser: a #GtkFileChooser
+ *
+ * Configures the default folder, and mime filter of a filechooser
+ * for images.
+ */
+void modest_maemo_utils_setup_images_filechooser (GtkFileChooser *chooser);
+
+
+/**
+ * modest_maemo_utils_get_osso_context:
+ *
+ * get the osso_context pointer for this application
+ * 
+ * Return: the osso context pointer 
+ */
+osso_context_t *modest_maemo_utils_get_osso_context (void);
+
+/**
+ * modest_maemo_open_mcc_mapping_file:
+ *
+ * open the mcc mapping file, or NULL if it fails
+ *
+ * Returns: file ptr or NULL in case of error
+ */
+FILE* modest_maemo_open_mcc_mapping_file (void);
+
+/**
+ * modest_maemo_set_thumbable_scrollbar:
+ * @win: a scrollable window
+ * @thumbable: set it to thumbable (TRUE) or small (FALSE)
+ *
+ * changes the thumbability of scrollbars in a scrollable window
+ */
+void modest_maemo_set_thumbable_scrollbar (GtkScrolledWindow *win, gboolean thumbable);
+
+
+/**
+ * modest_maemo_get_osso_context:
+ *
+ * retrieve the osso context for this application
+ * 
+ * Returns: the current osso_context_t ptr  
+ */
+osso_context_t* modest_maemo_utils_get_osso_context (void);
+
+/**
+ * modest_maemo_set_osso_context:
+ *
+ * remember the osso-context for this application 
+ * 
+ * @osso_context: a valid osso_context_t pointer
+ *  
+ */
+void modest_maemo_utils_set_osso_context (osso_context_t *osso_context);
+
+/**
+ * modest_maemo_utils_get_manager_menubar_as_menu:
+ * @manager: a #GtkUIManager
+ * @item_name: a string
+ *
+ * obtains the node with name @item_name in @manager (which happens to be a menubar) as a
+ * #GtkMenu.
+ *
+ * Returns: a #GtkMenu
+ */
+GtkWidget *modest_maemo_utils_get_manager_menubar_as_menu (GtkUIManager *manager, const gchar *item_name);
+
+#endif /*__MODEST_MAEMO_UTILS_H__*/
diff --git a/src/hildon2/modest-main-window-ui-dimming.h b/src/hildon2/modest-main-window-ui-dimming.h
new file mode 100644 (file)
index 0000000..eb3a8ab
--- /dev/null
@@ -0,0 +1,128 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MODEST_MAIN_WINDOW_UI_DIMMING_PRIV_H__
+#define __MODEST_MAIN_WINDOW_UI_DIMMING_PRIV_H__
+
+#include "modest-dimming-rules-group.h"
+#include "modest-ui-dimming-rules.h"
+
+G_BEGIN_DECLS
+
+
+/* Menu Dimming rules entries */
+static const ModestDimmingEntry modest_main_window_menu_dimming_entries [] = {
+
+       /* Email Menu */
+       { "/MenuBar/EmailMenu/EmailNewMainMenu", NULL },
+       { "/MenuBar/EmailMenu/EmailNewMainMenu/EmailNewMessageMenu", G_CALLBACK(modest_ui_dimming_rules_on_new_msg) },
+       { "/MenuBar/EmailMenu/EmailNewMainMenu/EmailNewFolderMenu", G_CALLBACK(modest_ui_dimming_rules_on_new_folder) },
+       { "/MenuBar/EmailMenu/EmailOpenMenu", G_CALLBACK(modest_ui_dimming_rules_on_open_msg) },
+       { "/MenuBar/EmailMenu/EmailReplyMenu", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/EmailMenu/EmailReplyAllMenu", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/EmailMenu/EmailForwardMenu",  G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/EmailMenu/EmailContentsMenu", G_CALLBACK(modest_ui_dimming_rules_on_contents_msg) },
+       { "/MenuBar/EmailMenu/EmailPurgeAttachmentsMenu", G_CALLBACK(modest_ui_dimming_rules_on_remove_attachments) },
+       { "/MenuBar/EmailMenu/EmailRenameMenu",  G_CALLBACK(modest_ui_dimming_rules_on_rename_folder) },
+       { "/MenuBar/EmailMenu/EmailDeleteMenu",  G_CALLBACK(modest_ui_dimming_rules_on_delete) },
+       { "/MenuBar/EmailMenu/EmailDetailsMenu", G_CALLBACK(modest_ui_dimming_rules_on_details) },
+
+       /* Edit Menu */
+       { "/MenuBar/EditMenu", NULL },
+       { "/MenuBar/EditMenu/EditSelectAllMenu", G_CALLBACK(modest_ui_dimming_rules_on_select_all)},
+       { "/MenuBar/EditMenu/EditMarkAsReadMenu", G_CALLBACK(modest_ui_dimming_rules_on_mark_as_read_msg) },
+       { "/MenuBar/EditMenu/EditMarkAsUnreadMenu", G_CALLBACK(modest_ui_dimming_rules_on_mark_as_unread_msg) },
+       { "/MenuBar/EditMenu/EditMoveToMenu", G_CALLBACK(modest_ui_dimming_rules_on_move_to) },
+
+       /* View Menu */
+       { "/MenuBar/ViewMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewSortMenu", G_CALLBACK(modest_ui_dimming_rules_on_sort) },
+       { "/MenuBar/ViewMenu/ViewToggleFoldersMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewToggleFullscreenMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewShowToolbarMainMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu", NULL },
+       
+       /* Tools Menu */
+       { "/MenuBar/ToolsMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsSettingsMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsAccountsMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsSMTPServersMenu", G_CALLBACK(modest_ui_dimming_rules_on_tools_smtp_servers) },
+       { "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu", G_CALLBACK(modest_ui_dimming_rules_on_send_receive_all) },
+       { "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu", G_CALLBACK(modest_ui_dimming_rules_on_cancel_sending) },
+       { "/MenuBar/ToolsMenu/ToolsContactsMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsSearchMessagesMenu", NULL },
+       { "/MenuBar/ToolsMenu/ToolsHelpMenu", NULL },
+
+       /* Close Menu */
+       { "/MenuBar/CloseMenu", NULL },
+       { "/MenuBar/ToolsMenu/CloseWindowMenu", NULL },
+       { "/MenuBar/ToolsMenu/CloseAllWindowsMenu", NULL },
+
+       /* Contextual Menus (Header View) */
+       { "/HeaderViewCSM/HeaderViewCSMOpen", G_CALLBACK(modest_ui_dimming_rules_on_open_msg) },
+       { "/HeaderViewCSM/HeaderViewCSMReply", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/HeaderViewCSM/HeaderViewCSMReplyAll", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/HeaderViewCSM/HeaderViewCSMForward", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/HeaderViewCSM/HeaderViewCSMDelete", G_CALLBACK(modest_ui_dimming_rules_on_delete_msg) },
+       { "/HeaderViewCSM/HeaderViewCSMCancelSending", G_CALLBACK(modest_ui_dimming_rules_on_cancel_sending) },
+       { "/HeaderViewCSM/HeaderViewCSMHelp", NULL },
+
+       /* Contextual Menus (Folder View) */
+       { "/FolderViewCSM/FolderViewCSMNewFolder", G_CALLBACK(modest_ui_dimming_rules_on_new_folder) },
+       { "/FolderViewCSM/FolderViewCSMRenameFolder", G_CALLBACK(modest_ui_dimming_rules_on_rename_folder) },
+       { "/FolderViewCSM/FolderViewCSMPasteMsgs", G_CALLBACK(modest_ui_dimming_rules_on_paste) },
+       { "/FolderViewCSM/FolderViewCSMDeleteFolder", G_CALLBACK(modest_ui_dimming_rules_on_delete_folder) },
+       { "/FolderViewCSM/FolderViewCSMSearchMessages", NULL },
+       { "/FolderViewCSM/FolderViewCSMHelp", NULL },
+
+       /* Contextual Menus (Toolbar) */
+       { "/ToolbarReplyCSM/ToolbarMessageForward", NULL },
+       { "/ToolbarReplyCSM/ToolbarMessageReplyAll", NULL },
+       { "/ToolbarReplyCSM/ToolbarMessageReply", NULL },
+       
+};
+
+/* Toolbar Dimming rules entries */
+static const ModestDimmingEntry modest_main_window_toolbar_dimming_entries [] = {
+
+       /* Toolbar */
+       { "/ToolBar/ToolbarMessageNew", G_CALLBACK(modest_ui_dimming_rules_on_new_msg) },
+       { "/ToolBar/ToolbarMessageReply", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/ToolBar/ToolbarDeleteMessage", G_CALLBACK(modest_ui_dimming_rules_on_delete) },
+       { "/ToolBar/ToolbarToggleView", NULL },
+       { "/ToolBar/ToolbarSort", G_CALLBACK(modest_ui_dimming_rules_on_sort) },
+       { "/ToolBar/ToolbarSendReceive", G_CALLBACK(modest_ui_dimming_rules_on_send_receive) },
+       { "/ToolBar/ToolbarCancel", NULL },
+};
+
+G_END_DECLS
+#endif /* __MODEST_MAIN_WINDOW_UI_PRIV_H__ */
diff --git a/src/hildon2/modest-main-window-ui.h b/src/hildon2/modest-main-window-ui.h
new file mode 100644 (file)
index 0000000..9bbe466
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAIN_WINDOW_UI_PRIV_H__
+#define __MODEST_MAIN_WINDOW_UI_PRIV_H__
+
+#include <glib/gi18n.h>
+
+#include "modest-icon-names.h"
+#include "modest-ui-actions.h"
+
+G_BEGIN_DECLS
+
+
+/* Action entries */
+static const GtkActionEntry modest_action_entries [] = {
+
+       /* Toplevel menus */
+       { "Email",       NULL, N_("mcen_me_inbox_email"),        NULL, NULL, G_CALLBACK (modest_ui_actions_on_email_menu_activated) },
+       { "Edit",        NULL, N_("mcen_me_inbox_edit"),         NULL, NULL, G_CALLBACK (modest_ui_actions_on_edit_menu_activated) },
+       { "View",        NULL, N_("mcen_me_inbox_view"),         NULL, NULL, G_CALLBACK (modest_ui_actions_on_view_menu_activated) },
+       { "Tools",       NULL, N_("mcen_me_inbox_tools"),        NULL, NULL, G_CALLBACK (modest_ui_actions_on_tools_menu_activated) },
+       { "Attachments", NULL, N_("mcen_me_viewer_attachments"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_attachment_menu_activated) },
+       { "Close",       NULL, N_("mcen_me_inbox_close") },
+       { "Zoom",        NULL, N_("mcen_me_viewer_zoom") },
+
+       /* Zoom and fullscreen keyboard actions*/
+       { "ZoomPlus", NULL, N_("Zoom +"), "F7", NULL, G_CALLBACK (modest_ui_actions_on_zoom_plus) },
+       { "ZoomMinus", NULL, N_("Zoom -"), "F8", NULL, G_CALLBACK (modest_ui_actions_on_zoom_minus) },
+       { "ToggleFullscreen", NULL, N_("mcen_me_inbox_fullscreen"), "F6", NULL, G_CALLBACK (modest_ui_actions_on_change_fullscreen) },
+
+       /* Email */
+       { "EmailNew", NULL, N_("mcen_me_inbox_new") }, /* submenu */
+       { "EmailNewMessage",  NULL,  N_("mcen_me_inbox_message"),      "<CTRL>N", NULL,   G_CALLBACK (modest_ui_actions_on_new_msg) },
+       { "EmailNewDefault", NULL, N_("mcen_me_viewer_newemail"), "<CTRL>N", NULL, G_CALLBACK (modest_ui_actions_on_new_msg) },
+       { "EmailNewFolder",   NULL,  N_("mcen_me_inbox_folder"),       NULL,      NULL,   G_CALLBACK (modest_ui_actions_on_new_folder) },
+       { "EmailOpen",        NULL,  N_("mcen_me_inbox_open"),          "<CTRL>O", NULL,   G_CALLBACK (modest_ui_actions_on_open) },
+       { "EmailReply",       NULL,  N_("mcen_me_inbox_reply"),         "<CTRL>R",      NULL,   G_CALLBACK (modest_ui_actions_on_reply) },
+       { "EmailReplyAll",    NULL,  N_("mcen_me_inbox_replytoall"),      NULL,      NULL,   G_CALLBACK (modest_ui_actions_on_reply_all) },
+       { "EmailForward",     NULL,  N_("mcen_me_inbox_forward"),      "<CTRL>D",      NULL,   G_CALLBACK (modest_ui_actions_on_forward) },
+       { "EmailRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
+       { "EmailDelete",      NULL,  N_("mcen_me_inbox_delete"),    "BackSpace",      NULL,   G_CALLBACK (modest_ui_actions_on_delete_message_or_folder) },
+       { "EmailContents",    NULL,  N_("mcen_me_inbox_retrieve_contents"), NULL,      NULL,   G_CALLBACK (modest_ui_actions_on_retrieve_msg_contents) },
+       { "EmailDetails",     NULL,  N_("mcen_me_inbox_messagedetails"),        NULL,      NULL,   G_CALLBACK (modest_ui_actions_on_details) },
+       { "EmailPurgeAttachments", NULL, N_("mcen_me_inbox_remove_attachments"), NULL,  NULL,   G_CALLBACK (modest_ui_actions_remove_attachments) },
+       
+
+       /* Edit */
+       { "EditCut",         NULL,      N_("mcen_me_inbox_cut"),          "<CTRL>X",    NULL, G_CALLBACK (modest_ui_actions_on_cut) },
+       { "EditCopy",        NULL,      N_("mcen_me_inbox_copy"),         "<CTRL>C",    NULL, G_CALLBACK (modest_ui_actions_on_copy) },
+       { "EditPaste",       NULL,      N_("mcen_me_inbox_paste"),        "<CTRL>V",    NULL, G_CALLBACK (modest_ui_actions_on_paste) },
+       { "EditSelectAll",   NULL,      N_("mcen_me_viewer_selectall"),    "<CTRL>A",        NULL, G_CALLBACK (modest_ui_actions_on_select_all) },
+       { "EditMarkAsRead", NULL,      N_("mcen_me_inbox_mark_as_read"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_mark_as_read) },
+       { "EditMarkAsUnread", NULL,      N_("mcen_me_inbox_mark_as_unread"),       NULL,          NULL, G_CALLBACK (modest_ui_actions_on_mark_as_unread) },
+       { "EditMoveTo",      NULL,      N_("mcen_me_inbox_moveto"),    NULL,      NULL, G_CALLBACK (modest_ui_actions_on_move_to) },
+       
+       /* View */
+       { "ViewSort",            NULL,        N_("mcen_me_inbox_sort"),     NULL,      NULL,  G_CALLBACK (modest_ui_actions_on_sort) },
+       { "ViewShowToolbar", NULL, N_("mcen_me_inbox_toolbar") }, /* submenu */
+       { "ViewPreviousMessage", NULL,    N_("mcen_me_viewer_previousmessage"),         NULL, NULL, G_CALLBACK (modest_ui_actions_on_prev) },
+       { "ViewNextMessage", NULL, N_("mcen_me_viewer_nextmessage"),      NULL, NULL, G_CALLBACK (modest_ui_actions_on_next) },
+
+       /* Attachments */
+       { "ViewAttachment", NULL, N_("mcen_me_viewer_view_attachment"), NULL, NULL, G_CALLBACK (modest_ui_actions_view_attachment) },
+       { "SaveAttachment", NULL, N_("mcen_me_viewer_save_attachments"), NULL, NULL, G_CALLBACK (modest_ui_actions_save_attachments) },
+       { "RemoveAttachment", NULL, N_("mcen_me_inbox_remove_attachments"), NULL, NULL, G_CALLBACK (modest_ui_actions_remove_attachments) },
+       
+       /* Tools */
+       { "ToolsSettings",        NULL,      N_("mcen_me_inbox_options"),                     NULL, NULL, G_CALLBACK (modest_ui_actions_on_settings) },
+       { "ToolsAccounts",        NULL,      N_("mcen_me_inbox_accounts"),                NULL, NULL,  G_CALLBACK(modest_ui_actions_on_accounts) },
+       { "ToolsSMTPServers",     NULL,      N_("mcen_me_inbox_globalsmtpservers"),                NULL, NULL,  G_CALLBACK(modest_ui_actions_on_smtp_servers) },
+       { "ToolsSendReceive", NULL, N_("mcen_me_inbox_sendandreceive") }, /* submenu */
+       { "ToolsSendReceiveAll",    NULL,      N_("mcen_me_inbox_sendandreceive_all"),          NULL, NULL, G_CALLBACK (modest_ui_actions_on_send_receive) },
+       { "ToolsSendReceiveCancelSending",  NULL,      N_("mcen_me_outbox_cancelsend"),        NULL, NULL,  G_CALLBACK (modest_ui_actions_cancel_send) },
+       { "ToolsContacts",            NULL,      N_("mcen_me_inbox_open_addressbook"),                      NULL, NULL,  G_CALLBACK (modest_ui_actions_on_open_addressbook) },
+       { "ToolsAddToContacts",            NULL,      N_("mcen_me_viewer_addtocontacts"),                      NULL, NULL,  G_CALLBACK (modest_ui_actions_on_add_to_contacts) },
+       { "ToolsSearchMessages",            NULL,      N_("mcen_me_inbox_search"),  "<CTRL>E", NULL,  G_CALLBACK (modest_ui_actions_on_search_messages) },
+       { "ToolsHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
+
+       /* Close */
+       { "CloseWindow",          NULL,     N_("mcen_me_inbox_close_window"), "<CTRL>W", NULL,  G_CALLBACK (modest_ui_actions_on_close_window) },
+       { "CloseAllWindows",      NULL,     N_("mcen_me_inbox_close_windows"), "<CTRL>Q", NULL,  G_CALLBACK (modest_ui_actions_on_quit) },
+
+
+       /* Toolbar items; they is some overlap with the menu items,
+        * but we need to specificy them differently, they have icons for example
+        */
+       /* Headers Toolbar */
+       { "ToolbarMessageNew",        MODEST_STOCK_NEW_MAIL,     N_("qgn_toolb_messagin_new"), NULL, NULL,  G_CALLBACK (modest_ui_actions_on_new_msg) },
+       { "ToolbarMessageReply",      MODEST_STOCK_REPLY,     N_("mcen_me_inbox_reply"),      "<CTRL>R", NULL,  G_CALLBACK (modest_ui_actions_on_reply) },
+       { "ToolbarMessageReplyAll",   MODEST_STOCK_REPLY_ALL,     N_("mcen_me_inbox_replytoall"),         NULL, NULL,  G_CALLBACK (modest_ui_actions_on_reply_all) },
+       { "ToolbarMessageForward",    MODEST_STOCK_FORWARD,     N_("mcen_me_inbox_forward"),      NULL, NULL,  G_CALLBACK (modest_ui_actions_on_forward) },
+       { "ToolbarSendReceive",       MODEST_STOCK_REFRESH,   N_("qgn_toolb_gene_refresh"),      NULL, NULL,  G_CALLBACK (modest_ui_actions_on_send_receive) },
+       { "ToolbarDeleteMessage",     MODEST_STOCK_DELETE,     N_("qgn_toolb_gene_deletebutton"),             NULL, NULL,  G_CALLBACK (modest_ui_actions_on_delete_message_or_folder) },
+       { "ToolbarSort",     MODEST_STOCK_SORT,     N_("qgn_list_sort"),             NULL, NULL,  G_CALLBACK (modest_ui_actions_on_sort) },
+       { "ToolbarFindInMessage",     MODEST_TOOLBAR_ICON_FIND,       N_("qgn_toolb_gene_find"),         NULL, NULL, NULL },
+       { "ToolbarMessageBack",       MODEST_TOOLBAR_ICON_PREV,    N_("qgn_toolb_gene_back"),         NULL, NULL, G_CALLBACK (modest_ui_actions_on_prev) },
+       { "ToolbarMessageNext",    MODEST_TOOLBAR_ICON_NEXT, N_("qgn_toolb_gene_forward"),      NULL, NULL, G_CALLBACK (modest_ui_actions_on_next) },
+       { "ToolbarMessageMoveTo",     MODEST_TOOLBAR_ICON_MOVE_TO_FOLDER, N_("qgn_toolb_gene_movetofldr"),   NULL, NULL, G_CALLBACK(modest_ui_actions_on_move_to) },
+       { "ToolbarCancel",       GTK_STOCK_STOP,   "",      NULL, NULL,  NULL },
+};
+
+static const GtkToggleActionEntry modest_toggle_action_entries [] = {
+       { "ViewToggleFullscreen",     GTK_STOCK_FULLSCREEN, N_("mcen_me_inbox_fullscreen"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_toggle_fullscreen), FALSE },
+       { "ViewShowToolbarNormalScreen", NULL, N_("mcen_me_inbox_normalview"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_toggle_toolbar), TRUE },
+       { "ViewShowToolbarFullScreen", NULL, N_("mcen_me_inbox_fullscreen"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_toggle_toolbar), TRUE },
+};
+
+G_END_DECLS
+#endif /* __MODEST_MAIN_WINDOW_UI_PRIV_H__ */
diff --git a/src/hildon2/modest-main-window.c b/src/hildon2/modest-main-window.c
new file mode 100644 (file)
index 0000000..e252f7f
--- /dev/null
@@ -0,0 +1,3104 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtktreeviewcolumn.h>
+#include <tny-account-store-view.h>
+#include <tny-simple-list.h>
+#include <tny-list.h>
+#include <tny-iterator.h>
+#include <tny-error.h>
+#include "modest-hildon-includes.h"
+#include "modest-defs.h"
+#include <string.h>
+#include "widgets/modest-header-view-priv.h"
+#include "widgets/modest-main-window.h"
+#include "widgets/modest-msg-edit-window.h"
+#include "widgets/modest-account-view-window.h"
+#include "modest-runtime.h"
+#include "modest-account-mgr-helpers.h"
+#include "modest-platform.h"
+#include "modest-widget-memory.h"
+#include "modest-window-priv.h"
+#include "modest-main-window-ui.h"
+#include "modest-main-window-ui-dimming.h"
+#include "modest-account-mgr.h"
+#include "modest-tny-account.h"
+#include "modest-tny-folder.h"
+#include "modest-conf.h"
+#include <modest-utils.h>
+#include <modest-maemo-utils.h>
+#include "modest-tny-platform-factory.h"
+#include "modest-tny-msg.h"
+#include "modest-mail-operation.h"
+#include "modest-icon-names.h"
+#include "modest-progress-bar.h"
+#include "modest-text-utils.h"
+#include "modest-ui-dimming-manager.h"
+#include "maemo/modest-osso-state-saving.h"
+#include "modest-text-utils.h"
+#include "modest-signal-mgr.h"
+
+#define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
+
+#define XALIGN 0.5
+#define YALIGN 0.0
+#define XSPACE 1
+#define YSPACE 0
+
+/* 'private'/'protected' functions */
+static void modest_main_window_class_init  (ModestMainWindowClass *klass);
+static void modest_main_window_init        (ModestMainWindow *obj);
+static void modest_main_window_finalize    (GObject *obj);
+
+static gboolean modest_main_window_window_state_event (GtkWidget *widget, 
+                                                      GdkEventWindowState *event, 
+                                                      gpointer userdata);
+
+static void connect_signals (ModestMainWindow *self);
+
+static void modest_main_window_disconnect_signals (ModestWindow *self);
+
+static void restore_settings (ModestMainWindow *self, 
+                             gboolean do_folder_view_too);
+
+static void save_state (ModestWindow *self);
+
+static void update_menus (ModestMainWindow* self);
+
+static void modest_main_window_show_toolbar   (ModestWindow *window,
+                                              gboolean show_toolbar);
+
+static void cancel_progressbar (GtkToolButton *toolbutton,
+                               ModestMainWindow *self);
+
+static void on_queue_changed   (ModestMailOperationQueue *queue,
+                               ModestMailOperation *mail_op,
+                               ModestMailOperationQueueNotification type,
+                               ModestMainWindow *self);
+
+static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
+
+static void on_account_inserted (TnyAccountStore *accoust_store,
+                                TnyAccount *account,
+                                gpointer user_data);
+
+static void on_account_removed  (TnyAccountStore *accoust_store,
+                                TnyAccount *account,
+                                gpointer user_data);
+
+static void on_account_changed  (TnyAccountStore *account_store,
+                                TnyAccount *account,
+                                gpointer user_data);
+
+static void on_default_account_changed (ModestAccountMgr* mgr,
+                                       gpointer user_data);
+
+static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
+                                              GdkEventKey *event,
+                                              gpointer user_data);
+
+static void on_configuration_key_changed      (ModestConf* conf, 
+                                              const gchar *key, 
+                                              ModestConfEvent event,
+                                              ModestConfNotificationId id,
+                                              ModestMainWindow *self);
+
+static void set_toolbar_mode                  (ModestMainWindow *self, 
+                                              ModestToolBarModes mode);
+
+static gboolean set_toolbar_transfer_mode     (ModestMainWindow *self); 
+
+static void on_show_account_action_toggled      (GtkToggleAction *action,
+                                                gpointer user_data);
+
+static void on_refresh_account_action_activated   (GtkAction *action,
+                                                  gpointer user_data);
+
+static void on_send_receive_csm_activated         (GtkMenuItem *item,
+                                                  gpointer user_data);
+
+static void on_msg_count_changed (ModestHeaderView *header_view,
+                                 TnyFolder *folder,
+                                 TnyFolderChange *change,
+                                 ModestMainWindow *main_window);
+
+static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
+
+
+static GtkWidget * create_empty_view (void);
+
+static gboolean  on_folder_view_focus_in (GtkWidget *widget,
+                                         GdkEventFocus *event,
+                                         gpointer userdata);
+
+static gboolean  on_header_view_focus_in (GtkWidget *widget,
+                                         GdkEventFocus *event,
+                                         gpointer userdata);
+
+static void      on_folder_selection_changed (ModestFolderView *folder_view,
+                                             TnyFolderStore *folder_store, 
+                                             gboolean selected,
+                                             ModestMainWindow *main_window);
+                                               
+static void set_at_least_one_account_visible(ModestMainWindow *self);
+
+static void on_updating_msg_list (ModestHeaderView *header_view,
+                                 gboolean starting,
+                                 gpointer user_data);
+
+static gboolean restore_paned_timeout_handler (gpointer *data);
+
+static gboolean show_opening_banner (gpointer user_data);
+
+static void on_window_destroy (GtkObject *widget,
+                              gpointer userdata);
+
+static void on_window_hide (GObject    *gobject,
+                           GParamSpec *arg1,
+                           gpointer    user_data);
+
+typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
+struct _ModestMainWindowPrivate {
+       GtkWidget *msg_paned;
+       GtkWidget *main_paned;
+       GtkWidget *main_vbox;
+       GtkWidget *contents_widget;
+       GtkWidget *empty_view;
+
+       /* Progress observers */
+       GtkWidget   *progress_bar;
+       GSList      *progress_widgets;
+
+       /* Tollbar items */
+       GtkWidget   *progress_toolitem;
+       GtkWidget   *cancel_toolitem;
+       GtkWidget   *sort_toolitem;
+       GtkWidget   *refresh_toolitem;
+       ModestToolBarModes current_toolbar_mode;
+
+       /* Merge ids used to add/remove accounts to the ViewMenu*/
+       GByteArray *merge_ids;
+       GtkActionGroup *view_additions_group;
+
+       /* On-demand widgets */
+       GtkWidget *accounts_popup;
+       GtkWidget *details_widget;
+
+       /* Optimized view enabled */
+       gboolean optimized_view;
+
+       /* Optimized view enabled */
+       gboolean send_receive_in_progress;
+
+       ModestHeaderView *header_view;
+       ModestFolderView *folder_view;
+
+       ModestMainWindowStyle style;
+       ModestMainWindowContentsStyle contents_style;
+       gboolean wait_for_settings;
+
+       guint progress_bar_timeout;
+       guint restore_paned_timeout;
+
+       /* Signal handler UIDs */
+       GList *queue_err_signals;
+       GSList *sighandlers;
+
+       /* "Updating" banner for header view */
+       GtkWidget *updating_banner;
+       guint updating_banner_timeout;
+
+       /* "Opening" banner for header view */
+       GtkWidget *opening_banner;
+       guint opening_banner_timeout;
+
+       /* Display state */
+       osso_display_state_t display_state;
+};
+#define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                MODEST_TYPE_MAIN_WINDOW, \
+                                                ModestMainWindowPrivate))
+
+typedef struct _GetMsgAsyncHelper {
+       ModestMainWindowPrivate *main_window_private;
+       guint action;
+       ModestTnyMsgReplyType reply_type;
+       ModestTnyMsgForwardType forward_type;
+       gchar *from;
+       TnyIterator *iter;
+} GetMsgAsyncHelper;
+
+
+/* globals */
+static GtkWindowClass *parent_class = NULL;
+
+
+/* Private actions */
+/* This is the context sensitive menu: */
+static const GtkActionEntry modest_folder_view_action_entries [] = {
+
+       /* Folder View CSM actions */
+       { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
+       { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
+       { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL,  G_CALLBACK (modest_ui_actions_on_paste)},
+       { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
+       { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
+       { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
+};
+
+static const GtkActionEntry modest_header_view_action_entries [] = {
+
+       /* Header View CSM actions */
+       { "HeaderViewCSMOpen",          NULL,  N_("mcen_me_inbox_open"),        NULL,       NULL, G_CALLBACK (modest_ui_actions_on_open) },
+       { "HeaderViewCSMReply",         NULL,  N_("mcen_me_inbox_reply"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply) },
+       { "HeaderViewCSMReplyAll",      NULL,  N_("mcen_me_inbox_replytoall"),  NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
+       { "HeaderViewCSMForward",       NULL,  N_("mcen_me_inbox_forward"),     NULL,      NULL, G_CALLBACK (modest_ui_actions_on_forward) },
+       { "HeaderViewCSMCut",           NULL,  N_("mcen_me_inbox_cut"),         "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
+       { "HeaderViewCSMCopy",          NULL,  N_("mcen_me_inbox_copy"),        "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
+       { "HeaderViewCSMPaste",         NULL,  N_("mcen_me_inbox_paste"),       "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
+       { "HeaderViewCSMDelete",        NULL,  N_("mcen_me_inbox_delete"),      NULL,      NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
+       { "HeaderViewCSMCancelSending", NULL,  N_("mcen_me_outbox_cancelsend"), NULL,      NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
+       { "HeaderViewCSMHelp",          NULL,  N_("mcen_me_inbox_help"),        NULL,      NULL, G_CALLBACK (modest_ui_actions_on_help) },
+};
+
+static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
+       { "ToggleFolders",     MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
+};
+
+/************************************************************************/
+
+GType
+modest_main_window_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestMainWindowClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_main_window_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestMainWindow),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_main_window_init,
+                       NULL
+               };
+               my_type = g_type_register_static (MODEST_TYPE_WINDOW,
+                                                 "ModestMainWindow",
+                                                 &my_info, 0);
+       }
+       return my_type;
+}
+
+static void
+modest_main_window_class_init (ModestMainWindowClass *klass)
+{
+       GObjectClass *gobject_class;
+       gobject_class = (GObjectClass*) klass;
+       ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_main_window_finalize;
+
+       g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
+       
+       modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
+       modest_window_class->save_state_func = save_state;
+       modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
+       modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
+       modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
+}
+
+static void
+modest_main_window_init (ModestMainWindow *obj)
+{
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
+
+       priv->queue_err_signals = NULL;
+       priv->msg_paned    = NULL;
+       priv->main_paned   = NULL;      
+       priv->main_vbox    = NULL;
+       priv->header_view  = NULL;
+       priv->folder_view  = NULL;
+       priv->contents_widget  = NULL;
+       priv->accounts_popup  = NULL;
+       priv->details_widget  = NULL;
+       priv->empty_view  = NULL;
+       priv->progress_widgets  = NULL;
+       priv->progress_bar = NULL;
+       priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
+       priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
+       priv->wait_for_settings = TRUE;
+       priv->contents_style  = -1; /* invalid contents style. We need this to select it for the first time */
+       priv->merge_ids = NULL;
+       priv->optimized_view  = FALSE;
+       priv->send_receive_in_progress  = FALSE;
+       priv->progress_bar_timeout = 0;
+       priv->restore_paned_timeout = 0;
+       priv->sighandlers = NULL;
+       priv->updating_banner = NULL;
+       priv->updating_banner_timeout = 0;
+       priv->opening_banner = NULL;
+       priv->opening_banner_timeout = 0;
+       priv->display_state = OSSO_DISPLAY_ON;
+       
+       modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
+                                           GTK_WINDOW(obj),
+                                           "applications_email_mainview");
+}
+
+static void
+modest_main_window_finalize (GObject *obj)
+{
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
+
+       /* Sanity check: shouldn't be needed, the window mgr should
+          call this function before */
+       modest_main_window_disconnect_signals (MODEST_WINDOW (obj));    
+       modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
+
+       if (priv->empty_view) {
+               g_object_unref (priv->empty_view);
+               priv->empty_view = NULL;
+       }
+       
+       if (priv->header_view) {
+               g_object_unref (priv->header_view);
+               priv->header_view = NULL;
+       }
+       
+       g_slist_free (priv->progress_widgets);
+
+       g_byte_array_free (priv->merge_ids, TRUE);
+
+       if (priv->progress_bar_timeout > 0) {
+               g_source_remove (priv->progress_bar_timeout);
+               priv->progress_bar_timeout = 0;
+       }
+
+       if (priv->updating_banner_timeout > 0) {
+               g_source_remove (priv->updating_banner_timeout);
+               priv->updating_banner_timeout = 0;
+       }
+
+       if (priv->updating_banner) {
+               gtk_widget_destroy (priv->updating_banner);
+               priv->updating_banner = NULL;
+       }
+
+       if (priv->opening_banner_timeout > 0) {
+               g_source_remove (priv->opening_banner_timeout);
+               priv->opening_banner_timeout = 0;
+       }
+
+       if (priv->opening_banner) {
+               gtk_widget_destroy (priv->opening_banner);
+               priv->opening_banner = NULL;
+       }
+
+       if (priv->restore_paned_timeout > 0) {
+               g_source_remove (priv->restore_paned_timeout);
+               priv->restore_paned_timeout = 0;
+       }
+       
+       G_OBJECT_CLASS(parent_class)->finalize (obj);
+}
+
+GtkWidget*
+modest_main_window_get_child_widget (ModestMainWindow *self,
+                                    ModestMainWindowWidgetType widget_type)
+{
+       ModestMainWindowPrivate *priv;
+       GtkWidget *widget;
+       
+       g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
+       g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
+                             NULL);
+       
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       switch (widget_type) {
+       case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
+               widget = (GtkWidget*)priv->header_view; break;
+       case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
+               widget = (GtkWidget*)priv->folder_view; break;
+       default:
+               return NULL;
+       }
+
+       /* Note that the window could have been destroyed, and so
+          their children, but still have some references */
+       return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
+}
+
+static gboolean 
+restore_paned_timeout_handler (gpointer *data)
+{
+       ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
+       ModestConf *conf;
+
+       /* Timeouts are outside the main lock */
+       gdk_threads_enter ();
+       if (GTK_WIDGET_VISIBLE (main_window)) {
+               conf = modest_runtime_get_conf ();
+               modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
+                                             MODEST_CONF_MAIN_PANED_KEY);
+       }
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+
+static void
+restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
+{
+       ModestConf *conf;
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       conf = modest_runtime_get_conf ();
+
+       modest_widget_memory_restore (conf, G_OBJECT(self),
+                                     MODEST_CONF_MAIN_WINDOW_KEY);
+
+       modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
+                                     MODEST_CONF_HEADER_VIEW_KEY);
+
+       if (do_folder_view_too)
+               modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
+                                     MODEST_CONF_FOLDER_VIEW_KEY);
+
+/*     modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
+/*                                   MODEST_CONF_MAIN_PANED_KEY); */
+
+       g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
+
+       /* We need to force a redraw here in order to get the right
+          position of the horizontal paned separator */
+       gtk_widget_show (GTK_WIDGET (self));
+}
+
+
+static void
+save_state (ModestWindow *window)
+{
+       ModestConf *conf;
+       ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
+       ModestMainWindowPrivate *priv;
+               
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       conf = modest_runtime_get_conf ();
+       
+       modest_widget_memory_save (conf,G_OBJECT(self), 
+                                  MODEST_CONF_MAIN_WINDOW_KEY);
+       /* Only save main paned position if we're in split mode */
+       if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
+               modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
+                                          MODEST_CONF_MAIN_PANED_KEY);
+       modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
+                                  MODEST_CONF_FOLDER_VIEW_KEY);
+}
+
+static gint
+compare_display_names (ModestAccountSettings *a,
+                      ModestAccountSettings *b)
+{
+       return g_utf8_collate (modest_account_settings_get_display_name (a),
+                              modest_account_settings_get_display_name (b));
+
+}
+
+/* We use this function to prevent the send&receive CSM to be shown
+   when there are less than two account */
+static gboolean
+tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
+{
+       return TRUE;
+}
+
+static void
+update_menus (ModestMainWindow* self)
+{      
+       GSList *account_names, *iter, *accounts;
+       ModestMainWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv;
+       ModestAccountMgr *mgr;
+       gint i, num_accounts;
+       GList *groups;
+       gchar *default_account;
+       const gchar *active_account_name;
+       GtkWidget *send_receive_button, *item;
+       GtkAction *send_receive_all = NULL;
+       GSList *radio_group;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
+
+       /* Get enabled account IDs */
+       mgr = modest_runtime_get_account_mgr ();
+       account_names = modest_account_mgr_account_names (mgr, TRUE);
+       iter = account_names;
+       accounts = NULL;
+
+       while (iter) {
+               ModestAccountSettings *settings = 
+                       modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
+               accounts = g_slist_prepend (accounts, settings);
+
+               iter = iter->next;
+       }
+       modest_account_mgr_free_account_names (account_names);
+       account_names = NULL;
+
+       /* Order the list of accounts by its display name */
+       accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
+       num_accounts = g_slist_length (accounts);
+
+       send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                     "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
+       gtk_action_set_visible (send_receive_all, num_accounts > 0);
+
+       /* Delete old send&receive popup items. We can not just do a
+          menu_detach because it does not work well with
+          tap_and_hold */
+       if (priv->accounts_popup)
+               gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
+                                      (GtkCallback) gtk_widget_destroy, NULL);
+
+       /* Delete old entries in the View menu. Do not free groups, it
+          belongs to Gtk+ */
+       groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
+       while (groups) {
+               if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
+                            gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
+                       gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
+                                                           GTK_ACTION_GROUP (groups->data));
+                       groups = NULL;
+                       /* Remove uis */
+                       if (priv->merge_ids) {
+                               for (i = 0; i < priv->merge_ids->len; i++)
+                                       gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
+                               g_byte_array_free (priv->merge_ids, TRUE);
+                       }
+                       /* We need to call this in order to ensure
+                          that the new actions are added in the right
+                          order (alphabetical) */
+                       gtk_ui_manager_ensure_update (parent_priv->ui_manager);
+               } else 
+                       groups = g_list_next (groups);
+       }
+       priv->merge_ids = g_byte_array_sized_new (num_accounts);
+
+       /* Get send receive button */
+       send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
+                                                         "/ToolBar/ToolbarSendReceive");
+
+       /* Create the menu */
+       if (num_accounts > 1) {
+               if (!priv->accounts_popup)
+                       priv->accounts_popup = gtk_menu_new ();
+               item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
+               gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
+               g_signal_connect (G_OBJECT (item), 
+                                 "activate", 
+                                 G_CALLBACK (on_send_receive_csm_activated),
+                                 NULL);
+               item = gtk_separator_menu_item_new ();
+               gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
+       }
+
+       /* Create a new action group */
+       default_account = modest_account_mgr_get_default_account (mgr);
+       active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
+       
+       if (!active_account_name) 
+               modest_window_set_active_account (MODEST_WINDOW (self), default_account);
+       
+       priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
+       radio_group = NULL;
+       for (i = 0; i < num_accounts; i++) {
+               gchar *display_name = NULL;     
+               const gchar *account_name;
+               ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
+
+               if (!settings) {
+                       g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
+                       continue;
+               }
+               account_name = modest_account_settings_get_account_name (settings);
+       
+               if (default_account && account_name && 
+                   !(strcmp (default_account, account_name) == 0)) {
+                       display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
+                                                       modest_account_settings_get_display_name (settings));
+               } else {
+                       display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
+                                                       modest_account_settings_get_display_name (settings));
+               }
+
+               
+               
+               /* Create action and add it to the action group. The
+                  action name must be the account name, this way we
+                  could know in the handlers the account to show */
+               if (settings && account_name) {
+                       gchar* item_name, *refresh_action_name;
+                       guint8 merge_id = 0;
+                       GtkAction *view_account_action, *refresh_account_action;
+                       gchar *escaped_display_name;
+
+                       escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
+
+                       view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
+                                                                               escaped_display_name, NULL, NULL, 0));
+                       g_free (escaped_display_name);
+                       gtk_action_group_add_action (priv->view_additions_group, view_account_action);
+                       gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
+                       radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
+
+                       if (active_account_name) {
+                               if (active_account_name && account_name && 
+                                   (strcmp (active_account_name, account_name) == 0)) {
+                                       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
+                               }
+                       }
+
+                       /* Add ui from account data. We allow 2^9-1 account
+                          changes in a single execution because we're
+                          downcasting the guint to a guint8 in order to use a
+                          GByteArray. It should be enough :-) */
+                       item_name = g_strconcat (account_name, "Menu", NULL);
+                       merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
+                       priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
+                       gtk_ui_manager_add_ui (parent_priv->ui_manager,
+                                              merge_id,
+                                              "/MenuBar/ViewMenu/ViewMenuAdditions",
+                                              item_name,
+                                              account_name,
+                                              GTK_UI_MANAGER_MENUITEM,
+                                              FALSE);
+
+                       /* Connect the action signal "activate" */
+                       g_signal_connect_after (G_OBJECT (view_account_action),
+                                               "toggled",
+                                               G_CALLBACK (on_show_account_action_toggled),
+                                               self);
+
+                       /* Create the items for the Tools->Send&Receive submenu */
+                       refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
+                       refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
+                                                                display_name, NULL, NULL);
+                       gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
+
+                       merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
+                       priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
+                       gtk_ui_manager_add_ui (parent_priv->ui_manager, 
+                                              merge_id,
+                                              "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
+                                              item_name,
+                                              refresh_action_name,
+                                              GTK_UI_MANAGER_MENUITEM,
+                                              FALSE);
+                       g_free (refresh_action_name);
+
+                       g_signal_connect_data (G_OBJECT (refresh_account_action), 
+                                              "activate", 
+                                              G_CALLBACK (on_refresh_account_action_activated), 
+                                              g_strdup (account_name),
+                                              (GClosureNotify) g_free,
+                                              0);
+
+                       /* Create item and add it to the send&receive
+                          CSM. If there is only one account then
+                          it'll be no menu */
+                       if (num_accounts > 1) {
+                               GtkWidget *label = gtk_label_new(NULL);
+                               gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+                               if (default_account && (strcmp(account_name, default_account) == 0)) {
+                                       gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
+                                       gtk_label_set_markup (GTK_LABEL (label), escaped);
+                                       g_free (escaped);
+                               } else {
+                                       gtk_label_set_text (GTK_LABEL (label), display_name);
+                               }
+
+                               item = gtk_menu_item_new ();
+                               gtk_container_add (GTK_CONTAINER (item), label);
+
+                               gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), 
+                                                       GTK_WIDGET (item));
+                               g_signal_connect_data (G_OBJECT (item), 
+                                                      "activate", 
+                                                      G_CALLBACK (on_send_receive_csm_activated),
+                                                      g_strdup (account_name),
+                                                      (GClosureNotify) g_free,
+                                                      0);
+                       }
+                       g_free (item_name);
+               }
+
+               /* Frees */
+               g_free (display_name);
+       }
+
+       gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
+
+       /* We cannot do this in the loop above because this relies on the action
+        * group being inserted. This makes the default account appear in bold.
+        * I agree it is a rather ugly way, but I don't see another possibility. armin. */
+       for (i = 0; i < num_accounts; i++) {
+               gchar *item_name, *path;
+               GtkWidget *item;
+               ModestAccountSettings *settings;
+               const gchar *account_name;
+               gboolean is_default;
+
+               settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
+               account_name = modest_account_settings_get_account_name (settings);
+               is_default = (account_name && default_account && !strcmp (account_name, default_account));
+
+               /* Get the item of the view menu */
+               item_name = g_strconcat (account_name, "Menu", NULL);
+               path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
+               item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
+               g_free(path);
+               
+               if (item) {
+                       GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
+                       if (GTK_IS_LABEL (child)) {
+                               const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
+                               if (is_default) {
+                                       gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
+                                       gtk_label_set_markup (GTK_LABEL (child), bold_name);
+                                       g_free (bold_name);
+                               }
+                               gtk_label_set_ellipsize (GTK_LABEL (child),  PANGO_ELLIPSIZE_END);
+                       }
+               }
+                       
+               /* Get the item of the tools menu */
+               path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
+               item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
+               g_free (path);
+
+               if (item) {
+                       GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
+                       if (GTK_IS_LABEL (child)) {
+                               const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
+                               if (is_default) {
+                                       gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
+                                       gtk_label_set_markup (GTK_LABEL (child), bold_name);
+                                       g_free (bold_name);
+                               }
+                               gtk_label_set_ellipsize (GTK_LABEL (child),  PANGO_ELLIPSIZE_END);
+                       }
+               }
+
+               g_free(item_name);
+               g_object_unref (settings);
+       }
+
+       if (num_accounts > 1) {
+               /* Disconnect the tap-and-hold-query if it's connected */
+               if (modest_signal_mgr_is_connected (priv->sighandlers, 
+                                                   G_OBJECT (send_receive_button),
+                                                   "tap-and-hold-query"))
+                       priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers, 
+                                                                         G_OBJECT (send_receive_button),
+                                                                         "tap-and-hold-query");
+
+               /* Mandatory in order to view the menu contents */
+               gtk_widget_show_all (priv->accounts_popup);
+
+               /* Setup tap_and_hold just if was not done before*/
+               if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
+                       gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
+       } else {
+               /* Connect the tap-and-hold-query in order not to show the CSM */
+               if (!modest_signal_mgr_is_connected (priv->sighandlers, 
+                                                    G_OBJECT (send_receive_button),
+                                                    "tap-and-hold-query"))
+                       priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, 
+                                                                      G_OBJECT (send_receive_button),
+                                                                      "tap-and-hold-query",
+                                                                      G_CALLBACK (tap_and_hold_query_cb), 
+                                                                      NULL);
+       }
+
+       /* Frees */
+       g_slist_free (accounts);
+       g_free (default_account);
+
+
+       /* Make sure that at least one account is viewed if there are any 
+        * accounts, for instance when adding the first account: */
+       set_at_least_one_account_visible (self);
+}
+
+static void
+wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
+{
+       if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
+               gtk_scrolled_window_add_with_viewport
+                       (GTK_SCROLLED_WINDOW(win), widget);
+       else
+               gtk_container_add (GTK_CONTAINER(win),
+                                  widget);
+}
+
+
+typedef struct {
+       TnySendQueue *queue;
+       guint signal;
+} QueueErrorSignal;
+
+static void
+modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+
+       GList *oerrsignals = priv->queue_err_signals;
+       while (oerrsignals) {
+               QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
+               g_signal_handler_disconnect (esignal->queue, esignal->signal);
+               g_slice_free (QueueErrorSignal, esignal);
+               oerrsignals = g_list_next (oerrsignals);
+       }
+       g_list_free (priv->queue_err_signals);
+       priv->queue_err_signals = NULL;
+}
+
+
+static void
+_folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
+
+       /* Update dimmed */
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
+}
+
+static void
+_header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
+
+       /* Update visibility */
+
+       /* Update dimmed */
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
+}
+
+static void
+modest_main_window_disconnect_signals (ModestWindow *self)
+{      
+       ModestMainWindowPrivate *priv;  
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
+       priv->sighandlers = NULL;       
+}
+
+static void
+connect_signals (ModestMainWindow *self)
+{      
+       ModestWindowPrivate *parent_priv;
+       ModestMainWindowPrivate *priv;
+       GtkWidget *menu;
+       
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       /* folder view */
+       
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT(priv->folder_view), "key-press-event",
+                                          G_CALLBACK(on_inner_widgets_key_pressed), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), 
+                                          "folder_selection_changed",
+                                          G_CALLBACK (on_folder_selection_changed), 
+                                          self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), 
+                                          "folder-display-name-changed",
+                                          G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), 
+                                          self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), 
+                                          "focus-in-event", 
+                                          G_CALLBACK (on_folder_view_focus_in), 
+                                          self);
+
+       /* Folder view CSM */
+       menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
+       gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
+       priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
+                                                      G_CALLBACK(_folder_view_csm_menu_activated),
+                                                      self);
+       /* header view */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
+                                          G_CALLBACK(modest_ui_actions_on_header_selected), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
+                                          G_CALLBACK(modest_ui_actions_on_header_activated), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
+                                          G_CALLBACK(modest_ui_actions_on_item_not_found), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
+                                          G_CALLBACK(on_inner_widgets_key_pressed), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
+                                          G_CALLBACK(on_msg_count_changed), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
+                                          G_CALLBACK (on_header_view_focus_in), self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (priv->header_view), 
+                                          "updating-msg-list",
+                                          G_CALLBACK (on_updating_msg_list), 
+                                          self);
+       
+       /* Header view CSM */
+       menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
+       gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
+                                          G_CALLBACK(_header_view_csm_menu_activated),
+                                          self);
+       
+       /* window */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
+                                          G_CALLBACK (modest_main_window_window_state_event),
+                                          NULL);
+       /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
+        * in destroy stage */
+       g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
+
+       g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
+
+       /* Mail Operation Queue */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (modest_runtime_get_mail_operation_queue ()),
+                                          "queue-changed", 
+                                          G_CALLBACK (on_queue_changed), self);
+       
+       /* Track changes in the device name */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT(modest_runtime_get_conf ()),
+                                          "key_changed", 
+                                          G_CALLBACK (on_configuration_key_changed), 
+                                          self);
+       
+       /* Track account changes. We need to refresh the toolbar */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (modest_runtime_get_account_store ()),
+                                          "account_inserted", 
+                                          G_CALLBACK (on_account_inserted),
+                                          self);
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (modest_runtime_get_account_store ()),
+                                          "account_removed", 
+                                          G_CALLBACK (on_account_removed),
+                                          self);
+
+       /* We need to refresh the send & receive menu to change the bold
+        * account when the default account changes. */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (modest_runtime_get_account_mgr ()),
+                                          "default_account_changed", 
+                                          G_CALLBACK (on_default_account_changed),
+                                          self);
+
+       /* Account store */
+       priv->sighandlers = 
+               modest_signal_mgr_connect (priv->sighandlers,
+                                          G_OBJECT (modest_runtime_get_account_store ()),
+                                          "account_changed", 
+                                          G_CALLBACK (on_account_changed),
+                                          self);
+}
+
+static void 
+on_hildon_program_is_topmost_notify(GObject *self,
+                                   GParamSpec *propert_param, 
+                                   gpointer user_data)
+{
+       HildonProgram *app = HILDON_PROGRAM (self);
+       
+       /* Note that use of hildon_program_set_can_hibernate() 
+        * is generally referred to as "setting the killable flag", 
+        * though hibernation does not seem equal to death.
+        * murrayc */
+                
+       if (hildon_program_get_is_topmost (app)) {
+               /* Prevent hibernation when the progam comes to the foreground,
+                * because hibernation should only happen when the application 
+                * is in the background: */
+               hildon_program_set_can_hibernate (app, FALSE);
+
+               /* Remove new mail visual notifications */
+               modest_platform_remove_new_mail_notifications (TRUE);
+       } else {
+               /* Allow hibernation if the program has gone to the background: */
+               
+               /* However, prevent hibernation while the settings are being changed: */
+               const gboolean hibernation_prevented = 
+                       modest_window_mgr_get_hibernation_is_prevented (
+                                                                       modest_runtime_get_window_mgr ()); 
+       
+               if (hibernation_prevented)
+                       hildon_program_set_can_hibernate (app, FALSE);
+               else {
+                       /* Allow hibernation, after saving the state: */
+                       modest_osso_save_state();
+                       hildon_program_set_can_hibernate (app, TRUE);
+               }
+       }       
+}
+
+typedef struct
+{
+       GtkWidget *folder_win;
+       gulong handler_id;
+} ShowHelper;
+
+static void
+modest_main_window_on_show (GtkWidget *self, gpointer user_data)
+{
+       ShowHelper *helper = (ShowHelper *) user_data;
+       GtkWidget *folder_win = helper->folder_win;
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       
+       priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
+       wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
+
+       gtk_widget_show (GTK_WIDGET (priv->folder_view));
+
+       /* Connect signals */
+       connect_signals (MODEST_MAIN_WINDOW (self));
+
+       /* Set account store */
+       tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
+                                                 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
+
+       /* Load previous osso state, for instance if we are being restored from 
+        * hibernation:  */
+       modest_osso_load_state ();
+
+       /* Restore window & widget settings */  
+       priv->wait_for_settings = TRUE;
+       restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
+       priv->wait_for_settings = FALSE;
+
+       /* Check if accounts exist and show the account wizard if not */
+       gboolean accounts_exist = 
+               modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
+
+       if (!accounts_exist) {
+               /* This is necessary to have the main window shown behind the dialog 
+               It's an ugly hack... jschmid */
+               gtk_widget_show_all(GTK_WIDGET(self));
+               modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
+       } else {
+               update_menus (MODEST_MAIN_WINDOW (self));
+       }
+
+       /* Never call this function again (NOTE that it could happen
+          as we hide the main window instead of closing it while
+          there are operations ongoing) and free the helper */
+       g_signal_handler_disconnect (self, helper->handler_id);
+       g_slice_free (ShowHelper, helper);
+}
+
+static void 
+osso_display_event_cb (osso_display_state_t state, 
+                      gpointer data)
+{
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
+
+       priv->display_state = state;
+
+       /* Stop blinking if the screen becomes on */
+       if (priv->display_state == OSSO_DISPLAY_ON)
+               modest_platform_remove_new_mail_notifications (TRUE);
+}
+
+ModestWindow *
+modest_main_window_new (void)
+{
+       ModestMainWindow *self = NULL;  
+       ModestMainWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;
+       GtkWidget *folder_win = NULL;
+       ModestDimmingRulesGroup *menu_rules_group = NULL;
+       ModestDimmingRulesGroup *toolbar_rules_group = NULL;
+       GtkActionGroup *action_group = NULL;
+       GError *error = NULL;
+       HildonProgram *app;
+       ModestConf *conf = NULL;
+       GtkAction *action = NULL;
+       GdkPixbuf *window_icon;
+       ShowHelper *helper;
+       
+       self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       parent_priv->ui_manager = gtk_ui_manager_new();
+       parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
+
+       action_group = gtk_action_group_new ("ModestMainWindowActions");
+       gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+
+       menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
+       toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
+
+       /* Add common actions */
+       gtk_action_group_add_actions (action_group,
+                                     modest_action_entries,
+                                     G_N_ELEMENTS (modest_action_entries),
+                                     self);
+
+       gtk_action_group_add_actions (action_group,
+                                     modest_folder_view_action_entries,
+                                     G_N_ELEMENTS (modest_folder_view_action_entries),
+                                     self);
+
+       gtk_action_group_add_actions (action_group,
+                                     modest_header_view_action_entries,
+                                     G_N_ELEMENTS (modest_header_view_action_entries),
+                                     self);
+
+       gtk_action_group_add_toggle_actions (action_group,
+                                            modest_toggle_action_entries,
+                                            G_N_ELEMENTS (modest_toggle_action_entries),
+                                            self);
+
+       gtk_action_group_add_toggle_actions (action_group,
+                                            modest_main_window_toggle_action_entries,
+                                            G_N_ELEMENTS (modest_main_window_toggle_action_entries),
+                                            self);
+
+       gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
+       g_object_unref (action_group);
+
+       /* Load the UI definition */
+       gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
+                                        MODEST_UIDIR "modest-main-window-ui.xml", &error);
+       if (error != NULL) {
+               g_warning ("Could not merge modest-ui.xml: %s", error->message);
+               g_error_free (error);
+               error = NULL;
+       }
+
+       /* Add common dimming rules */
+       modest_dimming_rules_group_add_rules (menu_rules_group, 
+                                             modest_main_window_menu_dimming_entries,
+                                             G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
+                                             MODEST_WINDOW (self));
+       modest_dimming_rules_group_add_rules (toolbar_rules_group, 
+                                             modest_main_window_toolbar_dimming_entries,
+                                             G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
+                                             MODEST_WINDOW (self));
+
+       /* Insert dimming rules group for this window */
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
+       g_object_unref (menu_rules_group);
+       g_object_unref (toolbar_rules_group);
+       
+       /* Add accelerators */
+       gtk_window_add_accel_group (GTK_WINDOW (self), 
+                                   gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
+
+       /* Menubar. Update the state of some toggles */
+       parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
+       conf = modest_runtime_get_conf ();
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
+       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
+       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
+       hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
+       gtk_widget_show (parent_priv->menubar);
+
+       /* Get device name */
+       modest_maemo_utils_get_device_name ();
+
+       /* header view */
+       priv->header_view =
+               MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
+       g_object_ref (priv->header_view);
+       if (!priv->header_view)
+               g_printerr ("modest: cannot instantiate header view\n");
+       modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
+       modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
+                                     MODEST_CONF_HEADER_VIEW_KEY);
+
+       /* Other style properties of header view */
+       g_object_set (G_OBJECT (priv->header_view), 
+                     "rules-hint", FALSE,
+                     NULL);
+       /* gtk_widget_show (priv->header_view); */
+
+       /* Empty view */ 
+       priv->empty_view = create_empty_view ();
+       gtk_widget_show (priv->empty_view);
+       g_object_ref (priv->empty_view);
+                
+       /* Create scrolled windows */
+       folder_win = gtk_scrolled_window_new (NULL, NULL);
+       priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
+                                       GTK_POLICY_NEVER,
+                                       GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
+                                       GTK_POLICY_NEVER,
+                                       GTK_POLICY_AUTOMATIC);
+       /* gtk_widget_show (priv->contents_widget); */
+
+       /* paned */
+       priv->main_paned = gtk_hpaned_new ();
+       gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
+       gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
+       gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
+
+       /* putting it all together... */
+       priv->main_vbox = gtk_vbox_new (FALSE, 6);
+       gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
+       gtk_widget_show (priv->main_vbox);
+       
+       gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
+       
+       app = hildon_program_get_instance ();
+       hildon_program_add_window (app, HILDON_WINDOW (self));
+       
+       g_signal_connect (G_OBJECT(app), "notify::is-topmost",
+               G_CALLBACK (on_hildon_program_is_topmost_notify), self);
+
+       /* Connect to "show" action. We delay the creation of some
+          elements until that moment */
+       helper = g_slice_new0 (ShowHelper);
+       helper->folder_win = folder_win;
+       helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
+                                              G_CALLBACK (modest_main_window_on_show), 
+                                              helper);
+       
+       /* Set window icon */
+       window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
+       if (window_icon) {
+               gtk_window_set_icon (GTK_WINDOW (self), window_icon);
+               g_object_unref (window_icon);
+       }
+
+       /* Listen for changes in the screen, we don't want to show a
+          led pattern when the display is on for example */
+       osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
+                                     osso_display_event_cb,
+                                     self); 
+
+       /* Dont't restore settings here, 
+        * because it requires a gtk_widget_show(), 
+        * and we don't want to do that until later,
+        * so that the UI is not visible for non-menu D-Bus activation.
+        */
+
+       return MODEST_WINDOW(self);
+}
+
+void 
+modest_main_window_set_style (ModestMainWindow *self, 
+                             ModestMainWindowStyle style)
+{
+       ModestMainWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv;
+       GtkAction *action;
+       gboolean active;
+       GtkTreeSelection *sel;
+       GList *rows, *list;
+       
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       /* no change -> nothing to do */
+       if (priv->style == style)
+               return;
+
+       /* Get toggle button and update the state if needed. This will
+         happen only when the set_style is not invoked from the UI,
+         for example when it's called from widget memory */
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
+       active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+       if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
+          (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
+              g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
+              gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
+              g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
+       }
+
+       /* We need to store the selection because it's lost when the
+         widget is reparented */
+       sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
+       rows = gtk_tree_selection_get_selected_rows (sel, NULL);
+
+       priv->style = style;
+       switch (style) {
+       case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
+
+               if (!priv->wait_for_settings)
+                       modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
+                                                  MODEST_CONF_MAIN_PANED_KEY);
+               /* Remove main paned */
+               g_object_ref (priv->main_paned);
+               gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
+
+               /* Reparent the contents widget to the main vbox */
+               gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
+
+               break;
+       case MODEST_MAIN_WINDOW_STYLE_SPLIT:
+               /* Remove header view */
+               g_object_ref (priv->contents_widget);
+               gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
+
+               /* Reparent the main paned */
+               gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
+               gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
+
+               g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
+
+               break;
+       default:
+               g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+               g_list_free (rows);
+               g_return_if_reached ();
+       }
+
+       /* Reselect the previously selected folders. We disable the
+          dimming rules execution during that time because there is
+          no need to work out it again and it could take a lot of
+          time if all the headers are selected */
+       list = rows;
+       modest_window_disable_dimming (MODEST_WINDOW (self));
+       while (list) {
+               gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
+               list = g_list_next (list);
+       }
+       modest_window_enable_dimming (MODEST_WINDOW (self));
+
+       /* Free */
+       g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+       g_list_free (rows);
+
+       /* Let header view grab the focus if it's being shown */
+       if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
+               gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
+       } else {
+               if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
+               else
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
+       }
+
+       /* Check dimming rules */
+        modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+
+       /* Show changes */
+       gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
+}
+
+ModestMainWindowStyle
+modest_main_window_get_style (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       return priv->style;
+}
+
+static void
+toolbar_resize (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;
+       GtkWidget *widget;
+       gint static_button_size;
+       ModestWindowMgr *mgr;
+
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       mgr = modest_runtime_get_window_mgr ();
+       static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
+
+       if (parent_priv->toolbar) {
+               /* left size buttons */
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
+       }
+               
+}
+
+
+
+static gboolean
+modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
+{
+       if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+               ModestWindowPrivate *parent_priv;
+               ModestWindowMgr *mgr;
+               gboolean is_fullscreen;
+               GtkAction *fs_toggle_action;
+               gboolean active;
+               
+               mgr = modest_runtime_get_window_mgr ();
+               
+               is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
+
+               parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
+               
+               fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
+               active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
+               if (is_fullscreen != active) {
+                       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
+               }
+
+               toolbar_resize (MODEST_MAIN_WINDOW (widget));
+       }
+
+       return FALSE;
+
+}
+
+static void 
+modest_main_window_show_toolbar (ModestWindow *self,
+                                gboolean show_toolbar)
+{
+       ModestMainWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;        
+       GtkWidget *reply_button = NULL, *menu = NULL;
+       GtkWidget *placeholder = NULL;
+       gint insert_index;
+       const gchar *action_name;
+       GtkAction *action;
+
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       /* Set optimized view status */
+       priv->optimized_view = !show_toolbar;
+
+       if (!parent_priv->toolbar) {
+               parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
+                                                                 "/ToolBar");
+               gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
+
+               priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
+               priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
+               priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
+               priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
+               toolbar_resize (MODEST_MAIN_WINDOW (self));
+               
+               /* Add ProgressBar (Transfer toolbar) */ 
+               priv->progress_bar = modest_progress_bar_new ();
+               gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
+               placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
+               insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
+               gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
+               gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
+               
+               /* Connect cancel 'clicked' signal to abort progress mode */
+               g_signal_connect(priv->cancel_toolitem, "clicked",
+                                G_CALLBACK(cancel_progressbar),
+                                self);
+               
+               /* Add it to the observers list */
+               priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
+
+               /* Add to window */
+               hildon_window_add_toolbar (HILDON_WINDOW (self), 
+                                          GTK_TOOLBAR (parent_priv->toolbar));
+
+               /* Set reply button tap and hold menu */
+               reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
+                                                         "/ToolBar/ToolbarMessageReply");
+               menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
+                                                 "/ToolbarReplyCSM");
+               gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
+
+               /* Set send & receive button tap and hold menu */
+               update_menus (MODEST_MAIN_WINDOW (self));
+       }
+       
+       if (show_toolbar) {
+               /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
+               /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
+               gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
+
+               gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
+               if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
+                       set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
+               else
+                       set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
+       } else {
+               gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
+
+       }
+
+       /* Update also the actions (to update the toggles in the
+          menus), we have to do it manually because some other window
+          of the same time could have changed it (remember that the
+          toolbar fullscreen mode is shared by all the windows of the
+          same type */
+       if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
+               action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
+       else
+               action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                                           show_toolbar);
+}
+
+static void
+on_account_inserted (TnyAccountStore *accoust_store,
+                     TnyAccount *account,
+                     gpointer user_data)
+{
+       /* Transport accounts and local ones (MMC and the Local
+          folders account do now cause menu changes */
+       if (TNY_IS_STORE_ACCOUNT (account) && 
+           modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
+               /* Update menus */
+               update_menus (MODEST_MAIN_WINDOW (user_data));
+       }
+}
+
+static void
+on_default_account_changed (ModestAccountMgr* mgr,
+                           gpointer user_data)
+{
+       update_menus (MODEST_MAIN_WINDOW (user_data));
+}
+
+static void
+on_account_removed (TnyAccountStore *accoust_store,
+                     TnyAccount *account,
+                     gpointer user_data)
+{
+       /* Transport accounts and local ones (MMC and the Local
+          folders account do now cause menu changes */
+       if (TNY_IS_STORE_ACCOUNT (account) && 
+           modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
+               update_menus (MODEST_MAIN_WINDOW (user_data));
+}
+
+static void
+on_account_changed (TnyAccountStore *account_store,
+                    TnyAccount *account,
+                    gpointer user_data)
+{
+       ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
+
+       /* Transport accounts and local ones (MMC and the Local
+          folders account do now cause menu changes */
+       if (TNY_IS_STORE_ACCOUNT (account)) {
+               /* We need to refresh the details widget because it could have changed */
+               if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
+                       modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
+
+               /* Update the menus as well, name could change */
+               if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
+                       update_menus (MODEST_MAIN_WINDOW (user_data));
+       }
+}
+
+/* 
+ * This function manages the key events used to navigate between
+ * header and folder views (when the window is in split view)
+ *
+ * FROM         KEY        ACTION
+ * -------------------------------------------------
+ * HeaderView   GDK_Left   Move focus to folder view
+ * FolderView   GDK_Right  Move focus to header view
+ *
+ * There is no need to scroll to selected row, the widgets will be the
+ * responsibles of doing that (probably managing the focus-in event
+ */
+static gboolean 
+on_inner_widgets_key_pressed (GtkWidget *widget,
+                             GdkEventKey *event,
+                             gpointer user_data)
+{
+       ModestMainWindowPrivate *priv;
+
+       if (event->type == GDK_KEY_RELEASE)
+               return FALSE;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
+
+       /* Do nothing if we're in SIMPLE style */
+       if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
+               return FALSE;
+
+       if (MODEST_IS_HEADER_VIEW (widget)) {
+               if (event->keyval == GDK_Left)
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
+               else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
+                       guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
+                       if (selected_headers > 1) {
+                               hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
+                               return TRUE;
+                       } else {
+                               GtkTreePath * cursor_path;
+                               gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
+                               if (cursor_path == NULL) {
+                                       GtkTreeSelection *selection;
+                                       GList *list;
+                                       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+                                       list = gtk_tree_selection_get_selected_rows (selection, NULL);
+
+                                       if (list != NULL)
+                                               gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
+                                       g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
+                                       g_list_free (list);
+                               }
+                       }
+               }
+       } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
+#if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
+               GtkTreePath *selected_path = NULL;
+               GtkTreePath *start_path = NULL;
+               GtkTreePath *end_path = NULL;
+               GList *selected;
+               GtkTreeSelection *selection;
+
+               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
+               selected = gtk_tree_selection_get_selected_rows (selection, NULL);
+               if (selected != NULL) {
+                       selected_path = (GtkTreePath *) selected->data;
+                       if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
+                                                            &start_path,
+                                                            &end_path)) {
+                               
+                               if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
+                                   (gtk_tree_path_compare (end_path, selected_path) != 1)) {
+                                       
+                                       /* Scroll to first path */
+                                       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
+                                                                     selected_path,
+                                                                     NULL,
+                                                                     TRUE,
+                                                                     0.5,
+                                                                     0.0);
+                               }
+                       }
+                       if (start_path)
+                               gtk_tree_path_free (start_path);
+                       if (end_path)
+                               gtk_tree_path_free (end_path);
+                       g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
+                       g_list_free (selected);
+               }
+#endif /* GTK_CHECK_VERSION */
+                       /* fix scroll */
+               gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
+       }
+
+       return FALSE;
+}
+
+static void
+set_alignment (GtkWidget *widget,
+              gpointer data)
+{
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
+       gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
+}
+
+static GtkWidget *
+create_empty_view (void)
+{
+       GtkLabel *label = NULL;
+       GtkWidget *align = NULL;
+
+       align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
+       label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
+       gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
+       gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
+
+       return GTK_WIDGET(align);
+}
+
+/*
+ * Free the returned string
+ */
+static gchar *
+get_gray_color_markup (GtkWidget *styled_widget)
+{
+       gchar *gray_color_markup = NULL;
+#ifndef MODEST_HAVE_HILDON0_WIDGETS
+       /* Obtain the secondary text color. We need a realized widget, that's why 
+          we get styled_widget from outside */
+       GdkColor color;
+       if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color)) 
+               gray_color_markup = modest_text_utils_get_color_string (&color);
+#endif /*MODEST_HAVE_HILDON0_WIDGETS*/
+       
+       if (!gray_color_markup) 
+               gray_color_markup = g_strdup ("#BBBBBB");
+
+       return gray_color_markup;
+}
+
+/*
+ * Free the returned string
+ */
+static gchar*
+create_device_name_visual_string (const gchar *device_name,
+                                 const gchar *gray_color_markup)
+{
+       gchar *tmp, *label;
+
+       /* We have to use "" to fill the %s of the translation. We can
+          not just use the device name because the device name is
+          shown in a different color, so it could not be included
+          into the <span> tag */
+       tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
+       label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
+                                        gray_color_markup, 
+                                        tmp, 
+                                        device_name);
+       g_free (tmp);
+
+       return label;
+}
+
+typedef struct
+{
+       GtkWidget *count_label;
+       GtkWidget *msg_count_label;
+       GtkWidget *size_label;
+       gchar *color_markup;
+} DetailsWidgets;
+
+static gchar *
+create_uint_label (const gchar *markup,
+                  const gchar *name,
+                  guint count)
+{
+       return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
+}
+
+static gchar *
+create_gchar_label (const gchar *markup,
+                   const gchar *name,
+                   gchar *count)
+{
+       return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
+}
+
+static void
+update_folder_stats_status_cb (ModestFolderStats stats,
+                              gpointer user_data)
+{
+       DetailsWidgets *widgets = (DetailsWidgets *) user_data;
+       gchar *label, *tmp;
+
+       label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
+       gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
+       g_free (label);
+
+       label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
+       gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
+       g_free (label);
+
+       if (widgets->size_label) {
+               tmp = modest_text_utils_get_display_size (stats.local_size);
+               label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
+               gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
+               g_free (label);
+               g_free (tmp);
+       }
+}
+
+static void
+update_folder_stats_cb (ModestFolderStats stats,
+                       gpointer user_data)
+{
+       DetailsWidgets *widgets = (DetailsWidgets *) user_data;
+
+       /* refresh data */
+       update_folder_stats_status_cb (stats, user_data);
+
+       /* frees. Note that the widgets could have been destroyed but
+          we still keep a reference */
+       g_free (widgets->color_markup);
+       if (widgets->count_label)
+               g_object_unref (widgets->count_label);
+       if (widgets->msg_count_label)
+               g_object_unref (widgets->msg_count_label);
+       if (widgets->size_label)
+       g_object_unref (widgets->size_label);
+       g_slice_free (DetailsWidgets, widgets);
+}
+
+static GtkWidget *
+create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
+{
+       /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
+       
+       GtkWidget *vbox;
+       GtkWidget *label_w;
+       gchar *label;
+       gchar *gray_color_markup;
+       DetailsWidgets *widgets;
+
+       vbox = gtk_vbox_new (FALSE, 0);
+       widgets = g_slice_new0 (DetailsWidgets);
+
+       gray_color_markup = get_gray_color_markup (styled_widget);
+       widgets->color_markup = g_strdup (gray_color_markup);
+
+       /* Account description: */
+       if (modest_tny_account_is_virtual_local_folders (account)
+               || (modest_tny_account_is_memory_card_account (account))) {
+       
+               /* Get device name */
+               gchar *device_name = NULL;
+               if (modest_tny_account_is_virtual_local_folders (account))
+                       device_name = modest_conf_get_string (modest_runtime_get_conf(),
+                                                     MODEST_CONF_DEVICE_NAME, NULL);
+               else
+                       device_name = g_strdup (tny_account_get_name (account));
+
+               label = create_device_name_visual_string ((const gchar *) device_name, 
+                                                         (const gchar *) gray_color_markup);
+               label_w = gtk_label_new (NULL);
+               gtk_label_set_markup (GTK_LABEL (label_w), label);
+               gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+               gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+               g_free (device_name);
+               g_free (label);
+       } else {
+               if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
+                       gtk_box_pack_start (GTK_BOX (vbox), 
+                               gtk_label_new (tny_account_get_name (account)), 
+                               FALSE, FALSE, 0);
+               } else {
+                       /* Other accounts, such as IMAP and POP: */
+                       
+                       GString *proto;
+                       gchar *tmp;
+       
+                       /* Put proto in uppercase */
+                       proto = g_string_new (tny_account_get_proto (account));
+                       proto = g_string_ascii_up (proto);
+                       
+                       /* note: mcen_fi_localroot_description is something like "%s account"
+                        * however, we should display "%s account: %s"... therefore, ugly tmp */
+                       tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
+                       label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
+                                                        gray_color_markup, tmp, tny_account_get_name (account));
+                       g_free (tmp);
+
+                       label_w = gtk_label_new (NULL);
+                       gtk_label_set_markup (GTK_LABEL (label_w), label);
+                       gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+                       gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+                       g_string_free (proto, TRUE);
+                       g_free (label);
+               }
+       }
+
+       /* Message count */
+       TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
+       label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
+       label_w = gtk_label_new (NULL);
+       gtk_label_set_markup (GTK_LABEL (label_w), label);
+       gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+       gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+       g_free (label);
+
+       widgets->msg_count_label = g_object_ref (label_w);
+
+       /* Folder count */
+       label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
+       label_w = gtk_label_new (NULL);
+       gtk_label_set_markup (GTK_LABEL (label_w), label);
+       gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+       gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+       g_free (label);
+
+       widgets->count_label = g_object_ref (label_w);
+
+       /* Size / Date */
+       if (modest_tny_account_is_virtual_local_folders (account)
+               || modest_tny_account_is_memory_card_account (account)) {
+
+               label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
+               
+               label_w = gtk_label_new (NULL);
+               gtk_label_set_markup (GTK_LABEL (label_w), label);
+               gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+               gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+               g_free (label);
+
+               widgets->size_label = g_object_ref (label_w);
+
+       } else if (TNY_IS_ACCOUNT(folder_store)) {
+               TnyAccount *account = TNY_ACCOUNT(folder_store);
+               
+               time_t last_updated;
+               const gchar *last_updated_string;
+               /* Get last updated from configuration */
+               last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), 
+                                                                   tny_account_get_id (account));
+
+               if (last_updated > 0) 
+                       last_updated_string = modest_text_utils_get_display_date(last_updated);
+               else
+                       last_updated_string = g_strdup (_("mcen_va_never"));
+
+               label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
+                                                gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
+               label_w = gtk_label_new (NULL);
+               gtk_label_set_markup (GTK_LABEL (label_w), label);
+               gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
+               gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
+               g_free (label);
+       }
+
+       g_free (gray_color_markup);
+
+       /* Refresh folder stats asynchronously */
+       modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
+                                                 update_folder_stats_cb,
+                                                 update_folder_stats_status_cb,
+                                                 widgets);
+
+       /* Set alignment */
+       gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
+
+       return vbox;
+}
+
+gboolean
+modest_main_window_send_receive_in_progress (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       return priv->send_receive_in_progress;
+}
+
+void 
+modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
+{
+       GtkAction *action = NULL;
+       GtkWidget *widget = NULL;
+       ModestMainWindowPrivate *priv = NULL;
+               
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       
+       priv->send_receive_in_progress  = TRUE;
+
+        action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");        
+       gtk_action_set_sensitive (action, FALSE);
+/*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
+/*     gtk_action_set_sensitive (action, FALSE); */
+        widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");      
+       gtk_widget_set_sensitive (widget, FALSE);
+} 
+
+void 
+modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
+{
+       GtkAction *action = NULL;
+       GtkWidget *widget = NULL;
+       ModestMainWindowPrivate *priv = NULL;
+               
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       priv->send_receive_in_progress  = FALSE;
+
+        action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");        
+       gtk_action_set_sensitive (action, TRUE);
+/*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");    */
+/*     gtk_action_set_sensitive (action, TRUE); */
+        widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");      
+       gtk_widget_set_sensitive (widget, TRUE);
+} 
+
+
+static void
+on_msg_count_changed (ModestHeaderView *header_view,
+                     TnyFolder *folder,
+                     TnyFolderChange *change,
+                     ModestMainWindow *main_window)
+{
+       gboolean refilter = FALSE;
+       gboolean folder_empty = FALSE;
+       gboolean all_marked_as_deleted = FALSE;
+       ModestMainWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
+       g_return_if_fail (TNY_IS_FOLDER(folder));
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
+
+       if (change != NULL) {
+               TnyFolderChangeChanged changed;
+
+               changed = tny_folder_change_get_changed (change);
+               /* If something changes */
+               if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
+                       folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
+               else
+                       folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
+
+               /* Play a sound (if configured) and make the LED blink  */
+               if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
+                       modest_platform_push_email_notification ();
+               }
+
+               if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
+                       refilter = TRUE;
+       } else {
+               folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
+       }
+
+       /* Check if all messages are marked to be deleted */
+       all_marked_as_deleted = modest_header_view_is_empty (header_view);
+       folder_empty = folder_empty || all_marked_as_deleted;
+
+       /* Set contents style of headers view */
+       if (folder_empty)  {
+               modest_main_window_set_contents_style (main_window,
+                                                      MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
+               gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
+       } else {
+               modest_main_window_set_contents_style (main_window,
+                                                      MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
+       }
+
+       if (refilter)
+               modest_header_view_refilter (header_view);
+}
+
+
+void 
+modest_main_window_set_contents_style (ModestMainWindow *self, 
+                                      ModestMainWindowContentsStyle style)
+{
+       ModestMainWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       /* We allow to set the same content style than the previously
+          set if there are details, because it could happen when we're
+          selecting different accounts consecutively */
+       if ((priv->contents_style == style) &&
+           (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
+               return;
+
+       /* Remove previous child. Delete it if it was an account
+          details widget */
+       GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
+       if (content) {
+               if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
+                       gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
+               }
+               
+               gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
+       }
+
+       priv->contents_style = style;
+
+       switch (priv->contents_style) {
+       case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
+               wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
+               modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
+                                                     TRUE);
+               if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
+               break;
+       case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
+       {
+               /* if we're started without main win, there may not be a folder
+                * view. this fixes a GLib-Critical */
+               if (priv->folder_view) {
+                       TnyFolderStore *selected_folderstore = 
+                               modest_folder_view_get_selected (priv->folder_view);
+                       if (TNY_IS_ACCOUNT (selected_folderstore)) {    
+                               priv->details_widget = create_details_widget (GTK_WIDGET (self),
+                                                               TNY_ACCOUNT (selected_folderstore));
+                               
+                               wrap_in_scrolled_window (priv->contents_widget, 
+                                                        priv->details_widget);
+                       }
+                       if (selected_folderstore)
+                               g_object_unref (selected_folderstore);
+                       modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
+                                                             FALSE);
+               }
+               if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
+               break;
+       }
+       case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
+               wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
+               modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
+                                                     FALSE);
+               if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
+                       gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
+               break;
+       default:
+               g_return_if_reached ();
+       }
+
+       /* Show */
+       gtk_widget_show_all (priv->contents_widget);
+}
+
+ModestMainWindowContentsStyle
+modest_main_window_get_contents_style (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       return priv->contents_style;
+}
+
+
+static void 
+on_configuration_key_changed (ModestConf* conf, 
+                             const gchar *key, 
+                             ModestConfEvent event,
+                             ModestConfNotificationId id, 
+                             ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       TnyAccount *account = NULL;
+
+       if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
+               return;
+
+       if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
+               return;
+
+       if (priv->folder_view) 
+               account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
+
+       if (account && TNY_IS_ACCOUNT (account) &&
+           strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
+               GList *children;
+               GtkLabel *label;
+               const gchar *device_name;
+               gchar *new_text, *gray_color_markup;
+               
+               /* Get label */
+               children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
+               label = GTK_LABEL (children->data);
+               
+               device_name = modest_conf_get_string (modest_runtime_get_conf(),
+                                                     MODEST_CONF_DEVICE_NAME, NULL);
+
+               gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
+               new_text = create_device_name_visual_string (device_name, gray_color_markup);
+               
+               gtk_label_set_markup (label, new_text);
+               gtk_widget_show (GTK_WIDGET (label));
+               
+               g_free (gray_color_markup);
+               g_free (new_text);
+               g_list_free (children);
+       }
+       g_object_unref (account);
+}
+
+static gboolean
+set_toolbar_transfer_mode (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
+       
+       if (priv->progress_bar_timeout > 0) {
+               g_source_remove (priv->progress_bar_timeout);
+               priv->progress_bar_timeout = 0;
+       }
+
+       return FALSE;
+}
+
+static void 
+set_toolbar_mode (ModestMainWindow *self, 
+                 ModestToolBarModes mode)
+{
+       ModestWindowPrivate *parent_priv = NULL;
+       ModestMainWindowPrivate *priv = NULL;
+       GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
+       
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
+
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       /* In case this was called before the toolbar exists: */
+       if (!(parent_priv->toolbar))
+               return;
+
+       g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
+       
+       sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
+       refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
+       cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
+
+       /* Sets current toolbar mode */
+       priv->current_toolbar_mode = mode;
+
+        /* Checks the dimming rules */
+        modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+
+       /* Show and hide toolbar items */
+       switch (mode) {
+       case TOOLBAR_MODE_NORMAL:
+               if (sort_action)
+                       gtk_action_set_visible (sort_action, TRUE);
+               if (refresh_action)
+                       gtk_action_set_visible (refresh_action, TRUE);
+               if (priv->progress_toolitem) {
+                       gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
+                       gtk_widget_hide (priv->progress_toolitem);
+               }
+               if (priv->progress_bar)
+                       gtk_widget_hide (priv->progress_bar);
+               
+               if (cancel_action)
+                       gtk_action_set_visible (cancel_action, FALSE);
+
+               /* Hide toolbar if optimized view is enabled */
+               if (priv->optimized_view)
+                       gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
+               break;
+       case TOOLBAR_MODE_TRANSFER:
+               if (sort_action)
+                       gtk_action_set_visible (sort_action, FALSE);
+               if (refresh_action)
+                       gtk_action_set_visible (refresh_action, FALSE);
+               if (cancel_action)
+                       gtk_action_set_visible (cancel_action, TRUE);
+               if (priv->progress_bar)
+                       gtk_widget_show (priv->progress_bar);
+               if (priv->progress_toolitem) {
+                       gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
+                       gtk_widget_show (priv->progress_toolitem);
+               }
+
+               /* Show toolbar if it's hiden (optimized view ) */
+               if (priv->optimized_view)
+                       gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
+               break;
+       default:
+               g_return_if_reached ();
+       }
+}
+
+gboolean
+modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
+}
+
+static void
+cancel_progressbar (GtkToolButton *toolbutton,
+                   ModestMainWindow *self)
+{
+       GSList *tmp;
+       ModestMainWindowPrivate *priv;
+       
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+
+       /* Get operation observers and cancel all the operations */
+       tmp = priv->progress_widgets;
+       while (tmp) {
+               modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
+               tmp=g_slist_next(tmp);
+       }
+}
+
+static gboolean
+observers_empty (ModestMainWindow *self)
+{
+       GSList *tmp = NULL;
+       ModestMainWindowPrivate *priv;
+       gboolean is_empty = TRUE;
+       guint pending_ops = 0;
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       tmp = priv->progress_widgets;
+
+       /* Check all observers */
+       while (tmp && is_empty)  {
+               pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
+               is_empty = pending_ops == 0;
+               
+               tmp = g_slist_next(tmp);
+       }
+       
+       return is_empty;
+}
+
+
+/**
+ * Gets the toolbar mode needed for each mail operation. It stores in
+ * @mode_changed if the toolbar mode has changed or not
+ */
+static ModestToolBarModes
+get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
+                                     ModestMailOperation *mail_op,
+                                     gboolean *mode_changed)
+{
+       ModestToolBarModes mode;
+       ModestMainWindowPrivate *priv;
+
+       *mode_changed = FALSE;
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+
+       /* Get toolbar mode from operation id*/
+       switch (modest_mail_operation_get_type_operation (mail_op)) {
+       case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
+       case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
+               mode = TOOLBAR_MODE_TRANSFER;
+               if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
+                       *mode_changed = TRUE;
+               break;
+       default:
+               mode = TOOLBAR_MODE_NORMAL;             
+       }
+       return mode;
+}
+
+static void 
+on_mail_operation_started (ModestMailOperation *mail_op,
+                          gpointer user_data)
+{
+       ModestMainWindow *self;
+       ModestMailOperationTypeOperation op_type;
+       ModestMainWindowPrivate *priv;
+       ModestToolBarModes mode;
+       GSList *tmp;
+       gboolean mode_changed = FALSE;
+       TnyAccount *account = NULL;
+
+       self = MODEST_MAIN_WINDOW (user_data);
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+
+       /* Do not show progress for receiving operations if the
+          account is the local account or the MMC one */
+       op_type = modest_mail_operation_get_type_operation (mail_op);
+       account = modest_mail_operation_get_account (mail_op);
+       if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
+               gboolean is_remote;
+
+               is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
+                             modest_tny_account_is_memory_card_account (account));
+               if (!is_remote) {
+                       g_object_unref (account);
+                       return;
+               }
+
+               /* Show information banner. Remove old timeout */
+               if (priv->opening_banner_timeout > 0) {
+                       g_source_remove (priv->opening_banner_timeout);
+                       priv->opening_banner_timeout = 0;
+               }
+               /* Create a new timeout */
+               priv->opening_banner_timeout = 
+                       g_timeout_add (2000, show_opening_banner, self);
+       }
+
+       /* Not every mail operation has account, noop does not */
+       if (account)
+               g_object_unref (account);
+              
+       /* Get toolbar mode from operation id*/
+       mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
+
+       /* Add operation observers and change toolbar if neccessary*/
+       tmp = priv->progress_widgets;
+       if (mode == TOOLBAR_MODE_TRANSFER) {
+               if (mode_changed) {
+                       GObject *source = modest_mail_operation_get_source(mail_op);
+                       if (G_OBJECT (self) == source) {
+                               set_toolbar_transfer_mode(self);
+                       }
+                       g_object_unref (source);
+               }
+
+               while (tmp) {
+                       modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
+                                                             mail_op);
+                       tmp = g_slist_next (tmp);
+               }
+       }
+
+       /* Update the main menu as well, we need to explicitely do
+          this in order to enable/disable accelerators */
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+}
+
+static void 
+on_mail_operation_finished (ModestMailOperation *mail_op,
+                           gpointer user_data)
+{
+       ModestToolBarModes mode;
+       ModestMailOperationTypeOperation op_type;
+       GSList *tmp = NULL;
+       ModestMainWindow *self;
+       gboolean mode_changed;
+       TnyAccount *account = NULL;
+       ModestMainWindowPrivate *priv;
+
+       self = MODEST_MAIN_WINDOW (user_data);
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+
+       /* The mail operation was not added to the progress objects if
+          the account was the local account or the MMC one */
+       op_type = modest_mail_operation_get_type_operation (mail_op);
+       account = modest_mail_operation_get_account (mail_op);
+       if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
+               gboolean is_remote;
+
+               is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
+                             modest_tny_account_is_memory_card_account (account));
+               if (!is_remote) {
+                       g_object_unref (account);
+                       return;
+               }
+
+               /* Remove old timeout */
+               if (priv->opening_banner_timeout > 0) {
+                       g_source_remove (priv->opening_banner_timeout);
+                       priv->opening_banner_timeout = 0;
+               }
+
+               /* Remove the banner if exists */
+               if (priv->opening_banner) {
+                       gtk_widget_destroy (priv->opening_banner);
+                       priv->opening_banner = NULL;
+               }
+       }
+
+       /* Not every mail operation has account, noop does not */
+       if (account)
+               g_object_unref (account);
+
+       /* Get toolbar mode from operation id*/
+       mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
+
+       /* Change toolbar mode */
+       tmp = priv->progress_widgets;
+       if (mode == TOOLBAR_MODE_TRANSFER) {                    
+               while (tmp) {
+                       modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
+                                                                mail_op);
+                       tmp = g_slist_next (tmp);
+               }
+               
+               /* If no more operations are being observed, NORMAL mode is enabled again */
+               if (observers_empty (self)) {
+                       set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
+               }
+       }
+}
+
+static void
+on_queue_changed (ModestMailOperationQueue *queue,
+                 ModestMailOperation *mail_op,
+                 ModestMailOperationQueueNotification type,
+                 ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+
+       if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
+               priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
+                                                              G_OBJECT (mail_op),
+                                                              "operation-started",
+                                                              G_CALLBACK (on_mail_operation_started),
+                                                              self);
+               priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
+                                                              G_OBJECT (mail_op),
+                                                              "operation-finished",
+                                                              G_CALLBACK (on_mail_operation_finished),
+                                                              self);
+       } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
+               priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
+                                                                 G_OBJECT (mail_op),
+                                                                 "operation-started");
+               priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
+                                                                 G_OBJECT (mail_op),
+                                                                 "operation-finished");
+       }
+}
+
+static void
+set_account_visible(ModestMainWindow *self, const gchar *acc_name)
+{
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       GtkAction *action;
+       ModestAccountMgr *mgr;
+       ModestAccountSettings *settings;
+       ModestServerAccountSettings *store_settings = NULL;
+
+       /* Get account data */
+       mgr = modest_runtime_get_account_mgr ();
+       settings = modest_account_mgr_load_account_settings (mgr, acc_name);
+       if (settings)
+               store_settings = modest_account_settings_get_store_settings (settings);
+
+       /* Set the new visible & active account */
+       if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) { 
+               const gchar *account_name;
+
+               account_name = modest_account_settings_get_account_name (settings);
+
+               modest_folder_view_set_account_id_of_visible_server_account 
+                       (priv->folder_view,
+                        modest_server_account_settings_get_account_name (store_settings));
+               modest_folder_view_select_first_inbox_or_local (priv->folder_view);
+               modest_window_set_active_account (MODEST_WINDOW (self), account_name);
+
+               action = gtk_action_group_get_action (priv->view_additions_group, account_name);
+               if (action != NULL) {
+                       if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
+                               modest_utils_toggle_action_set_active_block_notify (
+                                       GTK_TOGGLE_ACTION (action),
+                                       TRUE);
+                       }
+               }
+       }
+       
+       /* Free */
+       if (settings) {
+               g_object_unref (store_settings);
+               g_object_unref (settings);
+       }
+}
+
+/* Make sure that at least one account is "viewed": */
+static void
+set_at_least_one_account_visible(ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
+       ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
+
+       if (!(priv->folder_view)) {
+               /* It is too early to do this. */
+               return; 
+       }
+       
+       const gchar *active_server_account_name = 
+               modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
+       
+       if (!active_server_account_name ||
+               !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
+       {
+               gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
+               gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
+               if (default_modest_name) {
+                       set_account_visible (self, default_modest_name);
+               } else if (first_modest_name) {
+                       set_account_visible (self, first_modest_name);
+               }
+               g_free (first_modest_name);
+               g_free (default_modest_name);
+       }
+}
+
+static void 
+on_show_account_action_toggled  (GtkToggleAction *action,
+                                  gpointer user_data)
+{
+       ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
+
+       const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
+       if (gtk_toggle_action_get_active (action))
+               set_account_visible (self, acc_name);
+}
+
+static void
+refresh_account (const gchar *account_name)
+{
+       ModestWindow *win;
+       
+       /* win must already exists here, obviously */ 
+       win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
+                                                FALSE);
+       if (!win) {
+               g_warning ("%s: BUG: no main window!", __FUNCTION__);
+               return;
+       }
+       
+       /* If account_name == NULL, we must update all (option All) */
+       if (!account_name)
+               modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
+       else
+               modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
+       
+}
+
+static void 
+on_refresh_account_action_activated  (GtkAction *action,
+                                     gpointer user_data)
+{
+       refresh_account ((const gchar*) user_data);
+}
+
+static void
+on_send_receive_csm_activated (GtkMenuItem *item,
+                              gpointer user_data)
+{
+       refresh_account ((const gchar*) user_data);
+}
+
+static gboolean
+on_zoom_minus_plus_not_implemented (ModestWindow *window)
+{
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
+
+       hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
+       return FALSE;
+
+}
+
+static gboolean
+on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
+{
+       ModestMainWindow *main_window = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
+       main_window = MODEST_MAIN_WINDOW (userdata);
+       
+       /* Update toolbar dimming state */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
+
+       return FALSE;
+}
+
+static gboolean
+on_header_view_focus_in (GtkWidget *widget,
+                        GdkEventFocus *event,
+                        gpointer userdata)
+{
+       ModestMainWindow *main_window = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
+
+       main_window = MODEST_MAIN_WINDOW (userdata);
+
+       /* Update toolbar dimming state */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
+
+       return FALSE;
+}
+
+static void 
+on_folder_selection_changed (ModestFolderView *folder_view,
+                            TnyFolderStore *folder_store, 
+                            gboolean selected,
+                            ModestMainWindow *main_window)
+{
+       ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
+       GtkAction *action = NULL;
+       gboolean show_reply = TRUE;
+       gboolean show_forward = TRUE;
+       gboolean show_cancel_send = FALSE;
+       gboolean show_clipboard = TRUE;
+       gboolean show_delete = TRUE;
+
+       if (selected) {
+               if (TNY_IS_ACCOUNT (folder_store)) {
+                       show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
+               } else if (TNY_IS_FOLDER (folder_store)) {
+                       if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
+                               TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
+                                       TNY_FOLDER (folder_store));
+                               switch (folder_type) {
+                               case TNY_FOLDER_TYPE_DRAFTS:
+                                       show_clipboard = show_delete = TRUE;
+                                       show_reply = show_forward = show_cancel_send = FALSE;
+                                       break;
+                               case TNY_FOLDER_TYPE_SENT:
+                                       show_forward = show_clipboard = show_delete = TRUE;
+                                       show_reply = show_cancel_send = FALSE;
+                                       break;
+                               case TNY_FOLDER_TYPE_OUTBOX:
+                                       show_clipboard = show_delete = show_cancel_send = TRUE;
+                                       show_reply = show_forward = FALSE;
+                                       break;
+                               case TNY_FOLDER_TYPE_INVALID:
+                                       g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
+                                       break;
+                               default:
+                                       show_reply = show_forward = show_clipboard = show_delete = TRUE;
+                                       show_cancel_send = FALSE;
+                               }
+                       } else {
+                               show_reply = show_forward = show_clipboard = show_delete = TRUE;
+                               show_cancel_send = FALSE;
+                       }
+               }
+       }
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
+       gtk_action_set_visible (action, show_reply);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
+       gtk_action_set_visible (action, show_reply);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
+       gtk_action_set_visible (action, show_forward);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
+       gtk_action_set_visible (action, show_cancel_send);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
+       gtk_action_set_visible (action, show_delete);
+
+       /* We finally call to the ui actions handler, after updating properly
+        * the header view CSM */
+       modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
+}
+
+gboolean 
+modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
+                                                  GtkTreeModel *model,
+                                                  GtkTreeRowReference *row_reference,
+                                                  ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = NULL;
+       GtkTreeModel *header_model = NULL;
+       GtkTreePath *path = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
+       g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+       header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
+
+       /* Do nothing if we changed the folder in the main view */
+       if (header_model != model)
+               return FALSE;
+
+       /* Select the message in the header view */
+       path = gtk_tree_row_reference_get_path (row_reference);
+       gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
+                                 path, NULL, FALSE);
+       gtk_tree_path_free (path);
+
+       return TRUE;
+}
+
+static void
+updating_banner_destroyed (gpointer data,
+                          GObject *where_the_object_was)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
+
+       priv->updating_banner = NULL;
+}
+
+static gboolean
+show_updating_banner (gpointer user_data)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
+
+       if (priv->updating_banner == NULL) {
+
+               /* We're outside the main lock */
+               gdk_threads_enter ();
+               priv->updating_banner = 
+                       modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
+                                                         _CS ("ckdg_pb_updating"));
+
+               /* We need this because banners in Maemo could be
+                  destroyed by dialogs so we need to properly update
+                  our reference to it */
+               g_object_weak_ref (G_OBJECT (priv->updating_banner),
+                                  updating_banner_destroyed,
+                                  user_data);
+               gdk_threads_leave ();
+       }
+
+       /* Remove timeout */
+       priv->updating_banner_timeout = 0;
+       return FALSE;
+}
+
+/**
+ * We use this function to show/hide a progress banner showing
+ * "Updating" while the header view is being filled. We're not showing
+ * it unless the update takes more than 2 seconds
+ *
+ * If starting = TRUE then the refresh is starting, otherwise it means
+ * that is has just finished
+ */
+static void 
+on_updating_msg_list (ModestHeaderView *header_view,
+                     gboolean starting,
+                     gpointer user_data)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
+       
+       /* Remove old timeout */
+       if (priv->updating_banner_timeout > 0) {
+               g_source_remove (priv->updating_banner_timeout);
+               priv->updating_banner_timeout = 0;
+       }
+
+       /* Create a new timeout */
+       if (starting) {
+               priv->updating_banner_timeout = 
+                       g_timeout_add (2000, show_updating_banner, user_data);
+       } else {
+               /* Remove the banner if exists */
+               if (priv->updating_banner) {
+                       gtk_widget_destroy (priv->updating_banner);
+                       priv->updating_banner = NULL;
+               }
+       }
+}
+
+gboolean
+modest_main_window_screen_is_on (ModestMainWindow *self)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
+       
+       return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
+}
+
+static void
+remove_banners (ModestMainWindow *window)
+{
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
+
+       if (priv->opening_banner_timeout > 0) {
+               g_source_remove (priv->opening_banner_timeout);
+               priv->opening_banner_timeout = 0;
+       }
+
+       if (priv->opening_banner != NULL) {
+               gtk_widget_destroy (priv->opening_banner);
+               priv->opening_banner = NULL;
+       }
+       
+       if (priv->updating_banner_timeout > 0) {
+               g_source_remove (priv->updating_banner_timeout);
+               priv->updating_banner_timeout = 0;
+       }
+
+       if (priv->updating_banner != NULL) {
+               gtk_widget_destroy (priv->updating_banner);
+               priv->updating_banner = NULL;
+       }       
+}
+
+
+static void
+on_window_hide (GObject    *gobject,
+               GParamSpec *arg1,
+               gpointer    user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
+
+       if (!GTK_WIDGET_VISIBLE (gobject)) {
+               TnyFolderStore *folder_store;
+               ModestMainWindowPrivate *priv;
+               
+               /* Remove the currently shown banners */
+               remove_banners (MODEST_MAIN_WINDOW (gobject));
+
+               /* Force the folder view to sync the currently selected folder
+                  to save the read/unread status and to expunge messages */
+               priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
+               folder_store = modest_folder_view_get_selected (priv->folder_view);
+               if (TNY_IS_FOLDER (folder_store)) {
+                       ModestMailOperation *mail_op;
+                       
+                       mail_op = modest_mail_operation_new (NULL);
+                       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
+                                                        mail_op);
+                       modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
+                       g_object_unref (mail_op);
+                       g_object_unref (folder_store);
+               }
+       }
+}
+
+static void
+on_window_destroy (GtkObject *widget, 
+                  gpointer user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
+
+       remove_banners (MODEST_MAIN_WINDOW (widget));
+}
+
+static void
+opening_banner_destroyed (gpointer data,
+                          GObject *where_the_object_was)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
+
+       priv->opening_banner = NULL;
+}
+
+static gboolean
+show_opening_banner (gpointer user_data)
+{
+       ModestMainWindowPrivate *priv = NULL;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
+
+       if (priv->opening_banner == NULL) {
+
+               /* We're outside the main lock */
+               gdk_threads_enter ();
+               priv->opening_banner = 
+                       modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
+                                                         _("mail_me_opening"));
+
+               /* We need this because banners in Maemo could be
+                  destroyed by dialogs so we need to properly update
+                  our reference to it */
+               g_object_weak_ref (G_OBJECT (priv->opening_banner),
+                                  opening_banner_destroyed,
+                                  user_data);
+
+               /* We need this because banners in Maemo could be
+                  destroyed by dialogs so we need to properly update
+                  our reference to it */
+               g_object_weak_ref (G_OBJECT (priv->updating_banner),
+                                  updating_banner_destroyed,
+                                  user_data);
+               gdk_threads_leave ();
+       }
+
+       /* Remove timeout */
+       priv->opening_banner_timeout = 0;
+       return FALSE;
+}
diff --git a/src/hildon2/modest-msg-edit-window-ui-dimming.h b/src/hildon2/modest-msg-edit-window-ui-dimming.h
new file mode 100644 (file)
index 0000000..6144a7b
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __MODEST_MSG_EDIT_WINDOW_UI_DIMMING_PRIV_H__
+#define __MODEST_MSG_EDIT_WINDOW_UI_DIMMING_PRIV_H__
+
+#include "modest-dimming-rules-group.h"
+#include "modest-ui-dimming-rules.h"
+
+G_BEGIN_DECLS
+
+
+/* Menu Dimming rules entries */
+static const ModestDimmingEntry modest_msg_edit_window_menu_dimming_entries [] = {
+
+       /* Format Menu */
+       { "/MenuBar/FormatMenu/SelectFontMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/FormatMenu/AlignmentMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/FormatMenu/AlignmentLeftMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/FormatMenu/AlignmentRightMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/FormatMenu/AlignmentCenterMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/FormatMenu/InsertImageMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/EditMenu/SelectAllMenu", G_CALLBACK (modest_ui_dimming_rules_on_select_all) },      
+       { "/MenuBar/EditMenu/UndoMenu", G_CALLBACK (modest_ui_dimming_rules_on_undo) }, 
+       { "/MenuBar/EditMenu/RedoMenu", G_CALLBACK (modest_ui_dimming_rules_on_redo) }, 
+       { "/MenuBar/EditMenu/PasteMenu", G_CALLBACK (modest_ui_dimming_rules_on_editor_paste) },        
+       { "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu", G_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment) }, 
+       { "/MenuBar/AttachmentsMenu/InsertImageMenu", G_CALLBACK (modest_ui_dimming_rules_on_set_style) },
+       { "/MenuBar/EmailMenu/SendMenu", G_CALLBACK (modest_ui_dimming_rules_on_send) },
+       { "/MenuBar/EmailMenu/SaveToDraftsMenu", G_CALLBACK (modest_ui_dimming_rules_on_save_to_drafts) },
+
+};
+
+/* Menu Dimming rules entries */
+static const ModestDimmingEntry modest_msg_edit_window_toolbar_dimming_entries [] = {
+
+       /* Toolbar */
+       { "/ToolBar/ToolbarSend", G_CALLBACK(modest_ui_dimming_rules_on_send) },
+       { "/ToolBar/ActionsBold", G_CALLBACK(modest_ui_dimming_rules_on_set_style) },
+       { "/ToolBar/ActionsItalics", G_CALLBACK(modest_ui_dimming_rules_on_set_style) },
+};
+
+/* Clipboard Dimming rules entries */
+static const ModestDimmingEntry modest_msg_edit_window_clipboard_dimming_entries [] = {
+
+       /* Toolbar */
+       { "/MenuBar/EditMenu/CutMenu", G_CALLBACK(modest_ui_dimming_rules_on_cut) },
+       { "/MenuBar/EditMenu/CopyMenu", G_CALLBACK(modest_ui_dimming_rules_on_copy) },
+       { "/MenuBar/EditMenu/PasteMenu", G_CALLBACK(modest_ui_dimming_rules_on_editor_paste) },
+};
+
+G_END_DECLS
+#endif /* __MODEST_MSG_VIEW_WINDOW_UI_PRIV_H__ */
diff --git a/src/hildon2/modest-msg-edit-window.c b/src/hildon2/modest-msg-edit-window.c
new file mode 100644 (file)
index 0000000..511eb0c
--- /dev/null
@@ -0,0 +1,3679 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <fcntl.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <tny-account-store.h>
+#include <tny-fs-stream.h>
+#include <tny-vfs-stream.h>
+#include <tny-camel-mem-stream.h>
+
+#include <config.h>
+
+#include <modest-account-mgr.h>
+#include <modest-account-mgr-helpers.h>
+
+#include <widgets/modest-msg-edit-window.h>
+#include <widgets/modest-combo-box.h>
+#include <widgets/modest-recpt-editor.h>
+#include <widgets/modest-attachments-view.h>
+
+#include <modest-runtime.h>
+
+#include "modest-platform.h"
+#include "modest-icon-names.h"
+#include "modest-widget-memory.h"
+#include "modest-window-priv.h"
+#include "modest-mail-operation.h"
+#include "modest-tny-platform-factory.h"
+#include "modest-tny-msg.h"
+#include "modest-tny-folder.h"
+#include "modest-tny-account.h"
+#include "modest-address-book.h"
+#include "modest-text-utils.h"
+#include <tny-simple-list.h>
+#include <wptextview.h>
+#include <wptextbuffer.h>
+#include "modest-scroll-area.h"
+#include "modest-msg-edit-window-ui-dimming.h"
+
+#include "modest-hildon-includes.h"
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+#include <hildon-widgets/hildon-color-chooser.h>
+#endif
+#include "widgets/modest-msg-edit-window-ui.h"
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#else
+#include <libgnomevfs/gnome-vfs-mime.h>
+#endif
+#include <modest-utils.h>
+#include "modest-maemo-utils.h"
+
+
+#define DEFAULT_FONT_SIZE 3
+#define DEFAULT_FONT 2
+#define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
+#define DEFAULT_SIZE_COMBOBOX_WIDTH 80
+#define DEFAULT_MAIN_VBOX_SPACING 6
+#define SUBJECT_MAX_LENGTH 1000
+#define IMAGE_MAX_WIDTH 560
+#define DEFAULT_FONT_SCALE 1.5
+
+static gboolean is_wp_text_buffer_started = FALSE;
+
+static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
+static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
+static void  modest_msg_edit_window_finalize     (GObject *obj);
+
+static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
+static void  body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
+static void  recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
+
+static void  text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
+static void  text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
+static void  text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
+static void  text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag, 
+                                   GtkTextIter *start, GtkTextIter *end,
+                                   gpointer userdata);
+static void  text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
+static void  subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
+static void  subject_field_insert_text (GtkEditable *editable, 
+                                       gchar *new_text,
+                                       gint new_text_length,
+                                       gint *position,
+                                       ModestMsgEditWindow *window);
+static void  modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
+                                                        gpointer userdata);
+static void  modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
+                                                gpointer userdata);
+static void  modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
+                                                gpointer userdata);
+static void  modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
+static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget, 
+                                                          GdkEventWindowState *event, 
+                                                          gpointer userdata);
+static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
+                                                    ModestRecptEditor *editor);
+static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
+                                                          ModestMsgEditWindow *window);
+
+/* ModestWindow methods implementation */
+static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
+static void modest_msg_edit_window_show_toolbar   (ModestWindow *window,
+                                                  gboolean show_toolbar);
+static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
+                                                          GdkEvent *event,
+                                                          ModestMsgEditWindow *window);
+static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
+static void subject_field_move_cursor (GtkEntry *entry,
+                                      GtkMovementStep step,
+                                      gint a1,
+                                      gboolean a2,
+                                      gpointer userdata);
+static void update_window_title (ModestMsgEditWindow *window);
+
+/* Find toolbar */
+static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
+                                                       ModestMsgEditWindow *window);
+static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
+                                                      ModestMsgEditWindow *window);
+static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
+                                                         const gchar *str,
+                                                         GtkTextIter *match_start,
+                                                         GtkTextIter *match_end);
+
+static void remove_tags (WPTextBuffer *buffer);
+
+static void on_account_removed (TnyAccountStore *account_store, 
+                               TnyAccount *account,
+                               gpointer user_data);
+
+static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
+static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
+static gdouble get_zoom_do_nothing (ModestWindow *window);
+
+static void init_window (ModestMsgEditWindow *obj);
+
+gboolean scroll_drag_timeout (gpointer userdata);
+static void correct_scroll (ModestMsgEditWindow *w);
+static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
+static void text_buffer_end_user_action (GtkTextBuffer *buffer,
+                                        ModestMsgEditWindow *userdata);
+static void text_buffer_mark_set (GtkTextBuffer *buffer,
+                                 GtkTextIter *iter,
+                                 GtkTextMark *mark,
+                                 ModestMsgEditWindow *userdata);
+static void vadj_changed (GtkAdjustment *adj, 
+                         ModestMsgEditWindow *window);
+
+static void DEBUG_BUFFER (WPTextBuffer *buffer)
+{
+#ifdef DEBUG
+       GtkTextIter iter;
+       g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
+
+       gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
+       while (!gtk_text_iter_is_end (&iter)) {
+               GString *output = g_string_new ("");
+               GSList *toggled_tags;
+               GSList *node;
+
+               toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
+               g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
+               for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
+                       GtkTextTag *tag = (GtkTextTag *) node->data;
+                       const gchar *name;
+                       g_object_get (G_OBJECT (tag), "name", &name, NULL);
+                       output = g_string_append (output, name);
+                       g_string_append (output, " ");
+               }
+               output = g_string_append (output, "] OPENED [ ");
+               toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
+               for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
+                       GtkTextTag *tag = (GtkTextTag *) node->data;
+                       const gchar *name;
+                       g_object_get (G_OBJECT (tag), "name", &name, NULL);
+                       output = g_string_append (output, name);
+                       g_string_append (output, " ");
+               }
+               output = g_string_append (output, "]\n");
+               g_message ("%s", output->str);
+               g_string_free (output, TRUE);
+               gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
+       }
+       g_message ("END BUFFER");
+#endif
+}
+
+
+/* static gboolean */
+/* on_key_pressed (GtkWidget *self, */
+/*             GdkEventKey *event, */
+/*             gpointer user_data); */
+
+/* list my signals */
+enum {
+       /* MY_SIGNAL_1, */
+       /* MY_SIGNAL_2, */
+       LAST_SIGNAL
+};
+
+typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
+struct _ModestMsgEditWindowPrivate {
+       GtkWidget   *msg_body;
+       GtkWidget   *frame;
+       GtkWidget   *header_box;
+       
+       ModestPairList *from_field_protos;
+       GtkWidget   *from_field;
+       gchar       *original_account_name;
+       
+       GtkWidget   *to_field;
+       GtkWidget   *cc_field;
+       GtkWidget   *bcc_field;
+       GtkWidget   *subject_field;
+       GtkWidget   *attachments_view;
+       GtkWidget   *priority_icon;
+       GtkWidget   *add_attachment_button;
+
+       GtkWidget   *cc_caption;
+       GtkWidget   *bcc_caption;
+       gboolean     update_caption_visibility;
+       GtkWidget   *attachments_caption;
+
+       GtkTextBuffer *text_buffer;
+
+       GtkWidget   *font_size_toolitem;
+       GtkWidget   *font_face_toolitem;
+       GtkWidget   *font_color_button;
+       GSList      *font_items_group;
+       GtkWidget   *font_tool_button_label;
+       GSList      *size_items_group;
+       GtkWidget   *size_tool_button_label;
+       
+       GtkWidget   *find_toolbar;
+       gchar       *last_search;
+
+       GtkWidget   *font_dialog;
+
+       GtkWidget   *scroll;
+       guint        scroll_drag_timeout_id;
+       gdouble      last_upper;
+
+       gint next_cid;
+       TnyList *attachments;
+       TnyList *images;
+       guint64 images_size;
+       gint images_count;
+
+       TnyHeaderFlags priority_flags;
+       
+       gboolean    can_undo, can_redo;
+       gulong      clipboard_change_handler_id;
+       gulong      default_clipboard_change_handler_id;
+       gulong      account_removed_handler_id;
+       guint       clipboard_owner_idle;
+       gchar       *clipboard_text;
+
+       TnyMsg      *draft_msg;
+       TnyMsg      *outbox_msg;
+       gchar       *msg_uid;
+
+       gboolean    sent;
+};
+
+#define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                    MODEST_TYPE_MSG_EDIT_WINDOW, \
+                                                    ModestMsgEditWindowPrivate))
+/* globals */
+static GtkWindowClass *parent_class = NULL;
+
+/* uncomment the following if you have defined any signals */
+/* static guint signals[LAST_SIGNAL] = {0}; */
+
+GType
+modest_msg_edit_window_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestMsgEditWindowClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_msg_edit_window_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestMsgEditWindow),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_msg_edit_window_init,
+                       NULL
+               };
+               my_type = g_type_register_static (MODEST_TYPE_WINDOW,
+                                                 "ModestMsgEditWindow",
+                                                 &my_info, 0);
+
+       }
+       return my_type;
+}
+
+static void
+save_state (ModestWindow *self)
+{
+       modest_widget_memory_save (modest_runtime_get_conf(),
+                                  G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
+}
+
+
+static void
+restore_settings (ModestMsgEditWindow *self)
+{
+       ModestConf *conf = NULL;
+       GtkAction *action;
+       ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
+
+       conf = modest_runtime_get_conf ();
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
+
+       /* set initial state of cc and bcc */
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                              modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                              modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
+
+       /* Dim at start clipboard actions */
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
+       gtk_action_set_sensitive (action, FALSE);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
+       gtk_action_set_sensitive (action, FALSE);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
+       gtk_action_set_sensitive (action, FALSE);
+
+       modest_widget_memory_restore (conf,
+                                     G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
+}
+
+
+static void
+modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
+{
+       GObjectClass *gobject_class;
+       ModestWindowClass *modest_window_class;
+       gobject_class = (GObjectClass*) klass;
+       modest_window_class = (ModestWindowClass*) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_msg_edit_window_finalize;
+
+       modest_window_class->set_zoom_func = set_zoom_do_nothing;
+       modest_window_class->get_zoom_func = get_zoom_do_nothing;
+       modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
+       modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
+       modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
+       modest_window_class->save_state_func = save_state;
+       modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
+
+       g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
+}
+
+static void
+modest_msg_edit_window_init (ModestMsgEditWindow *obj)
+{
+       ModestMsgEditWindowPrivate *priv;
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
+
+       priv->msg_body      = NULL;
+       priv->frame         = NULL;
+       priv->from_field    = NULL;
+       priv->to_field      = NULL;
+       priv->cc_field      = NULL;
+       priv->bcc_field     = NULL;
+       priv->subject_field = NULL;
+       priv->attachments   = TNY_LIST (tny_simple_list_new ());
+       priv->images        = TNY_LIST (tny_simple_list_new ());
+       priv->images_size   = 0;
+       priv->images_count  = 0;
+       priv->next_cid      = 0;
+
+       priv->cc_caption    = NULL;
+       priv->bcc_caption    = NULL;
+       priv->update_caption_visibility = FALSE;
+
+       priv->priority_flags = 0;
+
+       priv->find_toolbar = NULL;
+       priv->last_search = NULL;
+
+       priv->draft_msg = NULL;
+       priv->outbox_msg = NULL;
+       priv->msg_uid = NULL;
+
+       priv->can_undo = FALSE;
+       priv->can_redo = FALSE;
+       priv->clipboard_change_handler_id = 0;
+       priv->default_clipboard_change_handler_id = 0;
+       priv->account_removed_handler_id = 0;
+       priv->clipboard_owner_idle = 0;
+       priv->clipboard_text = NULL;
+       priv->sent = FALSE;
+
+       priv->scroll_drag_timeout_id = 0;
+       priv->last_upper = 0.0;
+
+       priv->font_dialog = NULL;
+
+       modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
+                                           GTK_WINDOW(obj),"applications_email_editor");
+
+       if (!is_wp_text_buffer_started) {
+               is_wp_text_buffer_started = TRUE;
+               wp_text_buffer_library_init ();
+       }
+
+       init_window (obj);
+       
+       hildon_program_add_window (hildon_program_get_instance(),
+                                  HILDON_WINDOW(obj));
+}
+
+
+/* FIXME: this is a dup from the one in gtk/ */
+
+/** 
+ * @result: A ModestPairList, which must be freed with modest_pair_list_free().
+ */
+static ModestPairList*
+get_transports (void)
+{
+       GSList *transports = NULL;
+       
+       ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
+       GSList *accounts = modest_account_mgr_account_names (account_mgr, 
+                                                            TRUE /* only enabled accounts. */); 
+                                               
+       GSList *cursor = accounts;
+       while (cursor) {
+               gchar *account_name = cursor->data;
+               gchar *from_string  = NULL;
+               if (account_name) {
+                       from_string = modest_account_mgr_get_from_string (account_mgr,
+                                                                         account_name);
+               }
+               
+               if (from_string && account_name) {
+                       gchar *name = account_name;
+                       ModestPair *pair = modest_pair_new ((gpointer) name,
+                                               (gpointer) from_string , TRUE);
+                       transports = g_slist_prepend (transports, pair);
+               }
+               
+               cursor = cursor->next;
+       }
+       g_slist_free (accounts); /* only free the accounts, not the elements,
+                                 * because they are used in the pairlist */
+       return transports;
+}
+
+static void window_focus (GtkWindow *window,
+                         GtkWidget *widget,
+                         gpointer userdata)
+{
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
+}
+
+gboolean
+scroll_drag_timeout (gpointer userdata)
+{
+       ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
+
+       correct_scroll_without_drag_check (win, TRUE);
+
+       priv->scroll_drag_timeout_id = 0;
+
+       return FALSE;
+}
+
+static void
+correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
+{
+       ModestMsgEditWindowPrivate *priv;
+       GtkTextMark *insert;
+       GtkTextIter iter;
+       GdkRectangle rectangle;
+       GtkAdjustment *vadj;
+       gdouble new_value;
+       gint offset;
+       GdkWindow *window;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
+
+       if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
+               return;
+
+       insert = gtk_text_buffer_get_insert (priv->text_buffer);
+       gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
+
+       gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
+       vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
+       offset = priv->msg_body->allocation.y;
+
+       new_value = vadj->value;
+       
+       if ((offset + rectangle.y + rectangle.height) > 
+           ((gint) (vadj->value +vadj->page_size))) {
+               new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
+               if (new_value > vadj->upper - vadj->page_size)
+                       new_value = vadj->upper - vadj->page_size;
+       } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
+               new_value = (offset + rectangle.y - vadj->page_size * 0.75);
+               if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
+                       new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
+               if (new_value < 0.0)
+                       new_value = 0.0;
+               if (new_value > vadj->value)
+                       new_value = vadj->value;
+       }
+
+       if (vadj->value != new_value) {
+               g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
+                                      "invalidated");
+               vadj->value = new_value;
+               gtk_adjustment_value_changed (vadj);
+               /* invalidate body */
+               window = gtk_widget_get_parent_window (priv->msg_body);
+               if (window)
+                       gdk_window_invalidate_rect (window, NULL, TRUE);
+       }
+
+}
+
+static void
+correct_scroll (ModestMsgEditWindow *w)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
+       if (gtk_grab_get_current () == priv->msg_body) {
+               if (priv->scroll_drag_timeout_id == 0) {
+                       priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
+                                                                     (gpointer) w);
+               }
+               return;
+       }
+
+       correct_scroll_without_drag_check (w, TRUE);
+}
+
+static void
+text_buffer_end_user_action (GtkTextBuffer *buffer,
+                            ModestMsgEditWindow *userdata)
+{
+
+       correct_scroll (userdata);
+}
+
+static void
+text_buffer_mark_set (GtkTextBuffer *buffer,
+                     GtkTextIter *iter,
+                     GtkTextMark *mark,
+                     ModestMsgEditWindow *userdata)
+{
+       gtk_text_buffer_begin_user_action (buffer);
+       gtk_text_buffer_end_user_action (buffer);
+}
+
+static void
+cut_clipboard_check (GtkTextView *text_view,
+                    gpointer userdata)
+{
+       GtkTextBuffer *buffer;
+       
+       buffer = gtk_text_view_get_buffer (text_view);
+       if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
+               g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
+       }
+}
+
+static void
+copy_clipboard_check (GtkTextView *text_view,
+                    gpointer userdata)
+{
+       GtkTextBuffer *buffer;
+       
+       buffer = gtk_text_view_get_buffer (text_view);
+       if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
+               g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
+       }
+}
+
+static void 
+vadj_changed (GtkAdjustment *adj,
+             ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (priv->last_upper != adj->upper) {
+               priv->last_upper = adj->upper;
+               correct_scroll (window);
+       }
+}
+
+static void
+attachment_deleted (ModestAttachmentsView *attachments_view,
+                   gpointer user_data)
+{
+       modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
+                                                  NULL);
+}
+
+static void
+connect_signals (ModestMsgEditWindow *obj)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
+
+       g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
+                         G_CALLBACK (text_buffer_refresh_attributes), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
+                         G_CALLBACK (text_buffer_can_undo), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
+                         G_CALLBACK (text_buffer_can_redo), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
+                          G_CALLBACK (body_changed), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
+                          G_CALLBACK (body_changed), obj);
+       g_signal_connect (G_OBJECT (obj), "window-state-event",
+                         G_CALLBACK (modest_msg_edit_window_window_state_event),
+                         NULL);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
+                         G_CALLBACK (text_buffer_end_user_action), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
+                         G_CALLBACK (text_buffer_mark_set), obj);
+       g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
+                               G_CALLBACK (text_buffer_apply_tag), obj);
+       g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook", 
+                                 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
+       g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook", 
+                                 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
+       g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook", 
+                                 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
+
+       g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
+                         G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
+
+       g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
+                         G_CALLBACK (msg_body_focus), obj);
+       g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
+                         G_CALLBACK (msg_body_focus), obj);
+       g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
+       g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
+                         "changed", G_CALLBACK (recpt_field_changed), obj);
+       g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
+                         "changed", G_CALLBACK (recpt_field_changed), obj);
+       g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
+                         "changed", G_CALLBACK (recpt_field_changed), obj);
+       g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
+       g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
+       g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
+
+       g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
+       g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
+
+       g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
+                         "changed",
+                         G_CALLBACK (vadj_changed),
+                         obj);
+
+       priv->clipboard_change_handler_id = 
+               g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
+                                 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
+       priv->default_clipboard_change_handler_id = 
+               g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
+                                 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
+
+       g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
+       g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
+       g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
+}
+
+static void
+init_window (ModestMsgEditWindow *obj)
+{
+       GtkWidget *from_caption, *to_caption, *subject_caption;
+       GtkWidget *main_vbox;
+       ModestMsgEditWindowPrivate *priv;
+       GtkActionGroup *action_group;
+       ModestWindowPrivate *parent_priv;
+       GdkPixbuf *window_icon = NULL;
+       GError *error = NULL;
+
+       GtkSizeGroup *size_group;
+       GtkWidget *subject_box;
+       GtkWidget *attachment_icon;
+       GtkWidget *window_box;
+#if (GTK_MINOR_VERSION >= 10)
+       GdkAtom deserialize_type;
+#endif
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
+
+       parent_priv->ui_manager = gtk_ui_manager_new();
+       action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
+       gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+
+       /* Add common actions */
+       gtk_action_group_add_actions (action_group,
+                                     modest_msg_edit_action_entries,
+                                     G_N_ELEMENTS (modest_msg_edit_action_entries),
+                                     obj);
+       gtk_action_group_add_toggle_actions (action_group,
+                                            modest_msg_edit_toggle_action_entries,
+                                            G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
+                                            obj);
+       gtk_action_group_add_radio_actions (action_group,
+                                           modest_msg_edit_alignment_radio_action_entries,
+                                           G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
+                                           GTK_JUSTIFY_LEFT,
+                                           G_CALLBACK (modest_ui_actions_on_change_justify),
+                                           obj);
+       gtk_action_group_add_radio_actions (action_group,
+                                           modest_msg_edit_priority_action_entries,
+                                           G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
+                                           0,
+                                           G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
+                                           obj);
+       gtk_action_group_add_radio_actions (action_group,
+                                           modest_msg_edit_file_format_action_entries,
+                                           G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
+                                           modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
+                                           G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
+                                           obj);
+       gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
+       g_object_unref (action_group);
+
+       /* Load the UI definition */
+       gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
+                                        &error);
+       if (error != NULL) {
+               g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
+               g_clear_error (&error);
+       }
+
+       /* Add accelerators */
+       gtk_window_add_accel_group (GTK_WINDOW (obj), 
+                                   gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
+
+       parent_priv->menubar = NULL;
+
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->from_field    = modest_combo_box_new (NULL, g_str_equal);
+
+       priv->to_field      = modest_recpt_editor_new ();
+       priv->cc_field      = modest_recpt_editor_new ();
+       priv->bcc_field     = modest_recpt_editor_new ();
+       subject_box = gtk_hbox_new (FALSE, 0);
+       priv->priority_icon = gtk_image_new ();
+       gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
+       priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
+       g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field), 
+                                        HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
+       gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
+       priv->add_attachment_button = gtk_button_new ();
+       GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
+       gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
+       gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
+       gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
+       attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
+       gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
+       gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
+       priv->attachments_view = modest_attachments_view_new (NULL);
+       
+       priv->header_box = gtk_vbox_new (FALSE, 0);
+       
+       from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
+       to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
+       priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
+       priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
+       subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
+       priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
+       g_object_unref (size_group);
+
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+       modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
+       modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
+       modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
+       gtk_size_group_add_widget (size_group, priv->subject_field);
+       gtk_size_group_add_widget (size_group, priv->attachments_view);
+       g_object_unref (size_group);
+
+       gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
+       gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
+
+
+       priv->msg_body = wp_text_view_new ();
+       gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
+       priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
+       g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
+       wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+#if (GTK_MINOR_VERSION >= 10)
+       gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
+       deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), 
+                                                                      NULL);
+       gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer), 
+                                                        deserialize_type, TRUE);
+#endif
+       wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+
+       priv->find_toolbar = hildon_find_toolbar_new (NULL);
+       gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
+
+/*     g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
+
+       priv->scroll = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
+       modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
+
+       main_vbox = gtk_vbox_new  (FALSE, DEFAULT_MAIN_VBOX_SPACING);
+
+       gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
+       priv->frame = gtk_frame_new (NULL);
+       gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
+
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
+       gtk_widget_show_all (GTK_WIDGET(priv->scroll));
+       
+       window_box = gtk_vbox_new (FALSE, 0);
+       gtk_container_add (GTK_CONTAINER(obj), window_box);
+
+       gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
+
+       gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
+
+       /* Set window icon */
+       window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG); 
+       if (window_icon) {
+               gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
+               g_object_unref (window_icon);
+       }       
+}
+       
+static void
+modest_msg_edit_window_disconnect_signals (ModestWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
+           g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY), 
+                                          priv->clipboard_change_handler_id))
+               g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), 
+                                            priv->clipboard_change_handler_id);
+       if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
+           g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), 
+                                          priv->default_clipboard_change_handler_id))
+               g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), 
+                                            priv->default_clipboard_change_handler_id);
+
+       if (priv->account_removed_handler_id && 
+           g_signal_handler_is_connected (modest_runtime_get_account_store (), 
+                                          priv->account_removed_handler_id))
+               g_signal_handler_disconnect(modest_runtime_get_account_store (), 
+                                          priv->account_removed_handler_id);
+}
+
+static void
+modest_msg_edit_window_finalize (GObject *obj)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
+       
+       /* Sanity check: shouldn't be needed, the window mgr should
+          call this function before */
+       modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
+
+       if (priv->font_dialog != NULL) {
+               gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
+       }
+
+       if (priv->clipboard_text != NULL) {
+               g_free (priv->clipboard_text);
+               priv->clipboard_text = NULL;
+       }
+       
+       if (priv->draft_msg != NULL) {
+               TnyHeader *header = tny_msg_get_header (priv->draft_msg);
+               if (TNY_IS_HEADER (header)) {
+                       ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
+                       modest_window_mgr_unregister_header (mgr, header);
+               }
+               g_object_unref (priv->draft_msg);
+               priv->draft_msg = NULL;
+       }
+       if (priv->outbox_msg != NULL) {
+               TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
+               if (TNY_IS_HEADER (header)) {
+                       ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
+                       modest_window_mgr_unregister_header (mgr, header);
+               }
+               g_object_unref (priv->outbox_msg);
+               priv->outbox_msg = NULL;
+       }
+       if (priv->scroll_drag_timeout_id > 0) {
+               g_source_remove (priv->scroll_drag_timeout_id);
+               priv->scroll_drag_timeout_id = 0;
+       }
+       if (priv->clipboard_owner_idle > 0) {
+               g_source_remove (priv->clipboard_owner_idle);
+               priv->clipboard_owner_idle = 0;
+       }
+       if (priv->original_account_name)
+               g_free (priv->original_account_name);
+       g_free (priv->msg_uid);
+       g_free (priv->last_search);
+       g_slist_free (priv->font_items_group);
+       g_slist_free (priv->size_items_group);
+       g_object_unref (priv->attachments);
+       g_object_unref (priv->images);
+
+       /* This had to stay alive for as long as the combobox that used it: */
+       modest_pair_list_free (priv->from_field_protos);
+       
+       G_OBJECT_CLASS(parent_class)->finalize (obj);
+}
+
+static GdkPixbuf *
+pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
+{
+       GdkPixbufLoader *loader;
+       GdkPixbuf *pixbuf;
+       guint64 size;
+       
+       size = 0;
+
+       loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
+
+       if (loader == NULL) {
+               if (stream_size)
+                       *stream_size = 0;
+               return NULL;
+       }
+
+       tny_stream_reset (TNY_STREAM (stream));
+       while (!tny_stream_is_eos (TNY_STREAM (stream))) {
+               GError *error = NULL;
+               unsigned char read_buffer[128];
+               gint readed;
+               readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
+               size += readed;
+               if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
+                       break;
+               }
+       }
+
+       pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+       if (pixbuf) 
+               g_object_ref (pixbuf);
+       gdk_pixbuf_loader_close (loader, NULL);
+       g_object_unref (loader);
+
+       if (!pixbuf)
+               return NULL;
+
+       if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
+               GdkPixbuf *new_pixbuf;
+               gint new_height;
+               new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
+                       gdk_pixbuf_get_width (pixbuf);
+               new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
+               g_object_unref (pixbuf);
+               pixbuf = new_pixbuf;
+       }
+
+       if (stream_size)
+               *stream_size = size;
+
+       return pixbuf;
+}
+
+static void
+replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
+{
+       ModestMsgEditWindowPrivate *priv;
+       TnyIterator *iter;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       for (iter = tny_list_create_iterator (attachments);
+            !tny_iterator_is_done (iter);
+            tny_iterator_next (iter)) {
+               TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
+               const gchar *cid = tny_mime_part_get_content_id (part);
+               const gchar *mime_type = tny_mime_part_get_content_type (part);
+               if ((cid != NULL)&&(mime_type != NULL)) {
+                       guint64 stream_size;
+                       TnyStream *stream = tny_mime_part_get_decoded_stream (part);
+                       GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
+
+
+                       g_object_unref (stream);
+
+                       if (pixbuf != NULL) {
+                               priv->images_count ++;
+                               priv->images_size += stream_size;
+                               wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
+                               g_object_unref (pixbuf);
+                       }
+               }
+               g_object_unref (part);
+       }
+       g_object_unref (iter);
+}
+
+static void
+get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
+{
+       TnyMimePart *parent = NULL;
+       const gchar *content_type = NULL;
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
+       
+       if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
+               parent = g_object_ref (msg);
+       } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
+               TnyList *parts = TNY_LIST (tny_simple_list_new ());
+               TnyIterator *iter;
+
+               tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
+               iter = tny_list_create_iterator (parts);
+               while (!tny_iterator_is_done (iter)) {
+                       TnyMimePart *part;
+                       part = TNY_MIME_PART (tny_iterator_get_current (iter));
+                       content_type = tny_mime_part_get_content_type (part);
+                       if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
+                               parent = part;
+                               break;
+                       } else {
+                               g_object_unref (part);
+                       }
+                       tny_iterator_next (iter);
+               }
+               g_object_unref (iter);
+               g_object_unref (parts);
+       }
+
+       if (parent != NULL) {
+               TnyList *parts = TNY_LIST (tny_simple_list_new ());
+               TnyIterator *iter;
+
+               tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
+               iter = tny_list_create_iterator (parts);
+               while (!tny_iterator_is_done (iter)) {
+                       TnyMimePart *part;
+                       part = TNY_MIME_PART (tny_iterator_get_current (iter));
+                       content_type = tny_mime_part_get_content_type (part);
+                       if (content_type && g_str_has_prefix (content_type, "image/")) {
+                               tny_list_prepend (priv->images, (GObject *) part);
+                       } 
+                       g_object_unref (part);
+                       tny_iterator_next (iter);
+               }
+               g_object_unref (iter);
+               g_object_unref (parts);
+               g_object_unref (parent);
+       }
+}
+
+static void
+update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
+{
+       TnyIterator *iter;
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       for (iter = tny_list_create_iterator (attachments) ; 
+            !tny_iterator_is_done (iter);
+            tny_iterator_next (iter)) {
+               TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
+               const gchar *cid = tny_mime_part_get_content_id (part);
+               if (cid != NULL) {
+                       char *invalid = NULL;
+                       gint int_cid = strtol (cid, &invalid, 10);
+                       if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
+                               priv->next_cid = int_cid + 1;
+                       }
+               }
+               g_object_unref (part);
+       }
+       g_object_unref (iter);
+}
+
+static void
+set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
+{
+       TnyHeader *header;
+       gchar *to, *cc, *bcc, *subject;
+       gchar *body;
+       ModestMsgEditWindowPrivate *priv;
+       GtkTextIter iter;
+       TnyHeaderFlags priority_flags;
+       TnyFolder *msg_folder;
+       gboolean is_html = FALSE;
+       
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
+       g_return_if_fail (TNY_IS_MSG (msg));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       header = tny_msg_get_header (msg);
+       to      = tny_header_dup_to (header);
+       cc      = tny_header_dup_cc (header);
+       bcc     = tny_header_dup_bcc (header);
+       subject = tny_header_dup_subject (header);
+       priority_flags = tny_header_get_priority (header);
+
+       if (to)
+               modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field),  to);
+       if (cc) {
+               modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field),  cc);
+               gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
+               gtk_widget_show (priv->cc_caption);
+       } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
+               gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
+               gtk_widget_hide (priv->cc_caption);
+       }
+       if (bcc) {
+               modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
+               gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
+               gtk_widget_show (priv->bcc_caption);
+       } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
+               gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
+               gtk_widget_hide (priv->bcc_caption);
+       } 
+       if (subject)
+               gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
+       modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
+                                                  priority_flags);
+
+       update_window_title (self);
+
+       wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+       body = modest_tny_msg_get_body (msg, TRUE, &is_html);
+
+       if ((body == NULL)||(body[0] == '\0')) {
+               g_free (body);
+               body = modest_text_utils_convert_to_html ("");
+               is_html = FALSE;
+       }
+       wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+       wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
+                                           (gchar *) body,
+                                           strlen (body));
+       wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
+       g_free (body);
+
+       /* Add attachments to the view */
+       modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
+       priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
+       if (tny_list_get_length (priv->attachments) == 0) {
+               gtk_widget_hide (priv->attachments_caption);
+       } else {
+               gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
+               gtk_widget_show_all (priv->attachments_caption);
+       }
+       get_related_images (self, msg);
+       update_next_cid (self, priv->attachments);
+       update_next_cid (self, priv->images);
+       replace_with_images (self, priv->images);
+
+       if (preserve_is_rich && !is_html) {
+               wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
+       /* Get the default format required from configuration */
+       } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
+               wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
+       }
+
+       /* Set the default focus depending on having already a To: field or not */
+       if ((!to)||(*to == '\0')) {
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
+       } else {
+               gtk_widget_grab_focus (priv->msg_body);
+       }
+
+       /* TODO: lower priority, select in the From: combo to the
+          value that comes from msg <- not sure, should it be
+          allowed? */
+       
+       DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
+
+       gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
+       gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
+
+       modest_msg_edit_window_set_modified (self, FALSE);
+
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+       text_buffer_can_undo (priv->text_buffer, FALSE, self);
+       text_buffer_can_redo (priv->text_buffer, FALSE, self);
+
+       if (priv->msg_uid) {
+               g_free (priv->msg_uid);
+               priv->msg_uid = NULL;
+       }
+
+       /* we should set a reference to the incoming message if it is a draft */
+       msg_folder = tny_msg_get_folder (msg);
+       if (msg_folder) {               
+               if (modest_tny_folder_is_local_folder (msg_folder)) {
+                       TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
+                       if (type == TNY_FOLDER_TYPE_INVALID)
+                               g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
+                       
+                       if (type == TNY_FOLDER_TYPE_DRAFTS) 
+                               priv->draft_msg = g_object_ref(msg);
+                       if (type == TNY_FOLDER_TYPE_OUTBOX)
+                               priv->outbox_msg = g_object_ref(msg);
+                       priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
+               }
+               g_object_unref (msg_folder);
+       }
+
+       g_free (to);
+       g_free (subject);
+       g_free (cc);
+       g_free (bcc);
+}
+
+static void
+menu_tool_button_clicked_popup (GtkMenuToolButton *item,
+                               gpointer data)
+{
+       GList *item_children, *node;
+       GtkWidget *bin_child;
+
+       bin_child = gtk_bin_get_child (GTK_BIN(item));
+
+       item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
+       
+       for (node = item_children; node != NULL; node = g_list_next (node)) {
+               if (GTK_IS_TOGGLE_BUTTON (node->data)) {
+                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
+               }
+       }
+       g_list_free (item_children);
+}
+
+static void
+menu_tool_button_dont_expand (GtkMenuToolButton *item)
+{
+       GtkWidget *box;
+       GList *item_children, *node;
+
+       box = gtk_bin_get_child (GTK_BIN (item));
+       gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
+       item_children = gtk_container_get_children (GTK_CONTAINER (box));
+       
+       for (node = item_children; node != NULL; node = g_list_next (node)) {
+               gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
+               if (GTK_IS_TOGGLE_BUTTON (node->data))
+                       gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
+               else if (GTK_IS_BUTTON (node->data))
+                       gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
+       }
+       g_list_free (item_children);
+}
+
+
+static void
+modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
+{
+       ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       GtkWidget *placeholder;
+       GtkWidget *tool_item;
+       gint insert_index;
+       gchar size_text[5];
+       gint size_index;
+       gint font_index;
+       GtkWidget *sizes_menu;
+       GtkWidget *fonts_menu;
+       GSList *radio_group = NULL;
+       GSList *node = NULL;
+       gchar *markup;
+
+       /* Toolbar */
+       parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
+       hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
+
+       /* Font color placeholder */
+       placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
+       insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
+
+       /* font color */
+       tool_item = GTK_WIDGET (gtk_tool_item_new ());
+       priv->font_color_button = hildon_color_button_new ();
+       GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
+       GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
+       gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
+       g_signal_connect_swapped (G_OBJECT (priv->font_color_button), 
+                                 "notify::color", 
+                                 G_CALLBACK (modest_msg_edit_window_color_button_change), 
+                                 window);
+
+       /* Font size and face placeholder */
+       placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
+       insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
+       /* font_size */
+       tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
+       priv->size_tool_button_label = gtk_label_new (NULL);
+       snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
+       markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
+                             size_text,"</span>", NULL);
+       gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
+       g_free (markup);
+       gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
+       sizes_menu = gtk_menu_new ();
+       priv->size_items_group = NULL;
+       radio_group = NULL;
+       for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
+               GtkWidget *size_menu_item;
+
+               snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
+               size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
+               radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
+               gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
+               gtk_widget_show (size_menu_item);
+
+               priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
+                       
+       }
+
+       for (node = radio_group; node != NULL; node = g_slist_next (node)) {
+               GtkWidget *item = (GtkWidget *) node->data;
+               g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
+                                 window);
+       }
+
+       priv->size_items_group = g_slist_reverse (priv->size_items_group);
+       gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
+       g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
+       gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+       menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
+       priv->font_size_toolitem = tool_item;
+
+       /* font face */
+       tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
+       priv->font_tool_button_label = gtk_label_new (NULL);
+       markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
+       gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
+       g_free(markup);
+       gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
+       fonts_menu = gtk_menu_new ();
+       priv->font_items_group = NULL;
+       radio_group = NULL;
+       for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
+               GtkWidget *font_menu_item;
+               GtkWidget *child_label;
+
+               font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
+               child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
+               markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>", 
+                                     wp_get_font_name (font_index), "</span>", NULL);
+               gtk_label_set_markup (GTK_LABEL (child_label), markup);
+               g_free (markup);
+               
+               radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
+               gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
+               gtk_widget_show (font_menu_item);
+
+               priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
+                       
+       }
+       for (node = radio_group; node != NULL; node = g_slist_next (node)) {
+               GtkWidget *item = (GtkWidget *) node->data;
+               g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
+                                 window);
+       }
+       priv->font_items_group = g_slist_reverse (priv->font_items_group);
+       gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
+       g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
+       gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+       menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
+       priv->font_face_toolitem = tool_item;
+
+       /* Set expand and homogeneous for remaining items */
+       tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+       tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+       tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
+       gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
+       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
+
+       /* Explicitelly show all the toolbar (a normal gtk_widget_show
+          will not show the tool items added to the placeholders) */
+       gtk_widget_show_all (parent_priv->toolbar);
+
+       /* Set the no show all *after* showing all items. We do not
+          want the toolbar to be shown with a show all because it
+          could go agains the gconf setting regarding showing or not
+          the toolbar of the editor window */
+       gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
+}
+
+
+
+ModestWindow*
+modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
+{
+       GObject *obj;
+       ModestWindowPrivate *parent_priv;
+       ModestMsgEditWindowPrivate *priv;
+       ModestDimmingRulesGroup *menu_rules_group = NULL;
+       ModestDimmingRulesGroup *toolbar_rules_group = NULL;
+       ModestDimmingRulesGroup *clipboard_rules_group = NULL;
+       ModestWindowMgr *mgr = NULL;
+
+       g_return_val_if_fail (msg, NULL);
+       g_return_val_if_fail (account_name, NULL);
+
+       mgr = modest_runtime_get_window_mgr ();
+       
+       obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
+
+       /* Menubar. Update the state of some toggles */
+       parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
+       hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
+       priv->from_field_protos = get_transports ();
+       modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
+       modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
+       modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
+       hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
+
+       /* Init window */
+       connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
+
+       restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
+               
+       modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
+
+       priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
+
+       parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
+       menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
+       toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
+       clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
+       /* Add common dimming rules */
+       modest_dimming_rules_group_add_rules (menu_rules_group, 
+                                             modest_msg_edit_window_menu_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
+                                             MODEST_WINDOW (obj));
+       modest_dimming_rules_group_add_rules (toolbar_rules_group, 
+                                             modest_msg_edit_window_toolbar_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
+                                             MODEST_WINDOW (obj));
+       modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
+                                                   G_CALLBACK (modest_ui_dimming_rules_on_set_style),
+                                                   MODEST_WINDOW (obj));
+       modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
+                                                   G_CALLBACK (modest_ui_dimming_rules_on_set_style),
+                                                   MODEST_WINDOW (obj));
+       modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
+                                                   G_CALLBACK (modest_ui_dimming_rules_on_set_style),
+                                                   MODEST_WINDOW (obj));
+       modest_dimming_rules_group_add_rules (clipboard_rules_group, 
+                                             modest_msg_edit_window_clipboard_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
+                                             MODEST_WINDOW (obj));
+       /* Insert dimming rules group for this window */
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
+        /* Checks the dimming rules */
+       g_object_unref (menu_rules_group);
+       g_object_unref (toolbar_rules_group);
+       g_object_unref (clipboard_rules_group);
+       set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
+
+       text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
+
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
+       priv->update_caption_visibility = TRUE;
+
+       modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
+
+       /* Track account-removed signal, this window should be closed
+          in the case we're creating a mail associated to the account
+          that is deleted */
+       priv->account_removed_handler_id = 
+               g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
+                                 "account_removed",
+                                 G_CALLBACK(on_account_removed),
+                                 obj);
+
+       modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
+
+       return (ModestWindow*) obj;
+}
+
+static gint
+get_formatted_data_cb (const gchar *buffer, gpointer user_data)
+{
+       GString **string_buffer = (GString **) user_data;
+
+       *string_buffer = g_string_append (*string_buffer, buffer);
+   
+       return 0;
+}
+
+/**
+ * @result: A new string which should be freed with g_free().
+ */
+static gchar *
+get_formatted_data (ModestMsgEditWindow *edit_window)
+{
+       ModestMsgEditWindowPrivate *priv;
+       GString *string_buffer = g_string_new ("");
+       
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
+
+       wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
+
+       modest_text_utils_hyperlinkify (string_buffer);
+
+       gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+
+       return g_string_free (string_buffer, FALSE);
+                                                                       
+}
+
+MsgData * 
+modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
+{
+       MsgData *data;
+       const gchar *account_name;
+       ModestMsgEditWindowPrivate *priv;
+       TnyIterator *att_iter;
+       
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
+                                                                       
+       account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
+       g_return_val_if_fail (account_name, NULL);
+       
+       
+       /* don't free these (except from) */
+       data = g_slice_new0 (MsgData);
+       data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
+                                                            account_name);
+       data->account_name = g_strdup (account_name);
+       data->to      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
+       data->cc      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
+       data->bcc     =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
+       data->subject =  g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
+       if (priv->draft_msg) {
+               data->draft_msg = g_object_ref (priv->draft_msg);
+       } else if (priv->outbox_msg) {
+               data->draft_msg = g_object_ref (priv->outbox_msg);
+       } else {
+               data->draft_msg = NULL;
+       }
+
+       GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
+       GtkTextIter b, e;
+       gtk_text_buffer_get_bounds (buf, &b, &e);
+       data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
+
+       if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
+               data->html_body = get_formatted_data (edit_window); /* returns a copy. */
+       else
+               data->html_body = NULL;
+
+       /* deep-copy the data */
+       att_iter = tny_list_create_iterator (priv->attachments);
+       data->attachments = NULL;
+       while (!tny_iterator_is_done (att_iter)) {
+               TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
+               if (!(TNY_IS_MIME_PART(part))) {
+                       g_warning ("strange data in attachment list");
+                       g_object_unref (part);
+                       tny_iterator_next (att_iter);
+                       continue;
+               }
+               data->attachments = g_list_append (data->attachments,
+                                                  part);
+               tny_iterator_next (att_iter);
+       }
+       g_object_unref (att_iter);
+
+       GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
+       att_iter = tny_list_create_iterator (priv->images);
+       data->images = NULL;
+       while (!tny_iterator_is_done (att_iter)) {
+               TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
+               const gchar *cid;
+               if (!(TNY_IS_MIME_PART(part))) {
+                       g_warning ("strange data in attachment list");
+                       g_object_unref (part);
+                       tny_iterator_next (att_iter);
+                       continue;
+               }
+               cid = tny_mime_part_get_content_id (part);
+               if (cid) {                      
+                       gchar *image_tag_id;
+                       GtkTextTag *image_tag;
+                       GtkTextIter iter;
+                       image_tag_id = g_strdup_printf ("image-tag-%s", cid);
+                       image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
+                       g_free (image_tag_id);
+                       
+                       gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
+                       if (image_tag && 
+                           ((gtk_text_iter_has_tag (&iter, image_tag))||
+                            (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
+                               data->images = g_list_append (data->images,
+                                                             g_object_ref (part));
+               }
+               g_object_unref (part);
+               tny_iterator_next (att_iter);
+       }
+       g_object_unref (att_iter);
+       
+       data->priority_flags = priv->priority_flags;
+
+       return data;
+}
+
+
+static void
+unref_gobject (GObject *obj, gpointer data)
+{
+       if (!G_IS_OBJECT(obj))
+               return;
+       g_object_unref (obj);
+}
+
+void 
+modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
+                                                     MsgData *data)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
+
+       if (!data)
+               return;
+
+       g_free (data->to);
+       g_free (data->cc);
+       g_free (data->bcc);
+       g_free (data->from);
+       g_free (data->subject);
+       g_free (data->plain_body);
+       g_free (data->html_body);
+       g_free (data->account_name);
+       
+       if (data->draft_msg != NULL) {
+               g_object_unref (data->draft_msg);
+               data->draft_msg = NULL;
+       }
+       
+       g_list_foreach (data->attachments, (GFunc)unref_gobject,  NULL);
+       g_list_free (data->attachments);
+       g_list_foreach (data->images, (GFunc)unref_gobject,  NULL);
+       g_list_free (data->images);
+       
+       g_slice_free (MsgData, data);
+}
+
+void                    
+modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
+                                      gint *parts_count,
+                                      guint64 *parts_size)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
+
+       /* TODO: add images */
+       *parts_size += priv->images_size;
+       *parts_count += priv->images_count;
+
+}
+
+ModestMsgEditFormat
+modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
+{
+       gboolean rich_text;
+       ModestMsgEditWindowPrivate *priv = NULL;
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
+       if (rich_text)
+               return MODEST_MSG_EDIT_FORMAT_HTML;
+       else
+               return MODEST_MSG_EDIT_FORMAT_TEXT;
+}
+
+void
+modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
+                                  ModestMsgEditFormat format)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       switch (format) {
+       case MODEST_MSG_EDIT_FORMAT_HTML:
+               wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+               break;
+       case MODEST_MSG_EDIT_FORMAT_TEXT:
+               wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
+               break;
+       default:
+               g_return_if_reached ();
+       }
+}
+
+ModestMsgEditFormatState *
+modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
+{
+       ModestMsgEditFormatState *format_state = NULL;
+       ModestMsgEditWindowPrivate *priv;
+       WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
+
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
+
+       format_state = g_new0 (ModestMsgEditFormatState, 1);
+       format_state->bold = buffer_format->bold&0x1;
+       format_state->italics = buffer_format->italic&0x1;
+       format_state->bullet = buffer_format->bullet&0x1;
+       format_state->color = buffer_format->color;
+       format_state->font_size = buffer_format->font_size;
+       format_state->font_family = wp_get_font_name (buffer_format->font);
+       format_state->justification = buffer_format->justification;
+       g_free (buffer_format);
+
+       return format_state;
+}
+
+void
+modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
+                                        const ModestMsgEditFormatState *format_state)
+{
+       ModestMsgEditWindowPrivate *priv;
+       WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
+       WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
+       g_return_if_fail (format_state != NULL);
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
+       gtk_widget_grab_focus (priv->msg_body);
+       buffer_format->bold = (format_state->bold != FALSE);
+       buffer_format->italic = (format_state->italics != FALSE);
+       buffer_format->color = format_state->color;
+       buffer_format->font_size = format_state->font_size;
+       buffer_format->font = wp_get_font_index (format_state->font_family, 0);
+       buffer_format->justification = format_state->justification;
+       buffer_format->bullet = format_state->bullet;
+
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
+
+       buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
+       buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
+       buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
+       buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
+       buffer_format->cs.font = (buffer_format->font != current_format->font);
+       buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
+       buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
+
+       wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
+       if (buffer_format->cs.bold) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
+                                             GINT_TO_POINTER (buffer_format->bold&0x1));
+       }
+       if (buffer_format->cs.italic) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
+                                             GINT_TO_POINTER (buffer_format->italic&0x1));
+       }
+       if (buffer_format->cs.color) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
+                                             GINT_TO_POINTER (&(buffer_format->color)));
+       }
+       if (buffer_format->cs.font_size) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
+                                             GINT_TO_POINTER (buffer_format->font_size));
+       }
+       if (buffer_format->cs.justification) {
+               switch (buffer_format->justification) {
+               case GTK_JUSTIFY_LEFT:
+                       wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
+                                                     GINT_TO_POINTER(TRUE));
+                       break;
+               case GTK_JUSTIFY_CENTER:
+                       wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
+                                                     GINT_TO_POINTER(TRUE));
+                       break;
+               case GTK_JUSTIFY_RIGHT:
+                       wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
+                                                     GINT_TO_POINTER(TRUE));
+                       break;
+               default:
+                       break;
+               }
+                       
+       }
+       if (buffer_format->cs.font) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
+                                             GINT_TO_POINTER (buffer_format->font));
+       }
+       wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
+       if (buffer_format->cs.bullet) {
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
+                                             GINT_TO_POINTER ((buffer_format->bullet)?1:0));
+       }
+/*     wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
+       
+       text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
+       
+       g_free (current_format);
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+}
+
+static void
+text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
+{
+       WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
+       GtkAction *action;
+       ModestWindowPrivate *parent_priv;
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *new_size_menuitem;
+       GtkWidget *new_font_menuitem;
+       
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
+               action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
+               if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+                       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
+       } else {
+               action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
+               if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+                       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
+       }
+
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
+
+/*     action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
+/*     modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
+
+       action = NULL;
+       switch (buffer_format->justification)
+       {
+       case GTK_JUSTIFY_LEFT:
+               action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
+               break;
+       case GTK_JUSTIFY_CENTER:
+               action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
+               break;
+       case GTK_JUSTIFY_RIGHT:
+               action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
+               break;
+       default:
+               break;
+       }
+       
+       if (action != NULL)
+               gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+       
+       g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
+                                        G_CALLBACK (modest_msg_edit_window_color_button_change),
+                                        window);
+       hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
+       g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
+                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
+                                          window);
+
+       new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
+                                                     buffer_format->font_size))->data);
+       if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
+               GtkWidget *label;
+               gchar *markup;
+
+               label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
+               markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
+               gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
+               g_free (markup);
+               g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
+                                                G_CALLBACK (modest_msg_edit_window_size_change),
+                                                window);
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
+               g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
+                                                  G_CALLBACK (modest_msg_edit_window_size_change),
+                                                  window);
+       }
+
+       new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
+                                                     buffer_format->font))->data);
+       if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
+               GtkWidget *label;
+               gchar *markup;
+
+               label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
+               markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
+               gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
+               g_free (markup);
+               g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
+                                                G_CALLBACK (modest_msg_edit_window_font_change),
+                                                window);
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
+               g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
+                                                  G_CALLBACK (modest_msg_edit_window_font_change),
+                                                  window);
+       }
+
+       g_free (buffer_format);
+
+}
+
+#ifdef MODEST_HILDON_VERSION_0
+void
+modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
+{
+       
+       WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *dialog = NULL;
+       gint response;
+       GdkColor *new_color = NULL;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
+       
+       dialog = hildon_color_selector_new (GTK_WINDOW (window));
+       hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
+       g_free (buffer_format);
+
+       if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
+               new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
+               if (new_color != NULL) {
+                       wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
+                                                     (gpointer) new_color);
+               }
+       }
+       gtk_widget_destroy (dialog);
+}
+
+
+void
+modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
+{
+       
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *dialog = NULL;
+       gint response;
+       GdkColor *old_color = NULL;
+       const GdkColor *new_color = NULL;
+       
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
+       
+       dialog = hildon_color_selector_new (GTK_WINDOW (window));
+       hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
+
+       if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
+               new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
+               if (new_color != NULL)
+                       wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
+       }
+       gtk_widget_destroy (dialog);
+
+}
+
+#else 
+void
+modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
+{
+       
+       WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *dialog = NULL;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
+               
+       dialog = hildon_color_chooser_new ();
+       hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
+       g_free (buffer_format);
+
+       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+               GdkColor col;
+               hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
+               wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
+                                             (gpointer) &col);
+       }
+       gtk_widget_destroy (dialog);
+}
+
+
+void
+modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
+{
+       
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *dialog = NULL;
+       GdkColor *old_color = NULL;
+       
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
+       
+       dialog = hildon_color_chooser_new ();
+       hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
+
+       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { 
+               GdkColor col;
+               hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
+               wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
+       }
+       gtk_widget_destroy (dialog);
+}
+
+#endif /*!MODEST_HILDON_VERSION_0*/
+
+
+
+static TnyStream*
+create_stream_for_uri (const gchar* uri)
+{
+       if (!uri)
+               return NULL;
+               
+       TnyStream *result = NULL;
+
+       GnomeVFSHandle *handle = NULL;
+       GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+       if (test == GNOME_VFS_OK) {
+               TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
+               /* Streams over OBEX (Bluetooth) are not seekable but
+                * we expect them to be (we might need to read them
+                * several times). So if this is a Bluetooth URI just
+                * read the whole file into memory (this is not a fast
+                * protocol so we can assume that these files are not
+                * going to be very big) */
+               if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
+                   (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
+                       TnyStream *memstream = tny_camel_mem_stream_new ();
+                       tny_stream_write_to_stream (vfssstream, memstream);
+                       g_object_unref (vfssstream);
+                       result = memstream;
+               } else {
+                       result = vfssstream;
+               }
+       }
+       
+       return result;
+}
+
+void
+modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
+{
+       
+       ModestMsgEditWindowPrivate *priv;
+       GtkWidget *dialog = NULL;
+       gint response = 0;
+       GSList *uris = NULL;
+       GSList *uri_node = NULL;
+       
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
+       gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
+       gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
+
+       modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
+
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
+                                    GTK_WINDOW (dialog));
+
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       switch (response) {
+       case GTK_RESPONSE_OK:
+               uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
+               break;
+       default:
+               break;
+       }
+       gtk_widget_destroy (dialog);
+
+       for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
+               const gchar *uri;
+               GnomeVFSHandle *handle = NULL;
+               GnomeVFSResult result;
+               GtkTextIter position;
+               GtkTextMark *insert_mark;
+
+               uri = (const gchar *) uri_node->data;
+               result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+               if (result == GNOME_VFS_OK) {
+                       GdkPixbuf *pixbuf;
+                       GnomeVFSFileInfo *info;
+                       gchar *filename, *basename, *escaped_filename;
+                       TnyMimePart *mime_part;
+                       gchar *content_id;
+                       const gchar *mime_type = NULL;
+                       GnomeVFSURI *vfs_uri;
+                       guint64 stream_size;
+
+                       gnome_vfs_close (handle);
+                       vfs_uri = gnome_vfs_uri_new (uri);
+
+                       escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
+                       filename = gnome_vfs_unescape_string_for_display (escaped_filename);
+                       g_free (escaped_filename);
+                       gnome_vfs_uri_unref (vfs_uri);
+                       info = gnome_vfs_file_info_new ();
+
+                       if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
+                                                    | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE) 
+                           == GNOME_VFS_OK)
+                               mime_type = gnome_vfs_file_info_get_mime_type (info);
+
+                       mime_part = tny_platform_factory_new_mime_part
+                               (modest_runtime_get_platform_factory ());
+                               
+                       TnyStream *stream = create_stream_for_uri (uri);
+
+                       if (stream == NULL) {
+
+                               modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+                               
+                               g_object_unref (mime_part);
+                               gnome_vfs_file_info_unref (info);
+                               continue;
+                       }
+
+                       tny_mime_part_construct (mime_part, stream, mime_type, "base64");
+                       
+                       content_id = g_strdup_printf ("%d", priv->next_cid);
+                       tny_mime_part_set_content_id (mime_part, content_id);
+                       g_free (content_id);
+                       priv->next_cid++;
+                       
+                       basename = g_path_get_basename (filename);
+                       tny_mime_part_set_filename (mime_part, basename);
+                       g_free (basename);
+
+                       pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
+                       
+                       if (pixbuf != NULL) {
+                               priv->images_size += stream_size;
+                               priv->images_count ++;
+                               insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
+                               gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
+                               wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
+                       } 
+
+                       tny_list_prepend (priv->images, (GObject *) mime_part);
+                       gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+                       g_free (filename);
+                       g_object_unref (mime_part);
+                       gnome_vfs_file_info_unref (info);
+
+               }
+       }
+
+
+}
+
+void
+modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
+{      
+       GtkWidget *dialog = NULL;
+       gint response = 0;
+       GSList *uris = NULL;
+       GSList *uri_node;
+       GnomeVFSFileSize total_size, allowed_size;
+       ModestMsgEditWindowPrivate *priv;
+       gint att_num;
+       guint64 att_size;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
+               
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
+               return;
+       
+       dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
+       gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
+       gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
+
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       switch (response) {
+       case GTK_RESPONSE_OK:
+               uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
+               break;
+       default:
+               break;
+       }
+       gtk_widget_destroy (dialog);
+
+       /* allowed size is the maximum size - what's already there */
+       modest_attachments_view_get_sizes (
+               MODEST_ATTACHMENTS_VIEW (priv->attachments_view), 
+               &att_num, &att_size);
+       allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
+
+       total_size = 0;
+       for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
+
+               const gchar *uri = (const gchar *) uri_node->data;
+               
+               total_size += modest_msg_edit_window_attach_file_one 
+                       (window, uri, allowed_size);
+               
+               if (total_size > allowed_size) {
+                       g_warning ("%s: total size: %u", 
+                                  __FUNCTION__, (unsigned int)total_size);
+                       break;
+               }
+
+               allowed_size -= total_size;
+               
+
+       }
+       g_slist_foreach (uris, (GFunc) g_free, NULL);
+       g_slist_free (uris);
+}
+
+
+GnomeVFSFileSize
+modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
+                                       const gchar *uri, 
+                                       GnomeVFSFileSize allowed_size)
+
+{
+       GnomeVFSHandle *handle = NULL;
+       ModestMsgEditWindowPrivate *priv;
+       GnomeVFSResult result;
+       GnomeVFSFileSize size = 0;
+       g_return_val_if_fail (window, 0);
+       g_return_val_if_fail (uri, 0);
+               
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+       if (result == GNOME_VFS_OK) {
+               TnyMimePart *mime_part;
+               TnyStream *stream;
+               const gchar *mime_type = NULL;
+               gchar *basename;
+               gchar *escaped_filename;
+               gchar *filename;
+               gchar *content_id;
+               GnomeVFSFileInfo *info;
+               GnomeVFSURI *vfs_uri;
+
+               gnome_vfs_close (handle);
+               vfs_uri = gnome_vfs_uri_new (uri);
+               
+
+               escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
+               filename = gnome_vfs_unescape_string_for_display (escaped_filename);
+               g_free (escaped_filename);
+               gnome_vfs_uri_unref (vfs_uri);
+
+               info = gnome_vfs_file_info_new ();
+               
+               if (gnome_vfs_get_file_info (uri, 
+                                            info, 
+                                            GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
+                   == GNOME_VFS_OK)
+                       mime_type = gnome_vfs_file_info_get_mime_type (info);
+               mime_part = tny_platform_factory_new_mime_part
+                       (modest_runtime_get_platform_factory ());
+               
+               /* try to get the attachment's size; this may fail for weird
+                * file systems, like obex, upnp... */
+               if (allowed_size != 0 &&
+                   info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
+                       size = info->size;
+                       if (size > allowed_size) {
+                               modest_platform_information_banner (NULL, NULL, 
+                                                                   dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+                               return 0;
+                       }
+               } else
+                       g_warning ("%s: could not get attachment size", __FUNCTION__);
+               
+               stream = create_stream_for_uri (uri);
+               
+               if (stream == NULL) {
+
+                       modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+
+                       g_object_unref (mime_part);
+                       gnome_vfs_file_info_unref (info);
+                       return 0;
+               }
+
+               tny_mime_part_construct (mime_part, stream, mime_type, "base64");
+               g_object_unref (stream);
+               
+               content_id = g_strdup_printf ("%d", priv->next_cid);
+               tny_mime_part_set_content_id (mime_part, content_id);
+               g_free (content_id);
+               priv->next_cid++;
+               
+               basename = g_path_get_basename (filename);
+               tny_mime_part_set_filename (mime_part, basename);
+               g_free (basename);
+               
+               tny_list_prepend (priv->attachments, (GObject *) mime_part);
+               modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
+                                                       mime_part,
+                                                       info->size == 0, info->size);
+               gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
+               gtk_widget_show_all (priv->attachments_caption);
+               gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+               g_free (filename);
+               g_object_unref (mime_part);
+               gnome_vfs_file_info_unref (info);
+       }
+
+       return size;
+}
+
+void
+modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
+                                          TnyList *att_list)
+{
+       ModestMsgEditWindowPrivate *priv;
+       TnyIterator *iter;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (att_list == NULL) {
+               att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
+       } else {
+               g_object_ref (att_list);
+       }
+
+       if (tny_list_get_length (att_list) == 0) {
+               hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
+       } else {
+               gboolean dialog_response;
+               gchar *message = NULL;
+               gchar *filename = NULL;
+
+               if (tny_list_get_length (att_list) == 1) {
+                       TnyMimePart *part;
+                       iter = tny_list_create_iterator (att_list);
+                       part = (TnyMimePart *) tny_iterator_get_current (iter);
+                       g_object_unref (iter);
+                       if (TNY_IS_MSG (part)) {
+                               TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
+                               if (header) {
+                                       filename = tny_header_dup_subject (header);
+                                       g_object_unref (header);
+                               }
+                               if (filename == NULL) {
+                                       filename = g_strdup (_("mail_va_no_subject"));
+                               }
+                       } else {
+                               filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
+                       }
+                       g_object_unref (part);
+               } else {
+                       filename = g_strdup ("");
+               }
+               message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
+                                                   tny_list_get_length (att_list)), filename);
+               g_free (filename);
+
+               dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
+               g_free (message);
+
+               if (dialog_response != GTK_RESPONSE_OK) {
+                       g_object_unref (att_list);
+                       return;
+               }
+               hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
+               
+               for (iter = tny_list_create_iterator (att_list);
+                    !tny_iterator_is_done (iter);
+                    tny_iterator_next (iter)) {
+                       TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+                       const gchar *att_id;
+                       tny_list_remove (priv->attachments, (GObject *) mime_part);
+
+                       modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
+                                                                  mime_part);
+                       if (tny_list_get_length (priv->attachments) == 0)
+                               gtk_widget_hide (priv->attachments_caption);
+                       att_id = tny_mime_part_get_content_id (mime_part);
+                       if (att_id != NULL)
+                               text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
+                                                                att_id);
+                       gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+                       g_object_unref (mime_part);
+               }
+               g_object_unref (iter);
+       }
+
+       g_object_unref (att_list);
+
+       /* if the last attachment has been removed, focus the Subject: field */
+       if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view))) 
+               gtk_widget_grab_focus (priv->subject_field);
+}
+
+static void
+modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
+                                           gpointer userdata)
+{
+       ModestMsgEditWindowPrivate *priv;
+       GdkColor *new_color;
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+#ifdef MODEST_HAVE_HILDON0_WIDGETS     
+       new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
+#else 
+       GdkColor col;
+       hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
+       new_color = &col;
+#endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
+
+       wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
+       
+       gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
+
+}
+
+static void
+modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
+                                   gpointer userdata)
+{
+       ModestMsgEditWindowPrivate *priv;
+       gint new_size_index;
+       ModestMsgEditWindow *window;
+       GtkWidget *label;
+       
+       window = MODEST_MSG_EDIT_WINDOW (userdata);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
+
+       if (gtk_check_menu_item_get_active (menu_item)) {
+               gchar *markup;
+               WPTextBufferFormat format;
+
+               memset (&format, 0, sizeof (format));
+               wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
+
+               label = gtk_bin_get_child (GTK_BIN (menu_item));
+               
+               new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
+               format.cs.font_size = TRUE;
+               format.cs.text_position = TRUE;
+               format.cs.font = TRUE;
+               format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
+/*             wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
+
+               if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
+                                                  GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
+                       wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
+               
+               text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
+               markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
+               gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
+               g_free (markup);
+       }
+}
+
+static void
+modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
+                                   gpointer userdata)
+{
+       ModestMsgEditWindowPrivate *priv;
+       gint new_font_index;
+       ModestMsgEditWindow *window;
+       GtkWidget *label;
+       
+       window = MODEST_MSG_EDIT_WINDOW (userdata);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
+
+       if (gtk_check_menu_item_get_active (menu_item)) {
+               gchar *markup;
+
+               label = gtk_bin_get_child (GTK_BIN (menu_item));
+               
+               new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
+
+               if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
+                                                  GINT_TO_POINTER(new_font_index)))
+                       wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
+               
+               text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
+                   markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
+               gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
+               g_free (markup);
+       }
+}
+
+static gboolean
+modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
+{
+       if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+               ModestWindowPrivate *parent_priv;
+               ModestWindowMgr *mgr;
+               gboolean is_fullscreen;
+               GtkAction *fs_toggle_action;
+               gboolean active;
+
+               mgr = modest_runtime_get_window_mgr ();
+               is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
+
+               parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
+               
+               fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
+               active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
+               if (is_fullscreen != active)
+                       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
+       }
+
+       return FALSE;
+
+}
+
+void
+modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
+                               gboolean show)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       if (!priv->update_caption_visibility)
+               return;
+
+       gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
+       if (show)
+               gtk_widget_show (priv->cc_caption);
+       else
+               gtk_widget_hide (priv->cc_caption);
+
+       modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
+}
+
+void
+modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
+                                gboolean show)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       if (!priv->update_caption_visibility)
+               return;
+
+       gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
+       if (show)
+               gtk_widget_show (priv->bcc_caption);
+       else
+               gtk_widget_hide (priv->bcc_caption);
+
+       modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
+}
+
+static void
+modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
+                                        ModestRecptEditor *editor)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
+       
+       /* we check for low-mem; in that case, show a warning, and don't allow
+        * for the addressbook
+        */
+       if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
+               return;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (editor == NULL) {
+               GtkWidget *view_focus;
+               view_focus = gtk_window_get_focus (GTK_WINDOW (window));
+
+               /* This code should be kept in sync with ModestRecptEditor. The
+                  textview inside the recpt editor is the one that really gets the
+                  focus. As it's inside a scrolled window, and this one inside the
+                  hbox recpt editor inherits from, we'll need to go up in the 
+                  hierarchy to know if the text view is part of the recpt editor
+                  or if it's a different text entry */
+
+               if (gtk_widget_get_parent (view_focus)) {
+                       GtkWidget *first_parent;
+
+                       first_parent = gtk_widget_get_parent (view_focus);
+                       if (gtk_widget_get_parent (first_parent) && 
+                           MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
+                               editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
+                       }
+               }
+
+               if (editor == NULL)
+                       editor = MODEST_RECPT_EDITOR (priv->to_field);
+
+       }
+
+       modest_address_book_select_addresses (editor);
+
+}
+
+void
+modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       modest_msg_edit_window_open_addressbook (window, NULL);
+}
+
+static void
+modest_msg_edit_window_show_toolbar (ModestWindow *self,
+                                    gboolean show_toolbar)
+{
+       ModestWindowPrivate *parent_priv;
+       const gchar *action_name;
+       GtkAction *action;
+       
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       /* We can not just use the code of
+          modest_msg_edit_window_setup_toolbar because it has a
+          mixture of both initialization and creation code. */
+       if (show_toolbar)
+               gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
+       else
+               gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
+
+       /* Update also the actions (to update the toggles in the
+          menus), we have to do it manually because some other window
+          of the same time could have changed it (remember that the
+          toolbar fullscreen mode is shared by all the windows of the
+          same type */
+       if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
+               action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
+       else
+               action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
+       
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                                           show_toolbar);
+
+}
+
+void
+modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
+                                          TnyHeaderFlags priority_flags)
+{
+       ModestMsgEditWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+
+       if (priv->priority_flags != priority_flags) {
+               GtkAction *priority_action = NULL;
+
+               priv->priority_flags = priority_flags;
+
+               switch (priority_flags) {
+               case TNY_HEADER_FLAG_HIGH_PRIORITY:
+                       gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
+                       gtk_widget_show (priv->priority_icon);
+                       priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                                    "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
+                       break;
+               case TNY_HEADER_FLAG_LOW_PRIORITY:
+                       gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
+                       gtk_widget_show (priv->priority_icon);
+                       priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                                    "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
+                       break;
+               default:
+                       gtk_widget_hide (priv->priority_icon);
+                       priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                                    "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
+                       break;
+               }
+               gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
+               gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+       }
+}
+
+void
+modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
+                                       gint file_format)
+{
+       ModestMsgEditWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv;
+       gint current_format;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
+               ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
+
+       if (current_format != file_format) {
+               switch (file_format) {
+               case MODEST_FILE_FORMAT_FORMATTED_TEXT:
+                       wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
+                       remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
+                       break;
+               case MODEST_FILE_FORMAT_PLAIN_TEXT:
+               {
+                       GtkWidget *dialog;
+                       gint response;
+                       dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
+                       response = gtk_dialog_run (GTK_DIALOG (dialog));
+                       gtk_widget_destroy (dialog);
+                       if (response == GTK_RESPONSE_OK) {
+                               wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
+                       } else {
+                               GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
+                               modest_utils_toggle_action_set_active_block_notify (action, TRUE);
+                       }
+               }
+                       break;
+               }
+               modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+               modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+               text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
+       }
+}
+
+void
+modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
+{
+       GtkWidget *dialog;
+       ModestMsgEditWindowPrivate *priv;
+       WPTextBufferFormat oldfmt, fmt;
+       gint old_position = 0;
+       gint response = 0;
+       gint position = 0;
+       gint font_size;
+       GdkColor *color = NULL;
+       gboolean bold, bold_set, italic, italic_set;
+       gboolean underline, underline_set;
+       gboolean strikethrough, strikethrough_set;
+       gboolean position_set;
+       gboolean font_size_set, font_set, color_set;
+       gchar *font_name;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
+                                    GTK_WINDOW(dialog));
+
+       /* First we get the currently selected font information */
+       wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
+
+       switch (oldfmt.text_position) {
+       case TEXT_POSITION_NORMAL:
+               old_position = 0;
+               break;
+       case TEXT_POSITION_SUPERSCRIPT:
+               old_position = 1;
+               break;
+       default:
+               old_position = -1;
+               break;
+       }
+
+       g_object_set (G_OBJECT (dialog),
+                     "bold", oldfmt.bold != FALSE,
+                     "bold-set", !oldfmt.cs.bold,
+                     "underline", oldfmt.underline != FALSE,
+                     "underline-set", !oldfmt.cs.underline,
+                     "italic", oldfmt.italic != FALSE,
+                     "italic-set", !oldfmt.cs.italic,
+                     "strikethrough", oldfmt.strikethrough != FALSE,
+                     "strikethrough-set", !oldfmt.cs.strikethrough,
+                     "color", &oldfmt.color,
+                     "color-set", !oldfmt.cs.color,
+                     "size", wp_font_size[oldfmt.font_size],
+                     "size-set", !oldfmt.cs.font_size,
+                     "position", old_position,
+                     "position-set", !oldfmt.cs.text_position,
+                     "family", wp_get_font_name (oldfmt.font),
+                     "family-set", !oldfmt.cs.font,
+                     NULL);
+
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
+                                    GTK_WINDOW (dialog));
+       gtk_widget_show_all (dialog);
+       priv->font_dialog = dialog;
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       priv->font_dialog = NULL;
+       if (response == GTK_RESPONSE_OK) {
+
+               g_object_get( dialog,
+                             "bold", &bold,
+                             "bold-set", &bold_set,
+                             "underline", &underline,
+                             "underline-set", &underline_set,
+                             "italic", &italic,
+                             "italic-set", &italic_set,
+                             "strikethrough", &strikethrough,
+                             "strikethrough-set", &strikethrough_set,
+                             "color", &color,
+                             "color-set", &color_set,
+                             "size", &font_size,
+                             "size-set", &font_size_set,
+                             "family", &font_name,
+                             "family-set", &font_set,
+                             "position", &position,
+                             "position-set", &position_set,
+                             NULL );
+               
+       }       
+
+       if (response == GTK_RESPONSE_OK) {
+               memset(&fmt, 0, sizeof(fmt));
+               if (bold_set) {
+                       fmt.bold = bold;
+                       fmt.cs.bold = TRUE;
+               }
+               if (italic_set) {
+                       fmt.italic = italic;
+                       fmt.cs.italic = TRUE;
+               }
+               if (underline_set) {
+                       fmt.underline = underline;
+                       fmt.cs.underline = TRUE;
+               }
+               if (strikethrough_set) {
+                       fmt.strikethrough = strikethrough;
+                       fmt.cs.strikethrough = TRUE;
+               }
+               if (position_set) {
+                       fmt.text_position =
+                               ( position == 0 )
+                               ? TEXT_POSITION_NORMAL
+                               : ( ( position == 1 )
+                                   ? TEXT_POSITION_SUPERSCRIPT
+                                   : TEXT_POSITION_SUBSCRIPT );
+                       fmt.cs.text_position = TRUE;
+                       fmt.font_size = oldfmt.font_size;
+               }
+               if (color_set) {
+                       fmt.color = *color;
+                       fmt.cs.color = TRUE;
+               }
+               if (font_set) {
+                       fmt.font = wp_get_font_index(font_name,
+                                                    DEFAULT_FONT);
+                       fmt.cs.font = TRUE;
+               }
+               g_free(font_name);
+               if (font_size_set) {
+                       fmt.cs.font_size = TRUE;
+                       fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
+               }
+               wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
+               text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
+       }
+       gtk_widget_destroy (dialog);
+       
+       gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
+}
+
+void
+modest_msg_edit_window_undo (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
+
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+}
+
+void
+modest_msg_edit_window_redo (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       
+       wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
+
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+
+}
+
+static void  
+text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       priv->can_undo = can_undo;
+}
+
+static void  
+text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       priv->can_redo = can_redo;
+}
+
+gboolean            
+modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       return priv->can_undo;
+}
+
+gboolean            
+modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       return priv->can_redo;
+}
+
+
+static void
+text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
+{
+       GtkTextIter iter;
+       GtkTextIter match_start, match_end;
+
+       if (image_id == NULL)
+               return;
+
+       gtk_text_buffer_get_start_iter (buffer, &iter);
+
+       while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
+               GSList *tags = gtk_text_iter_get_tags (&match_start);
+               GSList *node;
+               for (node = tags; node != NULL; node = g_slist_next (node)) {
+                       GtkTextTag *tag = (GtkTextTag *) node->data;
+                       if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
+                               gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
+                               if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
+                                       gint offset;
+                                       offset = gtk_text_iter_get_offset (&match_start);
+                                       gtk_text_buffer_delete (buffer, &match_start, &match_end);
+                                       gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
+                               }
+                       }
+               }
+               gtk_text_iter_forward_char (&iter);
+       }
+}
+
+gboolean
+message_is_empty (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
+        * so we can ignore markup.
+        */
+       GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
+       gint count = 0;
+       if (buf)
+               count = gtk_text_buffer_get_char_count (buf);
+
+       return count == 0;
+}
+
+static gboolean
+msg_body_focus (GtkWidget *focus,
+               GdkEventFocus *event,
+               gpointer userdata)
+{
+       
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
+       return FALSE;
+}
+
+static void
+recpt_field_changed (GtkTextBuffer *buffer,
+                 ModestMsgEditWindow *editor)
+{
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
+}
+
+static void
+body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
+{
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
+}
+
+void
+modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
+                                    gboolean modified)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
+       GtkTextBuffer *buffer;
+
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
+       gtk_text_buffer_set_modified (buffer, modified);
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
+       gtk_text_buffer_set_modified (buffer, modified);
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
+       gtk_text_buffer_set_modified (buffer, modified);
+       gtk_text_buffer_set_modified (priv->text_buffer, modified);
+}
+
+gboolean
+modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
+       const char *account_name;
+       GtkTextBuffer *buffer;
+
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
+       if (gtk_text_buffer_get_modified (buffer))
+               return TRUE;
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
+       if (gtk_text_buffer_get_modified (buffer))
+               return TRUE;
+       buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
+       if (gtk_text_buffer_get_modified (buffer))
+               return TRUE;
+       if (gtk_text_buffer_get_modified (priv->text_buffer))
+               return TRUE;
+       account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
+       if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+
+
+gboolean
+modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       /* check if there's no recipient added */
+       if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
+           (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
+           (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
+               /* no recipient contents, then select contacts */
+               modest_msg_edit_window_open_addressbook (window, NULL);
+               return FALSE;
+       }
+
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),  add_to_addressbook)) {
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
+               return FALSE;
+       }
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),  add_to_addressbook)) {
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
+               return FALSE;
+       }
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
+               return FALSE;
+       }
+
+       if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
+           !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
+               modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
+
+       return TRUE;
+
+}
+
+static void
+modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
+                                              ModestMsgEditWindow *window)
+{
+       modest_msg_edit_window_offer_attach_file (window);
+}
+
+const gchar *
+modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
+
+       return priv->clipboard_text;
+}
+
+static void
+modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
+                                              GdkEvent *event,
+                                              ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+       gchar *text = NULL;
+       if (!GTK_WIDGET_VISIBLE (window))
+               return;
+
+       g_object_ref (window);
+       text = gtk_clipboard_wait_for_text (selection_clipboard);
+
+       if (priv->clipboard_text != NULL) {
+               g_free (priv->clipboard_text);
+       }
+       priv->clipboard_text = text;
+
+       if (GTK_WIDGET_VISIBLE (window)) {
+               modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+       }
+       g_object_unref (window);
+}
+
+static gboolean clipboard_owner_change_idle (gpointer userdata)
+{
+       ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
+       ModestMsgEditWindowPrivate *priv;
+
+       gdk_threads_enter ();
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       priv->clipboard_owner_idle = 0;
+       modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+static void
+modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       if (priv->clipboard_owner_idle == 0) {
+               priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
+       }
+}
+
+static void 
+subject_field_move_cursor (GtkEntry *entry,
+                          GtkMovementStep step,
+                          gint a1,
+                          gboolean a2,
+                          gpointer window)
+{
+       if (!GTK_WIDGET_VISIBLE (window))
+               return;
+
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+}
+
+static void 
+update_window_title (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+       const gchar *subject;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
+       if (subject == NULL || subject[0] == '\0')
+               subject = _("mail_va_new_email");
+
+       gtk_window_set_title (GTK_WINDOW (window), subject);
+
+}
+
+static void  
+subject_field_changed (GtkEditable *editable, 
+                      ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       update_window_title (window);
+       gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+}
+
+static void  
+subject_field_insert_text (GtkEditable *editable, 
+                          gchar *new_text,
+                          gint new_text_length,
+                          gint *position,
+                          ModestMsgEditWindow *window)
+{
+       GString *result = g_string_new ("");
+       gchar *current;
+       gint result_len = 0;
+       const gchar *entry_text = NULL;
+       gint old_length;
+
+       entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
+       old_length = g_utf8_strlen (entry_text, -1);
+
+       for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
+               gunichar c = g_utf8_get_char_validated (current, 8);
+               /* Invalid unichar, stop */
+               if (c == -1)
+                       break;
+               /* a bullet */
+               if (c == 0x2022)
+                       continue;
+               result = g_string_append_unichar (result, c);
+               result_len++;
+       }
+
+       if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
+               g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
+               if (result_len > 0)
+               {
+                       /* Prevent endless recursion */
+                       g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
+                       g_signal_emit_by_name (editable, "insert-text", 
+                                              (gpointer) result->str, (gpointer) result->len,
+                                              (gpointer) position, (gpointer) window);
+                      g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
+               }
+       }
+
+       if (result_len + old_length > 1000) {
+               hildon_banner_show_information (GTK_WIDGET (window), NULL, 
+                                               dgettext("hildon-common-strings",
+                                                        "ckdg_ib_maximum_characters_reached"));
+       }
+       
+       g_string_free (result, TRUE);
+}
+
+void
+modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
+                                           gboolean show)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
+
+       if (show) {
+               gtk_widget_show_all (priv->find_toolbar);
+               hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
+       } else {
+               gtk_widget_hide_all (priv->find_toolbar);
+               gtk_widget_grab_focus (priv->msg_body);
+       }
+    
+}
+
+static gboolean 
+gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
+                                         const gchar *str,
+                                         GtkTextIter *match_start,
+                                         GtkTextIter *match_end)
+{
+       GtkTextIter end_iter;
+       gchar *str_casefold;
+       gint str_chars_n;
+       gchar *range_text;
+       gchar *range_casefold;
+       gint offset;
+       gint range_chars_n;
+       gboolean result = FALSE;
+
+       if (str == NULL)
+               return TRUE;
+       
+       /* get end iter */
+       end_iter = *iter;
+       gtk_text_iter_forward_to_end (&end_iter);
+
+       str_casefold = g_utf8_casefold (str, -1);
+       str_chars_n = strlen (str);
+
+       range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
+       range_casefold = g_utf8_casefold (range_text, -1);
+       range_chars_n = strlen (range_casefold);
+
+       if (range_chars_n < str_chars_n) {
+               g_free (str_casefold);
+               g_free (range_text);
+               g_free (range_casefold);
+               return FALSE;
+       }
+
+       for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
+               gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
+               if (!g_utf8_collate (range_subtext, str_casefold)) {
+                       gchar *found_text = g_strndup (range_text + offset, str_chars_n);
+                       result = TRUE;
+                       gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
+                                                     match_start, match_end, NULL);
+                       g_free (found_text);
+               }
+               g_free (range_subtext);
+               if (result)
+                       break;
+       }
+       g_free (str_casefold);
+       g_free (range_text);
+       g_free (range_casefold);
+
+       return result;
+}
+
+
+static void 
+modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
+                                           ModestMsgEditWindow *window)
+{
+       gchar *current_search = NULL;
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       gboolean result;
+       GtkTextIter selection_start, selection_end;
+       GtkTextIter match_start, match_end;
+       gboolean continue_search = FALSE;
+
+       if (message_is_empty (window)) {
+               g_free (priv->last_search);
+               priv->last_search = NULL;
+               hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
+               return;
+       }
+
+       g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
+       if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
+               g_free (current_search);
+               g_free (priv->last_search);
+               priv->last_search = NULL;
+               /* Information banner about empty search */
+               hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
+               return;
+       }
+
+       if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
+               continue_search = TRUE;
+       } else {
+               g_free (priv->last_search);
+               priv->last_search = g_strdup (current_search);
+       }
+
+       if (continue_search) {
+               gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
+               result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search, 
+                                                                  &match_start, &match_end);
+               if (!result)
+                       hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
+       } else {
+               GtkTextIter buffer_start;
+               gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
+               result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search, 
+                                                                  &match_start, &match_end);
+               if (!result)
+                       hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
+       }
+
+       /* Mark as selected the string found in search */
+       if (result) {
+               gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
+               gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
+               correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
+       } else {
+               g_free (priv->last_search);
+               priv->last_search = NULL;
+       }
+       g_free (current_search);
+}
+
+static void
+modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
+                                          ModestMsgEditWindow *window)
+{
+       GtkToggleAction *toggle;
+       ModestWindowPrivate *parent_priv;
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+
+       toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
+       gtk_toggle_action_set_active (toggle, FALSE);
+}
+
+gboolean 
+modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
+       return priv->sent;
+}
+
+void 
+modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
+                                gboolean sent)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
+       priv->sent = sent;
+}
+
+
+void            
+modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
+                                 TnyMsg *draft)
+{
+       ModestMsgEditWindowPrivate *priv;
+       TnyHeader *header = NULL;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
+
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
+
+       if (priv->draft_msg != NULL) {
+               g_object_unref (priv->draft_msg);
+       }
+
+       if (draft != NULL) {
+               g_object_ref (draft);
+               header = tny_msg_get_header (draft);
+               if (priv->msg_uid) {
+                       g_free (priv->msg_uid);
+                       priv->msg_uid = NULL;
+               }
+               priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
+               if (GTK_WIDGET_REALIZED (window))
+                       modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
+       }
+
+       priv->draft_msg = draft;
+}
+
+static void  
+text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag, 
+                      GtkTextIter *start, GtkTextIter *end,
+                      gpointer userdata)
+{
+       ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
+       gchar *tag_name;
+
+       if (tag == NULL+13) return;
+       g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
+       if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
+               replace_with_images (window, priv->images);
+       }
+}
+
+void                    
+modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
+                                TnyMimePart *part)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       g_return_if_fail (TNY_IS_MIME_PART (part));
+       tny_list_prepend (priv->attachments, (GObject *) part);
+       modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
+       gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
+       gtk_widget_show_all (priv->attachments_caption);
+       gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
+}
+
+const gchar*    
+modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);        
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       return priv->msg_uid;
+}
+
+GtkWidget *
+modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
+                                        ModestMsgEditWindowWidgetType widget_type)
+{
+       ModestMsgEditWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
+
+       switch (widget_type) {
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
+               return priv->msg_body;
+               break;
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
+               return priv->to_field;
+               break;
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
+               return priv->cc_field;
+               break;
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
+               return priv->bcc_field;
+               break;
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
+               return priv->subject_field;
+               break;
+       case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
+               return priv->attachments_view;
+               break;
+       default:
+               return NULL;
+       }
+}
+
+static void 
+remove_tags (WPTextBuffer *buffer)
+{
+       GtkTextIter start, end;
+
+       gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
+       gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
+
+       gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
+}
+
+static void
+on_account_removed (TnyAccountStore *account_store, 
+                   TnyAccount *account,
+                   gpointer user_data)
+{
+       /* Do nothing if it's a store account, because we use the
+          transport to send the messages */
+       if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
+               const gchar *parent_acc = NULL;
+               const gchar *our_acc = NULL;
+
+               our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
+               parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
+               /* Close this window if I'm showing a message of the removed account */
+               if (strcmp (parent_acc, our_acc) == 0)
+                       modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
+       }
+}
+
+static gboolean
+on_zoom_minus_plus_not_implemented (ModestWindow *window)
+{
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+
+       hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
+       return FALSE;
+
+}
+
+static void
+set_zoom_do_nothing (ModestWindow *window,
+                                gdouble zoom)
+{
+}
+
+static gdouble
+get_zoom_do_nothing (ModestWindow *window)
+{
+       return 1.0;
+}
+
diff --git a/src/hildon2/modest-msg-view-window-ui-dimming.h b/src/hildon2/modest-msg-view-window-ui-dimming.h
new file mode 100644 (file)
index 0000000..79f678c
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __MODEST_MSG_VIEW_WINDOW_UI_DIMMING_PRIV_H__
+#define __MODEST_MSG_VIEW_WINDOW_UI_DIMMING_PRIV_H__
+
+#include "modest-dimming-rules-group.h"
+#include "modest-ui-dimming-rules.h"
+
+G_BEGIN_DECLS
+
+
+/* Menu Dimming rules entries */
+static const ModestDimmingEntry modest_msg_view_menu_dimming_entries [] = {
+
+       /* Message Menu */
+       { "/MenuBar/MessageMenu/MessageNewMenu", G_CALLBACK(modest_ui_dimming_rules_on_new_msg) },
+       { "/MenuBar/MessageMenu/MessageReplyMenu", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/MessageMenu/MessageReplyAllMenu", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/MessageMenu/MessageForwardMenu",  G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/MenuBar/MessageMenu/MessageDeleteMenu",  G_CALLBACK(modest_ui_dimming_rules_on_delete_msg) },
+       { "/MenuBar/MessageMenu/MessageDetailsMenu", G_CALLBACK(modest_ui_dimming_rules_on_details) },
+
+       /* Edit Menu */
+       { "/MenuBar/EditMenu", NULL },
+       { "/MenuBar/EditMenu/EditPasteMenu", G_CALLBACK(modest_ui_dimming_rules_always_dimmed) },
+       { "/MenuBar/EditMenu/EditSelectAllMenu", NULL },
+       { "/MenuBar/EditMenu/EditMoveToMenu", G_CALLBACK(modest_ui_dimming_rules_on_move_to) },
+
+       /* View Menu */
+       { "/MenuBar/ViewMenu", NULL },
+       { "/MenuBar/ViewMenu/ZoomMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewToggleFullscreenMenu", NULL },
+       { "/MenuBar/ViewMenu/ViewPreviousMessageMenu", G_CALLBACK(modest_ui_dimming_rules_on_view_previous) },
+       { "/MenuBar/ViewMenu/ViewNextMessageMenu",  G_CALLBACK(modest_ui_dimming_rules_on_view_next)},
+       
+       /* Attachments Menu */
+       { "/MenuBar/AttachmentsMenu", NULL },
+       { "/MenuBar/AttachmentsMenu/ViewAttachmentMenu", G_CALLBACK(modest_ui_dimming_rules_on_view_attachments) },
+       { "/MenuBar/AttachmentsMenu/SaveAttachmentMenu", G_CALLBACK(modest_ui_dimming_rules_on_save_attachments) },
+       { "/MenuBar/AttachmentsMenu/RemoveAttachmentMenu", G_CALLBACK(modest_ui_dimming_rules_on_remove_attachments) },
+
+       /* Tools Menu */
+       { "/MenuBar/ToolsMenu", NULL },
+
+       /* Close Menu */
+       { "/MenuBar/CloseMenu", NULL },
+       { "/MenuBar/ToolsMenu/CloseWindowMenu", NULL },
+       { "/MenuBar/ToolsMenu/CloseAllWindowsMenu", NULL },
+
+       /* Contextual Menus (Toolbar) */
+       { "/ToolbarReplyCSM/MessageForwardMenu", NULL },
+       { "/ToolbarReplyCSM/MessageReplyAllMenu", NULL },
+       { "/ToolbarReplyCSM/MessageReplyMenu", NULL },
+       
+};
+
+/* Clipboard status dimming rule entries */
+static const ModestDimmingEntry modest_msg_view_clipboard_dimming_entries [] = {
+       { "/MenuBar/EditMenu/EditCutMenu", G_CALLBACK(modest_ui_dimming_rules_always_dimmed) },
+       { "/MenuBar/EditMenu/EditCopyMenu", G_CALLBACK(modest_ui_dimming_rules_on_copy) },
+       { "/MenuBar/ToolsMenu/ToolsAddToContactsMenu", G_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts) },
+};
+
+/* Menu Dimming rules entries */
+static const ModestDimmingEntry modest_msg_view_toolbar_dimming_entries [] = {
+
+       /* Toolbar */
+       { "/ToolBar/ToolbarMessageReply", G_CALLBACK(modest_ui_dimming_rules_on_reply_msg) },
+       { "/ToolBar/ToolbarMessageMoveTo", G_CALLBACK(modest_ui_dimming_rules_on_move_to) },
+       { "/ToolBar/ToolbarDeleteMessage",  G_CALLBACK(modest_ui_dimming_rules_on_delete_msg) },
+       { "/ToolBar/FindInMessage", G_CALLBACK(modest_ui_dimming_rules_on_find_msg) },
+       { "/ToolBar/ToolbarMessageBack", G_CALLBACK(modest_ui_dimming_rules_on_view_previous) },
+       { "/ToolBar/ToolbarMessageNext", G_CALLBACK(modest_ui_dimming_rules_on_view_next) },
+       { "/ToolBar/ToolbarCancel", NULL },
+};
+
+G_END_DECLS
+#endif /* __MODEST_MSG_VIEW_WINDOW_UI_PRIV_H__ */
diff --git a/src/hildon2/modest-msg-view-window.c b/src/hildon2/modest-msg-view-window.c
new file mode 100644 (file)
index 0000000..4f1f139
--- /dev/null
@@ -0,0 +1,3200 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <glib/gi18n.h>
+#include <string.h>
+#include <tny-account-store.h>
+#include <tny-simple-list.h>
+#include <tny-msg.h>
+#include <tny-mime-part.h>
+#include <tny-vfs-stream.h>
+#include "modest-marshal.h"
+#include "modest-platform.h"
+#include <modest-utils.h>
+#include <modest-maemo-utils.h>
+#include <modest-tny-msg.h>
+#include <modest-msg-view-window.h>
+#include <modest-main-window-ui.h>
+#include "modest-msg-view-window-ui-dimming.h"
+#include <modest-widget-memory.h>
+#include <modest-runtime.h>
+#include <modest-window-priv.h>
+#include <modest-tny-folder.h>
+#include <modest-text-utils.h>
+#include <modest-account-mgr-helpers.h>
+#include "modest-progress-bar.h"
+#include "modest-defs.h"
+#include "modest-hildon-includes.h"
+#include "modest-ui-dimming-manager.h"
+#include <gdk/gdkkeysyms.h>
+#include <modest-tny-account.h>
+#include <modest-mime-part-view.h>
+#include <modest-isearch-view.h>
+#include <modest-tny-mime-part.h>
+#include <math.h>
+#include <errno.h>
+#include <glib/gstdio.h>
+#include <modest-debug.h>
+
+#define DEFAULT_FOLDER "MyDocs/.documents"
+
+static void  modest_msg_view_window_class_init   (ModestMsgViewWindowClass *klass);
+static void  modest_msg_view_window_init         (ModestMsgViewWindow *obj);
+static void  modest_header_view_observer_init(
+               ModestHeaderViewObserverIface *iface_class);
+static void  modest_msg_view_window_finalize     (GObject *obj);
+static void  modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *obj,
+                                                        gpointer data);
+static void  modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
+                                                       ModestMsgViewWindow *obj);
+static void  modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
+                                                       ModestMsgViewWindow *obj);
+
+static void modest_msg_view_window_disconnect_signals (ModestWindow *self);
+static void modest_msg_view_window_set_zoom (ModestWindow *window,
+                                            gdouble zoom);
+static gdouble modest_msg_view_window_get_zoom (ModestWindow *window);
+static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window);
+static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window);
+static gboolean modest_msg_view_window_key_event (GtkWidget *window,
+                                                 GdkEventKey *event,
+                                                 gpointer userdata);
+static gboolean modest_msg_view_window_window_state_event (GtkWidget *widget, 
+                                                          GdkEventWindowState *event, 
+                                                          gpointer userdata);
+static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_show_toolbar   (ModestWindow *window,
+                                                  gboolean show_toolbar);
+
+static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
+                                                          GdkEvent *event,
+                                                          ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_changed (GtkTreeModel *header_model,
+                                                  GtkTreePath *arg1,
+                                                  GtkTreeIter *arg2,
+                                                  ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_deleted (GtkTreeModel *header_model,
+                                                  GtkTreePath *arg1,
+                                                  ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_inserted (GtkTreeModel *header_model,
+                                                   GtkTreePath *tree_path,
+                                                   GtkTreeIter *tree_iter,
+                                                   ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_reordered (GtkTreeModel *header_model,
+                                                    GtkTreePath *arg1,
+                                                    GtkTreeIter *arg2,
+                                                    gpointer arg3,
+                                                    ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_update_model_replaced (ModestHeaderViewObserver *window,
+                                                         GtkTreeModel *model,
+                                                         const gchar *tny_folder_id);
+
+static void cancel_progressbar  (GtkToolButton *toolbutton,
+                                ModestMsgViewWindow *self);
+
+static void on_queue_changed    (ModestMailOperationQueue *queue,
+                                ModestMailOperation *mail_op,
+                                ModestMailOperationQueueNotification type,
+                                ModestMsgViewWindow *self);
+
+static void on_account_removed  (TnyAccountStore *account_store, 
+                                TnyAccount *account,
+                                gpointer user_data);
+
+static void on_move_focus (GtkWidget *widget,
+                          GtkDirectionType direction,
+                          gpointer userdata);
+
+static void view_msg_cb         (ModestMailOperation *mail_op, 
+                                TnyHeader *header, 
+                                gboolean canceled,
+                                TnyMsg *msg, 
+                                GError *error,
+                                gpointer user_data);
+
+static void set_toolbar_mode    (ModestMsgViewWindow *self, 
+                                ModestToolBarModes mode);
+
+static void update_window_title (ModestMsgViewWindow *window);
+
+static gboolean set_toolbar_transfer_mode     (ModestMsgViewWindow *self); 
+static void init_window (ModestMsgViewWindow *obj);
+
+static gboolean msg_is_visible (TnyHeader *header, gboolean check_outbox);
+
+static void check_dimming_rules_after_change (ModestMsgViewWindow *window);
+
+static gboolean on_fetch_image (ModestMsgView *msgview,
+                               const gchar *uri,
+                               TnyStream *stream,
+                               ModestMsgViewWindow *window);
+
+static gboolean modest_msg_view_window_scroll_child (ModestMsgViewWindow *self,
+                                                    GtkScrollType scroll_type,
+                                                    gboolean horizontal,
+                                                    gpointer userdata);
+
+/* list my signals */
+enum {
+       MSG_CHANGED_SIGNAL,
+       SCROLL_CHILD_SIGNAL,
+       LAST_SIGNAL
+};
+
+static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
+       { "FindInMessage",    MODEST_TOOLBAR_ICON_FIND,    N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
+       { "ToolsFindInMessage", NULL, N_("mcen_me_viewer_find"), "<CTRL>F", NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
+};
+
+static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
+       { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
+       { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
+       { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
+       { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
+       { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
+       { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
+};
+
+typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
+struct _ModestMsgViewWindowPrivate {
+
+       GtkWidget   *msg_view;
+       GtkWidget   *main_scroll;
+       GtkWidget   *find_toolbar;
+       gchar       *last_search;
+
+       /* Progress observers */
+       GtkWidget        *progress_bar;
+       GSList           *progress_widgets;
+
+       /* Tollbar items */
+       GtkWidget   *progress_toolitem;
+       GtkWidget   *cancel_toolitem;
+       GtkWidget   *prev_toolitem;
+       GtkWidget   *next_toolitem;
+       ModestToolBarModes current_toolbar_mode;
+
+       /* Optimized view enabled */
+       gboolean optimized_view;
+
+       /* Whether this was created via the *_new_for_search_result() function. */
+       gboolean is_search_result;
+
+       /* Whether the message is in outbox */
+       gboolean is_outbox;
+       
+       /* A reference to the @model of the header view 
+        * to allow selecting previous/next messages,
+        * if the message is currently selected in the header view.
+        */
+       const gchar *header_folder_id;
+       GtkTreeModel *header_model;
+       GtkTreeRowReference *row_reference;
+       GtkTreeRowReference *next_row_reference;
+
+       gulong clipboard_change_handler;
+       gulong queue_change_handler;
+       gulong account_removed_handler;
+       gulong row_changed_handler;
+       gulong row_deleted_handler;
+       gulong row_inserted_handler;
+       gulong rows_reordered_handler;
+
+       guint purge_timeout;
+       GtkWidget *remove_attachment_banner;
+
+       guint progress_bar_timeout;
+
+       gchar *msg_uid;
+       
+       GSList *sighandlers;
+};
+
+#define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                    MODEST_TYPE_MSG_VIEW_WINDOW, \
+                                                    ModestMsgViewWindowPrivate))
+/* globals */
+static GtkWindowClass *parent_class = NULL;
+
+/* uncomment the following if you have defined any signals */
+static guint signals[LAST_SIGNAL] = {0};
+
+GType
+modest_msg_view_window_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestMsgViewWindowClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_msg_view_window_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestMsgViewWindow),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_msg_view_window_init,
+                       NULL
+               };
+               my_type = g_type_register_static (MODEST_TYPE_WINDOW,
+                                                 "ModestMsgViewWindow",
+                                                 &my_info, 0);
+
+               static const GInterfaceInfo modest_header_view_observer_info = 
+               {
+                       (GInterfaceInitFunc) modest_header_view_observer_init,
+                       NULL,         /* interface_finalize */
+                       NULL          /* interface_data */
+               };
+
+               g_type_add_interface_static (my_type,
+                               MODEST_TYPE_HEADER_VIEW_OBSERVER,
+                               &modest_header_view_observer_info);
+       }
+       return my_type;
+}
+
+static void
+save_state (ModestWindow *self)
+{
+       modest_widget_memory_save (modest_runtime_get_conf (),
+                                  G_OBJECT(self), 
+                                  MODEST_CONF_MSG_VIEW_WINDOW_KEY);
+}
+
+
+static void
+restore_settings (ModestMsgViewWindow *self)
+{
+       ModestConf *conf;
+       ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
+       GtkAction *action;
+
+       conf = modest_runtime_get_conf ();
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
+       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_MSG_VIEW_WINDOW_SHOW_TOOLBAR, NULL));
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarFullScreenMenu");
+       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+                                     modest_conf_get_bool (conf, MODEST_CONF_MSG_VIEW_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
+       modest_widget_memory_restore (conf,
+                                     G_OBJECT(self), 
+                                     MODEST_CONF_MSG_VIEW_WINDOW_KEY);
+}
+
+static gboolean modest_msg_view_window_scroll_child (ModestMsgViewWindow *self,
+                                                    GtkScrollType scroll_type,
+                                                    gboolean horizontal,
+                                                    gpointer userdata)
+{
+       ModestMsgViewWindowPrivate *priv;
+       gboolean return_value;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+       g_signal_emit_by_name (priv->main_scroll, "scroll-child", scroll_type, horizontal, &return_value);
+       return return_value;
+}
+
+static void
+add_scroll_binding (GtkBindingSet *binding_set,
+                   guint keyval,
+                   GtkScrollType scroll)
+{
+       guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left;
+       
+       gtk_binding_entry_add_signal (binding_set, keyval, 0,
+                                     "scroll_child", 2,
+                                     GTK_TYPE_SCROLL_TYPE, scroll,
+                                     G_TYPE_BOOLEAN, FALSE);
+       gtk_binding_entry_add_signal (binding_set, keypad_keyval, 0,
+                                     "scroll_child", 2,
+                                     GTK_TYPE_SCROLL_TYPE, scroll,
+                                     G_TYPE_BOOLEAN, FALSE);
+}
+
+static void
+modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
+{
+       GObjectClass *gobject_class;
+       ModestWindowClass *modest_window_class;
+       GtkBindingSet *binding_set;
+
+       gobject_class = (GObjectClass*) klass;
+       modest_window_class = (ModestWindowClass *) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_msg_view_window_finalize;
+
+       modest_window_class->set_zoom_func = modest_msg_view_window_set_zoom;
+       modest_window_class->get_zoom_func = modest_msg_view_window_get_zoom;
+       modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus;
+       modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus;
+       modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar;
+       modest_window_class->disconnect_signals_func = modest_msg_view_window_disconnect_signals;
+
+       modest_window_class->save_state_func = save_state;
+
+       klass->scroll_child = modest_msg_view_window_scroll_child;
+
+       signals[MSG_CHANGED_SIGNAL] =
+               g_signal_new ("msg-changed",
+                             G_TYPE_FROM_CLASS (gobject_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (ModestMsgViewWindowClass, msg_changed),
+                             NULL, NULL,
+                             modest_marshal_VOID__POINTER_POINTER,
+                             G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+
+       signals[SCROLL_CHILD_SIGNAL] =
+               g_signal_new ("scroll-child",
+                             G_TYPE_FROM_CLASS (gobject_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (ModestMsgViewWindowClass, scroll_child),
+                             NULL, NULL,
+                             modest_marshal_BOOLEAN__ENUM_BOOLEAN,
+                             G_TYPE_BOOLEAN, 2, GTK_TYPE_SCROLL_TYPE, G_TYPE_BOOLEAN);
+
+       binding_set = gtk_binding_set_by_class (klass);
+       add_scroll_binding (binding_set, GDK_Up, GTK_SCROLL_STEP_UP);
+       add_scroll_binding (binding_set, GDK_Down, GTK_SCROLL_STEP_DOWN);
+       add_scroll_binding (binding_set, GDK_Page_Up, GTK_SCROLL_PAGE_UP);
+       add_scroll_binding (binding_set, GDK_Page_Down, GTK_SCROLL_PAGE_DOWN);
+       add_scroll_binding (binding_set, GDK_Home, GTK_SCROLL_START);
+       add_scroll_binding (binding_set, GDK_End, GTK_SCROLL_END);
+
+       g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
+
+}
+
+static void modest_header_view_observer_init(
+               ModestHeaderViewObserverIface *iface_class)
+{
+       iface_class->update_func = modest_msg_view_window_update_model_replaced;
+}
+
+static void
+modest_msg_view_window_init (ModestMsgViewWindow *obj)
+{
+       ModestMsgViewWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv = NULL;
+       GtkActionGroup *action_group = NULL;
+       GError *error = NULL;
+       GdkPixbuf *window_icon;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
+       parent_priv->ui_manager = gtk_ui_manager_new();
+
+       action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
+       gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+
+       /* Add common actions */
+       gtk_action_group_add_actions (action_group,
+                                     modest_action_entries,
+                                     G_N_ELEMENTS (modest_action_entries),
+                                     obj);
+       gtk_action_group_add_toggle_actions (action_group,
+                                            modest_toggle_action_entries,
+                                            G_N_ELEMENTS (modest_toggle_action_entries),
+                                            obj);
+       gtk_action_group_add_toggle_actions (action_group,
+                                            msg_view_toggle_action_entries,
+                                            G_N_ELEMENTS (msg_view_toggle_action_entries),
+                                            obj);
+       gtk_action_group_add_radio_actions (action_group,
+                                           msg_view_zoom_action_entries,
+                                           G_N_ELEMENTS (msg_view_zoom_action_entries),
+                                           100,
+                                           G_CALLBACK (modest_ui_actions_on_change_zoom),
+                                           obj);
+
+       gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
+       g_object_unref (action_group);
+
+       /* Load the UI definition */
+       gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-view-window-ui.xml",
+                                        &error);
+       if (error) {
+               g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
+               g_error_free (error);
+               error = NULL;
+       }
+       /* ****** */
+
+       /* Add accelerators */
+       gtk_window_add_accel_group (GTK_WINDOW (obj), 
+                                   gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
+       
+       priv->is_search_result = FALSE;
+       priv->is_outbox = FALSE;
+
+       priv->msg_view      = NULL;
+       priv->header_model  = NULL;
+       priv->header_folder_id  = NULL;
+       priv->clipboard_change_handler = 0;
+       priv->queue_change_handler = 0;
+       priv->account_removed_handler = 0;
+       priv->row_changed_handler = 0;
+       priv->row_deleted_handler = 0;
+       priv->row_inserted_handler = 0;
+       priv->rows_reordered_handler = 0;
+       priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
+
+       priv->optimized_view  = FALSE;
+       priv->progress_bar_timeout = 0;
+       priv->purge_timeout = 0;
+       priv->remove_attachment_banner = NULL;
+       priv->msg_uid = NULL;
+       
+       priv->sighandlers = NULL;
+       
+       /* Init window */
+       init_window (MODEST_MSG_VIEW_WINDOW(obj));
+       
+       /* Set window icon */
+       window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON, MODEST_ICON_SIZE_BIG); 
+       if (window_icon) {
+               gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
+               g_object_unref (window_icon);
+       }       
+       
+       hildon_program_add_window (hildon_program_get_instance(),
+                                  HILDON_WINDOW(obj));
+
+       modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
+                                           GTK_WINDOW(obj),"applications_email_viewer");
+}
+
+
+static gboolean
+set_toolbar_transfer_mode (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+
+       set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
+       
+       if (priv->progress_bar_timeout > 0) {
+               g_source_remove (priv->progress_bar_timeout);
+               priv->progress_bar_timeout = 0;
+       }
+       
+       return FALSE;
+}
+
+static void 
+set_toolbar_mode (ModestMsgViewWindow *self, 
+                 ModestToolBarModes mode)
+{
+       ModestWindowPrivate *parent_priv;
+       ModestMsgViewWindowPrivate *priv;
+/*     GtkWidget *widget = NULL; */
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
+
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+                       
+       /* Sets current toolbar mode */
+       priv->current_toolbar_mode = mode;
+
+       /* Update toolbar dimming state */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+
+       switch (mode) {
+       case TOOLBAR_MODE_NORMAL:               
+               if (priv->progress_toolitem) {
+                       gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
+                       gtk_widget_hide (priv->progress_toolitem);
+               }
+
+               if (priv->progress_bar)
+                       gtk_widget_hide (priv->progress_bar);
+                       
+               if (priv->cancel_toolitem)
+                       gtk_widget_hide (priv->cancel_toolitem);
+
+               if (priv->prev_toolitem)
+                       gtk_widget_show (priv->prev_toolitem);
+               
+               if (priv->next_toolitem)
+                       gtk_widget_show (priv->next_toolitem);
+                       
+               /* Hide toolbar if optimized view is enabled */
+               if (priv->optimized_view) {
+                       gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
+                       gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
+               }
+
+               break;
+       case TOOLBAR_MODE_TRANSFER:
+               if (priv->prev_toolitem)
+                       gtk_widget_hide (priv->prev_toolitem);
+               
+               if (priv->next_toolitem)
+                       gtk_widget_hide (priv->next_toolitem);
+               
+               if (priv->progress_bar)
+                       gtk_widget_show (priv->progress_bar);
+
+               if (priv->progress_toolitem) {
+                       gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
+                       gtk_widget_show (priv->progress_toolitem);
+               }
+                       
+               if (priv->cancel_toolitem)
+                       gtk_widget_show (priv->cancel_toolitem);
+
+               /* Show toolbar if it's hiden (optimized view ) */
+               if (priv->optimized_view) {
+                       gtk_widget_set_no_show_all (parent_priv->toolbar, FALSE);
+                       gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
+               }
+
+               break;
+       default:
+               g_return_if_reached ();
+       }
+
+}
+
+
+static void
+init_window (ModestMsgViewWindow *obj)
+{
+       GtkWidget *main_vbox;
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
+
+       priv->msg_view = GTK_WIDGET (tny_platform_factory_new_msg_view (modest_tny_platform_factory_get_instance ()));
+       modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
+       main_vbox = gtk_vbox_new  (FALSE, 6);
+
+#ifdef MODEST_USE_MOZEMBED
+       priv->main_scroll = priv->msg_view;
+       gtk_widget_set_size_request (priv->msg_view, -1, 1600);
+#else
+       priv->main_scroll = gtk_scrolled_window_new (NULL, NULL);
+       gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view);
+#endif
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE);
+       modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->main_scroll), TRUE);
+
+       gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0);
+       gtk_container_add   (GTK_CONTAINER(obj), main_vbox);
+
+       priv->find_toolbar = hildon_find_toolbar_new (NULL);
+       hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
+       gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
+       
+       gtk_widget_show_all (GTK_WIDGET(main_vbox));
+}
+
+static void
+modest_msg_view_window_disconnect_signals (ModestWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv;
+       ModestHeaderView *header_view = NULL;
+       ModestWindow *main_window = NULL;
+       
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
+           g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
+                                          priv->clipboard_change_handler)) 
+               g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), 
+                                            priv->clipboard_change_handler);
+
+       if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
+                                          priv->queue_change_handler))
+               g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), 
+                                            priv->queue_change_handler);
+
+       if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_account_store ()), 
+                                          priv->account_removed_handler))
+               g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_account_store ()), 
+                                            priv->account_removed_handler);
+
+       if (priv->header_model) {
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_changed_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_changed_handler);
+               
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_deleted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                            priv->row_deleted_handler);
+               
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_inserted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_inserted_handler);
+               
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->rows_reordered_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->rows_reordered_handler);
+       }
+
+       modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
+       priv->sighandlers = NULL;
+       
+       main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
+                                                        FALSE); /* don't create */
+       if (!main_window)
+               return;
+       
+       header_view = MODEST_HEADER_VIEW(
+                       modest_main_window_get_child_widget(
+                               MODEST_MAIN_WINDOW(main_window),
+                               MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
+       if (header_view == NULL)
+               return;
+       
+       modest_header_view_remove_observer(header_view,
+                       MODEST_HEADER_VIEW_OBSERVER(self));
+}      
+
+static void
+modest_msg_view_window_finalize (GObject *obj)
+{
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
+
+       /* Sanity check: shouldn't be needed, the window mgr should
+          call this function before */
+       modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj));
+
+       if (priv->header_model != NULL) {
+               g_object_unref (priv->header_model);
+               priv->header_model = NULL;
+       }
+
+       if (priv->progress_bar_timeout > 0) {
+               g_source_remove (priv->progress_bar_timeout);
+               priv->progress_bar_timeout = 0;
+       }
+
+       if (priv->remove_attachment_banner) {
+               gtk_widget_destroy (priv->remove_attachment_banner);
+               g_object_unref (priv->remove_attachment_banner);
+               priv->remove_attachment_banner = NULL;
+       }
+
+       if (priv->purge_timeout > 0) {
+               g_source_remove (priv->purge_timeout);
+               priv->purge_timeout = 0;
+       }
+
+       if (priv->row_reference) {
+               gtk_tree_row_reference_free (priv->row_reference);
+               priv->row_reference = NULL;
+       }
+
+       if (priv->next_row_reference) {
+               gtk_tree_row_reference_free (priv->next_row_reference);
+               priv->next_row_reference = NULL;
+       }
+
+       if (priv->msg_uid) {
+               g_free (priv->msg_uid);
+               priv->msg_uid = NULL;
+       }
+
+       G_OBJECT_CLASS(parent_class)->finalize (obj);
+}
+
+static gboolean
+select_next_valid_row (GtkTreeModel *model,
+                      GtkTreeRowReference **row_reference,
+                      gboolean cycle,
+                      gboolean is_outbox)
+{
+       GtkTreeIter tmp_iter;
+       GtkTreePath *path;
+       GtkTreePath *next = NULL;
+       gboolean retval = FALSE, finished;
+
+       g_return_val_if_fail (gtk_tree_row_reference_valid (*row_reference), FALSE);
+
+       path = gtk_tree_row_reference_get_path (*row_reference);
+       gtk_tree_model_get_iter (model, &tmp_iter, path);
+       gtk_tree_row_reference_free (*row_reference);
+       *row_reference = NULL;
+
+       finished = FALSE;
+       do {
+               TnyHeader *header = NULL;
+
+               if (gtk_tree_model_iter_next (model, &tmp_iter)) {
+                       gtk_tree_model_get (model, &tmp_iter, 
+                                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, 
+                                           &header, -1);
+
+                       if (header) {
+                               if (msg_is_visible (header, is_outbox)) {
+                                       next = gtk_tree_model_get_path (model, &tmp_iter);
+                                       *row_reference = gtk_tree_row_reference_new (model, next);
+                                       retval = TRUE;
+                                       finished = TRUE;
+                               }
+                               g_object_unref (header);
+                               header = NULL;
+                       }
+               } else if (cycle && gtk_tree_model_get_iter_first (model, &tmp_iter)) {
+                       next = gtk_tree_model_get_path (model, &tmp_iter);
+                       
+                       /* Ensure that we are not selecting the same */
+                       if (gtk_tree_path_compare (path, next) != 0) {
+                               gtk_tree_model_get (model, &tmp_iter, 
+                                                   TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, 
+                                                   &header, -1);                               
+                               if (header) {
+                                       if (msg_is_visible (header, is_outbox)) {
+                                               *row_reference = gtk_tree_row_reference_new (model, next);
+                                               retval = TRUE;
+                                               finished = TRUE;
+                                       }
+                                       g_object_unref (header);
+                                       header = NULL;
+                               }
+                       } else {
+                               /* If we ended up in the same message
+                                  then there is no valid next
+                                  message */
+                               finished = TRUE;
+                       }
+               } else {
+                       /* If there are no more messages and we don't
+                          want to start again in the first one then
+                          there is no valid next message */
+                       finished = TRUE;
+               }
+       } while (!finished);
+
+       /* Free */
+       gtk_tree_path_free (path);
+       if (next)
+               gtk_tree_path_free (next);
+
+       return retval;
+}
+
+/* TODO: This should be in _init(), with the parameters as properties. */
+static void
+modest_msg_view_window_construct (ModestMsgViewWindow *self, 
+                                 const gchar *modest_account_name,
+                                 const gchar *msg_uid)
+{
+       GObject *obj = NULL;
+       ModestMsgViewWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;
+       ModestDimmingRulesGroup *menu_rules_group = NULL;
+       ModestDimmingRulesGroup *toolbar_rules_group = NULL;
+       ModestDimmingRulesGroup *clipboard_rules_group = NULL;
+
+       obj = G_OBJECT (self);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
+
+       priv->msg_uid = g_strdup (msg_uid);
+
+       /* Menubar */
+       parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
+       hildon_window_set_menu    (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
+       gtk_widget_show (parent_priv->menubar);
+       parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
+
+       menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
+       toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
+       clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
+
+       /* Add common dimming rules */
+       modest_dimming_rules_group_add_rules (menu_rules_group, 
+                                             modest_msg_view_menu_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
+                                             MODEST_WINDOW (self));
+       modest_dimming_rules_group_add_rules (toolbar_rules_group, 
+                                             modest_msg_view_toolbar_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
+                                             MODEST_WINDOW (self));
+       modest_dimming_rules_group_add_rules (clipboard_rules_group, 
+                                             modest_msg_view_clipboard_dimming_entries,
+                                             G_N_ELEMENTS (modest_msg_view_clipboard_dimming_entries),
+                                             MODEST_WINDOW (self));
+
+       /* Insert dimming rules group for this window */
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
+       modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
+       g_object_unref (menu_rules_group);
+       g_object_unref (toolbar_rules_group);
+       g_object_unref (clipboard_rules_group);
+
+       restore_settings (MODEST_MSG_VIEW_WINDOW(obj));
+       
+       /* g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj); */
+
+       priv->clipboard_change_handler = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change", G_CALLBACK (modest_msg_view_window_clipboard_owner_change), obj);
+       g_signal_connect (G_OBJECT(priv->msg_view), "activate_link",
+                         G_CALLBACK (modest_ui_actions_on_msg_link_clicked), obj);
+       g_signal_connect (G_OBJECT(priv->msg_view), "link_hover",
+                         G_CALLBACK (modest_ui_actions_on_msg_link_hover), obj);
+       g_signal_connect (G_OBJECT(priv->msg_view), "attachment_clicked",
+                         G_CALLBACK (modest_ui_actions_on_msg_attachment_clicked), obj);
+       g_signal_connect (G_OBJECT(priv->msg_view), "recpt_activated",
+                         G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
+       g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
+                         G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
+       g_signal_connect (G_OBJECT (priv->msg_view), "fetch_image",
+                         G_CALLBACK (on_fetch_image), obj);
+
+       g_signal_connect (G_OBJECT (obj), "key-release-event",
+                         G_CALLBACK (modest_msg_view_window_key_event),
+                         NULL);
+
+       g_signal_connect (G_OBJECT (obj), "key-press-event",
+                         G_CALLBACK (modest_msg_view_window_key_event),
+                         NULL);
+
+       g_signal_connect (G_OBJECT (obj), "window-state-event",
+                         G_CALLBACK (modest_msg_view_window_window_state_event),
+                         NULL);
+
+       g_signal_connect (G_OBJECT (obj), "move-focus",
+                         G_CALLBACK (on_move_focus), obj);
+
+       /* Mail Operation Queue */
+       priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
+                                                      "queue-changed",
+                                                      G_CALLBACK (on_queue_changed),
+                                                      obj);
+
+       /* Account manager */
+       priv->account_removed_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
+                                                         "account_removed",
+                                                         G_CALLBACK(on_account_removed),
+                                                         obj);
+
+       modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
+
+       g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj);
+       g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj);
+       priv->last_search = NULL;
+
+       /* Init the clipboard actions dim status */
+       modest_msg_view_grab_focus(MODEST_MSG_VIEW (priv->msg_view));
+
+       update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
+
+
+}
+
+/* FIXME: parameter checks */
+ModestWindow *
+modest_msg_view_window_new_with_header_model (TnyMsg *msg, 
+                                             const gchar *modest_account_name,
+                                             const gchar *msg_uid,
+                                             GtkTreeModel *model, 
+                                             GtkTreeRowReference *row_reference)
+{
+       ModestMsgViewWindow *window = NULL;
+       ModestMsgViewWindowPrivate *priv = NULL;
+       TnyFolder *header_folder = NULL;
+       ModestHeaderView *header_view = NULL;
+       ModestWindow *main_window = NULL;
+       ModestWindowMgr *mgr = NULL;
+
+       MODEST_DEBUG_BLOCK (
+              modest_tny_mime_part_to_string (TNY_MIME_PART (msg), 0);
+       );
+
+       mgr = modest_runtime_get_window_mgr ();
+       window = MODEST_MSG_VIEW_WINDOW (modest_window_mgr_get_msg_view_window (mgr));
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
+
+       modest_msg_view_window_construct (window, modest_account_name, msg_uid);
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /* Remember the message list's TreeModel so we can detect changes 
+        * and change the list selection when necessary: */
+
+       main_window = modest_window_mgr_get_main_window(mgr, FALSE); /* don't create */
+       if (main_window) {
+               header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget(
+                                                        MODEST_MAIN_WINDOW(main_window),
+                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
+       }
+       
+       if (header_view != NULL){
+               header_folder = modest_header_view_get_folder(header_view);
+               /* This could happen if the header folder was
+                  unseleted before opening this msg window (for
+                  example if the user selects an account in the
+                  folder view of the main window */
+               if (header_folder) {
+                       priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == TNY_FOLDER_TYPE_OUTBOX);
+                       priv->header_folder_id = tny_folder_get_id(header_folder);
+                       g_assert(priv->header_folder_id != NULL);
+                       g_object_unref(header_folder);
+               }
+       }
+
+       /* Setup row references and connect signals */
+       priv->header_model = g_object_ref (model);
+
+       if (row_reference) {
+               priv->row_reference = gtk_tree_row_reference_copy (row_reference);
+               priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
+               select_next_valid_row (model, &(priv->next_row_reference), TRUE, priv->is_outbox);
+       } else {
+               priv->row_reference = NULL;
+               priv->next_row_reference = NULL;
+       }
+
+       /* Connect signals */
+       priv->row_changed_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-changed",
+                                 G_CALLBACK(modest_msg_view_window_on_row_changed),
+                                 window);
+       priv->row_deleted_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-deleted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_deleted),
+                                 window);
+       priv->row_inserted_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-inserted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_inserted),
+                                 window);
+       priv->rows_reordered_handler = 
+               g_signal_connect(GTK_TREE_MODEL(model), "rows-reordered",
+                                G_CALLBACK(modest_msg_view_window_on_row_reordered),
+                                window);
+
+       if (header_view != NULL){
+               modest_header_view_add_observer(header_view,
+                               MODEST_HEADER_VIEW_OBSERVER(window));
+       }
+
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       update_window_title (MODEST_MSG_VIEW_WINDOW (window));
+       gtk_widget_show_all (GTK_WIDGET (window));
+       modest_msg_view_window_update_priority (window);
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+
+       return MODEST_WINDOW(window);
+}
+
+ModestWindow *
+modest_msg_view_window_new_for_search_result (TnyMsg *msg, 
+                                             const gchar *modest_account_name,
+                                             const gchar *msg_uid)
+{
+       ModestMsgViewWindow *window = NULL;
+       ModestMsgViewWindowPrivate *priv = NULL;
+       ModestWindowMgr *mgr = NULL;
+
+       mgr = modest_runtime_get_window_mgr ();
+       window = MODEST_MSG_VIEW_WINDOW (modest_window_mgr_get_msg_view_window (mgr));
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
+       modest_msg_view_window_construct (window, modest_account_name, msg_uid);
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /* Remember that this is a search result, 
+        * so we can disable some UI appropriately: */
+       priv->is_search_result = TRUE;
+
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       
+       update_window_title (window);
+       gtk_widget_show_all (GTK_WIDGET (window));
+       modest_msg_view_window_update_priority (window);
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+
+       return MODEST_WINDOW(window);
+}
+
+ModestWindow *
+modest_msg_view_window_new_for_attachment (TnyMsg *msg, 
+                           const gchar *modest_account_name,
+                           const gchar *msg_uid)
+{
+       GObject *obj = NULL;
+       ModestMsgViewWindowPrivate *priv;       
+       ModestWindowMgr *mgr = NULL;
+
+       g_return_val_if_fail (msg, NULL);
+       mgr = modest_runtime_get_window_mgr ();
+       obj = G_OBJECT (modest_window_mgr_get_msg_view_window (mgr));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
+       modest_msg_view_window_construct (MODEST_MSG_VIEW_WINDOW (obj), 
+               modest_account_name, msg_uid);
+
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
+
+       gtk_widget_show_all (GTK_WIDGET (obj));
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
+
+       return MODEST_WINDOW(obj);
+}
+
+static void
+modest_msg_view_window_on_row_changed (GtkTreeModel *header_model,
+                                      GtkTreePath *arg1,
+                                      GtkTreeIter *arg2,
+                                      ModestMsgViewWindow *window)
+{
+       check_dimming_rules_after_change (window);
+}
+
+static void 
+modest_msg_view_window_on_row_deleted(GtkTreeModel *header_model,
+                                     GtkTreePath *arg1,
+                                     ModestMsgViewWindow *window)
+{
+       check_dimming_rules_after_change (window);
+}
+       /* The window could have dissapeared */
+
+static void
+check_dimming_rules_after_change (ModestMsgViewWindow *window)
+{
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+}
+
+
+/* On insertions we check if the folder still has the message we are
+ * showing or do not. If do not, we do nothing. Which means we are still
+ * not attached to any header folder and thus next/prev buttons are
+ * still dimmed. Once the message that is shown by msg-view is found, the
+ * new model of header-view will be attached and the references will be set.
+ * On each further insertions dimming rules will be checked. However
+ * this requires extra CPU time at least works.
+ * (An message might be deleted from TnyFolder and thus will not be
+ * inserted into the model again for example if it is removed by the
+ * imap server and the header view is refreshed.)
+ */
+static void 
+modest_msg_view_window_on_row_inserted (GtkTreeModel *model,
+                                       GtkTreePath *tree_path,
+                                       GtkTreeIter *tree_iter,
+                                       ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv = NULL; 
+       TnyHeader *header = NULL;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       g_assert (model == priv->header_model);
+       
+       /* Check if the newly inserted message is the same we are actually
+        * showing. IF not, we should remain detached from the header model
+        * and thus prev and next toolbar buttons should remain dimmed. */
+       gtk_tree_model_get (model, tree_iter, 
+                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, 
+                           &header, -1);
+
+       if (TNY_IS_HEADER (header)) {
+               gchar *uid = NULL;
+
+               uid = modest_tny_folder_get_header_unique_id (header);
+               if (!g_str_equal(priv->msg_uid, uid)) {
+                       check_dimming_rules_after_change (window);
+                       g_free(uid);
+                       g_object_unref (G_OBJECT(header));
+                       return;
+               }
+               g_free(uid);
+               g_object_unref(G_OBJECT(header));
+       }
+
+       if (priv->row_reference) {
+               gtk_tree_row_reference_free (priv->row_reference); 
+       }
+
+       /* Setup row_reference for the actual msg. */
+       priv->row_reference = gtk_tree_row_reference_new (priv->header_model, tree_path);
+       if (priv->row_reference == NULL) {
+               g_warning("No reference for msg header item.");
+               return;
+       }
+
+       /* Now set up next_row_reference. */
+       if (priv->next_row_reference) {
+               gtk_tree_row_reference_free (priv->next_row_reference); 
+       }
+
+       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+       select_next_valid_row (priv->header_model,
+                              &(priv->next_row_reference), FALSE, priv->is_outbox);
+
+       /* Connect the remaining callbacks to become able to detect
+        * changes in header-view. */
+       priv->row_changed_handler = 
+               g_signal_connect (priv->header_model, "row-changed",
+                                 G_CALLBACK (modest_msg_view_window_on_row_changed),
+                                 window);
+       priv->row_deleted_handler = 
+               g_signal_connect (priv->header_model, "row-deleted",
+                                 G_CALLBACK (modest_msg_view_window_on_row_deleted),
+                                 window);
+       priv->rows_reordered_handler = 
+               g_signal_connect (priv->header_model, "rows-reordered",
+                                 G_CALLBACK (modest_msg_view_window_on_row_reordered),
+                                 window);
+
+       check_dimming_rules_after_change (window);      
+}
+
+static void 
+modest_msg_view_window_on_row_reordered (GtkTreeModel *header_model,
+                                        GtkTreePath *arg1,
+                                        GtkTreeIter *arg2,
+                                        gpointer arg3,
+                                        ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv = NULL; 
+       gboolean already_changed = FALSE;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(window);
+
+       /* If the current row was reordered select the proper next
+          valid row. The same if the next row reference changes */
+       if (priv->row_reference && 
+           gtk_tree_row_reference_valid (priv->row_reference)) {
+               GtkTreePath *path;
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
+               if (gtk_tree_path_compare (path, arg1) == 0) {
+                       if (priv->next_row_reference) {
+                               gtk_tree_row_reference_free (priv->next_row_reference);
+                       }
+                       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+                       select_next_valid_row (header_model, &(priv->next_row_reference), FALSE, priv->is_outbox);
+                       already_changed = TRUE;
+               }
+               gtk_tree_path_free (path);
+       }
+       if (!already_changed &&
+           priv->next_row_reference &&
+           gtk_tree_row_reference_valid (priv->next_row_reference)) {
+               GtkTreePath *path;
+               path = gtk_tree_row_reference_get_path (priv->next_row_reference);
+               if (gtk_tree_path_compare (path, arg1) == 0) {
+                       if (priv->next_row_reference) {
+                               gtk_tree_row_reference_free (priv->next_row_reference);
+                       }
+                       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+                       select_next_valid_row (header_model, &(priv->next_row_reference), FALSE, priv->is_outbox);
+               }
+               gtk_tree_path_free (path);
+       }
+       check_dimming_rules_after_change (window);
+}
+
+/* The modest_msg_view_window_update_model_replaced implements update
+ * function for ModestHeaderViewObserver. Checks whether the TnyFolder
+ * actually belongs to the header-view is the same as the TnyFolder of
+ * the message of msg-view or not. If they are different, there is
+ * nothing to do. If they are the same, then the model has replaced and
+ * the reference in msg-view shall be replaced from the old model to
+ * the new model. In this case the view will be detached from it's
+ * header folder. From this point the next/prev buttons are dimmed.
+ */
+static void 
+modest_msg_view_window_update_model_replaced (ModestHeaderViewObserver *observer,
+                                             GtkTreeModel *model,
+                                             const gchar *tny_folder_id)
+{
+       ModestMsgViewWindowPrivate *priv = NULL; 
+       ModestMsgViewWindow *window = NULL;
+
+       g_assert(MODEST_IS_HEADER_VIEW_OBSERVER(observer));
+       g_assert(MODEST_IS_MSG_VIEW_WINDOW(observer));
+
+       window = MODEST_MSG_VIEW_WINDOW(observer);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(window);
+
+       /* If there is an other folder in the header-view then we do
+        * not care about it's model (msg list). Else if the
+        * header-view shows the folder the msg shown by us is in, we
+        * shall replace our model reference and make some check. */
+       if(model == NULL || tny_folder_id == NULL || 
+          (priv->header_folder_id && !g_str_equal(tny_folder_id, priv->header_folder_id)))
+               return;
+
+       /* Model is changed(replaced), so we should forget the old
+        * one. Because there might be other references and there
+        * might be some change on the model even if we unreferenced
+        * it, we need to disconnect our signals here. */
+       if (priv->header_model) {
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_changed_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_changed_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_deleted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_deleted_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_inserted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_inserted_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->rows_reordered_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->rows_reordered_handler);
+
+               /* Frees */
+               if (priv->row_reference)
+                       gtk_tree_row_reference_free (priv->row_reference);
+               if (priv->next_row_reference)
+                       gtk_tree_row_reference_free (priv->next_row_reference);
+               g_object_unref(priv->header_model);
+
+               /* Initialize */
+               priv->row_changed_handler = 0;
+               priv->row_deleted_handler = 0;
+               priv->row_inserted_handler = 0;
+               priv->rows_reordered_handler = 0;
+               priv->next_row_reference = NULL;
+               priv->row_reference = NULL;
+               priv->header_model = NULL;
+       }
+
+       priv->header_model = g_object_ref (model);
+
+       /* Also we must connect to the new model for row insertions.
+        * Only for insertions now. We will need other ones only after
+        * the msg is show by msg-view is added to the new model. */
+       priv->row_inserted_handler =
+               g_signal_connect (priv->header_model, "row-inserted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_inserted),
+                                 window);
+
+       modest_ui_actions_check_menu_dimming_rules(MODEST_WINDOW(window));
+       modest_ui_actions_check_toolbar_dimming_rules(MODEST_WINDOW(window));
+}
+
+gboolean 
+modest_msg_view_window_toolbar_on_transfer_mode     (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv= NULL; 
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
+}
+
+TnyHeader*
+modest_msg_view_window_get_header (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv= NULL; 
+       TnyMsg *msg = NULL;
+       TnyHeader *header = NULL;
+       GtkTreePath *path = NULL;
+       GtkTreeIter iter;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), NULL);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       /* If the message was not obtained from a treemodel,
+        * for instance if it was opened directly by the search UI:
+        */
+       if (priv->header_model == NULL || 
+           priv->row_reference == NULL ||
+           !gtk_tree_row_reference_valid (priv->row_reference)) {
+               msg = modest_msg_view_window_get_message (self);
+               if (msg) {
+                       header = tny_msg_get_header (msg);
+                       g_object_unref (msg);
+               }
+               return header;
+       }
+
+       /* Get iter of the currently selected message in the header view: */
+       path = gtk_tree_row_reference_get_path (priv->row_reference);
+       g_return_val_if_fail (path != NULL, NULL);
+       gtk_tree_model_get_iter (priv->header_model, 
+                                &iter, 
+                                path);
+
+       /* Get current message header */
+       gtk_tree_model_get (priv->header_model, &iter, 
+                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, 
+                           &header, -1);
+
+       gtk_tree_path_free (path);
+       return header;
+}
+
+TnyMsg*
+modest_msg_view_window_get_message (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv;
+       
+       g_return_val_if_fail (self, NULL);
+       
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+       
+       return tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+}
+
+const gchar*
+modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv;
+
+       g_return_val_if_fail (self, NULL);
+       
+       priv  = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       return (const gchar*) priv->msg_uid;
+}
+
+static void 
+modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
+                                           gpointer data)
+{
+       ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data);
+       ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+       ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       gboolean is_active;
+       GtkAction *action;
+
+       is_active = gtk_toggle_action_get_active (toggle);
+
+       if (is_active) {
+               gtk_widget_show (priv->find_toolbar);
+               hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
+       } else {
+               gtk_widget_hide (priv->find_toolbar);
+       }
+
+       /* update the toggle buttons status */
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsFindInMessageMenu");
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
+       
+}
+
+static void
+modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
+                                          ModestMsgViewWindow *obj)
+{
+       GtkToggleAction *toggle;
+       ModestWindowPrivate *parent_priv;
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
+       
+       toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
+       gtk_toggle_action_set_active (toggle, FALSE);
+       modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+}
+
+static void
+modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
+                                          ModestMsgViewWindow *obj)
+{
+       gchar *current_search;
+       ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
+
+       if (modest_mime_part_view_is_empty (MODEST_MIME_PART_VIEW (priv->msg_view))) {
+               hildon_banner_show_information (NULL, NULL, _("mail_ib_nothing_to_find"));
+               return;
+       }
+
+       g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
+
+       if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
+               g_free (current_search);
+               hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
+               return;
+       }
+
+       if ((priv->last_search == NULL) || (strcmp (priv->last_search, current_search) != 0)) {
+               gboolean result;
+               g_free (priv->last_search);
+               priv->last_search = g_strdup (current_search);
+               result = modest_isearch_view_search (MODEST_ISEARCH_VIEW (priv->msg_view),
+                                                    priv->last_search);
+               if (!result) {
+                       hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_no_matches"));
+                       g_free (priv->last_search);
+                       priv->last_search = NULL;
+               } else {
+                       modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+                       hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
+               }
+       } else {
+               if (!modest_isearch_view_search_next (MODEST_ISEARCH_VIEW (priv->msg_view))) {
+                       hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_search_complete"));
+                       g_free (priv->last_search);
+                       priv->last_search = NULL;
+               } else {
+                       modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+                       hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
+               }
+       }
+       
+       g_free (current_search);
+               
+}
+
+static void
+modest_msg_view_window_set_zoom (ModestWindow *window,
+                                gdouble zoom)
+{
+       ModestMsgViewWindowPrivate *priv;
+       ModestWindowPrivate *parent_priv;
+       GtkAction *action = NULL;
+       gint int_zoom = (gint) rint (zoom*100.0+0.1);
+     
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       modest_zoomable_set_zoom (MODEST_ZOOMABLE (priv->msg_view), zoom);
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                           "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu");
+
+       gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action), int_zoom);
+}
+
+static gdouble
+modest_msg_view_window_get_zoom (ModestWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+     
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+       return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->msg_view));
+}
+
+static gboolean
+modest_msg_view_window_zoom_plus (ModestWindow *window)
+{
+       ModestWindowPrivate *parent_priv;
+       GtkRadioAction *zoom_radio_action;
+       GSList *group, *node;
+
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                                        "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
+
+       group = gtk_radio_action_get_group (zoom_radio_action);
+
+       if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
+               hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
+               return FALSE;
+       }
+
+       for (node = group; node != NULL; node = g_slist_next (node)) {
+               if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
+                       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static gboolean
+modest_msg_view_window_zoom_minus (ModestWindow *window)
+{
+       ModestWindowPrivate *parent_priv;
+       GtkRadioAction *zoom_radio_action;
+       GSList *group, *node;
+
+       parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
+       zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
+                                                                        "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
+
+       group = gtk_radio_action_get_group (zoom_radio_action);
+
+       for (node = group; node != NULL; node = g_slist_next (node)) {
+               if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
+                       if (node->next != NULL) {
+                               gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
+                               return TRUE;
+                       } else {
+                         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
+                               return FALSE;
+                       }
+                       break;
+               }
+       }
+       return FALSE;
+}
+
+static gboolean
+modest_msg_view_window_key_event (GtkWidget *window,
+                                 GdkEventKey *event,
+                                 gpointer userdata)
+{
+       GtkWidget *focus;
+
+       focus = gtk_window_get_focus (GTK_WINDOW (window));
+
+       /* for the find toolbar case */
+       if (focus && GTK_IS_ENTRY (focus)) {
+               if (event->keyval == GDK_BackSpace) {
+                       GdkEvent *copy;
+                       copy = gdk_event_copy ((GdkEvent *) event);
+                       gtk_widget_event (focus, copy);
+                       gdk_event_free (copy);
+                       return TRUE;
+               } else 
+                       return FALSE;
+       }
+       if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
+           event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
+           event->keyval == GDK_Page_Up || event->keyval == GDK_KP_Page_Up ||
+           event->keyval == GDK_Page_Down || event->keyval == GDK_KP_Page_Down ||
+           event->keyval == GDK_Home || event->keyval == GDK_KP_Home ||
+           event->keyval == GDK_End || event->keyval == GDK_KP_End) {
+               /* ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); */
+               /* gboolean return_value; */
+
+               if (event->type == GDK_KEY_PRESS) {
+                       GtkScrollType scroll_type;
+                       
+                       switch (event->keyval) {
+                       case GDK_Up: 
+                       case GDK_KP_Up:
+                               scroll_type = GTK_SCROLL_STEP_UP; break;
+                       case GDK_Down: 
+                       case GDK_KP_Down:
+                               scroll_type = GTK_SCROLL_STEP_DOWN; break;
+                       case GDK_Page_Up:
+                       case GDK_KP_Page_Up:
+                               scroll_type = GTK_SCROLL_PAGE_UP; break;
+                       case GDK_Page_Down:
+                       case GDK_KP_Page_Down:
+                               scroll_type = GTK_SCROLL_PAGE_DOWN; break;
+                       case GDK_Home:
+                       case GDK_KP_Home:
+                               scroll_type = GTK_SCROLL_START; break;
+                       case GDK_End:
+                       case GDK_KP_End:
+                               scroll_type = GTK_SCROLL_END; break;
+                       default: scroll_type = GTK_SCROLL_NONE;
+                       }
+                       
+                       /* g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child",  */
+                       /*                     scroll_type, FALSE, &return_value); */
+                       return FALSE;
+               } else {
+                       return FALSE;
+               }
+       } else {
+               return FALSE;
+       }
+}
+
+gboolean
+modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
+{
+       GtkTreePath *path;
+       ModestMsgViewWindowPrivate *priv;
+       GtkTreeIter tmp_iter;
+       gboolean is_last_selected;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /*if no model (so no rows at all), then virtually we are the last*/
+       if (!priv->header_model || !priv->row_reference)
+               return TRUE;
+
+       if (!gtk_tree_row_reference_valid (priv->row_reference))
+               return TRUE;
+
+       path = gtk_tree_row_reference_get_path (priv->row_reference);
+       if (path == NULL)
+               return TRUE;
+
+       is_last_selected = TRUE;
+       while (is_last_selected) {
+               TnyHeader *header;
+               gtk_tree_path_next (path);
+               if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
+                       break;
+               gtk_tree_model_get (priv->header_model, &tmp_iter,
+                               TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                               &header, -1);
+               if (header) {
+                       if (msg_is_visible (header, priv->is_outbox))
+                               is_last_selected = FALSE;
+                       g_object_unref(G_OBJECT(header));
+               }
+       }
+       gtk_tree_path_free (path);
+       return is_last_selected;
+}
+
+gboolean
+modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       return priv->header_model != NULL;
+}
+
+gboolean
+modest_msg_view_window_is_search_result (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       return priv->is_search_result;
+}
+
+static gboolean
+msg_is_visible (TnyHeader *header, gboolean check_outbox)
+{
+       if ((tny_header_get_flags(header) & TNY_HEADER_FLAG_DELETED))
+               return FALSE;
+       if (!check_outbox) {
+               return TRUE;
+       } else {
+               ModestTnySendQueueStatus status;
+               status = modest_tny_all_send_queues_get_msg_status (header);
+               return ((status != MODEST_TNY_SEND_QUEUE_FAILED) &&
+                       (status != MODEST_TNY_SEND_QUEUE_SENDING));
+       }
+}
+
+gboolean
+modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
+{
+       GtkTreePath *path;
+       ModestMsgViewWindowPrivate *priv;
+       gboolean is_first_selected;
+       GtkTreeIter tmp_iter;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /*if no model (so no rows at all), then virtually we are the first*/
+       if (!priv->header_model || !priv->row_reference)
+               return TRUE;
+
+       if (!gtk_tree_row_reference_valid (priv->row_reference))
+               return TRUE;
+
+       path = gtk_tree_row_reference_get_path (priv->row_reference);
+       if (!path)
+               return TRUE;
+
+       is_first_selected = TRUE;
+       while (is_first_selected) {
+               TnyHeader *header;
+               if(!gtk_tree_path_prev (path))
+                       break;
+               /* Here the 'if' is needless for logic, but let make sure
+                * iter is valid for gtk_tree_model_get. */
+               if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
+                       break;
+               gtk_tree_model_get (priv->header_model, &tmp_iter,
+                               TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                               &header, -1);
+               if (header) {
+                       if (msg_is_visible (header, priv->is_outbox))
+                               is_first_selected = FALSE;
+                       g_object_unref(G_OBJECT(header));
+               }
+       }
+       gtk_tree_path_free (path);
+       return is_first_selected;
+}
+
+typedef struct {
+       TnyHeader *header;
+       GtkTreeRowReference *row_reference;
+} MsgReaderInfo;
+
+static void
+message_reader_performer (gboolean canceled, 
+                         GError *err,
+                         GtkWindow *parent_window, 
+                         TnyAccount *account, 
+                         gpointer user_data)
+{
+       ModestMailOperation *mail_op = NULL;
+       MsgReaderInfo *info;
+
+       info = (MsgReaderInfo *) user_data;
+       if (canceled || err) {
+               goto frees;
+       }
+
+       /* Register the header - it'll be unregistered in the callback */
+       modest_window_mgr_register_header (modest_runtime_get_window_mgr (), info->header, NULL);
+
+       /* New mail operation */
+       mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
+                                                                modest_ui_actions_disk_operations_error_handler, 
+                                                                NULL, NULL);
+                               
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
+       modest_mail_operation_get_msg (mail_op, info->header, TRUE, view_msg_cb, info->row_reference);
+       g_object_unref (mail_op);
+
+       /* Update dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (parent_window));
+
+ frees:
+       /* Frees. The row_reference will be freed by the view_msg_cb callback */
+       g_object_unref (info->header);
+       g_slice_free (MsgReaderInfo, info);
+}
+
+
+/**
+ * Reads the message whose summary item is @header. It takes care of
+ * several things, among others:
+ *
+ * If the message was not previously downloaded then ask the user
+ * before downloading. If there is no connection launch the connection
+ * dialog. Update toolbar dimming rules.
+ *
+ * Returns: TRUE if the mail operation was started, otherwise if the
+ * user do not want to download the message, or if the user do not
+ * want to connect, then the operation is not issued
+ **/
+static gboolean
+message_reader (ModestMsgViewWindow *window,
+               ModestMsgViewWindowPrivate *priv,
+               TnyHeader *header,
+               GtkTreeRowReference *row_reference)
+{
+       gboolean already_showing = FALSE;
+       ModestWindow *msg_window = NULL;
+       ModestWindowMgr *mgr;
+       TnyAccount *account;
+       TnyFolder *folder;
+       MsgReaderInfo *info;
+
+       g_return_val_if_fail (row_reference != NULL, FALSE);
+
+       mgr = modest_runtime_get_window_mgr ();
+       already_showing = modest_window_mgr_find_registered_header (mgr, header, &msg_window);
+       if (already_showing && (msg_window != MODEST_WINDOW (window))) {
+               gboolean retval;
+               if (msg_window)
+                       gtk_window_present (GTK_WINDOW (msg_window));
+               g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &retval);
+               return TRUE;
+       }
+
+       /* Msg download completed */
+       if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)) {
+               /* Ask the user if he wants to download the message if
+                  we're not online */
+               if (!tny_device_is_online (modest_runtime_get_device())) {
+                       GtkResponseType response;
+
+                       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
+                                                                           _("mcen_nc_get_msg"));
+                       if (response == GTK_RESPONSE_CANCEL)
+                               return FALSE;
+               
+                       folder = tny_header_get_folder (header);
+                       info = g_slice_new (MsgReaderInfo);
+                       info->header = g_object_ref (header);
+                       info->row_reference = gtk_tree_row_reference_copy (row_reference);
+
+                       /* Offer the connection dialog if necessary */
+                       modest_platform_connect_if_remote_and_perform ((GtkWindow *) window, 
+                                                                      TRUE,
+                                                                      TNY_FOLDER_STORE (folder),
+                                                                      message_reader_performer, 
+                                                                      info);
+                       g_object_unref (folder);
+                       return TRUE;
+               }
+       }
+       
+       folder = tny_header_get_folder (header);
+       account = tny_folder_get_account (folder);
+       info = g_slice_new (MsgReaderInfo);
+       info->header = g_object_ref (header);
+       info->row_reference = gtk_tree_row_reference_copy (row_reference);
+       
+       message_reader_performer (FALSE, NULL, (GtkWindow *) window, account, info);
+       g_object_unref (account);
+       g_object_unref (folder);
+
+       return TRUE;
+}
+
+gboolean        
+modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+       GtkTreePath *path= NULL;
+       GtkTreeIter tmp_iter;
+       TnyHeader *header;
+       gboolean retval = TRUE;
+       GtkTreeRowReference *row_reference = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       if (!priv->row_reference)
+               return FALSE;
+
+       /* Update the next row reference if it's not valid. This could
+          happen if for example the header which it was pointing to,
+          was deleted. The best place to do it is in the row-deleted
+          handler but the tinymail model do not work like the glib
+          tree models and reports the deletion when the row is still
+          there */
+       if (!gtk_tree_row_reference_valid (priv->next_row_reference)) {
+               if (gtk_tree_row_reference_valid (priv->row_reference)) {
+                       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+                       select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE, priv->is_outbox);
+               }
+       }
+       if (priv->next_row_reference)
+               path = gtk_tree_row_reference_get_path (priv->next_row_reference);
+       if (path == NULL)
+               return FALSE;
+
+       row_reference = gtk_tree_row_reference_copy (priv->next_row_reference);
+
+       gtk_tree_model_get_iter (priv->header_model,
+                                &tmp_iter,
+                                path);
+       gtk_tree_path_free (path);
+
+       gtk_tree_model_get (priv->header_model, &tmp_iter, 
+                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                           &header, -1);
+       
+       /* Read the message & show it */
+       if (!message_reader (window, priv, header, row_reference)) {
+               retval = FALSE;
+       }
+       gtk_tree_row_reference_free (row_reference);
+
+       /* Free */
+       g_object_unref (header);
+
+       return retval;
+}
+
+gboolean        
+modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv = NULL;
+       GtkTreePath *path;
+       gboolean finished = FALSE;
+       gboolean retval = FALSE;
+
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /* Return inmediatly if there is no header model */
+       if (!priv->header_model || !priv->row_reference)
+               return FALSE;
+
+       path = gtk_tree_row_reference_get_path (priv->row_reference);
+       while (!finished && gtk_tree_path_prev (path)) {
+               TnyHeader *header;
+               GtkTreeIter iter;
+
+               gtk_tree_model_get_iter (priv->header_model, &iter, path);
+               gtk_tree_model_get (priv->header_model, &iter, 
+                                   TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                                   &header, -1);
+               finished = TRUE;
+               if (header) {
+                       if (msg_is_visible (header, priv->is_outbox)) {
+                               GtkTreeRowReference *row_reference;
+                               row_reference = gtk_tree_row_reference_new (priv->header_model, path);
+                               /* Read the message & show it */
+                               retval = message_reader (window, priv, header, row_reference);
+                               gtk_tree_row_reference_free (row_reference);
+                       } else {
+                               finished = FALSE;
+                       }
+                       g_object_unref (header);
+               }
+       }
+
+       gtk_tree_path_free (path);
+       return retval;
+}
+
+static void
+view_msg_cb (ModestMailOperation *mail_op, 
+            TnyHeader *header, 
+            gboolean canceled,
+            TnyMsg *msg, 
+            GError *error,
+            gpointer user_data)
+{
+       ModestMsgViewWindow *self = NULL;
+       ModestMsgViewWindowPrivate *priv = NULL;
+       GtkTreeRowReference *row_reference = NULL;
+
+       /* Unregister the header (it was registered before creating the mail operation) */
+       modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), header);
+
+       row_reference = (GtkTreeRowReference *) user_data;
+       if (canceled) {
+               gtk_tree_row_reference_free (row_reference);
+               return;
+       }
+       
+       /* If there was any error */
+       if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
+               gtk_tree_row_reference_free (row_reference);                    
+               return;
+       }
+
+       /* Get the window */ 
+       self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       /* Update the row reference */
+       if (priv->row_reference != NULL) {
+               gtk_tree_row_reference_free (priv->row_reference);
+               priv->row_reference = gtk_tree_row_reference_copy (row_reference);
+               if (priv->next_row_reference != NULL) {
+                       gtk_tree_row_reference_free (priv->next_row_reference);
+               }
+               priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+               select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE, priv->is_outbox);
+       }
+
+       /* Mark header as read */
+       if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
+               tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
+
+       /* Set new message */
+       if (priv->msg_view != NULL && TNY_IS_MSG_VIEW (priv->msg_view)) {
+               tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+               modest_msg_view_window_update_priority (self);
+               update_window_title (MODEST_MSG_VIEW_WINDOW (self));
+               modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+       }
+
+       /* Set the new message uid of the window  */
+       if (priv->msg_uid) {
+               g_free (priv->msg_uid);
+               priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
+       }
+
+       /* Notify the observers */
+       g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL], 
+                      0, priv->header_model, priv->row_reference);
+
+       /* Frees */
+       g_object_unref (self);
+       gtk_tree_row_reference_free (row_reference);            
+}
+
+TnyFolderType
+modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+       TnyMsg *msg;
+       TnyFolderType folder_type;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       folder_type = TNY_FOLDER_TYPE_UNKNOWN;
+
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+       if (msg) {
+               TnyFolder *folder;
+
+               folder = tny_msg_get_folder (msg);
+               if (folder) {
+                       folder_type = modest_tny_folder_guess_folder_type (folder);
+                       g_object_unref (folder);
+               }
+               g_object_unref (msg);
+       }
+
+       return folder_type;
+}
+
+
+static void
+modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv;
+       TnyHeader *header = NULL;
+       TnyHeaderFlags flags = 0;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       if (priv->header_model && priv->row_reference) {
+               GtkTreeIter iter;
+               GtkTreePath *path = NULL;
+
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
+               g_return_if_fail (path != NULL);
+               gtk_tree_model_get_iter (priv->header_model, 
+                                        &iter, 
+                                        gtk_tree_row_reference_get_path (priv->row_reference));
+
+               gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                                   &header, -1);
+               gtk_tree_path_free (path);
+       } else {
+               TnyMsg *msg;
+               msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+               if (msg) {
+                       header = tny_msg_get_header (msg);
+                       g_object_unref (msg);
+               }
+       }
+
+       if (header) {
+               flags = tny_header_get_flags (header);
+               g_object_unref(G_OBJECT(header));
+       }
+
+       modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
+
+}
+
+static void
+toolbar_resize (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;
+       GtkWidget *widget;
+       gint static_button_size;
+       ModestWindowMgr *mgr;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       mgr = modest_runtime_get_window_mgr ();
+       static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
+
+       if (parent_priv->toolbar) {
+               /* left size buttons */
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FindInMessage");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->next_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->next_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->prev_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->prev_toolitem), TRUE);
+       }
+               
+}
+
+static gboolean
+modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
+{
+       if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+               ModestWindowPrivate *parent_priv;
+               ModestWindowMgr *mgr;
+               gboolean is_fullscreen;
+               GtkAction *fs_toggle_action;
+               gboolean active;
+
+               mgr = modest_runtime_get_window_mgr ();
+               is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
+
+               parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
+               
+               fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
+               active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
+               if (is_fullscreen != active) {
+                       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
+               }
+               toolbar_resize (MODEST_MSG_VIEW_WINDOW (widget));
+       }
+
+       return FALSE;
+
+}
+
+static void
+modest_msg_view_window_show_toolbar (ModestWindow *self,
+                                    gboolean show_toolbar)
+{
+       ModestMsgViewWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv;
+       GtkWidget *reply_button = NULL, *menu = NULL;
+       GtkWidget *placeholder = NULL;
+       gint insert_index;
+       const gchar *action_name;
+       GtkAction *action;
+       
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+
+       /* Set optimized view status */
+       priv->optimized_view = !show_toolbar;
+
+       if (!parent_priv->toolbar) {
+               parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
+                                                                 "/ToolBar");
+               gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
+
+               priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
+               priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
+               priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
+               priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
+               toolbar_resize (MODEST_MSG_VIEW_WINDOW (self));
+
+               /* Add ProgressBar (Transfer toolbar) */ 
+               priv->progress_bar = modest_progress_bar_new ();
+               gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
+               placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
+               insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
+               gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
+               gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
+               
+               /* Connect cancel 'clicked' signal to abort progress mode */
+               g_signal_connect(priv->cancel_toolitem, "clicked",
+                                G_CALLBACK(cancel_progressbar),
+                                self);
+               
+               /* Add it to the observers list */
+               priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
+
+               /* Add to window */
+               hildon_window_add_toolbar (HILDON_WINDOW (self), 
+                                          GTK_TOOLBAR (parent_priv->toolbar));
+
+               /* Set reply button tap and hold menu */        
+               reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
+                                                         "/ToolBar/ToolbarMessageReply");
+               menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
+                                                 "/ToolbarReplyCSM");
+               gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
+       }
+
+       if (show_toolbar) {
+               /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
+               /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
+               gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
+
+               gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
+               if (modest_msg_view_window_transfer_mode_enabled (MODEST_MSG_VIEW_WINDOW (self))) 
+                       set_toolbar_mode (MODEST_MSG_VIEW_WINDOW (self), TOOLBAR_MODE_TRANSFER);
+               else
+                       set_toolbar_mode (MODEST_MSG_VIEW_WINDOW (self), TOOLBAR_MODE_NORMAL);
+
+       } else {
+               gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
+               gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
+       }
+
+       /* Update also the actions (to update the toggles in the
+          menus), we have to do it manually because some other window
+          of the same time could have changed it (remember that the
+          toolbar fullscreen mode is shared by all the windows of the
+          same type */
+       if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
+               action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarFullScreenMenu";
+       else
+               action_name = "/MenuBar/ViewMenu/ViewShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
+
+       action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
+       modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
+                                                           show_toolbar);
+}
+
+static void 
+modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
+                                              GdkEvent *event,
+                                              ModestMsgViewWindow *window)
+{
+       if (!GTK_WIDGET_VISIBLE (window))
+               return;
+
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+}
+
+gboolean 
+modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv;
+       
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE); 
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+
+       return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
+}
+
+static void
+cancel_progressbar (GtkToolButton *toolbutton,
+                   ModestMsgViewWindow *self)
+{
+       GSList *tmp;
+       ModestMsgViewWindowPrivate *priv;
+       
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+
+       /* Get operation observers and cancel its current operation */
+       tmp = priv->progress_widgets;
+       while (tmp) {
+               modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
+               tmp=g_slist_next(tmp);
+       }
+}
+static gboolean
+observers_empty (ModestMsgViewWindow *self)
+{
+       GSList *tmp = NULL;
+       ModestMsgViewWindowPrivate *priv;
+       gboolean is_empty = TRUE;
+       guint pending_ops = 0;
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
+       tmp = priv->progress_widgets;
+
+       /* Check all observers */
+       while (tmp && is_empty)  {
+               pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
+               is_empty = pending_ops == 0;
+               
+               tmp = g_slist_next(tmp);
+       }
+       
+       return is_empty;
+}
+
+static void
+on_account_removed (TnyAccountStore *account_store, 
+                   TnyAccount *account,
+                   gpointer user_data)
+{
+       /* Do nothing if it's a transport account, because we only
+          show the messages of a store account */
+       if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_STORE) {
+               const gchar *parent_acc = NULL;
+               const gchar *our_acc = NULL;
+
+               our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
+               parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
+
+               /* Close this window if I'm showing a message of the removed account */
+               if (strcmp (parent_acc, our_acc) == 0)
+                       modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
+       }
+}
+
+static void 
+on_mail_operation_started (ModestMailOperation *mail_op,
+                          gpointer user_data)
+{
+       ModestMsgViewWindow *self;
+       ModestMailOperationTypeOperation op_type;
+       GSList *tmp;
+       ModestMsgViewWindowPrivate *priv;
+       GObject *source = NULL;
+
+       self = MODEST_MSG_VIEW_WINDOW (user_data);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+       op_type = modest_mail_operation_get_type_operation (mail_op);
+       tmp = priv->progress_widgets;
+       source = modest_mail_operation_get_source(mail_op);
+       if (G_OBJECT (self) == source) {
+               if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ) {
+                       set_toolbar_transfer_mode(self);
+                       while (tmp) {
+                               modest_progress_object_add_operation (
+                                               MODEST_PROGRESS_OBJECT (tmp->data),
+                                               mail_op);
+                               tmp = g_slist_next (tmp);
+                       }
+               }
+       }
+       g_object_unref (source);
+}
+
+static void 
+on_mail_operation_finished (ModestMailOperation *mail_op,
+                           gpointer user_data)
+{
+       ModestMsgViewWindow *self;
+       ModestMailOperationTypeOperation op_type;
+       GSList *tmp;
+       ModestMsgViewWindowPrivate *priv;
+       
+       self = MODEST_MSG_VIEW_WINDOW (user_data);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+       op_type = modest_mail_operation_get_type_operation (mail_op);
+       tmp = priv->progress_widgets;
+       
+       if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ) {
+               while (tmp) {
+                       modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
+                                                                mail_op);
+                       tmp = g_slist_next (tmp);
+               }
+
+               /* If no more operations are being observed, NORMAL mode is enabled again */
+               if (observers_empty (self)) {
+                       set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
+               }
+
+               /* Update dimming rules. We have to do this right here
+                  and not in view_msg_cb because at that point the
+                  transfer mode is still enabled so the dimming rule
+                  won't let the user delete the message that has been
+                  readed for example */
+               modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+               modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
+       }
+}
+
+static void
+on_queue_changed (ModestMailOperationQueue *queue,
+                 ModestMailOperation *mail_op,
+                 ModestMailOperationQueueNotification type,
+                 ModestMsgViewWindow *self)
+{      
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+       /* If this operations was created by another window, do nothing */
+       if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self))) 
+           return;
+
+       if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
+               priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
+                                                              G_OBJECT (mail_op),
+                                                              "operation-started",
+                                                              G_CALLBACK (on_mail_operation_started),
+                                                              self);
+               priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
+                                                              G_OBJECT (mail_op),
+                                                              "operation-finished",
+                                                              G_CALLBACK (on_mail_operation_finished),
+                                                              self);
+       } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
+               priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
+                                                                 G_OBJECT (mail_op),
+                                                                 "operation-started");
+               priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
+                                                                 G_OBJECT (mail_op),
+                                                                 "operation-finished");
+       }
+}
+
+TnyList *
+modest_msg_view_window_get_attachments (ModestMsgViewWindow *win) 
+{
+       ModestMsgViewWindowPrivate *priv;
+       TnyList *selected_attachments = NULL;
+       
+       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
+
+       selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
+       
+       return selected_attachments;
+}
+
+typedef struct {
+       gchar *filepath;
+       GtkWidget *banner;
+       guint banner_idle_id;
+} DecodeAsyncHelper;
+
+static gboolean
+decode_async_banner_idle (gpointer user_data)
+{
+       DecodeAsyncHelper *helper = (DecodeAsyncHelper *) user_data;
+
+       helper->banner_idle_id = 0;
+       helper->banner = hildon_banner_show_animation (NULL, NULL, _("mail_me_opening"));
+       g_object_ref (helper->banner);
+
+       return FALSE;
+}
+
+static void
+on_decode_to_stream_async_handler (TnyMimePart *mime_part, 
+                                  gboolean cancelled, 
+                                  TnyStream *stream, 
+                                  GError *err, 
+                                  gpointer user_data)
+{
+       DecodeAsyncHelper *helper = (DecodeAsyncHelper *) user_data;
+
+       if (helper->banner_idle_id > 0) {
+               g_source_remove (helper->banner_idle_id);
+               helper->banner_idle_id = 0;
+       }
+       if (helper->banner) {
+               gtk_widget_destroy (helper->banner);
+       }
+       if (cancelled || err) {
+               modest_platform_information_banner (NULL, NULL, 
+                                                   _("mail_ib_file_operation_failed"));
+               goto free;
+       }
+
+       /* make the file read-only */
+       g_chmod(helper->filepath, 0444);
+       
+       /* Activate the file */
+       modest_platform_activate_file (helper->filepath, tny_mime_part_get_content_type (mime_part));
+
+ free:
+       /* Frees */
+       g_free (helper->filepath);
+       g_object_unref (helper->banner);
+       g_slice_free (DecodeAsyncHelper, helper);
+}
+
+void
+modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, 
+                                       TnyMimePart *mime_part)
+{
+       ModestMsgViewWindowPrivate *priv;
+       const gchar *msg_uid;
+       gchar *attachment_uid = NULL;
+       gint attachment_index = 0;
+       TnyList *attachments;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
+       g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window));
+       attachments = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
+       attachment_index = modest_list_index (attachments, (GObject *) mime_part);
+       g_object_unref (attachments);
+       
+       if (msg_uid && attachment_index >= 0) {
+               attachment_uid = g_strdup_printf ("%s/%d", msg_uid, attachment_index);
+       }
+
+       if (mime_part == NULL) {
+               gboolean error = FALSE;
+               TnyList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
+               if (selected_attachments == NULL || tny_list_get_length (selected_attachments) == 0) {
+                       error = TRUE;
+               } else if (tny_list_get_length (selected_attachments) > 1) {
+                       hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
+                       error = TRUE;
+               } else {
+                       TnyIterator *iter;
+                       iter = tny_list_create_iterator (selected_attachments);
+                       mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+                       g_object_unref (iter);
+               }
+               g_object_unref (selected_attachments);
+
+               if (error)
+                       return;
+       } else {
+               g_object_ref (mime_part);
+       }
+
+       if (tny_mime_part_is_purged (mime_part)) {
+               g_object_unref (mime_part);
+               return;
+       }
+
+       if (!modest_tny_mime_part_is_msg (mime_part)) {
+               gchar *filepath = NULL;
+               const gchar *att_filename = tny_mime_part_get_filename (mime_part);
+               gboolean show_error_banner = FALSE;
+               TnyFsStream *temp_stream = NULL;
+               temp_stream = modest_utils_create_temp_stream (att_filename, attachment_uid,
+                                                              &filepath);
+               
+               if (temp_stream != NULL) {
+                       DecodeAsyncHelper *helper = g_slice_new (DecodeAsyncHelper);
+                       helper->filepath = g_strdup (filepath);
+                       helper->banner = NULL;
+                       helper->banner_idle_id = g_timeout_add (1000, decode_async_banner_idle, helper);
+                       tny_mime_part_decode_to_stream_async (mime_part, TNY_STREAM (temp_stream), 
+                                                             on_decode_to_stream_async_handler, 
+                                                             NULL, 
+                                                             helper);
+                       g_object_unref (temp_stream);
+                       /* NOTE: files in the temporary area will be automatically
+                        * cleaned after some time if they are no longer in use */
+               } else {
+                       if (filepath) {
+                               const gchar *content_type;
+                               /* the file may already exist but it isn't writable,
+                                * let's try to open it anyway */
+                               content_type = tny_mime_part_get_content_type (mime_part);
+                               modest_platform_activate_file (filepath, content_type);
+                       } else {
+                               g_warning ("%s: modest_utils_create_temp_stream failed", __FUNCTION__);
+                               show_error_banner = TRUE;
+                       }
+               }
+               if (filepath)
+                       g_free (filepath);
+               if (show_error_banner)
+                       modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
+       } else {
+               /* message attachment */
+               TnyHeader *header = NULL;
+               ModestWindowMgr *mgr;
+               ModestWindow *msg_win = NULL;
+               gboolean found;
+               
+               header = tny_msg_get_header (TNY_MSG (mime_part));
+               mgr = modest_runtime_get_window_mgr ();         
+               found = modest_window_mgr_find_registered_header (mgr, header, &msg_win);
+
+               if (found) {
+                       if (msg_win)                            /* there is already a window for this uid; top it */
+                               gtk_window_present (GTK_WINDOW(msg_win));
+                       else 
+                               /* if it's found, but there is no msg_win, it's probably in the process of being created;
+                                * thus, we don't do anything */
+                               g_warning ("window for is already being created");
+               } else { 
+                       /* it's not found, so create a new window for it */
+                       modest_window_mgr_register_header (mgr, header, attachment_uid); /* register the uid before building the window */
+                       gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window)));
+                       if (!account)
+                               account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
+                       msg_win = modest_msg_view_window_new_for_attachment (TNY_MSG (mime_part), account, attachment_uid);
+                       modest_window_set_zoom (MODEST_WINDOW (msg_win), 
+                                               modest_window_get_zoom (MODEST_WINDOW (window)));
+                       modest_window_mgr_register_window (mgr, msg_win);
+                       gtk_widget_show_all (GTK_WIDGET (msg_win));
+               }
+       }
+       g_object_unref (mime_part);
+}
+
+typedef struct
+{
+       gchar *filename;
+       TnyMimePart *part;
+} SaveMimePartPair;
+
+typedef struct
+{
+       GList *pairs;
+       GtkWidget *banner;
+       GnomeVFSResult result;
+} SaveMimePartInfo;
+
+static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
+static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info);
+static gpointer save_mime_part_to_file (SaveMimePartInfo *info);
+static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info);
+
+static void 
+save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
+{
+       
+       GList *node;
+       for (node = info->pairs; node != NULL; node = g_list_next (node)) {
+               SaveMimePartPair *pair = (SaveMimePartPair *) node->data;
+               g_free (pair->filename);
+               g_object_unref (pair->part);
+               g_slice_free (SaveMimePartPair, pair);
+       }
+       g_list_free (info->pairs);
+       info->pairs = NULL;
+       if (with_struct) {
+               gtk_widget_destroy (info->banner);
+               g_slice_free (SaveMimePartInfo, info);
+       }
+}
+
+static gboolean
+idle_save_mime_part_show_result (SaveMimePartInfo *info)
+{
+       if (info->pairs != NULL) {
+               save_mime_part_to_file (info);
+       } else {
+               /* This is a GDK lock because we are an idle callback and
+                * hildon_banner_show_information is or does Gtk+ code */
+
+               gdk_threads_enter (); /* CHECKED */
+               save_mime_part_info_free (info, TRUE);
+               if (info->result == GNOME_VFS_OK) {
+                       hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
+               } else if (info->result == GNOME_VFS_ERROR_NO_SPACE) {
+                       hildon_banner_show_information (NULL, NULL, dgettext("ke-recv", 
+                                                                            "cerm_device_memory_full"));
+               } else {
+                       hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
+               }
+               gdk_threads_leave (); /* CHECKED */
+       }
+
+       return FALSE;
+}
+
+static gpointer
+save_mime_part_to_file (SaveMimePartInfo *info)
+{
+       GnomeVFSHandle *handle;
+       TnyStream *stream;
+       SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
+
+       info->result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0644);
+       if (info->result == GNOME_VFS_OK) {
+               GError *error = NULL;
+               stream = tny_vfs_stream_new (handle);
+               if (tny_mime_part_decode_to_stream (pair->part, stream, &error) < 0) {
+                       g_warning ("modest: could not save attachment %s: %d (%s)\n", pair->filename, error?error->code:-1, error?error->message:"Unknown error");
+                       
+                       info->result = GNOME_VFS_ERROR_IO;
+               }
+               g_object_unref (G_OBJECT (stream));
+               g_object_unref (pair->part);
+               g_slice_free (SaveMimePartPair, pair);
+               info->pairs = g_list_delete_link (info->pairs, info->pairs);
+       } else {
+               g_warning ("modest: could not create save attachment %s: %s\n", pair->filename, gnome_vfs_result_to_string (info->result));
+               save_mime_part_info_free (info, FALSE);
+       }
+
+       g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
+       return NULL;
+}
+
+static void
+save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
+{
+       gboolean is_ok = TRUE;
+        gint replaced_files = 0;
+        const GList *files = info->pairs;
+        const GList *iter;
+
+        for (iter = files; (iter != NULL) && (replaced_files < 2); iter = g_list_next(iter)) {
+                SaveMimePartPair *pair = iter->data;
+                if (modest_utils_file_exists (pair->filename)) {
+                       replaced_files++;
+                }
+        }
+       if (replaced_files) {
+               GtkWidget *confirm_overwrite_dialog;
+                const gchar *message = (replaced_files == 1) ?
+                        _FM("docm_nc_replace_file") : _FM("docm_nc_replace_multiple");
+                confirm_overwrite_dialog = hildon_note_new_confirmation (NULL, message);
+               if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) {
+                       is_ok = FALSE;
+               }
+               gtk_widget_destroy (confirm_overwrite_dialog);
+       }
+
+       if (!is_ok) {
+               save_mime_part_info_free (info, TRUE);
+       } else {
+               GtkWidget *banner = hildon_banner_show_animation (NULL, NULL, 
+                                                                 _CS("sfil_ib_saving"));
+               info->banner = banner;
+               g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
+       }
+
+}
+
+static void
+save_attachments_response (GtkDialog *dialog,
+                          gint       arg1,
+                          gpointer   user_data)  
+{
+       TnyList *mime_parts;
+       gchar *chooser_uri;
+       GList *files_to_save = NULL;
+
+       mime_parts = TNY_LIST (user_data);
+
+       if (arg1 != GTK_RESPONSE_OK)
+               goto end;
+
+       chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+       if (!modest_utils_folder_writable (chooser_uri)) {
+               hildon_banner_show_information 
+                       (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
+       } else {
+               TnyIterator *iter;
+
+               iter = tny_list_create_iterator (mime_parts);
+               while (!tny_iterator_is_done (iter)) {
+                       TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+
+                       if ((modest_tny_mime_part_is_attachment_for_modest (mime_part)) &&
+                           !tny_mime_part_is_purged (mime_part) &&
+                           (tny_mime_part_get_filename (mime_part) != NULL)) {
+                               SaveMimePartPair *pair;
+                                       
+                               pair = g_slice_new0 (SaveMimePartPair);
+
+                               if (tny_list_get_length (mime_parts) > 1) {
+                                       gchar *escaped = 
+                                               gnome_vfs_escape_slashes (tny_mime_part_get_filename (mime_part));
+                                       pair->filename = g_build_filename (chooser_uri, escaped, NULL);
+                                       g_free (escaped);
+                               } else {
+                                       pair->filename = g_strdup (chooser_uri);
+                               }
+                               pair->part = mime_part;
+                               files_to_save = g_list_prepend (files_to_save, pair);
+                       }
+                       tny_iterator_next (iter);
+               }
+               g_object_unref (iter);
+       }
+       g_free (chooser_uri);
+
+       if (files_to_save != NULL) {
+               SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
+               info->pairs = files_to_save;
+               info->result = TRUE;
+               save_mime_parts_to_file_with_checks (info);
+       }
+
+ end:
+       /* Free and close the dialog */
+       g_object_unref (mime_parts);
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+void
+modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, TnyList *mime_parts)
+{
+       ModestMsgViewWindowPrivate *priv;
+       GtkWidget *save_dialog = NULL;
+       gchar *folder = NULL;
+       gchar *filename = NULL;
+       gchar *save_multiple_str = NULL;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       if (mime_parts == NULL) {
+               mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
+               if (mime_parts == NULL || tny_list_get_length (mime_parts) == 0)
+                       return;
+       } else {
+               g_object_ref (mime_parts);
+       }
+
+       /* prepare dialog */
+       if (tny_list_get_length (mime_parts) == 1) {
+               TnyIterator *iter;
+               /* only one attachment selected */
+               iter = tny_list_create_iterator (mime_parts);
+               TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+               g_object_unref (iter);
+               if (!modest_tny_mime_part_is_msg (mime_part) && 
+                   modest_tny_mime_part_is_attachment_for_modest (mime_part) &&
+                   !tny_mime_part_is_purged (mime_part)) {
+                       filename = g_strdup (tny_mime_part_get_filename (mime_part));
+               } else {
+                       /* TODO: show any error? */
+                       g_warning ("Tried to save a non-file attachment");
+                       g_object_unref (mime_parts);
+                       return;
+               }
+               g_object_unref (mime_part);
+       } else {
+               save_multiple_str = g_strdup_printf (_FM("sfil_va_number_of_objects_attachments"), 
+                                                    tny_list_get_length (mime_parts));
+       }
+       
+       save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), 
+                                                     GTK_FILE_CHOOSER_ACTION_SAVE);
+
+       /* set folder */
+       folder = g_build_filename (g_get_home_dir (), DEFAULT_FOLDER, NULL);
+       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), folder);
+       g_free (folder);
+
+       /* set filename */
+       if (filename) {
+               gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog), 
+                                                  filename);
+               g_free (filename);
+       }
+
+       /* if multiple, set multiple string */
+       if (save_multiple_str) {
+               g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
+               gtk_window_set_title (GTK_WINDOW (save_dialog), _FM("sfil_ti_save_objects_files"));
+       }
+
+       /* We must run this asynchronously, because the hildon dialog
+          performs a gtk_dialog_run by itself which leads to gdk
+          deadlocks */
+       g_signal_connect (save_dialog, "response", 
+                         G_CALLBACK (save_attachments_response), mime_parts);
+
+       gtk_widget_show_all (save_dialog);
+}
+
+static gboolean
+show_remove_attachment_information (gpointer userdata)
+{
+       ModestMsgViewWindow *window = (ModestMsgViewWindow *) userdata;
+       ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       /* We're outside the main lock */
+       gdk_threads_enter ();
+
+       if (priv->remove_attachment_banner != NULL) {
+               gtk_widget_destroy (priv->remove_attachment_banner);
+               g_object_unref (priv->remove_attachment_banner);
+       }
+
+       priv->remove_attachment_banner = g_object_ref (
+               hildon_banner_show_animation (NULL, NULL, _("mcen_ib_removing_attachment")));
+
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+void
+modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
+{
+       ModestMsgViewWindowPrivate *priv;
+       TnyList *mime_parts = NULL;
+       gchar *confirmation_message;
+       gint response;
+       gint n_attachments;
+       TnyMsg *msg;
+       TnyIterator *iter;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       if (get_all)
+               mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
+       else
+               mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
+               
+       /* Remove already purged messages from mime parts list */
+       iter = tny_list_create_iterator (mime_parts);
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part = TNY_MIME_PART (tny_iterator_get_current (iter));
+               tny_iterator_next (iter);
+               if (tny_mime_part_is_purged (part)) {
+                       tny_list_remove (mime_parts, (GObject *) part);
+               }
+               g_object_unref (part);
+       }
+       g_object_unref (iter);
+
+       if (tny_list_get_length (mime_parts) == 0) {
+               g_object_unref (mime_parts);
+               return;
+       }
+
+       n_attachments = tny_list_get_length (mime_parts);
+       if (n_attachments == 1) {
+               gchar *filename;
+               TnyMimePart *part;
+
+               iter = tny_list_create_iterator (mime_parts);
+               part = (TnyMimePart *) tny_iterator_get_current (iter);
+               g_object_unref (iter);
+               if (modest_tny_mime_part_is_msg (part)) {
+                       TnyHeader *header;
+                       header = tny_msg_get_header (TNY_MSG (part));
+                       filename = tny_header_dup_subject (header);
+                       g_object_unref (header);
+                       if (filename == NULL)
+                               filename = g_strdup (_("mail_va_no_subject"));
+               } else {
+                       filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
+               }
+               confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
+               g_free (filename);
+               g_object_unref (part);
+       } else {
+               confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text", 
+                                                                "mcen_nc_purge_files_text", 
+                                                                n_attachments), n_attachments);
+       }
+       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
+                                                           confirmation_message);
+       g_free (confirmation_message);
+
+       if (response != GTK_RESPONSE_OK) {
+               g_object_unref (mime_parts);
+               return;
+       }
+
+       priv->purge_timeout = g_timeout_add (2000, show_remove_attachment_information, window);
+       
+       iter = tny_list_create_iterator (mime_parts);
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part;
+
+               part = (TnyMimePart *) tny_iterator_get_current (iter);
+               tny_mime_part_set_purged (TNY_MIME_PART (part));
+               g_object_unref (part);
+               tny_iterator_next (iter);
+       }
+       g_object_unref (iter);
+
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+       tny_msg_view_clear (TNY_MSG_VIEW (priv->msg_view));
+       tny_msg_rewrite_cache (msg);
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       g_object_unref (msg);
+
+       g_object_unref (mime_parts);
+
+       if (priv->purge_timeout > 0) {
+               g_source_remove (priv->purge_timeout);
+               priv->purge_timeout = 0;
+       }
+
+       if (priv->remove_attachment_banner) {
+               gtk_widget_destroy (priv->remove_attachment_banner);
+               g_object_unref (priv->remove_attachment_banner);
+               priv->remove_attachment_banner = NULL;
+       }
+
+
+}
+
+
+static void
+update_window_title (ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+       TnyMsg *msg = NULL;
+       TnyHeader *header = NULL;
+       gchar *subject = NULL;
+       
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+
+       if (msg != NULL) {
+               header = tny_msg_get_header (msg);
+               subject = tny_header_dup_subject (header);
+               g_object_unref (header);
+               g_object_unref (msg);
+       }
+
+       if ((subject == NULL)||(subject[0] == '\0')) {
+               g_free (subject);
+               subject = g_strdup (_("mail_va_no_subject"));
+       }
+
+       gtk_window_set_title (GTK_WINDOW (window), subject);
+}
+
+
+static void on_move_focus (GtkWidget *widget,
+                          GtkDirectionType direction,
+                          gpointer userdata)
+{
+       g_signal_stop_emission_by_name (G_OBJECT (widget), "move-focus");
+}
+
+static TnyStream *
+fetch_image_open_stream (TnyStreamCache *self, gint64 *expected_size, gchar *uri)
+{
+       GnomeVFSResult result;
+       GnomeVFSHandle *handle = NULL;
+       GnomeVFSFileInfo *info = NULL;
+       TnyStream *stream;
+
+       result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+       if (result != GNOME_VFS_OK) {
+               *expected_size = 0;
+               return NULL;
+       }
+       
+       info = gnome_vfs_file_info_new ();
+       result = gnome_vfs_get_file_info_from_handle (handle, info, GNOME_VFS_FILE_INFO_DEFAULT);
+       if (result != GNOME_VFS_OK || ! (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
+               /* We put a "safe" default size for going to cache */
+               *expected_size = (300*1024);
+       } else {
+               *expected_size = info->size;
+       }
+       gnome_vfs_file_info_unref (info);
+
+       stream = tny_vfs_stream_new (handle);
+
+       return stream;
+
+}
+
+typedef struct {
+       gchar *uri;
+       gchar *cache_id;
+       TnyStream *output_stream;
+       GtkWidget *msg_view;
+} FetchImageData;
+
+gboolean
+on_fetch_image_idle_refresh_view (gpointer userdata)
+{
+
+       FetchImageData *fidata = (FetchImageData *) userdata;
+       g_message ("REFRESH VIEW");
+       if (GTK_WIDGET_DRAWABLE (fidata->msg_view)) {
+               g_message ("QUEUING DRAW");
+               gtk_widget_queue_draw (fidata->msg_view);
+       }
+       g_object_unref (fidata->msg_view);
+       g_slice_free (FetchImageData, fidata);
+       return FALSE;
+}
+
+static gpointer
+on_fetch_image_thread (gpointer userdata)
+{
+       FetchImageData *fidata = (FetchImageData *) userdata;
+       TnyStreamCache *cache;
+       TnyStream *cache_stream;
+
+       cache = modest_runtime_get_images_cache ();
+       cache_stream = tny_stream_cache_get_stream (cache, fidata->cache_id, (TnyStreamCacheOpenStreamFetcher) fetch_image_open_stream, (gpointer) fidata->uri);
+       g_free (fidata->cache_id);
+       g_free (fidata->uri);
+
+       if (cache_stream != NULL) {
+               tny_stream_write_to_stream (cache_stream, fidata->output_stream);
+               tny_stream_close (cache_stream);
+               g_object_unref (cache_stream);
+       }
+
+       tny_stream_close (fidata->output_stream);
+       g_object_unref (fidata->output_stream);
+
+
+       gdk_threads_enter ();
+       g_idle_add (on_fetch_image_idle_refresh_view, fidata);
+       gdk_threads_leave ();
+
+       return NULL;
+}
+
+static gboolean
+on_fetch_image (ModestMsgView *msgview,
+               const gchar *uri,
+               TnyStream *stream,
+               ModestMsgViewWindow *window)
+{
+       const gchar *current_account;
+       ModestMsgViewWindowPrivate *priv;
+       FetchImageData *fidata;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       current_account = modest_window_get_active_account (MODEST_WINDOW (window));
+
+       fidata = g_slice_new0 (FetchImageData);
+       fidata->msg_view = g_object_ref (msgview);
+       fidata->uri = g_strdup (uri);
+       fidata->cache_id = modest_images_cache_get_id (current_account, uri);
+       fidata->output_stream = g_object_ref (stream);
+
+       if (g_thread_create (on_fetch_image_thread, fidata, FALSE, NULL) == NULL) {
+               g_object_unref (fidata->output_stream);
+               g_free (fidata->cache_id);
+               g_free (fidata->uri);
+               g_object_unref (fidata->msg_view);
+               g_slice_free (FetchImageData, fidata);
+               tny_stream_close (stream);
+               return FALSE;
+       }
+
+       return TRUE;;
+}
diff --git a/src/hildon2/modest-osso-autosave-callbacks.c b/src/hildon2/modest-osso-autosave-callbacks.c
new file mode 100644 (file)
index 0000000..e58ef7e
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <maemo/modest-osso-autosave-callbacks.h>
+
+void modest_on_osso_application_autosave(gpointer data)
+{
+       
+}
+
+
+
+
diff --git a/src/hildon2/modest-osso-autosave-callbacks.h b/src/hildon2/modest-osso-autosave-callbacks.h
new file mode 100644 (file)
index 0000000..3676e8b
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MODEST_OSSO_AUTOSAVE_CALLBACKS_H__
+#define __MODEST_OSSO_AUTOSAVE_CALLBACKS_H__
+
+#include <glib.h>
+#include <libosso.h>
+
+void modest_on_osso_application_autosave(gpointer data);
+
+
+#endif /* __MODEST_OSSO_AUTOSAVE_CALLBACKS_H__ */
diff --git a/src/hildon2/modest-osso-state-saving.c b/src/hildon2/modest-osso-state-saving.c
new file mode 100644 (file)
index 0000000..03a8f15
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <maemo/modest-osso-state-saving.h>
+#include "modest-runtime.h"
+#include <libosso.h>
+
+void modest_osso_load_state()
+{
+       /* We don't need to call osso_state_read() 
+        * - we use our general widget-state-saving technique instead. */
+}
+
+void modest_osso_save_state()
+{
+       /* We don't need to call osso_state_write() 
+        * - we use our general widget-state-saving technique instead: */
+       modest_window_mgr_save_state_for_all_windows(
+               modest_runtime_get_window_mgr ());
+}
+
+
+
+
diff --git a/src/hildon2/modest-osso-state-saving.h b/src/hildon2/modest-osso-state-saving.h
new file mode 100644 (file)
index 0000000..eee23df
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MODEST_OSSO_STATE_SAVING_H__
+#define __MODEST_OSSO_STATE_SAVING_H__
+
+#include <glib.h>
+
+void modest_osso_load_state();
+
+void modest_osso_save_state();
+
+#endif /* __MODEST_OSSO_STATE_SAVING_H__ */
diff --git a/src/hildon2/modest-platform.c b/src/hildon2/modest-platform.c
new file mode 100644 (file)
index 0000000..06ece71
--- /dev/null
@@ -0,0 +1,2118 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <modest-platform.h>
+#include <modest-runtime.h>
+#include <modest-main-window.h>
+#include <modest-header-view.h>
+#include "maemo/modest-maemo-global-settings-dialog.h"
+#include "modest-widget-memory.h"
+#include <modest-hildon-includes.h>
+#include <modest-maemo-utils.h>
+#include <dbus_api/modest-dbus-callbacks.h>
+#include <maemo/modest-osso-autosave-callbacks.h>
+#include <libosso.h>
+#include <tny-maemo-conic-device.h>
+#include <tny-simple-list.h>
+#include <tny-folder.h>
+#include <tny-camel-imap-store-account.h>
+#include <tny-camel-pop-store-account.h>
+#include <gtk/gtkicontheme.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkmain.h>
+#include <modest-text-utils.h>
+#include "modest-tny-folder.h"
+#include "modest-tny-account.h"
+#include <string.h>
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include <modest-account-settings-dialog.h>
+#include <modest-easysetup-wizard-dialog.h>
+#include "modest-hildon-sort-dialog.h"
+#include <hildon/hildon-sound.h>
+#include <osso-mem.h>
+
+#ifdef MODEST_HAVE_MCE
+#include <mce/dbus-names.h>
+#endif /*MODEST_HAVE_MCE*/
+
+#ifdef MODEST_HAVE_ABOOK
+#include <libosso-abook/osso-abook.h>
+#endif /*MODEST_HAVE_ABOOK*/
+
+#ifdef MODEST_HAVE_LIBALARM
+#include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
+#endif /*MODEST_HAVE_LIBALARM*/
+
+
+#define HILDON_OSSO_URI_ACTION "uri-action"
+#define URI_ACTION_COPY "copy:"
+#define MODEST_NEW_MAIL_SOUND_FILE "/usr/share/sounds/ui-new_email.wav"
+#define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
+
+static void    
+on_modest_conf_update_interval_changed (ModestConf* self, 
+                                       const gchar *key, 
+                                       ModestConfEvent event,
+                                       ModestConfNotificationId id, 
+                                       gpointer user_data)
+{
+       g_return_if_fail (key);
+       
+       if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
+               const guint update_interval_minutes = 
+                       modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
+               modest_platform_set_update_interval (update_interval_minutes);
+       }
+}
+
+
+
+static gboolean
+check_required_files (void)
+{
+       FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
+       if (!mcc_file) {
+               g_printerr ("modest: check for mcc file failed\n");
+               return FALSE;
+       } else 
+               fclose (mcc_file);
+       
+       if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
+           access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
+               g_printerr ("modest: cannot find providers data\n");
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+
+
+/* the gpointer here is the osso_context. */
+gboolean
+modest_platform_init (int argc, char *argv[])
+{
+       osso_context_t *osso_context;
+       
+       osso_hw_state_t hw_state = { 0 };
+       DBusConnection *con;    
+       GSList *acc_names;
+       
+       if (!check_required_files ()) {
+               g_printerr ("modest: missing required files\n");
+               return FALSE;
+       }
+       
+       osso_context =  osso_initialize(PACKAGE,PACKAGE_VERSION,
+                                       FALSE, NULL);   
+       if (!osso_context) {
+               g_printerr ("modest: failed to acquire osso context\n");
+               return FALSE;
+       }
+       modest_maemo_utils_set_osso_context (osso_context);
+
+       if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
+               g_printerr ("modest: could not get dbus connection\n");
+               return FALSE;
+       }
+
+       /* Add a D-Bus handler to be used when the main osso-rpc 
+        * D-Bus handler has not handled something.
+        * We use this for D-Bus methods that need to use more complex types 
+        * than osso-rpc supports. 
+        */
+       if (!dbus_connection_add_filter (con,
+                                        modest_dbus_req_filter,
+                                        NULL,
+                                        NULL)) {
+
+               g_printerr ("modest: Could not add D-Bus filter\n");
+               return FALSE;
+       }
+
+       /* Register our simple D-Bus callbacks, via the osso API: */
+       osso_return_t result = osso_rpc_set_cb_f(osso_context, 
+                               MODEST_DBUS_SERVICE, 
+                               MODEST_DBUS_OBJECT, 
+                               MODEST_DBUS_IFACE,
+                               modest_dbus_req_handler, NULL /* user_data */);
+       if (result != OSSO_OK) {
+                       g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
+               return FALSE;
+       }
+
+       /* Register hardware event dbus callback: */
+       hw_state.shutdown_ind = TRUE;
+       osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
+
+       /* Register osso auto-save callbacks: */
+       result = osso_application_set_autosave_cb (osso_context, 
+               modest_on_osso_application_autosave, NULL /* user_data */);
+       if (result != OSSO_OK) {
+               g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
+               return FALSE;
+       }
+       
+
+       /* Make sure that the update interval is changed whenever its gconf key 
+        * is changed */
+       /* CAUTION: we're not using here the
+          modest_conf_listen_to_namespace because we know that there
+          are other parts of Modest listening for this namespace, so
+          we'll receive the notifications anyway. We basically do not
+          use it because there is no easy way to do the
+          modest_conf_forget_namespace */
+       ModestConf *conf = modest_runtime_get_conf ();
+       g_signal_connect (G_OBJECT(conf),
+                         "key_changed",
+                         G_CALLBACK (on_modest_conf_update_interval_changed), 
+                         NULL);
+
+       /* only force the setting of the default interval, if there are actually
+        * any accounts */
+       acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
+       if (acc_names) {
+               /* Get the initial update interval from gconf: */
+               on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
+                                                      MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
+               modest_account_mgr_free_account_names (acc_names);
+       }
+
+       
+#ifdef MODEST_HAVE_ABOOK
+       /* initialize the addressbook */
+       if (!osso_abook_init (&argc, &argv, osso_context)) {
+               g_printerr ("modest: failed to initialized addressbook\n");
+               return FALSE;
+       }
+#endif /*MODEST_HAVE_ABOOK*/
+
+       return TRUE;
+}
+
+gboolean
+modest_platform_uninit (void)
+{
+       osso_context_t *osso_context =
+               modest_maemo_utils_get_osso_context ();
+       if (osso_context)
+               osso_deinitialize (osso_context);
+
+       return TRUE;
+}
+
+
+
+
+TnyDevice*
+modest_platform_get_new_device (void)
+{
+       return TNY_DEVICE (tny_maemo_conic_device_new ());
+}
+
+gchar*
+modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
+                                   gchar **effective_mime_type)
+{
+       GString *mime_str = NULL;
+       gchar *icon_name  = NULL;
+       gchar **icons, **cursor;
+       
+       if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0) 
+               mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
+       else {
+               mime_str = g_string_new (mime_type);
+               g_string_ascii_down (mime_str);
+       }
+       
+       icons = hildon_mime_get_icon_names (mime_str->str, NULL);
+       
+       for (cursor = icons; cursor; ++cursor) {
+               if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
+                   !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
+                       icon_name = g_strdup ("qgn_list_messagin");
+                       break;
+               } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
+                       icon_name = g_strdup (*cursor);
+                       break;
+               }
+       }
+       g_strfreev (icons);
+
+       if (effective_mime_type)
+               *effective_mime_type = g_string_free (mime_str, FALSE);
+       else
+               g_string_free (mime_str, TRUE);
+       
+       return icon_name;
+}
+
+
+static gboolean
+checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
+{
+       GError *err = NULL;
+       gboolean result;
+
+       g_return_val_if_fail (uri, FALSE);
+       
+       result = hildon_uri_open (uri, action, &err);
+       if (!result) {
+               g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
+                           uri, action,  err && err->message ? err->message : "unknown error");
+               if (err)
+                       g_error_free (err);
+       }
+       return result;
+}
+
+
+
+gboolean 
+modest_platform_activate_uri (const gchar *uri)
+{
+       HildonURIAction *action;
+       gboolean result = FALSE;
+       GSList *actions, *iter = NULL;
+       
+       g_return_val_if_fail (uri, FALSE);
+       if (!uri)
+               return FALSE;
+
+       /* don't try to activate file: uri's -- they might confuse the user,
+        * and/or might have security implications */
+       if (!g_str_has_prefix (uri, "file:")) {
+               
+               actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
+               
+               for (iter = actions; iter; iter = g_slist_next (iter)) {
+                       action = (HildonURIAction*) iter->data;
+                       if (action && strcmp (hildon_uri_action_get_service (action),
+                                             "com.nokia.modest") == 0) {
+                               result = checked_hildon_uri_open (uri, action);
+                               break;
+                       }
+               }
+               
+               /* if we could not open it with email, try something else */
+               if (!result)
+                       result = checked_hildon_uri_open (uri, NULL);   
+       } 
+       
+       if (!result) {
+               ModestWindow *parent =
+                       modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
+               hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
+                                               _("mcen_ib_unsupported_link"));
+               g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
+       } 
+       
+       return result;
+}
+
+gboolean 
+modest_platform_activate_file (const gchar *path, const gchar *mime_type)
+{
+       gint result = 0;
+       DBusConnection *con;
+       gchar *uri_path = NULL;
+       
+       uri_path = gnome_vfs_get_uri_from_local_path (path);    
+       con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
+       
+       if (mime_type)
+               result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
+       if (result != 1)
+               result = hildon_mime_open_file (con, uri_path);
+       if (result != 1)
+               modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
+       
+       return result != 1;
+}
+
+typedef struct  {
+       GSList *actions;
+       gchar  *uri;
+} ModestPlatformPopupInfo;
+
+static gboolean
+delete_uri_popup (GtkWidget *menu,
+                 GdkEvent *event,
+                 gpointer userdata)
+{
+       ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
+
+       g_free (popup_info->uri);
+       hildon_uri_free_actions (popup_info->actions);
+
+       return FALSE;
+}
+
+static void
+activate_uri_popup_item (GtkMenuItem *menu_item,
+                        gpointer userdata)
+{
+       GSList *node;
+       ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
+       const gchar* action_name;
+
+       action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
+       if (!action_name) {
+               g_printerr ("modest: no action name defined\n");
+               return;
+       }
+
+       /* special handling for the copy menu item -- copy the uri to the clipboard */
+       /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
+       if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
+               GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
+               action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
+
+               if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
+                       action_name += strlen ("mailto:");
+               
+               gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
+               modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
+               return; /* we're done */
+       }
+       
+       /* now, the real uri-actions... */
+       for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
+               HildonURIAction *action = (HildonURIAction *) node->data;
+               if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
+                       if (!checked_hildon_uri_open (popup_info->uri, action)) {
+                               ModestWindow *parent =
+                                       modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
+                               hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
+                                                               _("mcen_ib_unsupported_link"));
+                       }
+                       break;
+               }
+       }
+}
+
+gboolean 
+modest_platform_show_uri_popup (const gchar *uri)
+{
+       GSList *actions_list;
+
+       if (uri == NULL)
+               return FALSE;
+       
+       actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
+       if (actions_list) {
+
+               GtkWidget *menu = gtk_menu_new ();
+               ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
+
+               /* don't add actions for file: uri's -- they might confuse the user,
+                * and/or might have security implications
+                * we still allow to copy the url though
+                */
+               if (!g_str_has_prefix (uri, "file:")) {                 
+               
+                       GSList *node;                   
+                       popup_info->actions = actions_list;
+                       popup_info->uri = g_strdup (uri);
+                       
+                       for (node = actions_list; node != NULL; node = g_slist_next (node)) {
+                               GtkWidget *menu_item;
+                               const gchar *action_name;
+                               const gchar *translation_domain;
+                               HildonURIAction *action = (HildonURIAction *) node->data;
+                               action_name = hildon_uri_action_get_name (action);
+                               translation_domain = hildon_uri_action_get_translation_domain (action);
+                               menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
+                               g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name);  /* hack */
+                               g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
+                                                 popup_info);
+                               
+                               if (hildon_uri_is_default_action (action, NULL)) {
+                                       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
+                               } else {
+                                       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+                               }
+                               gtk_widget_show (menu_item);
+                       }
+               }
+
+               /* always add the copy item */
+               GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri",
+                                                                             "uri_link_copy_link_location"));
+               g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
+                                       g_strconcat (URI_ACTION_COPY, uri, NULL),
+                                       g_free);
+               g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+               gtk_widget_show (menu_item);
+
+               
+               /* and what to do when the link is deleted */
+               g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
+               gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
+                                                 
+       } else {
+               hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
+       }
+       
+       return TRUE;
+}
+
+
+GdkPixbuf*
+modest_platform_get_icon (const gchar *name, guint icon_size)
+{
+       GError *err = NULL;
+       GdkPixbuf* pixbuf = NULL;
+       GtkIconTheme *current_theme = NULL;
+
+       g_return_val_if_fail (name, NULL);
+
+       /* strlen == 0 is not really an error; it just
+        * means the icon is not available
+        */
+       if (!name || strlen(name) == 0)
+               return NULL;
+       
+       current_theme = gtk_icon_theme_get_default ();
+       pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
+                                          GTK_ICON_LOOKUP_NO_SVG,
+                                          &err);
+       if (!pixbuf) {
+               g_printerr ("modest: error loading theme icon '%s': %s\n",
+                           name, err->message);
+               g_error_free (err);
+       } 
+       return pixbuf;
+}
+
+const gchar*
+modest_platform_get_app_name (void)
+{
+       return _("mcen_ap_name");
+}
+
+static void 
+entry_insert_text (GtkEditable *editable,
+                  const gchar *text,
+                  gint         length,
+                  gint        *position,
+                  gpointer     data)
+{
+       gchar *chars;
+       gint chars_length;
+
+       chars = gtk_editable_get_chars (editable, 0, -1);
+       chars_length = g_utf8_strlen (chars, -1);
+
+       /* Show WID-INF036 */
+       if (chars_length >= 20) {
+               hildon_banner_show_information  (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
+                                                _CS("ckdg_ib_maximum_characters_reached"));
+       } else {
+               if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
+                       /* Show an error */
+                       gchar *tmp, *msg;
+                       
+                       tmp = g_strndup (folder_name_forbidden_chars, 
+                                        FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
+                       msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
+                       hildon_banner_show_information  (gtk_widget_get_parent (GTK_WIDGET (data)), 
+                                                        NULL, msg);
+                       g_free (msg);
+                       g_free (tmp);
+               } else {        
+                       /* Write the text in the entry if it's valid */
+                       g_signal_handlers_block_by_func (editable,
+                                                        (gpointer) entry_insert_text, data);
+                       gtk_editable_insert_text (editable, text, length, position);
+                       g_signal_handlers_unblock_by_func (editable,
+                                                          (gpointer) entry_insert_text, data);
+               }
+       }
+       /* Do not allow further processing */
+       g_signal_stop_emission_by_name (editable, "insert_text");
+}
+
+static void
+entry_changed (GtkEditable *editable,
+              gpointer     user_data)
+{
+       gchar *chars;
+       GtkWidget *ok_button;
+       GList *buttons;
+
+       buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
+       ok_button = GTK_WIDGET (buttons->next->data);
+       
+       chars = gtk_editable_get_chars (editable, 0, -1);
+       g_return_if_fail (chars != NULL);
+
+       
+       if (g_utf8_strlen (chars,-1) >= 21)
+               hildon_banner_show_information  (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
+                                                _CS("ckdg_ib_maximum_characters_reached"));
+       else
+               gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
+               
+       /* Free */
+       g_list_free (buttons);
+       g_free (chars);
+}
+
+
+
+static void
+on_response (GtkDialog *dialog,
+            gint response,
+            gpointer user_data)
+{
+       GList *child_vbox, *child_hbox;
+       GtkWidget *hbox, *entry;
+       TnyFolderStore *parent;
+       const gchar *new_name;
+       gboolean exists;
+
+       if (response != GTK_RESPONSE_ACCEPT)
+               return;
+       
+       /* Get entry */
+       child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
+       hbox = child_vbox->data;
+       child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
+       entry = child_hbox->next->data;
+       
+       parent = TNY_FOLDER_STORE (user_data);
+       new_name = gtk_entry_get_text (GTK_ENTRY (entry));
+       exists = FALSE;
+       
+       /* Look for another folder with the same name */
+       if (modest_tny_folder_has_subfolder_with_name (parent, 
+                                                      new_name,
+                                                      TRUE)) {
+               exists = TRUE;
+       }
+       
+       if (!exists) {
+               if (TNY_IS_ACCOUNT (parent) &&
+                   modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
+                   modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
+                                                                        new_name)) {
+                       exists = TRUE;
+               }
+       }
+       
+       if (exists) {
+               
+               /* Show an error */
+               hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)), 
+                                               NULL, _CS("ckdg_ib_folder_already_exists"));
+               /* Select the text */
+               gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
+               gtk_widget_grab_focus (entry);
+               /* Do not close the dialog */
+               g_signal_stop_emission_by_name (dialog, "response");
+       }
+}
+
+
+
+static gint
+modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
+                                       TnyFolderStore *parent,
+                                       const gchar *dialog_title,
+                                       const gchar *label_text,
+                                       const gchar *suggested_name,
+                                       gchar **folder_name)
+{
+       GtkWidget *accept_btn = NULL; 
+       GtkWidget *dialog, *entry, *label, *hbox;
+       GList *buttons = NULL;
+       gint result;
+
+       /* Ask the user for the folder name */
+       dialog = gtk_dialog_new_with_buttons (dialog_title,
+                                             parent_window,
+                                             GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                             _("mcen_bd_dialog_ok"),
+                                             GTK_RESPONSE_ACCEPT,
+                                             _("mcen_bd_dialog_cancel"),
+                                             GTK_RESPONSE_REJECT,
+                                             NULL);
+
+       /* Add accept button (with unsensitive handler) */
+       buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
+       accept_btn = GTK_WIDGET (buttons->next->data);
+       /* Create label and entry */
+       label = gtk_label_new (label_text);
+       /* TODO: check that the suggested name does not exist */
+       /* We set 21 as maximum because we want to show WID-INF036
+          when the user inputs more that 20 */
+       entry = gtk_entry_new_with_max_length (21);
+       if (suggested_name)
+               gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
+       else
+               gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
+       gtk_entry_set_width_chars (GTK_ENTRY (entry),
+                                  MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
+                                       g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
+       gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
+
+       /* Connect to the response method to avoid closing the dialog
+          when an invalid name is selected*/
+       g_signal_connect (dialog,
+                         "response",
+                         G_CALLBACK (on_response),
+                         parent);
+
+       /* Track entry changes */
+       g_signal_connect (entry,
+                         "insert-text",
+                         G_CALLBACK (entry_insert_text),
+                         dialog);
+       g_signal_connect (entry,
+                         "changed",
+                         G_CALLBACK (entry_changed),
+                         dialog);
+
+
+       /* Some locales like pt_BR need this to get the full window
+          title shown */
+       gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
+
+       /* Create the hbox */
+       hbox = gtk_hbox_new (FALSE, 12);
+       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+
+       /* Add hbox to dialog */
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
+                           hbox, FALSE, FALSE, 0);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
+                                    GTK_WINDOW (dialog));
+       gtk_widget_show_all (GTK_WIDGET(dialog));
+               
+       result = gtk_dialog_run (GTK_DIALOG(dialog));
+       if (result == GTK_RESPONSE_ACCEPT)
+               *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+       gtk_widget_destroy (dialog);
+
+       while (gtk_events_pending ())
+               gtk_main_iteration ();
+
+       return result;
+}
+
+gint
+modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
+                                      TnyFolderStore *parent_folder,
+                                      gchar *suggested_name,
+                                      gchar **folder_name)
+{
+       gchar *real_suggested_name = NULL, *tmp = NULL;
+       gint result;
+
+       if(suggested_name == NULL)
+       {
+               const gchar *default_name = _("mcen_ia_default_folder_name");
+               unsigned int i;
+               gchar num_str[3];
+
+               for(i = 0; i < 100; ++ i) {
+                       gboolean exists = FALSE;
+
+                       sprintf(num_str, "%.2u", i);
+
+                       if (i == 0)
+                               real_suggested_name = g_strdup (default_name);
+                       else
+                               real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
+                                                                      num_str);
+                       exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
+                                                                           real_suggested_name,
+                                                                           TRUE);
+
+                       if (!exists)
+                               break;
+
+                       g_free (real_suggested_name);
+               }
+
+               /* Didn't find a free number */
+               if (i == 100)
+                       real_suggested_name = g_strdup (default_name);
+       } else {
+               real_suggested_name = suggested_name;
+       }
+
+       tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
+       result = modest_platform_run_folder_name_dialog (parent_window, 
+                                                        parent_folder,
+                                                        _("mcen_ti_new_folder"),
+                                                        tmp,
+                                                        real_suggested_name,
+                                                        folder_name);
+       g_free (tmp);
+
+       if (suggested_name == NULL)
+               g_free(real_suggested_name);
+
+       return result;
+}
+
+gint
+modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
+                                          TnyFolderStore *parent_folder,
+                                          const gchar *suggested_name,
+                                          gchar **folder_name)
+{
+       g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
+
+       return modest_platform_run_folder_name_dialog (parent_window, 
+                                                      parent_folder,
+                                                      _HL("ckdg_ti_rename_folder"),
+                                                      _HL("ckdg_fi_rename_name"),
+                                                      suggested_name,
+                                                      folder_name);
+}
+
+
+
+static void
+on_destroy_dialog (GtkWidget *dialog)
+{
+       /* This could happen when the dialogs get programatically
+          hidden or destroyed (for example when closing the
+          application while a dialog is being shown) */
+       if (!GTK_IS_WIDGET (dialog))
+               return;
+
+       gtk_widget_destroy (dialog);
+
+       if (gtk_events_pending ())
+               gtk_main_iteration ();
+}
+
+gint
+modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
+                                        const gchar *message)
+{
+       GtkWidget *dialog;
+       gint response;
+       
+       dialog = hildon_note_new_confirmation (parent_window, message);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
+                                    GTK_WINDOW (dialog));
+
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+       on_destroy_dialog (dialog);
+
+       return response;
+}
+
+gint
+modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
+                                                     const gchar *message,
+                                                     const gchar *button_accept,
+                                                     const gchar *button_cancel)
+{
+       GtkWidget *dialog;
+       gint response;
+       
+       dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
+                                                          button_accept, GTK_RESPONSE_ACCEPT,
+                                                          button_cancel, GTK_RESPONSE_CANCEL,
+                                                          NULL);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
+                                    GTK_WINDOW (dialog));
+
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+       on_destroy_dialog (dialog);
+
+       return response;
+}
+       
+gint
+modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
+                                  const gchar *message)
+{
+       GtkWidget *dialog;
+       gint response;
+       
+       dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
+                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
+                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
+                                                          NULL);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       
+       on_destroy_dialog (dialog);
+
+       return response;
+}
+
+
+
+void
+modest_platform_run_information_dialog (GtkWindow *parent_window,
+                                       const gchar *message,
+                                       gboolean block)
+{
+       GtkWidget *note;
+       
+       note = hildon_note_new_information (parent_window, message);
+       if (block)
+               modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
+                                            GTK_WINDOW (note));
+       
+       if (block) {
+               gtk_dialog_run (GTK_DIALOG (note));
+       
+               on_destroy_dialog (note);
+       } else {
+               g_signal_connect_swapped (note,
+                                         "response", 
+                                         G_CALLBACK (on_destroy_dialog),
+                                         note);
+
+               gtk_widget_show_all (note);
+       }
+}
+
+typedef struct _ConnectAndWaitData {
+       GMutex *mutex;
+       GMainLoop *wait_loop;
+       gboolean has_callback;
+       gulong handler;
+} ConnectAndWaitData;
+
+
+static void
+quit_wait_loop (TnyAccount *account,
+               ConnectAndWaitData *data) 
+{
+       /* Set the has_callback to TRUE (means that the callback was
+          executed and wake up every code waiting for cond to be
+          TRUE */
+       g_mutex_lock (data->mutex);
+       data->has_callback = TRUE;
+       if (data->wait_loop)
+               g_main_loop_quit (data->wait_loop);
+       g_mutex_unlock (data->mutex);
+}
+
+static void
+on_connection_status_changed (TnyAccount *account, 
+                             TnyConnectionStatus status,
+                             gpointer user_data)
+{
+       TnyConnectionStatus conn_status;
+       ConnectAndWaitData *data;
+                       
+       /* Ignore if reconnecting or disconnected */
+       conn_status = tny_account_get_connection_status (account);
+       if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
+           conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
+               return;
+
+       /* Remove the handler */
+       data = (ConnectAndWaitData *) user_data;
+       g_signal_handler_disconnect (account, data->handler);
+
+       /* Quit from wait loop */
+       quit_wait_loop (account, (ConnectAndWaitData *) user_data);
+}
+
+static void
+on_tny_camel_account_set_online_cb (TnyCamelAccount *account, 
+                                   gboolean canceled, 
+                                   GError *err, 
+                                   gpointer user_data)
+{
+       /* Quit from wait loop */
+       quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
+}
+
+gboolean 
+modest_platform_connect_and_wait (GtkWindow *parent_window, 
+                                 TnyAccount *account)
+{
+       ConnectAndWaitData *data = NULL;
+       gboolean device_online;
+       TnyDevice *device;
+       TnyConnectionStatus conn_status;
+       gboolean user_requested;
+       
+       device = modest_runtime_get_device();
+       device_online = tny_device_is_online (device);
+
+       /* Whether the connection is user requested or automatically
+          requested, for example via D-Bus */
+       user_requested = (parent_window) ? TRUE : FALSE;
+
+       /* If there is no account check only the device status */
+       if (!account) {
+               if (device_online)
+                       return TRUE;
+               else
+                       return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), 
+                                                              NULL, user_requested);
+       }
+
+       /* Return if the account is already connected */
+       conn_status = tny_account_get_connection_status (account);
+       if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
+               return TRUE;
+
+       /* Create the helper */
+       data = g_slice_new0 (ConnectAndWaitData);
+       data->mutex = g_mutex_new ();
+       data->has_callback = FALSE;
+
+       /* Connect the device */
+       if (!device_online) {
+               /* Track account connection status changes */
+               data->handler = g_signal_connect (account, "connection-status-changed",                                     
+                                                 G_CALLBACK (on_connection_status_changed),
+                                                 data);
+               /* Try to connect the device */
+               device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), 
+                                                               NULL, user_requested);
+
+               /* If the device connection failed then exit */
+               if (!device_online && data->handler)
+                       goto frees;
+       } else {
+               /* Force a reconnection of the account */
+               tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE, 
+                                             on_tny_camel_account_set_online_cb, data);
+       }
+
+       /* Wait until the callback is executed */
+       g_mutex_lock (data->mutex);
+       if (!data->has_callback) {
+               data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
+               gdk_threads_leave ();
+               g_mutex_unlock (data->mutex);
+               g_main_loop_run (data->wait_loop);
+               g_mutex_lock (data->mutex);
+               gdk_threads_enter ();
+       }
+       g_mutex_unlock (data->mutex);
+
+ frees:
+       if (data) {
+               if (g_signal_handler_is_connected (account, data->handler))
+                       g_signal_handler_disconnect (account, data->handler);
+               g_mutex_free (data->mutex);
+               g_main_loop_unref (data->wait_loop);
+               g_slice_free (ConnectAndWaitData, data);
+       }
+
+       conn_status = tny_account_get_connection_status (account);
+       return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
+}
+
+gboolean 
+modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
+{
+       if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
+               if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
+                   !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
+                       /* This must be a maildir account, which does not require a connection: */
+                       return TRUE;
+               }
+       }
+
+       return modest_platform_connect_and_wait (parent_window, account);
+}
+
+gboolean 
+modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
+{
+       if (!folder_store)
+               return TRUE; /* Maybe it is something local. */
+               
+       gboolean result = TRUE;
+       if (TNY_IS_FOLDER (folder_store)) {
+               /* Get the folder's parent account: */
+               TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
+               if (account != NULL) {
+                       result = modest_platform_connect_and_wait_if_network_account (NULL, account);
+                       g_object_unref (account);
+               }
+       } else if (TNY_IS_ACCOUNT (folder_store)) {
+               /* Use the folder store as an account: */
+               result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
+       }
+
+       return result;
+}
+
+GtkWidget *
+modest_platform_create_sort_dialog       (GtkWindow *parent_window)
+{
+       GtkWidget *dialog;
+
+       dialog = modest_hildon_sort_dialog_new (parent_window);
+
+       hildon_help_dialog_help_enable (GTK_DIALOG(dialog),
+                                       "applications_email_sort",
+                                       modest_maemo_utils_get_osso_context());
+
+       return dialog;
+}
+
+
+gboolean 
+modest_platform_set_update_interval (guint minutes)
+{
+#ifdef MODEST_HAVE_LIBALARM
+       
+       ModestConf *conf = modest_runtime_get_conf ();
+       if (!conf)
+               return FALSE;
+               
+       cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
+
+       /* Delete any existing alarm,
+        * because we will replace it: */
+       if (alarm_cookie) {
+               if (alarmd_event_del(alarm_cookie) != 1)
+                       g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
+               alarm_cookie = 0;
+               modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
+       }
+       
+       /* 0 means no updates: */
+       if (minutes == 0)
+               return TRUE;
+       
+     
+       /* Register alarm: */
+       
+       /* Set the interval in alarm_event_t structure: */
+       alarm_event_t *event = alarm_event_create ();
+       alarm_event_add_actions (event, 1);
+       alarm_action_t *action = alarm_event_get_action (event, 0);
+       event->alarm_time = minutes * 60; /* seconds */
+       
+       /* Set recurrence every few minutes: */
+       event->recur_secs = minutes*60;
+       event->recur_count = -1; /* Means infinite */
+
+       /* Specify what should happen when the alarm happens:
+        * It should call this D-Bus method: */
+        
+       action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
+       action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
+       action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
+       action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
+       action->flags = ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
+
+       /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if 
+        * exec_name or dbus_path is NULL, even though we have specified no dialog text.
+        * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails 
+        * This is why we want to use the Alarm API instead of just g_timeout_add().
+        * (The old maemo email-client did this, though it isn't specified in the UI spec.)
+        * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
+         */
+       event->flags = ALARM_EVENT_CONNECTED;
+       
+       alarm_cookie = alarmd_event_add (event);
+
+       /* now, free it */
+       alarm_event_delete (event);
+       
+       /* Store the alarm ID in GConf, so we can remove it later:
+        * This is apparently valid between application instances. */
+       modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
+       
+       if (!alarm_cookie) {
+           /* Error */
+           g_debug ("Error setting alarm event. \n");
+           
+           return FALSE;
+       }
+#endif /* MODEST_HAVE_LIBALARM */      
+       return TRUE;
+}
+
+void
+modest_platform_push_email_notification(void)
+{
+       gboolean play_sound;
+       ModestWindow *main_window;
+       gboolean screen_on = TRUE, app_in_foreground;
+
+       /* Check whether or not we should play a sound */
+       play_sound = modest_conf_get_bool (modest_runtime_get_conf (),
+                                          MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
+                                          NULL);
+
+       /* Get the screen status */
+       main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
+       if (main_window)
+               screen_on = modest_main_window_screen_is_on (MODEST_MAIN_WINDOW (main_window));
+
+       /* Get the window status */
+       app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
+
+       /* If the screen is on and the app is in the
+          foreground we don't show anything */
+       if (!(screen_on && app_in_foreground)) {
+               /* Play a sound */
+               if (play_sound)
+                       hildon_play_system_sound (MODEST_NEW_MAIL_SOUND_FILE);
+
+               /* Activate LED. This must be deactivated by
+                  modest_platform_remove_new_mail_notifications */
+#ifdef MODEST_HAVE_MCE
+               osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
+                                    MCE_SERVICE,
+                                    MCE_REQUEST_PATH,
+                                    MCE_REQUEST_IF,
+                                    MCE_ACTIVATE_LED_PATTERN,
+                                    NULL,
+                                    DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
+                                    DBUS_TYPE_INVALID);
+#endif
+       }
+}
+
+void 
+modest_platform_on_new_headers_received (TnyList *header_list,
+                                        gboolean show_visual)
+{
+       g_return_if_fail (TNY_IS_LIST(header_list));
+
+       if (tny_list_get_length(header_list) == 0) {
+               g_warning ("%s: header list is empty", __FUNCTION__);
+               return;
+       }
+       
+       if (!show_visual) {
+                modest_platform_push_email_notification ();
+               /* We do a return here to avoid indentation with an else */
+               return;
+       }
+
+#ifdef MODEST_HAVE_HILDON_NOTIFY
+       gboolean play_sound;
+
+       /* Check whether or not we should play a sound */
+       play_sound = modest_conf_get_bool (modest_runtime_get_conf (),
+                                          MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
+                                          NULL);
+
+       HildonNotification *notification;
+       TnyIterator *iter;
+       GSList *notifications_list = NULL;
+
+       /* Get previous notifications ids */
+       notifications_list = modest_conf_get_list (modest_runtime_get_conf (), 
+                                                  MODEST_CONF_NOTIFICATION_IDS, 
+                                                  MODEST_CONF_VALUE_INT, NULL);
+
+       iter = tny_list_create_iterator (header_list);
+       while (!tny_iterator_is_done (iter)) {
+               gchar *url = NULL, *display_address = NULL,  *summary = NULL;
+               const gchar *display_date;
+               TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
+               TnyFolder *folder = tny_header_get_folder (header);
+               gboolean first_notification = TRUE;
+               gint notif_id;
+               gchar *str;
+
+               /* constant string, don't free */
+               display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header));
+
+               display_address = tny_header_dup_from (header);
+               modest_text_utils_get_display_address (display_address); /* string is changed in-place */
+               
+               summary = g_strdup_printf ("%s - %s", display_date, display_address);
+               str = tny_header_dup_subject (header);
+               notification = hildon_notification_new (summary,
+                                                       str,
+                                                       "qgn_list_messagin",
+                                                       "email.arrive");
+               g_free (str);
+               /* Create the message URL */
+               str = tny_header_dup_uid (header);
+               url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder), 
+                                      str);
+               g_free (str);
+
+               hildon_notification_add_dbus_action(notification,
+                                                   "default",
+                                                   "Cancel",
+                                                   MODEST_DBUS_SERVICE,
+                                                   MODEST_DBUS_OBJECT,
+                                                   MODEST_DBUS_IFACE,
+                                                   MODEST_DBUS_METHOD_OPEN_MESSAGE,
+                                                   G_TYPE_STRING, url,
+                                                   -1);
+
+               /* Play sound if the user wants. Show the LED
+                  pattern. Show and play just one */
+               if (G_UNLIKELY (first_notification)) {
+                       first_notification = FALSE;
+                       if (play_sound)  {
+                               notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
+                                                                   "sound-file", MODEST_NEW_MAIL_SOUND_FILE);
+                       }
+
+                       /* Set the led pattern */
+                       notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
+                                                           "dialog-type", 4);
+                       notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
+                                                           "led-pattern",
+                                                           MODEST_NEW_MAIL_LIGHTING_PATTERN);                  
+               }
+
+               /* Notify. We need to do this in an idle because this function
+                  could be called from a thread */
+               notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
+
+               /* Save id in the list */
+               g_object_get(G_OBJECT(notification), "id", &notif_id, NULL);
+               notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
+               /* We don't listen for the "closed" signal, because we
+                  don't care about if the notification was removed or
+                  not to store the list in gconf */
+       
+               /* Free & carry on */
+               g_free (display_address);
+               g_free (summary);
+               g_free (url);
+               g_object_unref (folder);
+               g_object_unref (header);
+               tny_iterator_next (iter);
+       }
+       g_object_unref (iter);
+
+       /* Save the ids */
+       modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS, 
+                             notifications_list, MODEST_CONF_VALUE_INT, NULL);
+
+       g_slist_free (notifications_list);
+       
+#endif /*MODEST_HAVE_HILDON_NOTIFY*/
+}
+
+void
+modest_platform_remove_new_mail_notifications (gboolean only_visuals) 
+{
+       if (only_visuals) {
+#ifdef MODEST_HAVE_MCE
+               osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
+                                    MCE_SERVICE,
+                                    MCE_REQUEST_PATH,
+                                    MCE_REQUEST_IF,
+                                    MCE_DEACTIVATE_LED_PATTERN,
+                                    NULL,
+                                    DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
+                                    DBUS_TYPE_INVALID);
+#endif
+               return;
+       }
+
+#ifdef MODEST_HAVE_HILDON_NOTIFY
+       GSList *notif_list = NULL;
+
+       /* Get previous notifications ids */
+       notif_list = modest_conf_get_list (modest_runtime_get_conf (), 
+                                          MODEST_CONF_NOTIFICATION_IDS, 
+                                          MODEST_CONF_VALUE_INT, NULL);
+
+        while (notif_list) {
+               gint notif_id;
+               NotifyNotification *notif;
+
+               /* Nasty HACK to remove the notifications, set the id
+                  of the existing ones and then close them */
+               notif_id = GPOINTER_TO_INT(notif_list->data);
+               notif = notify_notification_new("dummy", NULL, NULL, NULL);
+               g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
+
+               /* Close the notification, note that some ids could be
+                  already invalid, but we don't care because it does
+                  not fail */
+               notify_notification_close(notif, NULL);
+               g_object_unref(notif);
+
+               /* Delete the link, it's like going to the next */
+               notif_list = g_slist_delete_link (notif_list, notif_list);
+        }
+
+       /* Save the ids */
+       modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS, 
+                             notif_list, MODEST_CONF_VALUE_INT, NULL);
+
+       g_slist_free (notif_list);
+
+#endif /* MODEST_HAVE_HILDON_NOTIFY */
+}
+
+
+
+GtkWidget * 
+modest_platform_get_global_settings_dialog ()
+{
+       return modest_maemo_global_settings_dialog_new ();
+}
+
+void
+modest_platform_show_help (GtkWindow *parent_window, 
+                          const gchar *help_id)
+{
+       osso_return_t result;
+       g_return_if_fail (help_id);
+
+       result = hildon_help_show (modest_maemo_utils_get_osso_context(),
+                                  help_id, HILDON_HELP_SHOW_DIALOG);
+       
+       if (result != OSSO_OK) {
+               gchar *error_msg;
+               error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id); 
+               hildon_banner_show_information (GTK_WIDGET (parent_window),
+                                               NULL,
+                                               error_msg);
+               g_free (error_msg);
+       }
+}
+
+void 
+modest_platform_show_search_messages (GtkWindow *parent_window)
+{
+       osso_return_t result = OSSO_ERROR;
+       
+       result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
+                                            "osso_global_search",
+                                            "search_email", NULL, DBUS_TYPE_INVALID);
+
+       if (result != OSSO_OK) {
+               g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
+       }
+}
+
+void 
+modest_platform_show_addressbook (GtkWindow *parent_window)
+{
+       osso_return_t result = OSSO_ERROR;
+       
+       result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
+                                            "osso_addressbook",
+                                            "top_application", NULL, DBUS_TYPE_INVALID);
+
+       if (result != OSSO_OK) {
+               g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
+       }
+}
+
+GtkWidget *
+modest_platform_create_folder_view (TnyFolderStoreQuery *query)
+{
+       GtkWidget *widget = modest_folder_view_new (query);
+
+       /* Show one account by default */
+       modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
+                                     MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
+
+       /* Restore settings */
+       modest_widget_memory_restore (modest_runtime_get_conf(), 
+                                     G_OBJECT (widget),
+                                     MODEST_CONF_FOLDER_VIEW_KEY);
+
+       return widget;
+}
+
+void
+banner_finish (gpointer data, GObject *object)
+{
+       ModestWindowMgr *mgr = (ModestWindowMgr *) data;
+       modest_window_mgr_unregister_banner (mgr);
+       g_object_unref (mgr);
+}
+
+void 
+modest_platform_information_banner (GtkWidget *parent,
+                                   const gchar *icon_name,
+                                   const gchar *text)
+{
+       GtkWidget *banner, *banner_parent = NULL;
+       ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
+
+       if (modest_window_mgr_num_windows (mgr) == 0)
+               return;
+
+       if (parent && GTK_IS_WINDOW (parent)) {
+               /* If the window is the active one then show the
+                  banner on top of this window */
+               if (gtk_window_is_active (GTK_WINDOW (parent)))
+                       banner_parent = parent;
+               /* If the window is not the topmost but it's visible
+                  (it's minimized for example) then show the banner
+                  with no parent */ 
+               else if (GTK_WIDGET_VISIBLE (parent))
+                       banner_parent = NULL;
+               /* If the window is hidden (like the main window when
+                  running in the background) then do not show
+                  anything */
+               else 
+                       return;
+       }
+
+
+       banner = hildon_banner_show_information (banner_parent, icon_name, text);
+
+       modest_window_mgr_register_banner (mgr);
+       g_object_ref (mgr);
+       g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
+}
+
+void
+modest_platform_information_banner_with_timeout (GtkWidget *parent,
+                                                const gchar *icon_name,
+                                                const gchar *text,
+                                                gint timeout)
+{
+       GtkWidget *banner;
+
+       if (modest_window_mgr_num_windows (modest_runtime_get_window_mgr ()) == 0)
+               return;
+
+       banner = hildon_banner_show_information (parent, icon_name, text);
+       hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
+}
+
+GtkWidget *
+modest_platform_animation_banner (GtkWidget *parent,
+                                 const gchar *animation_name,
+                                 const gchar *text)
+{
+       GtkWidget *inf_note = NULL;
+
+       g_return_val_if_fail (text != NULL, NULL);
+
+       if (modest_window_mgr_num_windows (modest_runtime_get_window_mgr ()) == 0)
+               return NULL;
+
+       /* If the parent is not visible then do not show */
+       if (parent && !GTK_WIDGET_VISIBLE (parent))
+               return NULL;
+
+       inf_note = hildon_banner_show_animation (parent, animation_name, text);
+
+       return inf_note;
+}
+
+typedef struct
+{
+       GMainLoop* loop;
+       TnyAccount *account;
+       gboolean is_online;
+       gint count_tries;
+} CheckAccountIdleData;
+
+#define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
+
+static gboolean 
+on_timeout_check_account_is_online(CheckAccountIdleData* data)
+{
+       gboolean stop_trying = FALSE;
+       g_return_val_if_fail (data && data->account, FALSE);
+       
+       printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
+               tny_account_get_connection_status (data->account));     
+       
+       if (data && data->account && 
+               /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
+                * after which the account is likely to be usable, or never likely to be usable soon: */
+               (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
+       {
+               data->is_online = TRUE;
+               
+               stop_trying = TRUE;
+       } else {
+               /* Give up if we have tried too many times: */
+               if (data->count_tries >= NUMBER_OF_TRIES) {
+                       stop_trying = TRUE;
+               } else {
+                       /* Wait for another timeout: */
+                       ++(data->count_tries);
+               }
+       }
+       
+       if (stop_trying) {
+               /* Allow the function that requested this idle callback to continue: */
+               if (data->loop)
+                       g_main_loop_quit (data->loop);
+                       
+               if (data->account)
+                       g_object_unref (data->account);
+               
+               return FALSE; /* Don't call this again. */
+       } else {
+               return TRUE; /* Call this timeout callback again. */
+       }
+}
+
+/* Return TRUE immediately if the account is already online,
+ * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as 
+ * soon as the account is online, or FALSE if the account does 
+ * not become online in the NUMBER_OF_TRIES seconds.
+ * This is useful when the D-Bus method was run immediately after 
+ * the application was started (when using D-Bus activation), 
+ * because the account usually takes a short time to go online.
+ * The return value is maybe not very useful.
+ */
+gboolean
+modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
+{
+       g_return_val_if_fail (account, FALSE);
+       
+       printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
+       
+       if (!tny_device_is_online (modest_runtime_get_device())) {
+               printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
+               return FALSE;
+       }
+       
+       /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
+        * so we avoid wait unnecessarily: */
+       if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) && 
+               !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
+               return TRUE;            
+       }
+               
+       printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
+               __FUNCTION__, tny_account_get_connection_status (account));
+       
+       /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED, 
+        * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that 
+        * we want to avoid. */
+       if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
+               return TRUE;
+               
+       /* This blocks on the result: */
+       CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
+       data->is_online = FALSE;
+       data->account = account;
+       g_object_ref (data->account);
+       data->count_tries = 0;
+               
+       GMainContext *context = NULL; /* g_main_context_new (); */
+       data->loop = g_main_loop_new (context, FALSE /* not running */);
+
+       g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
+
+       /* This main loop will run until the idle handler has stopped it: */
+       g_main_loop_run (data->loop);
+
+       g_main_loop_unref (data->loop);
+       /* g_main_context_unref (context); */
+
+       g_slice_free (CheckAccountIdleData, data);
+       
+       return data->is_online; 
+}
+
+
+
+static void
+on_cert_dialog_response (GtkDialog *dialog, gint response_id,  const gchar* cert)
+{
+       /* GTK_RESPONSE_HELP means we need to show the certificate */
+       if (response_id == GTK_RESPONSE_APPLY) {
+               GtkWidget *note;
+               gchar *msg;
+               
+               /* Do not close the dialog */
+               g_signal_stop_emission_by_name (dialog, "response");
+
+               msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);    
+               note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
+               gtk_dialog_run (GTK_DIALOG(note));
+               gtk_widget_destroy (note);
+       }
+}
+
+
+gboolean
+modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
+                                                    const gchar *certificate)
+{
+       GtkWidget *note;
+       gint response;
+       ModestWindow *main_win;
+       
+       if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
+               g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
+                          __FUNCTION__);
+               return FALSE;
+       }
+
+       /* don't create it */
+       main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
+       g_return_val_if_fail (main_win, FALSE); /* should not happen */
+       
+       
+       gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
+                                          server_name);
+       
+       /* We use GTK_RESPONSE_APPLY because we want the button in the
+          middle of OK and CANCEL the same as the browser does for
+          example. With GTK_RESPONSE_HELP the view button is aligned
+          to the left while the other two to the right */
+       note = hildon_note_new_confirmation_add_buttons  (
+               GTK_WINDOW(main_win),
+               question,
+               _("mcen_bd_dialog_ok"),     GTK_RESPONSE_OK,
+               _("mcen_bd_view"),          GTK_RESPONSE_APPLY,   /* abusing this... */
+               _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
+               NULL, NULL);
+       
+       g_signal_connect (G_OBJECT(note), "response", 
+                         G_CALLBACK(on_cert_dialog_response),
+                         (gpointer) certificate);
+       
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
+                                    GTK_WINDOW (note));
+       response = gtk_dialog_run(GTK_DIALOG(note));
+
+       on_destroy_dialog (note);
+       g_free (question);
+       
+       return response == GTK_RESPONSE_OK;
+}
+
+gboolean
+modest_platform_run_alert_dialog (const gchar* prompt, 
+                                 gboolean is_question)
+{      
+       ModestWindow *main_win; 
+
+       if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
+               g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
+                          " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
+               return is_question ? FALSE : TRUE;
+       }
+
+       main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
+       g_return_val_if_fail (main_win, FALSE); /* should not happen */
+       
+       gboolean retval = TRUE;
+       if (is_question) {
+               /* The Tinymail documentation says that we should show Yes and No buttons, 
+                * when it is a question.
+                * Obviously, we need tinymail to use more specific error codes instead,
+                * so we know what buttons to show. */
+               GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win), 
+                                                                             prompt));
+               modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
+                                            GTK_WINDOW (dialog));
+               
+               const int response = gtk_dialog_run (GTK_DIALOG (dialog));
+               retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
+               
+               on_destroy_dialog (dialog);             
+       } else {
+               /* Just show the error text and use the default response: */
+               modest_platform_run_information_dialog (GTK_WINDOW (main_win), 
+                                                       prompt, FALSE);
+       }
+       return retval;
+}
+
+/***************/
+typedef struct {
+       GtkWindow *parent_window;
+       ModestConnectedPerformer callback;
+       TnyAccount *account;
+       gpointer user_data;
+       gchar *iap;
+       TnyDevice *device;
+} OnWentOnlineInfo;
+static void 
+on_went_online_info_free (OnWentOnlineInfo *info)
+{
+       /* And if we cleanup, we DO cleanup  :-)  */
+       
+       if (info->device)
+               g_object_unref (info->device);
+       if (info->iap)
+               g_free (info->iap);
+       if (info->parent_window)
+               g_object_unref (info->parent_window);
+       if (info->account)
+               g_object_unref (info->account);
+       
+       g_slice_free (OnWentOnlineInfo, info);
+       
+       /* We're done ... */
+       
+       return;
+}
+static void
+on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
+{
+       OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
+       /* Now it's really time to callback to the caller. If going online didn't succeed,
+        * err will be set. We don't free it, Tinymail does that! If a cancel happened,
+        * canceled will be set. Etcetera etcetera. */
+       
+       if (info->callback) {
+               info->callback (canceled, err, info->parent_window, info->account, info->user_data);
+       }
+       
+       /* This is our last call, we must cleanup here if we didn't yet do that */
+       on_went_online_info_free (info);
+       
+       return;
+}
+static void
+on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
+{
+       OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
+       info->iap = g_strdup (iap_id);
+       
+       if (canceled || err || !info->account) {
+       
+               /* If there's a problem or if there's no account (then that's it for us, we callback
+                * the caller's callback now. He'll have to handle err or canceled, of course.
+                * We are not really online, as the account is not really online here ... */    
+               
+               /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
+                * this info. We don't cleanup err, Tinymail does that! */
+               
+               if (info->callback) {
+                       
+                       /* info->account can be NULL here, this means that the user did not
+                        * provide a nice account instance. We'll assume that the user knows
+                        * what he's doing and is happy with just the device going online. 
+                        * 
+                        * We can't do magic, we don't know what account the user wants to
+                        * see going online. So just the device goes online, end of story */
+                       
+                       info->callback (canceled, err, info->parent_window, info->account, info->user_data);
+               }
+               
+       } else if (info->account) {
+               
+               /* If there's no problem and if we have an account, we'll put the account
+                * online too. When done, the callback of bringing the account online
+                * will callback the caller's callback. This is the most normal case. */
+               info->device = TNY_DEVICE (g_object_ref (device));
+               
+               tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
+                                             on_account_went_online, info);
+               
+               /* The on_account_went_online cb frees up the info, go look if you
+                * don't believe me! (so we return here) */
+               
+               return;
+       }
+       
+       /* We cleanup if we are not bringing the account online too */
+       on_went_online_info_free (info);
+       return; 
+}
+       
+void 
+modest_platform_connect_and_perform (GtkWindow *parent_window, 
+                                    gboolean force,
+                                    TnyAccount *account, 
+                                    ModestConnectedPerformer callback, 
+                                    gpointer user_data)
+{
+       gboolean device_online;
+       TnyDevice *device;
+       TnyConnectionStatus conn_status;
+       OnWentOnlineInfo *info;
+       
+       device = modest_runtime_get_device();
+       device_online = tny_device_is_online (device);
+
+       /* If there is no account check only the device status */
+       if (!account) {
+               
+               if (device_online) {
+                       /* We promise to instantly perform the callback, so ... */
+                       if (callback) {
+                               callback (FALSE, NULL, parent_window, account, user_data);
+                       }
+                       
+               } else {
+                       
+                       info = g_slice_new0 (OnWentOnlineInfo);
+                       
+                       info->iap = NULL;
+                       info->device = NULL;
+                       info->account = NULL;
+               
+                       if (parent_window)
+                               info->parent_window = (GtkWindow *) g_object_ref (parent_window);
+                       else
+                               info->parent_window = NULL;
+                       info->user_data = user_data;
+                       info->callback = callback;
+               
+                       tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
+                                                             force, on_conic_device_went_online, 
+                                                             info);
+                       /* We'll cleanup in on_conic_device_went_online */
+               }
+               /* The other code has no more reason to run. This is all that we can do for the
+                * caller (he should have given us a nice and clean account instance!). We
+                * can't do magic, we don't know what account he intends to bring online. So
+                * we'll just bring the device online (and await his false bug report). */
+               
+               return;
+       }
+       
+       /* Return if the account is already connected */
+       
+       conn_status = tny_account_get_connection_status (account);
+       if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
+               /* We promise to instantly perform the callback, so ... */
+               if (callback) {
+                       callback (FALSE, NULL, parent_window, account, user_data);
+               }
+               
+               return;
+       }
+       
+       /* Else, we are in a state that requires that we go online before we
+        * call the caller's callback. */
+       
+       info = g_slice_new0 (OnWentOnlineInfo);
+       
+       info->device = NULL;
+       info->iap = NULL;
+       info->account = TNY_ACCOUNT (g_object_ref (account));
+       
+       if (parent_window)
+               info->parent_window = (GtkWindow *) g_object_ref (parent_window);
+       else
+               info->parent_window = NULL;
+       
+       /* So we'll put the callback away for later ... */
+       
+       info->user_data = user_data;
+       info->callback = callback;
+       
+       if (!device_online) {
+               /* If also the device is offline, then we connect both the device 
+                * and the account */
+               
+               tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
+                                                     force, on_conic_device_went_online, 
+                                                     info);
+               
+       } else {
+               
+               /* If the device is online, we'll just connect the account */
+               
+               tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE, 
+                                             on_account_went_online, info);
+       }
+       /* The info gets freed by on_account_went_online or on_conic_device_went_online
+        * in both situations, go look if you don't believe me! */
+       
+       return;
+}
+
+void
+modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window, 
+                                              gboolean force,
+                                              TnyFolderStore *folder_store, 
+                                              ModestConnectedPerformer callback, 
+                                              gpointer user_data)
+{
+       TnyAccount *account = NULL;
+       
+       if (!folder_store) {
+               /* We promise to instantly perform the callback, so ... */
+               if (callback) {
+                       callback (FALSE, NULL, parent_window, NULL, user_data);
+               }
+               return; 
+               
+               /* Original comment: Maybe it is something local. */
+               /* PVH's comment: maybe we should KNOW this in stead of assuming? */
+               
+       } else if (TNY_IS_FOLDER (folder_store)) {
+               /* Get the folder's parent account: */
+               account = tny_folder_get_account (TNY_FOLDER (folder_store));
+       } else if (TNY_IS_ACCOUNT (folder_store)) {
+               /* Use the folder store as an account: */
+               account = TNY_ACCOUNT (g_object_ref (folder_store));
+       }
+       if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
+               if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
+                   !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
+                       /* No need to connect a local account */
+                       if (callback)
+                               callback (FALSE, NULL, parent_window, account, user_data);
+
+                       goto clean;
+               }
+       }
+       modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
+ clean:
+       if (account)
+               g_object_unref (account);
+}
+
+static void
+src_account_connect_performer (gboolean canceled, 
+                              GError *err,
+                              GtkWindow *parent_window, 
+                              TnyAccount *src_account, 
+                              gpointer user_data)
+{
+       DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
+
+       if (canceled || err) {
+               /* If there was any error call the user callback */
+               info->callback (canceled, err, parent_window, src_account, info->data);
+       } else {
+               /* Connect the destination account */
+               modest_platform_connect_if_remote_and_perform (parent_window, TRUE, 
+                                                              TNY_FOLDER_STORE (info->dst_account),
+                                                              info->callback, info->data);
+       }
+
+       /* Free the info object */
+       g_object_unref (info->dst_account);
+       g_slice_free (DoubleConnectionInfo, info);
+}
+
+
+void 
+modest_platform_double_connect_and_perform (GtkWindow *parent_window, 
+                                           gboolean force,
+                                           TnyFolderStore *folder_store,
+                                           DoubleConnectionInfo *connect_info)
+{
+       modest_platform_connect_if_remote_and_perform(parent_window, 
+                                                     force,
+                                                     folder_store, 
+                                                     src_account_connect_performer, 
+                                                     connect_info);
+}
+
+GtkWidget *
+modest_platform_get_account_settings_wizard (void)
+{
+       ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
+
+       return GTK_WIDGET (dialog);
+}
+
+ModestConnectedVia
+modest_platform_get_current_connection (void)
+{
+       TnyDevice *device = NULL;
+       ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
+       
+       device = modest_runtime_get_device ();
+
+       if (!tny_device_is_online (device))
+               return MODEST_CONNECTED_VIA_ANY;
+
+#ifdef MODEST_HAVE_CONIC
+       /* Get iap id */
+       const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
+       if (iap_id) {
+               ConIcIap *iap = tny_maemo_conic_device_get_iap (
+                       TNY_MAEMO_CONIC_DEVICE (device), iap_id);
+               const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
+               if (bearer_type) {
+                       if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
+                           !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
+                           !strcmp (bearer_type, "WIMAX")) {
+                               retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
+                       } else {
+                               retval = MODEST_CONNECTED_VIA_ANY;
+                       }
+               }       
+               g_object_unref (iap);
+       }
+#else
+       retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */  
+#endif /* MODEST_HAVE_CONIC */
+       return retval;
+}
+
+
+
+gboolean
+modest_platform_check_memory_low (ModestWindow *win,
+                                 gboolean visuals)
+{
+       gboolean lowmem;
+       
+       /* are we in low memory state? */
+       lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
+       
+       if (win && lowmem && visuals)
+               modest_platform_run_information_dialog (
+                       GTK_WINDOW(win),
+                       dgettext("ke-recv","memr_ib_operation_disabled"),
+                       TRUE);
+
+       if (lowmem)
+               g_debug ("%s: low memory reached. disallowing some operations",
+                        __FUNCTION__);
+
+       return lowmem;
+}
diff --git a/src/hildon2/modest-presets.c b/src/hildon2/modest-presets.c
new file mode 100644 (file)
index 0000000..ef23742
--- /dev/null
@@ -0,0 +1,382 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h> /* for strcmp */
+#include <modest-protocol-registry.h>
+#include <modest-runtime.h>
+#include "modest-presets.h"
+#include <stdio.h>
+
+/* Include config.h so that _() works: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define MODEST_PRESETS_KEY_NAME                "Name"
+#define MODEST_PRESETS_KEY_DOMAIN              "Domain"
+#define MODEST_PRESETS_KEY_MCC                 "MCC"
+#define MODEST_PRESETS_KEY_INCOMING            "IncomingMailServer"
+#define MODEST_PRESETS_KEY_INCOMING_SECURITY   "IncomingSecurity"
+#define MODEST_PRESETS_KEY_OUTGOING            "OutgoingMailServer"
+#define MODEST_PRESETS_KEY_MAILBOX_TYPE        "MailboxType"
+#define MODEST_PRESETS_KEY_APOP                "APOPSecureLogin"
+#define MODEST_PRESETS_KEY_SECURE_SMTP         "SecureSmtp"
+#define MODEST_PRESETS_KEY_SMTP_PORT           "SmtpPort"
+                                                   
+
+ModestPresets*
+modest_presets_new (const gchar *presetfile)
+{
+       ModestPresets *presets = NULL;
+       GError        *err     = NULL;
+       
+       g_return_val_if_fail (presetfile, NULL);
+       
+       presets = g_new (ModestPresets, 1);
+       presets->keyfile = g_key_file_new ();
+
+       if (!presets->keyfile) {
+               g_printerr ("modest: cannot instantiate GKeyFile\n");
+               g_free (presets);
+               return NULL;
+       }
+       
+       if (!g_key_file_load_from_file (presets->keyfile, presetfile,
+                                       G_KEY_FILE_NONE, &err)) {
+               g_printerr ("modest: cannot open keyfile from %s:\n  %s\n", presetfile,
+                           err ? err->message : "unknown reason");
+               g_error_free (err);
+               g_free (presets);
+               return NULL;
+       }
+
+       return presets;
+}
+
+gchar**
+modest_presets_get_providers  (ModestPresets *self, guint mcc,
+                              gboolean include_globals, gchar ***provider_ids)
+{
+       gchar **all_providers = NULL;
+       gchar **all_provider_ids = NULL;
+       gchar **filtered  = NULL;
+       gchar **filtered_ids = NULL;
+       GError *err       = NULL;
+       guint i, j, len;
+       
+       g_return_val_if_fail (self && self->keyfile, NULL);
+
+       /* Get all the provider IDs: */
+       all_provider_ids = g_key_file_get_groups (self->keyfile, NULL);
+       len = g_strv_length(all_provider_ids);
+
+       /* Get the names for all these providers: */
+       all_providers = g_new0(gchar*, len + 1); /* Provider names. */
+       for (i=0; i != len; ++i) {
+               const gchar * provider_id = all_provider_ids[i];
+               if(provider_id) {
+                       gchar* name = g_key_file_get_string(self->keyfile, provider_id, 
+                               MODEST_PRESETS_KEY_NAME, NULL);
+                               
+                       /* Be forgiving of missing names.
+                        * If we use NULL then we will null-terminate the array.
+                        */
+                       if(!name)
+                               name = g_strdup("");
+                               
+                       all_providers[i] = name;        
+               }
+               else
+                       all_providers[i] = NULL;
+       };
+               
+       /* return *all* providers? */
+       /*
+       if (mcc == 0 && include_globals) {
+               *provider_ids = all_provider_ids;
+               return all_providers;
+       }
+       */
+       
+       /* nope: filter them */
+
+       filtered = g_new0(gchar*, len + 1); /* Provider names. */
+       filtered_ids = g_new0(gchar*, len + 1); /* Provider IDs */
+
+       for (i=0, j=0; i != len; ++i) {
+
+               int this_mcc;
+               this_mcc = g_key_file_get_integer (self->keyfile, all_provider_ids[i],
+                                                  MODEST_PRESETS_KEY_MCC, &err);
+               if (err) {
+                       g_strfreev (all_providers);
+                       g_strfreev (all_provider_ids);
+                       g_strfreev (filtered);
+                       g_strfreev (filtered_ids);
+                       
+                       g_printerr ("modest: error parsing keyfile: %s\n", err->message);
+                       g_error_free (err);
+                       
+                       return NULL;
+               }
+               
+               if (this_mcc == mcc || (this_mcc == 0 && include_globals)) {
+                       filtered[j]   = all_providers[i];
+                       filtered_ids[j]   = all_provider_ids[i];
+                       ++j;
+                       filtered[j] = NULL; /* the array must be NULL-terminated */
+                       filtered_ids[j] = NULL; /* the array must be NULL-terminated */
+                       
+                       all_providers[i]  = NULL; /*  g_strfreev: leave it alone */
+                       all_provider_ids[i]  = NULL; /*  g_strfreev: leave it alone */
+               }
+       }
+       
+       g_strfreev (all_providers);
+       g_strfreev (all_provider_ids);
+       
+       *provider_ids = filtered_ids;
+       return filtered;
+}
+
+
+gchar*
+modest_presets_get_server (ModestPresets *self, const gchar *provider_id,
+                          gboolean incoming_server)
+{      
+       g_return_val_if_fail (self && self->keyfile, NULL);
+       g_return_val_if_fail (provider_id, NULL);
+
+       return g_key_file_get_string (self->keyfile, provider_id, 
+                                     incoming_server ?
+                                     MODEST_PRESETS_KEY_INCOMING :
+                                     MODEST_PRESETS_KEY_OUTGOING,
+                                     NULL);
+}
+
+gchar *
+modest_presets_get_domain      (ModestPresets *self,
+                               const gchar *provider_id)
+{      
+       g_return_val_if_fail (self && self->keyfile, NULL);
+       g_return_val_if_fail (provider_id, NULL);
+
+       return g_key_file_get_string (self->keyfile, provider_id, 
+                                     MODEST_PRESETS_KEY_DOMAIN,
+                                     NULL);
+}              
+
+
+
+
+ModestProtocolType
+modest_presets_get_info_server_type (ModestPresets *self,
+                                    const gchar *provider_id,
+                                    gboolean incoming_server)
+{
+       ModestProtocolType protocol_type = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
+       ModestProtocolRegistry *protocol_registry;
+       ModestProtocol *protocol;
+       gchar *val = NULL;
+       
+       g_return_val_if_fail (self && self->keyfile, 0);
+       protocol_registry = modest_runtime_get_protocol_registry ();
+
+       if (incoming_server) {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_INCOMING, NULL);
+               if (!val)
+                       return protocol_type;
+               
+               g_free (val);
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_MAILBOX_TYPE,NULL);
+               
+               protocol = modest_protocol_registry_get_protocol_by_name (protocol_registry, MODEST_PROTOCOL_REGISTRY_STORE_PROTOCOLS, val);
+               if (protocol == NULL)
+                       return protocol_type;
+               protocol_type = modest_protocol_get_type_id (protocol);
+       } else {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_OUTGOING, NULL);
+               if (!val)
+                       return protocol_type;
+
+               protocol_type = MODEST_PROTOCOLS_TRANSPORT_SMTP;
+       }
+       g_free (val);
+
+       /* debug: */
+/*     g_message ("provider id: %s, server type: %d", provider_id, info); */
+       return protocol_type;
+}
+
+
+
+ModestProtocolType
+modest_presets_get_info_server_security (ModestPresets *self, const gchar *provider_id,
+                                        gboolean incoming_server)
+{
+       ModestProtocolType protocol_type = MODEST_PROTOCOLS_CONNECTION_NONE;
+       gchar *val = NULL;
+       
+       g_return_val_if_fail (self && self->keyfile, MODEST_PROTOCOLS_CONNECTION_NONE);
+
+       if (incoming_server) {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_INCOMING, NULL);
+               if (val) {
+                       g_free (val);   
+
+                       val = g_key_file_get_string (self->keyfile, provider_id,
+                                                    MODEST_PRESETS_KEY_INCOMING_SECURITY, NULL);
+                       if (val && ((strcmp (val, "1") == 0) || (strcmp (val, "2") == 0))) {
+                               protocol_type = MODEST_PROTOCOLS_CONNECTION_SSL;
+                       }
+                       g_free (val);
+               }
+       } else /* outgoing: */ {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_OUTGOING, NULL);
+               if (val) {
+                       g_free (val);
+                       
+                       val = g_key_file_get_string (self->keyfile, provider_id,
+                                                    MODEST_PRESETS_KEY_SECURE_SMTP, NULL);
+                       /* printf("debug: %s: provider_id=%s, secure-smtp val=%s\n", __FUNCTION__, provider_id, val); */
+                       if (val && strcmp(val,"true") == 0)
+                               protocol_type = MODEST_PROTOCOLS_CONNECTION_SSL;
+                       g_free(val);
+               }
+       }
+
+       return protocol_type;
+}
+
+gboolean 
+modest_presets_get_info_server_use_alternate_port (ModestPresets *self, const gchar *provider_id,
+                                                  gboolean incoming_server)
+{
+       gboolean result = FALSE;
+       gchar *val = NULL;
+       
+       g_return_val_if_fail (self && self->keyfile, MODEST_PROTOCOLS_CONNECTION_NONE);
+
+       if (incoming_server) {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_INCOMING, NULL);
+               if (val) {
+                       g_free (val);   
+
+                       val = g_key_file_get_string (self->keyfile, provider_id,
+                                                    MODEST_PRESETS_KEY_INCOMING_SECURITY, NULL);
+                       if (val && (strcmp (val, "2") == 0)) {
+                               result = TRUE;
+                       }
+                       g_free (val);
+               }
+       } 
+
+       return result;
+}
+
+ModestProtocolType
+modest_presets_get_info_server_auth (ModestPresets *self, const gchar *provider_id,
+                                        gboolean incoming_server)
+{
+       ModestProtocolType protocol_type = MODEST_PROTOCOLS_AUTH_NONE;
+       gchar *val = NULL;
+       
+       g_return_val_if_fail (self && self->keyfile, MODEST_PROTOCOLS_AUTH_NONE);
+
+       if (incoming_server) {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_INCOMING, NULL);
+               if (val) {
+                        g_free (val);   
+                        val = g_key_file_get_string (self->keyfile, provider_id,
+                                                     MODEST_PRESETS_KEY_APOP, NULL);
+                        if (val && strcmp(val, "true") == 0)
+                               protocol_type = MODEST_PROTOCOLS_AUTH_PASSWORD;
+                        g_free(val);
+
+               }
+       } else /* outgoing: */ {
+               val = g_key_file_get_string (self->keyfile, provider_id,
+                                            MODEST_PRESETS_KEY_OUTGOING, NULL);
+               if (val) {
+                       g_free (val);
+                       
+                       val = g_key_file_get_string (self->keyfile, provider_id,
+                                                    MODEST_PRESETS_KEY_SECURE_SMTP, NULL);
+                       /* printf("debug: %s: provider_id=%s, secure-smtp val=%s\n", __FUNCTION__, provider_id, val); */
+                       if (val && strcmp(val,"true") == 0)
+                               protocol_type = MODEST_PROTOCOLS_AUTH_PASSWORD;
+                       g_free(val);
+               }
+       }
+
+       return protocol_type;
+}
+
+/*
+ * at the moment, this only for mac.com, which have a special SMTP port
+ */
+guint
+modest_presets_get_port (ModestPresets *self, const gchar* provider_id,
+                        gboolean incoming_server)
+{
+       guint port;
+       
+       g_return_val_if_fail (self && self->keyfile, 0);
+
+       if (incoming_server)
+               port = 0; /* not used yet */
+       else 
+               port = (guint)g_key_file_get_integer (self->keyfile, provider_id,
+                                                     MODEST_PRESETS_KEY_SMTP_PORT, NULL);
+
+       return port;
+}
+
+
+
+
+       
+void
+modest_presets_destroy (ModestPresets *self)
+{
+       if (!self)
+               return;
+
+       g_key_file_free (self->keyfile);
+       self->keyfile = NULL;
+       
+       g_free (self);
+}
diff --git a/src/hildon2/modest-presets.h b/src/hildon2/modest-presets.h
new file mode 100644 (file)
index 0000000..96e90d1
--- /dev/null
@@ -0,0 +1,187 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_PRESETS_H__
+#define __MODEST_PRESETS_H__
+
+#include <glib.h>
+#include <modest-protocol.h>
+
+struct _ModestPresets {
+/* private data: don't touch */
+       GKeyFile *keyfile;
+};
+typedef struct _ModestPresets ModestPresets;
+
+
+/**
+ * modest_presets_new:
+ * @presetfile: the full path to the file with presets (in GKeyFile format)
+ * 
+ * make a new ModestPresets instance
+ *
+ * Returns: a new ModestPresets instance, or NULL in case of error.
+ */
+ModestPresets*            modest_presets_new             (const gchar *presetfile);
+
+
+/**
+ * modest_presets_get_providers:
+ * @self: a valid ModestPresets instance
+ * @mcc: limit the search to providers with this mcc (Mobile Country Code),
+ *       or 0  to get all
+ * @include_globals: include (global) providers without MCC (such as GMail, Yahoo)
+ * @provider_ids: Output parameter, which will be set to a newly allocated array of strings, or NULL in case of error.
+ * 
+ * get a list of providers matching certian criteria
+ *
+ * Returns: The provider names, as a newly allocated array of strings, or NULL in case of error
+ * should be freed with g_strfreev
+ * 
+ **/
+gchar **         modest_presets_get_providers   (ModestPresets *self, guint mcc, 
+                                                gboolean include_globals, gchar ***provider_ids);
+
+/**
+ * modest_presets_get_server:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get the incoming mailserver if TRUE, get the
+ * outgoing server otherwise
+ *
+ * get the name of a incoming or outgoing mailserver
+ * 
+ * Returns: a newly allocated string with the servername, or NULL in case
+ * of error, or server not found. (FIXME). Note that if the (incoming) server uses a
+ * non-standard port, the port number is appended to the name, eg. pop.foo.fi:995
+ */
+gchar *                   modest_presets_get_server      (ModestPresets *self,
+                                                         const gchar *provider_id,
+                                                         gboolean incoming_server);
+                                                         
+/**
+ * modest_presets_get_domain:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ *
+ * Get the name of the most-used domain for theis provider. For instance. hotmail.com
+ * 
+ * Returns: a newly allocated string with the domain name, or NULL in case
+ * of error.
+ */
+gchar *                   modest_presets_get_domain      (ModestPresets *self,
+                                                         const gchar *provider_id);
+
+/**
+ * modest_presets_get_info_server_type:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get the incoming mailserver if TRUE, get the
+ * outgoing server otherwise
+ *
+ * get information about some incoming or outgoing mailserver
+ *
+ * Returns: a #ModestProtocolType with the required information
+ */
+ModestProtocolType          modest_presets_get_info_server_type (ModestPresets *self,
+                                                                const gchar *provider_id,
+                                                                gboolean incoming_server);
+
+/**
+ * modest_presets_get_info_server_security:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get the incoming mailserver if TRUE, get the
+ * outgoing server otherwise
+ *
+ * get information about some incoming or outgoing mailserver
+ *
+ * Returns: #ModestProtocolType with server auth
+ */                                        
+ModestProtocolType          modest_presets_get_info_server_auth (ModestPresets *self,
+                                                                const gchar *provider_id,
+                                                                gboolean incoming_server);
+
+/**
+ * modest_presets_get_info_server_security:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get the incoming mailserver if TRUE, get the
+ * outgoing server otherwise
+ *
+ * get information about some incoming or outgoing mailserver
+ *
+ * Returns: #ModestProtocolType with server security
+ */                                        
+ModestProtocolType          modest_presets_get_info_server_security (ModestPresets *self,
+                                                                    const gchar *provider_id,
+                                                                    gboolean incoming_server);
+
+/**
+ * modest_presets_get_info_server_security:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get the incoming mailserver if TRUE, get the
+ * outgoing server otherwise
+ *
+ * get information about some incoming or outgoing mailserver
+ *
+ * Returns: %TRUE if we should use the alternate port.
+ */                                        
+gboolean          modest_presets_get_info_server_use_alternate_port (ModestPresets *self,
+                                                                    const gchar *provider_id,
+                                                                    gboolean incoming_server);
+
+
+/**
+ * modest_presets_get_port:
+ * @self: a valid ModestPresets instance
+ * @provider_id: ID of the provider 
+ * @incoming_server: get port# for the incoming mailserver if TRUE, for the outgoing server otherwise
+ *
+ * Returns: the specific port number for some provider
+ * function return 0 if the normal port number is valid
+ *
+ */
+guint modest_presets_get_port (ModestPresets *self, const gchar* provider_id,
+                              gboolean incoming_server);
+
+
+/**
+ * modest_presets_destroy:
+ * @self: a valid ModestPresets instance (ie. must not be NULL)
+ *
+ * destroy ModestPresets instance; this is required after you're done with it.
+ */
+void                      modest_presets_destroy         (ModestPresets *self);
+
+
+#endif /*__MODEST_PRESETS__*/
+
+
diff --git a/src/hildon2/modest-signature-editor-dialog.c b/src/hildon2/modest-signature-editor-dialog.c
new file mode 100644 (file)
index 0000000..a0a190d
--- /dev/null
@@ -0,0 +1,232 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "modest-signature-editor-dialog.h"
+#include "widgets/modest-ui-constants.h"
+#include "modest-hildon-includes.h"
+#include "widgets/modest-serversecurity-combo-box.h"
+#include "widgets/modest-secureauth-combo-box.h"
+#include "widgets/modest-validating-entry.h"
+#include "modest-runtime.h"
+#include <modest-account-mgr-helpers.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtktextview.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkstock.h>
+#include <glib/gi18n.h>
+#include <modest-maemo-utils.h>
+
+G_DEFINE_TYPE (ModestSignatureEditorDialog, modest_signature_editor_dialog, GTK_TYPE_DIALOG);
+
+#define SIGNATURE_EDITOR_DIALOG_GET_PRIVATE(o) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_SIGNATURE_EDITOR_DIALOG, ModestSignatureEditorDialogPrivate))
+
+typedef struct _ModestSignatureEditorDialogPrivate ModestSignatureEditorDialogPrivate;
+
+struct _ModestSignatureEditorDialogPrivate
+{
+       GtkWidget *checkbox_use;
+       GtkWidget *label;
+       GtkWidget *scrolledwindow;
+       GtkWidget *textview;
+};
+
+static void
+modest_signature_editor_dialog_get_property (GObject *object, guint property_id,
+                                                                                                                       GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_signature_editor_dialog_set_property (GObject *object, guint property_id,
+                                                                                                                       const GValue *value, GParamSpec *pspec)
+{
+       switch (property_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+       }
+}
+
+static void
+modest_signature_editor_dialog_dispose (GObject *object)
+{
+       if (G_OBJECT_CLASS (modest_signature_editor_dialog_parent_class)->dispose)
+               G_OBJECT_CLASS (modest_signature_editor_dialog_parent_class)->dispose (object);
+}
+
+static void
+modest_signature_editor_dialog_finalize (GObject *object)
+{
+       G_OBJECT_CLASS (modest_signature_editor_dialog_parent_class)->finalize (object);
+}
+
+static void
+modest_signature_editor_dialog_class_init (ModestSignatureEditorDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (ModestSignatureEditorDialogPrivate));
+
+       object_class->get_property = modest_signature_editor_dialog_get_property;
+       object_class->set_property = modest_signature_editor_dialog_set_property;
+       object_class->dispose = modest_signature_editor_dialog_dispose;
+       object_class->finalize = modest_signature_editor_dialog_finalize;
+}
+
+static void
+enable_widgets (ModestSignatureEditorDialog *self)
+{
+       ModestSignatureEditorDialogPrivate *priv = 
+               SIGNATURE_EDITOR_DIALOG_GET_PRIVATE (self);
+               
+       const gboolean enable = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->checkbox_use));
+       gtk_widget_set_sensitive (priv->label, enable);
+       gtk_widget_set_sensitive (priv->scrolledwindow, enable);
+       gtk_text_view_set_editable (GTK_TEXT_VIEW (priv->textview), enable);
+}
+
+static void
+on_toggle_button_changed (GtkToggleButton *togglebutton, gpointer user_data)
+{
+       ModestSignatureEditorDialog *self = MODEST_SIGNATURE_EDITOR_DIALOG (user_data);
+       enable_widgets (self);
+}
+
+static void
+modest_signature_editor_dialog_init (ModestSignatureEditorDialog *self)
+{
+       ModestSignatureEditorDialogPrivate *priv = 
+               SIGNATURE_EDITOR_DIALOG_GET_PRIVATE (self);
+       
+       gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_email_signatures_edit_title"));
+               
+       GtkWidget *box = GTK_DIALOG(self)->vbox; /* gtk_vbox_new (FALSE, MODEST_MARGIN_HALF); */
+       gtk_container_set_border_width (GTK_CONTAINER (box), MODEST_MARGIN_HALF);
+       
+       priv->checkbox_use = gtk_check_button_new_with_label (
+               _("mcen_fi_email_signatures_use_signature"));
+       gtk_box_pack_start (GTK_BOX (box), priv->checkbox_use, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->checkbox_use);
+       
+       g_signal_connect (G_OBJECT (priv->checkbox_use), "toggled",
+               G_CALLBACK (on_toggle_button_changed), self);
+               
+       
+       priv->label = gtk_label_new (""); /* Set in modest_signature_editor_dialog_set_settings(). */
+       gtk_box_pack_start (GTK_BOX (box), priv->label, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->label);
+       
+       priv->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+       gtk_container_set_border_width (GTK_CONTAINER (priv->scrolledwindow), MODEST_MARGIN_DEFAULT);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow), 
+               GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scrolledwindow), GTK_SHADOW_IN);
+       gtk_box_pack_start (GTK_BOX (box), priv->scrolledwindow, FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (priv->scrolledwindow);
+               
+       priv->textview = gtk_text_view_new ();
+       gtk_container_add (GTK_CONTAINER (priv->scrolledwindow), priv->textview);
+       gtk_widget_show (priv->textview);
+       GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->textview));
+       gtk_text_buffer_set_text (buffer, "--\n", -1); /* Default, as per the UI spec. */
+       
+       /* Add the buttons: */
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK);
+       gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL);
+       
+       gtk_widget_show (box);
+       gtk_widget_set_size_request (GTK_WIDGET (self), 480, -1);
+       
+       /* When this window is shown, hibernation should not be possible, 
+        * because there is no sensible way to save the state: */
+       modest_window_mgr_prevent_hibernation_while_window_is_shown (
+               modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
+       
+       hildon_help_dialog_help_enable (GTK_DIALOG(self), "applications_email_signatureeditor",
+                                       modest_maemo_utils_get_osso_context());
+}
+
+ModestSignatureEditorDialog*
+modest_signature_editor_dialog_new (void)
+{
+       return g_object_new (MODEST_TYPE_SIGNATURE_EDITOR_DIALOG, NULL);
+}
+
+void
+modest_signature_editor_dialog_set_settings (
+       ModestSignatureEditorDialog *window, gboolean use_signature, const gchar* signature, 
+       const gchar* account_title)
+{
+       ModestSignatureEditorDialogPrivate *priv = 
+               SIGNATURE_EDITOR_DIALOG_GET_PRIVATE (window);
+
+       /* This causes a warning because of the %s in the translation, but not in the original string: */
+       gchar* label_text = g_strdup_printf (_("mcen_ia_email_signatures_edit_dlg_label"), 
+               account_title);
+       gtk_label_set_text (GTK_LABEL (priv->label), label_text);
+       gtk_label_set_ellipsize (GTK_LABEL (priv->label),  PANGO_ELLIPSIZE_END);
+       g_free (label_text);
+       
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_use), use_signature);
+       
+       GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->textview));
+       if (signature)
+               gtk_text_buffer_set_text (buffer, signature, -1);
+       else
+               gtk_text_buffer_set_text (buffer, "--\n", -1); /* Default, as per the UI spec. */
+               
+       enable_widgets (window);
+}
+
+/*
+ * The result must be freed with g_free(). */
+gchar*
+modest_signature_editor_dialog_get_settings (
+       ModestSignatureEditorDialog *window, gboolean* use_signature)
+{
+       ModestSignatureEditorDialogPrivate *priv = 
+               SIGNATURE_EDITOR_DIALOG_GET_PRIVATE (window);
+               
+       g_assert(use_signature);
+       
+       *use_signature = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->checkbox_use));
+                       
+       GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->textview));
+       
+       GtkTextIter start, end;
+       gtk_text_buffer_get_bounds (buffer, &start, &end);
+       return gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
+}
diff --git a/src/hildon2/modest-signature-editor-dialog.h b/src/hildon2/modest-signature-editor-dialog.h
new file mode 100644 (file)
index 0000000..e9e22ea
--- /dev/null
@@ -0,0 +1,85 @@
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_MAEMO_SIGNATURE_EDITOR_DIALOG
+#define __MODEST_MAEMO_SIGNATURE_EDITOR_DIALOG
+
+#include <modest-account-mgr.h>
+#include <modest-account-mgr-helpers.h> /* For ModestServerAccountData */
+#include <gtk/gtkdialog.h>
+#include <gtk/gtktreeview.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_SIGNATURE_EDITOR_DIALOG modest_signature_editor_dialog_get_type()
+
+#define MODEST_SIGNATURE_EDITOR_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+       MODEST_TYPE_SIGNATURE_EDITOR_DIALOG, ModestSignatureEditorDialog))
+
+#define MODEST_SIGNATURE_EDITOR_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_CAST ((klass), \
+       MODEST_TYPE_SIGNATURE_EDITOR_DIALOG, ModestSignatureEditorDialogClass))
+
+#define MODEST_IS_SIGNATURE_EDITOR_DIALOG(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+       MODEST_TYPE_SIGNATURE_EDITOR_DIALOG))
+
+#define MODEST_IS_SIGNATURE_EDITOR_DIALOG_CLASS(klass) \
+       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+       MODEST_TYPE_SIGNATURE_EDITOR_DIALOG))
+
+#define MODEST_SIGNATURE_EDITOR_DIALOG_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+       MODEST_TYPE_SIGNATURE_EDITOR_DIALOG, ModestSignatureEditorDialogClass))
+
+typedef struct {
+       GtkDialog parent;
+       
+} ModestSignatureEditorDialog;
+
+typedef struct {
+       GtkDialogClass parent_class;
+} ModestSignatureEditorDialogClass;
+
+GType modest_signature_editor_dialog_get_type (void);
+
+ModestSignatureEditorDialog* modest_signature_editor_dialog_new (void);
+
+void modest_signature_editor_dialog_set_settings (
+       ModestSignatureEditorDialog *window, gboolean use_signature, const gchar* signature, 
+       const gchar* account_title);
+       
+gchar* modest_signature_editor_dialog_get_settings (
+       ModestSignatureEditorDialog *window, gboolean* use_signature);
+       
+       
+G_END_DECLS
+
+#endif /* __MODEST_MAEMO_CONNECTION_SPECIFIC_SMTP_WINDOW */
diff --git a/src/hildon2/modest.conf b/src/hildon2/modest.conf
new file mode 100644 (file)
index 0000000..cda0c61
--- /dev/null
@@ -0,0 +1,5 @@
+<backup-configuration>
+  <locations>
+    <location type="dir" category="emails">/home/user/.modest</location>
+  </locations>
+</backup-configuration>
diff --git a/src/hildon2/modest.desktop.in b/src/hildon2/modest.desktop.in
new file mode 100644 (file)
index 0000000..20f98ed
--- /dev/null
@@ -0,0 +1,27 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=@PACKAGE_VERSION@
+Type=Application
+Name=mcen_ap_name
+Comment=mcen_ap_name_thumb
+Exec=@prefix@/bin/modest
+
+X-Osso-Service=com.nokia.modest
+X-Osso-Type=application/x-executable
+
+Icon=qgn_list_messagin
+X-Window-Icon=qgn_list_messagin
+X-Window-Icon-Dimmed=qgn_list_messagin
+
+StartupWMClass=modest
+
+MimeType=application/x-executable;
+
+#
+# below to be activated when dbus/send to functionality works
+#
+X-Osso-URI-Actions=mailto;
+[X-Osso-URI-Action Handler mailto]
+Method=MailTo
+Name=uri_link_compose_email
+TranslationDomain=osso-uri
diff --git a/src/hildon2/pixmaps/modest-icon.png b/src/hildon2/pixmaps/modest-icon.png
new file mode 100644 (file)
index 0000000..5d18b49
Binary files /dev/null and b/src/hildon2/pixmaps/modest-icon.png differ
diff --git a/src/hildon2/ui/modest-main-window-ui.xml b/src/hildon2/ui/modest-main-window-ui.xml
new file mode 100644 (file)
index 0000000..11d1f7b
--- /dev/null
@@ -0,0 +1,151 @@
+<!--
+ * Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<ui>
+
+  <menubar name="MenuBar">
+    
+    <menu name="EmailMenu" action="Email">
+      <menu name="EmailNewMainMenu" action="EmailNew">
+       <menuitem name="EmailNewMessageMenu"  action="EmailNewMessage"/>
+       <menuitem name="EmailNewFolderMenu" action="EmailNewFolder"/>
+      </menu>
+      <menuitem name="EmailOpenMenu" action="EmailOpen"/>
+      <separator/>
+      <menuitem name="EmailReplyMenu" action="EmailReply"/>
+      <menuitem name="EmailReplyAllMenu" action="EmailReplyAll"/>
+      <menuitem name="EmailForwardMenu" action="EmailForward"/>
+      <separator/>
+      <menuitem name="EmailContentsMenu"     action="EmailContents"/>
+      <menuitem name="EmailPurgeAttachmentsMenu" action="EmailPurgeAttachments"/>
+      <separator/>
+      <menuitem name="EmailRenameMenu" action="EmailRenameFolder"/>
+      <menuitem name="EmailDeleteMenu" action="EmailDelete"/>
+      <separator/>
+      <menuitem name="EmailDetailsMenu" action="EmailDetails"/>
+    </menu>
+    
+    <menu name="EditMenu" action="Edit">
+<!--       <menuitem name="EditCutMenu" action="EditCut"/> -->
+<!--       <menuitem name="EditCopyMenu" action="EditCopy"/> -->
+<!--       <menuitem name="EditPasteMenu" action="EditPaste"/> -->
+<!--       <separator/> -->
+      <menuitem name="EditSelectAllMenu" action="EditSelectAll"/>
+      <menuitem name="EditMarkAsReadMenu" action="EditMarkAsRead"/>
+      <menuitem name="EditMarkAsUnreadMenu" action="EditMarkAsUnread"/>
+      <separator/>
+      <menuitem name="EditMoveToMenu" action="EditMoveTo"/>
+    </menu> 
+
+    <menu name="ViewMenu" action="View">
+      <menuitem name="ViewSortMenu" action="ViewSort"/>
+      <separator/>
+      <menuitem name="ViewToggleFoldersMenu" action="ToggleFolders"/>
+      <menuitem name="ViewToggleFullscreenMenu" action="ViewToggleFullscreen"/>
+      <separator/>
+      <menu name="ViewShowToolbarMainMenu" action="ViewShowToolbar">
+        <menuitem name="ViewShowToolbarNormalScreenMenu" action="ViewShowToolbarNormalScreen"/>
+        <menuitem name="ViewShowToolbarFullScreenMenu" action="ViewShowToolbarFullScreen"/>
+      </menu>
+      <separator/>
+      <placeholder name="ViewMenuAdditions" />
+   </menu>
+    
+    <menu name="ToolsMenu" action="Tools">
+      <menuitem name="ToolsSettingsMenu" action="ToolsSettings"/>   
+      <menuitem name="ToolsAccountsMenu" action="ToolsAccounts"/>
+      <menuitem name="ToolsSMTPServersMenu" action="ToolsSMTPServers"/>
+      <separator/>
+      <menu name="ToolsSendReceiveMainMenu" action="ToolsSendReceive">
+        <menuitem name="ToolsSendReceiveAllMenu"  action="ToolsSendReceiveAll"/>
+        <menuitem name="ToolsSendReceiveCancelSendingMenu"  action="ToolsSendReceiveCancelSending"/>
+        <separator/>
+        <placeholder name="ToolsMenuAdditions" />
+      </menu>
+      <separator/>
+      <menuitem name="ToolsContactsMenu" action="ToolsContacts"/>
+      <menuitem name="ToolsSearchMessagesMenu" action="ToolsSearchMessages"/>
+      <separator/>
+      <menuitem name="ToolsHelpMenu" action="ToolsHelp"/>
+    </menu>
+    
+    <menu name="CloseMenu" action="Close">
+      <menuitem name="CloseWindowMenu"     action="CloseWindow"/>
+      <menuitem name="CloseAllWindowsMenu" action="CloseAllWindows"/>
+    </menu>
+  </menubar>
+
+  <toolbar name="ToolBar">
+    <toolitem action="ToolbarMessageNew"/> 
+    <toolitem action="ToolbarMessageReply"/> 
+    <toolitem action="ToolbarDeleteMessage"/>
+    <toolitem action="ToggleFolders"/>
+    <toolitem action="ToolbarSort" position="bot"/>
+    <toolitem action="ToolbarSendReceive" position="bot"/>
+    <placeholder name="ProgressBarView"  position="bot"/>
+    <toolitem action="ToolbarCancel" position="bot"/>
+  </toolbar>
+
+  <popup name="HeaderViewCSM">
+    <menuitem action="HeaderViewCSMReply"/>
+    <menuitem action="HeaderViewCSMReplyAll"/>
+    <menuitem action="HeaderViewCSMForward"/>
+    <menuitem action="HeaderViewCSMCancelSending"/>
+<!--     <separator/> -->
+<!--     <menuitem action="HeaderViewCSMCut"/> -->
+<!--     <menuitem action="HeaderViewCSMCopy"/> -->
+<!--     <menuitem action="HeaderViewCSMPaste"/> -->
+    <separator/>
+    <menuitem action="HeaderViewCSMDelete"/>
+    <menuitem action="HeaderViewCSMHelp"/>
+  </popup>
+
+  <popup name="FolderViewCSM">
+    <menuitem action="FolderViewCSMNewFolder"/>
+    <menuitem action="FolderViewCSMRenameFolder"/>
+    <menuitem action="FolderViewCSMDeleteFolder"/>
+    <separator/>
+<!--    <menuitem action="FolderViewCSMPasteMsgs"/> -->
+    <separator/>
+    <separator/>
+    <menuitem action="FolderViewCSMSearchMessages"/>
+    <menuitem action="FolderViewCSMHelp"/>
+  </popup>
+
+  <popup name="ToolbarReplyCSM" action="ToolbarCSM">
+    <menuitem action="ToolbarMessageForward"/>
+    <menuitem action="ToolbarMessageReplyAll"/>
+<!--   <menuitem action="ToolbarMessageReply"/> -->
+  </popup>
+
+  <accelerator name="AccelZoomMinus" action="ZoomMinus"/>
+  <accelerator name="AccelZoomPlus" action="ZoomPlus"/>
+  <accelerator name="AccelToggleFullscreen" action="ToggleFullscreen"/>
+</ui>
diff --git a/src/hildon2/ui/modest-msg-edit-window-ui.xml b/src/hildon2/ui/modest-msg-edit-window-ui.xml
new file mode 100644 (file)
index 0000000..1386fba
--- /dev/null
@@ -0,0 +1,123 @@
+<!--
+ * Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<ui>
+
+  <menubar name="MenuBar">
+
+    <menu name="EmailMenu" action="Email">
+      <menuitem name="SendMenu" action="ActionsSend"/>
+      <menuitem name="SaveToDraftsMenu" action="ActionsSaveToDrafts"/>
+      <separator/>
+      <menuitem name="SelectContactsMenu" action="SelectContacts"/>
+      <menuitem name="CheckNamesMenu" action="CheckNames"/>
+      <separator/>
+      <menuitem name="NewMessageMenu" action="ActionsNewMessage"/>
+    </menu>
+
+    <menu name="EditMenu" action="Edit">
+      <menuitem name="UndoMenu" action="Undo"/>
+      <menuitem name="RedoMenu" action="Redo"/>
+      <separator/>
+      <menuitem name="CutMenu" action="Cut"/>
+      <menuitem name="CopyMenu" action="Copy"/>
+      <menuitem name="PasteMenu" action="Paste"/>
+      <separator/>
+      <menuitem name="SelectAllMenu" action="SelectAll"/>
+    </menu>
+
+    <menu name="ViewMenu" action="View">
+      <menuitem name="ViewToggleFullscreenMenu" action="ViewToggleFullscreen"/>
+      <separator/>
+      <menu name="ShowToolbarMenu" action="ShowToolbar">
+       <menuitem name="ViewShowToolbarNormalScreenMenu" action="ViewShowToolbarNormalScreen"/>
+       <menuitem name="ViewShowToolbarFullScreenMenu" action="ViewShowToolbarFullScreen"/>
+      </menu>
+      <separator/>
+      <menuitem name="ViewCcFieldMenu" action="ViewCcField"/>
+      <menuitem name="ViewBccFieldMenu" action="ViewBccField"/>
+    </menu>
+
+    <menu name="FormatMenu" action="Format">
+      <menuitem name="SelectFontMenu" action="SelectFont"/>
+<!--      <menuitem name="BulletedListMenu" action="ActionsBulletedList"/> -->
+      <menu name="AlignmentMenu" action="Alignment">
+         <menuitem name="AlignmentLeftMenu" action="AlignmentLeft"/>
+         <menuitem name="AlignmentCenterMenu" action="AlignmentCenter"/>
+         <menuitem name="AlignmentRightMenu" action="AlignmentRight"/>
+      </menu>
+      <separator/>
+      <menu name="FileFormatMenu" action="FileFormat">
+       <menuitem name="FileFormatPlainTextMenu" action="FileFormatPlainText"/>
+       <menuitem name="FileFormatFormattedTextMenu" action="FileFormatFormattedText"/>
+      </menu>
+    </menu>
+
+    <menu name="AttachmentsMenu" action="Attachments">
+      <menuitem name="AttachFileMenu" action="AttachFile"/>
+      <menuitem name="InsertImageMenu" action="InsertImage"/>
+      <separator/>
+      <menuitem name="RemoveAttachmentsMenu" action="RemoveAttachments"/>
+    </menu>
+
+    <menu name="ToolsMenu" action="Tools">
+      <menu name="MessagePriorityMenu" action="MessagePriority">
+       <menuitem name="MessagePriorityHighMenu" action="MessagePriorityHigh"/>
+       <menuitem name="MessagePriorityNormalMenu" action="MessagePriorityNormal"/>
+       <menuitem name="MessagePriorityLowMenu" action="MessagePriorityLow"/>
+      </menu>
+      <separator/>
+      <menuitem name="FindInMessageMenu" action="FindInMessage"/>
+      <menuitem name="ToolSearchMessagesMenu" action="SearchMessages"/>
+      <separator/>
+      <menuitem name="ToolsHelpMenu" action="Help"/>
+    </menu>
+
+    <menu name="CloseMenu" action="Close">
+      <menuitem name="CloseWindowMenu" action="CloseWindow"/>
+      <menuitem name="CloseAllWindowsMenu" action="CloseAllWindows"/>
+    </menu>
+  </menubar>
+
+  <toolbar name="ToolBar">
+    <toolitem action="ToolbarSend"/>
+    <separator/>
+    <placeholder name="FontAttributes" />
+    <toolitem action="ActionsBold"/>
+    <toolitem action="ActionsItalics"/>
+    <placeholder name="FontColor" />
+  </toolbar>
+
+  <accelerator name="AccelZoomMinus" action="ZoomMinus"/>
+  <accelerator name="AccelZoomPlus" action="ZoomPlus"/>
+  <accelerator name="AccelToggleFullscreen" action="ToggleFullscreen"/>
+  <accelerator name="AccelCloseWindow" action="CloseWindowShortcut"/>
+
+</ui>
diff --git a/src/hildon2/ui/modest-msg-view-window-ui.xml b/src/hildon2/ui/modest-msg-view-window-ui.xml
new file mode 100644 (file)
index 0000000..244140e
--- /dev/null
@@ -0,0 +1,119 @@
+<!--
+ * Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<ui>
+
+  <menubar name="MenuBar">
+    <menu name="MessageMenu" action="Email">
+      <menuitem name="MessageReplyMenu" action="EmailReply"/>
+      <menuitem name="MessageReplyAllMenu" action="EmailReplyAll"/>
+      <menuitem name="MessageForwardMenu" action="EmailForward"/>
+      <separator/>
+      <menuitem name="MessageNewMenu"  action="EmailNewDefault"/>
+      <separator/>
+      <menuitem name="MessageDeleteMenu" action="EmailDelete"/>
+      <separator/>
+      <menuitem name="MessageDetailsMenu"      action="EmailDetails"/>
+    </menu>
+       
+    <menu name="EditMenu" action="Edit">
+      <menuitem name="EditCutMenu" action="EditCut"/>
+      <menuitem name="EditCopyMenu" action="EditCopy"/>
+      <menuitem name="EditPasteMenu" action="EditPaste"/>
+      <separator/>
+      <menuitem name="EditSelectAllMenu" action="EditSelectAll"/>
+      <separator/>
+      <menuitem name="EditMoveToMenu" action="EditMoveTo"/>
+    </menu> 
+    <menu name="ViewMenu" action="View">
+      <menu name="ZoomMenu" action="Zoom">
+       <menuitem name="Zoom50Menu" action="Zoom50"/>
+       <menuitem name="Zoom80Menu" action="Zoom80"/>
+       <menuitem name="Zoom100Menu" action="Zoom100"/>
+       <menuitem name="Zoom120Menu" action="Zoom120"/>
+       <menuitem name="Zoom150Menu" action="Zoom150"/>
+       <menuitem name="Zoom200Menu" action="Zoom200"/>
+      </menu>
+      <separator/>
+      <menuitem name="ViewToggleFullscreenMenu" action="ViewToggleFullscreen"/>
+      <separator/>
+      <menu name="ViewShowToolbarMenu" action="ViewShowToolbar">
+       <menuitem name="ViewShowToolbarNormalScreenMenu" action="ViewShowToolbarNormalScreen"/>
+       <menuitem name="ViewShowToolbarFullScreenMenu" action="ViewShowToolbarFullScreen"/>
+      </menu>
+      <separator/>
+      <menuitem name="ViewPreviousMessageMenu" action="ViewPreviousMessage"/>
+      <menuitem name="ViewNextMessageMenu" action="ViewNextMessage"/>
+    </menu>
+
+    <menu name="AttachmentsMenu" action="Attachments">
+      <menuitem name="ViewAttachmentMenu" action="ViewAttachment"/>
+      <menuitem name="SaveAttachmentMenu" action="SaveAttachment"/>
+      <menuitem name="RemoveAttachmentMenu" action="RemoveAttachment"/>
+    </menu>
+
+   <menu name="ToolsMenu" action="Tools">
+      <menuitem name="ToolsAddToContactsMenu" action="ToolsAddToContacts"/>
+      <separator/>
+      <menuitem name="ToolsFindInMessageMenu" action="ToolsFindInMessage"/>
+      <menuitem name="ToolsSearchMessagesMenu" action="ToolsSearchMessages"/>
+      <separator/>
+      <menuitem name="ToolsHelpMenu" action="ToolsHelp"/>
+   </menu>
+
+   <menu name="CloseMenu" action="Close">
+      <menuitem name="CloseWindowMenu"     action="CloseWindow"/>
+      <menuitem name="CloseAllWindowsMenu"     action="CloseAllWindows"/>
+    </menu>
+  </menubar>
+
+  <toolbar name="ToolBar">
+    <toolitem action="ToolbarMessageReply"/> 
+    <toolitem action="ToolbarMessageMoveTo"/>
+    <toolitem action="ToolbarDeleteMessage"/>
+    <toolitem action="FindInMessage"/>
+    <toolitem action="ToolbarMessageBack" position="bot"/>
+    <toolitem action="ToolbarMessageNext" position="bot"/>
+    <placeholder name="ProgressbarView" position="bot">
+    </placeholder>
+    <toolitem action="ToolbarCancel" position="bot"/>
+  </toolbar>
+
+  <popup name="ToolbarReplyCSM">
+      <menuitem name="MessageReplyAllMenu" action="EmailReplyAll"/>
+      <menuitem name="MessageForwardMenu" action="EmailForward"/>
+  </popup>
+
+  <accelerator name="AccelZoomMinus" action="ZoomMinus"/>
+  <accelerator name="AccelZoomPlus" action="ZoomPlus"/>
+  <accelerator name="AccelToggleFullscreen" action="ToggleFullscreen"/>
+
+  </ui>
index 2239f56..ef2b24c 100644 (file)
 #include "modest-text-utils.h"
 
 #ifdef MODEST_HAVE_EASYSETUP
+#ifdef MODEST_TOOLKIT_HILDON2
+#include "modest-easysetup-wizard-dialog.h"
+#else
 #include "easysetup/modest-easysetup-wizard-dialog.h"
+#endif
 #endif /* MODEST_HAVE_EASYSETUP */
 
 #include <modest-widget-memory.h>
index ccdef8f..a4d31d1 100644 (file)
@@ -9,7 +9,7 @@ INCLUDES=\
        $(MODEST_HILDON_HELP_CFLAGS)    \
        $(MODEST_MOZEMBED_CFLAGS) \
        $(MODEST_HILDON_NOTIFY_CFLAGS) \
-       -I ${top_srcdir}/src/$(MODEST_PLATFORM) \
+       -I ${top_srcdir}/src/$(MODEST_TOOLKIT_DIR) \
        -I ${top_srcdir}/src \
        -DPREFIX=\"@prefix@\" \
        -DPIXMAP_PREFIX=\"${datadir}/pixmaps/modest/\" \
index fec105b..c9f6ffe 100644 (file)
@@ -30,7 +30,7 @@ INCLUDES=\
        $(MODEST_GSTUFF_CFLAGS)\
        $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \
        $(MODEST_LIBTINYMAIL_MAEMO_CFLAGS) \
-       -I$(MODEST_PLATFORM) \
+       -I$(MODEST_TOOLKIT_DIR) \
        -I${top_srcdir}/src \
        -DPREFIX=\"@prefix@\" \
        -DMODESTLOCALEDIR=\""$(modestlocaledir)"\"
@@ -39,7 +39,7 @@ objects=\
        $(MODEST_GSTUFF_LIBS) \
         $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_LIBS) \
         $(MODEST_LIBTINYMAIL_MAEMO_LIBS) \
-        ${top_srcdir}/src/$(MODEST_PLATFORM)/libmodest-ui.la \
+        ${top_srcdir}/src/$(MODEST_TOOLKIT_DIR)/libmodest-ui.la \
         ${top_srcdir}/src/widgets/libmodest-widgets.la \
         ${top_srcdir}/src/dbus_api/libmodest-dbus-api.la \
        ${top_srcdir}/src/modest-runtime.o \
index 01fa744..bc1dd67 100644 (file)
@@ -3,7 +3,7 @@ INCLUDES=\
        $(MODEST_GSTUFF_CFLAGS)\
        $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \
        $(MODEST_LIBTINYMAIL_MAEMO_CFLAGS) \
-       -I$(MODEST_PLATFORM) \
+       -I$(MODEST_TOOLKIT_DIR) \
        -I${top_srcdir}/src \
        -I$(top_srcdir) \
        -DPREFIX=\"@prefix@\" \