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
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
# 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
#
src/gnome/Makefile
src/maemo/Makefile
src/maemo/easysetup/Makefile
+src/hildon2/Makefile
src/widgets/Makefile
docs/Makefile
docs/reference/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
])
$(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)\" \
# 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) \
$(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\"
$(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
--- /dev/null
+# 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)
--- /dev/null
+[D-BUS Service]
+Name=com.nokia.modest
+Exec=@prefix@/bin/modest
--- /dev/null
+# 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
+
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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));
+ }
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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, ¤t_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 */
+}
+
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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 */
--- /dev/null
+
+/* 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", ¬ebook, 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", ¬ebook, 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", ¬ebook, 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", ¬ebook, 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", ¬ebook, 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", ¬ebook, 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);
+}
+
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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__*/
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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__*/
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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__ */
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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__ */
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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__*/
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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;
+}
--- /dev/null
+#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__ */
--- /dev/null
+/* 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", ¤t_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;
+}
+
--- /dev/null
+#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__ */
--- /dev/null
+/* 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", ¤t_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;;
+}
--- /dev/null
+/* 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)
+{
+
+}
+
+
+
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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 ());
+}
+
+
+
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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", ¬if_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;
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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__*/
+
+
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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 */
--- /dev/null
+<backup-configuration>
+ <locations>
+ <location type="dir" category="emails">/home/user/.modest</location>
+ </locations>
+</backup-configuration>
--- /dev/null
+[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
--- /dev/null
+<!--
+ * 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>
--- /dev/null
+<!--
+ * 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>
--- /dev/null
+<!--
+ * 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>
#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>
$(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/\" \
$(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)"\"
$(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 \
$(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@\" \