From 75d57ee139fed063e6fd7b0957963c1015267bc1 Mon Sep 17 00:00:00 2001 From: Murray Cumming Date: Tue, 3 Apr 2007 13:36:38 +0000 Subject: [PATCH] Added files from osso-modest-easysetup pmo-trunk-r1487 --- src/maemo/easysetup/Makefile.am | 30 + src/maemo/easysetup/localisation.h | 63 + src/maemo/easysetup/main.c | 64 ++ src/maemo/easysetup/mcc_mapping | 230 ++++ src/maemo/easysetup/mcc_mapping.en_GB | 107 ++ .../easysetup/modest-easysetup-country-combo-box.c | 304 +++++ .../easysetup/modest-easysetup-country-combo-box.h | 52 + .../modest-easysetup-provider-combo-box.c | 189 +++ .../modest-easysetup-provider-combo-box.h | 54 + .../modest-easysetup-secureauth-combo-box.c | 218 ++++ .../modest-easysetup-secureauth-combo-box.h | 55 + .../modest-easysetup-serversecurity-combo-box.c | 226 ++++ .../modest-easysetup-serversecurity-combo-box.h | 57 + .../modest-easysetup-servertype-combo-box.c | 211 ++++ .../modest-easysetup-servertype-combo-box.h | 55 + src/maemo/easysetup/modest-easysetup-wizard.c | 1201 ++++++++++++++++++++ src/maemo/easysetup/modest-easysetup-wizard.h | 92 ++ src/maemo/easysetup/modest-presets.c | 319 ++++++ src/maemo/easysetup/modest-presets.h | 159 +++ src/maemo/easysetup/modest-text-utils.c | 923 +++++++++++++++ src/maemo/easysetup/modest-text-utils.h | 253 +++++ src/maemo/easysetup/modest-validating-entry.c | 205 ++++ src/maemo/easysetup/modest-validating-entry.h | 52 + src/maemo/easysetup/modest-wizard-dialog.c | 536 +++++++++ src/maemo/easysetup/modest-wizard-dialog.h | 85 ++ src/maemo/easysetup/osso_countries_1.0.mo | Bin 0 -> 13730 bytes src/maemo/easysetup/osso_countries_1.0.po | 906 +++++++++++++++ src/maemo/easysetup/provider-data-test.keyfile | 41 + 28 files changed, 6687 insertions(+) create mode 100644 src/maemo/easysetup/Makefile.am create mode 100644 src/maemo/easysetup/localisation.h create mode 100644 src/maemo/easysetup/main.c create mode 100644 src/maemo/easysetup/mcc_mapping create mode 100644 src/maemo/easysetup/mcc_mapping.en_GB create mode 100644 src/maemo/easysetup/modest-easysetup-country-combo-box.c create mode 100644 src/maemo/easysetup/modest-easysetup-country-combo-box.h create mode 100644 src/maemo/easysetup/modest-easysetup-provider-combo-box.c create mode 100644 src/maemo/easysetup/modest-easysetup-provider-combo-box.h create mode 100644 src/maemo/easysetup/modest-easysetup-secureauth-combo-box.c create mode 100644 src/maemo/easysetup/modest-easysetup-secureauth-combo-box.h create mode 100644 src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.c create mode 100644 src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.h create mode 100644 src/maemo/easysetup/modest-easysetup-servertype-combo-box.c create mode 100644 src/maemo/easysetup/modest-easysetup-servertype-combo-box.h create mode 100644 src/maemo/easysetup/modest-easysetup-wizard.c create mode 100644 src/maemo/easysetup/modest-easysetup-wizard.h create mode 100644 src/maemo/easysetup/modest-presets.c create mode 100644 src/maemo/easysetup/modest-presets.h create mode 100644 src/maemo/easysetup/modest-text-utils.c create mode 100644 src/maemo/easysetup/modest-text-utils.h create mode 100644 src/maemo/easysetup/modest-validating-entry.c create mode 100644 src/maemo/easysetup/modest-validating-entry.h create mode 100644 src/maemo/easysetup/modest-wizard-dialog.c create mode 100644 src/maemo/easysetup/modest-wizard-dialog.h create mode 100644 src/maemo/easysetup/osso_countries_1.0.mo create mode 100644 src/maemo/easysetup/osso_countries_1.0.po create mode 100644 src/maemo/easysetup/provider-data-test.keyfile diff --git a/src/maemo/easysetup/Makefile.am b/src/maemo/easysetup/Makefile.am new file mode 100644 index 0000000..a79c6a1 --- /dev/null +++ b/src/maemo/easysetup/Makefile.am @@ -0,0 +1,30 @@ +SUBDIRS=modest-account-mgr +DIST_SUBDIRS= + +INCLUDES=\ + $(MODEST_GSTUFF_CFLAGS)\ + -DPREFIX=\"@prefix@\" \ + -DOSSO_MODEST_EASYSETUP_LOCALEDIR=\"$(OSSO_MODEST_EASYSETUP_LOCALEDIR)\" \ + -I$(srcdir)/modest-account-mgr + + +bin_PROGRAMS=\ + osso-modest-easysetup + +osso_modest_easysetup_SOURCES=\ + main.c \ + modest-wizard-dialog.h modest-wizard-dialog.c \ + modest-presets.h modest-presets.c \ + modest-easysetup-wizard.h modest-easysetup-wizard.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-easysetup-serversecurity-combo-box.h modest-easysetup-serversecurity-combo-box.c \ + modest-easysetup-secureauth-combo-box.h modest-easysetup-secureauth-combo-box.c \ + modest-validating-entry.h modest-validating-entry.c \ + modest-text-utils.h modest-text-utils.c + +osso_modest_easysetup_LDADD = \ + $(MODEST_GSTUFF_LIBS) \ + modest-account-mgr/libmodestaccountmgr.a + diff --git a/src/maemo/easysetup/localisation.h b/src/maemo/easysetup/localisation.h new file mode 100644 index 0000000..efdf636 --- /dev/null +++ b/src/maemo/easysetup/localisation.h @@ -0,0 +1,63 @@ +#ifndef LOCALISATION_H +#define LOCALISATION_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef ENABLE_NLS +#include +#define _(String) gettext(String) +#ifdef gettext_noop +#define N_(String) gettext_noop(String) +#else +#define N_(String) (String) +#endif +#define locale_init() setlocale(LC_ALL, "");\ + bindtextdomain(GETTEXT_PACKAGE, localedir);\ + textdomain(GETTEXT_PACKAGE); +#else /* NLS is disabled */ +#define locale_init() +#define _(String) (String) +#define N_(String) (String) +#define textdomain(String) (String) +#define gettext(String) (String) +#define dgettext(Domain,String) (String) +#define dcgettext(Domain,String,Type) (String) +#define bindtextdomain(Domain,Directory) (Domain) +#define bind_textdomain_codeset(Domain,Codeset) (Codeset) +#endif /* ENABLE_NLS */ + +#endif /* LOCALISATION_H */ +#ifndef LOCALISATION_H +#define LOCALISATION_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef ENABLE_NLS +#include +#define _(String) gettext(String) +#ifdef gettext_noop +#define N_(String) gettext_noop(String) +#else +#define N_(String) (String) +#endif +#define locale_init() setlocale(LC_ALL, "");\ + bindtextdomain(GETTEXT_PACKAGE, localedir);\ + textdomain(GETTEXT_PACKAGE); +#else /* NLS is disabled */ +#define locale_init() +#define _(String) (String) +#define N_(String) (String) +#define textdomain(String) (String) +#define gettext(String) (String) +#define dgettext(Domain,String) (String) +#define dcgettext(Domain,String,Type) (String) +#define bindtextdomain(Domain,Directory) (Domain) +#define bind_textdomain_codeset(Domain,Codeset) (Codeset) +#endif /* ENABLE_NLS */ + +#endif /* LOCALISATION_H */ + diff --git a/src/maemo/easysetup/main.c b/src/maemo/easysetup/main.c new file mode 100644 index 0000000..3cd0d74 --- /dev/null +++ b/src/maemo/easysetup/main.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#include /* For GETTEXT_PACKAGE, etc */ + +#include +#include +#include +#include +#include "modest-easysetup-wizard.h" + +/* Copied from modest-main.c: */ +typedef enum { + MODEST_ERR_NONE = 0, /* no error */ + MODEST_ERR_OPTIONS = 1, /* error in the options */ + MODEST_ERR_CONF = 2, /* error getting confuration db */ + MODEST_ERR_UI = 3, /* error in the UI */ + MODEST_ERR_HILDON = 4, /* error with Hildon (maemo-only) */ + MODEST_ERR_RUN = 5, /* error running */ + MODEST_ERR_PARAM = 7, /* error in one or more of the parameters */ + MODEST_ERR_INIT = 8 /* error in initialization */ +} ModestErrorCode; + +static gboolean modest_easysetup_init(int argc, char *argv[]) +{ + /* Setup gettext, to use our .po files: */ + /* GETTEXT_PACKAGE is defined in config.h */ + /* OSSO_MODEST_EASYSETUP_LOCALEDIR is defined in the Makefile.am */ + bindtextdomain (GETTEXT_PACKAGE, OSSO_MODEST_EASYSETUP_LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + if (!gtk_init_check(&argc, &argv)) { + g_printerr ("osso-modest-easysetup: failed to initialize GTK+\n"); + return FALSE; + } + + return TRUE; +} + +static gboolean modest_easysetup_uninit() +{ + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + if (!modest_easysetup_init (argc, argv)) { + g_printerr ("osso-modest-easysetup: cannot init runtime\n"); + return MODEST_ERR_INIT; + } + + ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new (); + gtk_dialog_run (GTK_DIALOG (wizard)); + + if (!modest_easysetup_uninit ()) + g_printerr ("osso-modest-easysetup: shutdown failed\n"); + + return MODEST_ERR_NONE; +} + diff --git a/src/maemo/easysetup/mcc_mapping b/src/maemo/easysetup/mcc_mapping new file mode 100644 index 0000000..6b984d1 --- /dev/null +++ b/src/maemo/easysetup/mcc_mapping @@ -0,0 +1,230 @@ +412 osso_db_country_afghanistan +276 osso_db_country_albania +603 osso_db_country_algeria +544 osso_db_country_american_samoa +213 osso_db_country_andorra +631 osso_db_country_angola +365 osso_db_country_anguilla +344 osso_db_country_antigua_and_barbuda +722 osso_db_country_argentina +283 osso_db_country_armenia +363 osso_db_country_aruba +505 osso_db_country_australia +232 osso_db_country_austria +400 osso_db_country_azerbaijani_republic +364 osso_db_country_bahamas +426 osso_db_country_bahrain +470 osso_db_country_bangladesh +342 osso_db_country_barbados +257 osso_db_country_belarus +206 osso_db_country_belgium +702 osso_db_country_belize +616 osso_db_country_benin +350 osso_db_country_bermuda +402 osso_db_country_bhutan +736 osso_db_country_bolivia +218 osso_db_country_bosnia_and_herzegovina +652 osso_db_country_botswana +724 osso_db_country_brazil +348 osso_db_country_british_virgin_islands +528 osso_db_country_brunei_darussalam +284 osso_db_country_bulgaria +613 osso_db_country_burkina_faso +642 osso_db_country_burundi +456 osso_db_country_cambodia +624 osso_db_country_cameroon +302 osso_db_country_canada +625 osso_db_country_cape_verde +346 osso_db_country_cayman_islands +623 osso_db_country_central_african_republic +622 osso_db_country_chad +730 osso_db_country_chile +461 osso_db_country_china +460 osso_db_country_china +732 osso_db_country_colombia +654 osso_db_country_comoros +629 osso_db_country_republic_of_the_congo +548 osso_db_country_cook_islands +712 osso_db_country_costa_rica +612 osso_db_country_cote_dlvoire +219 osso_db_country_croatia +368 osso_db_country_cuba +280 osso_db_country_cyprus +230 osso_db_country_czech_republic +630 osso_db_country_democratic_republic_of_the_congo +238 osso_db_country_denmark +638 osso_db_country_djibouti +366 osso_db_country_dominica +370 osso_db_country_dominican_republic +514 osso_db_country_east_timor +740 osso_db_country_ecuador +602 osso_db_country_egypt +706 osso_db_country_el_salvador +627 osso_db_country_equatorial_guinea +657 osso_db_country_eritrea +248 osso_db_country_estonia +636 osso_db_country_ethiopia +288 osso_db_country_faroe_islands +542 osso_db_country_fiji +244 osso_db_country_finland +208 osso_db_country_france +742 osso_db_country_french_guiana +547 osso_db_country_french_polynesia +628 osso_db_country_gobonese_republic +607 osso_db_country_gambia +282 osso_db_country_georgia +262 osso_db_country_germany +620 osso_db_country_ghana +266 osso_db_country_gibraltar +202 osso_db_country_greece +290 osso_db_country_greenland +352 osso_db_country_grenada +340 osso_db_country_guadeloupe +535 osso_db_country_guam +704 osso_db_country_guatemala +611 osso_db_country_guinea +632 osso_db_country_guinea_bissaus +738 osso_db_country_guyana +372 osso_db_country_haiti +708 osso_db_country_honduras +454 osso_db_country_hong_kong +216 osso_db_country_hungary +274 osso_db_country_iceland +404 osso_db_country_india +510 osso_db_country_indonesia +432 osso_db_country_iran +418 osso_db_country_iraq +272 osso_db_country_republic_of_ireland +425 osso_db_country_israel +222 osso_db_country_italy +338 osso_db_country_jamaica +441 osso_db_country_japan +440 osso_db_country_japan +416 osso_db_country_jordan +401 osso_db_country_kazakhstan +639 osso_db_country_kenya +545 osso_db_country_kiribati +467 osso_db_country_korea_north +450 osso_db_country_country_south_korea +419 osso_db_country_kuwait +437 osso_db_country_kyrgyz_republic +457 osso_db_country_laos +247 osso_db_country_latvia +415 osso_db_country_lebanon +651 osso_db_country_lesotho +618 osso_db_country_liberia +606 osso_db_country_libya +295 osso_db_country_liechtenstein +246 osso_db_country_lithuania +270 osso_db_country_luxembourg +455 osso_db_country_macao +294 osso_db_country_the_former_yugoslav_republic_of_macedonia +646 osso_db_country_madagascar +650 osso_db_country_malawi +502 osso_db_country_malaysia +472 osso_db_country_maldives +610 osso_db_country_mali +278 osso_db_country_malta +551 osso_db_country_marshall_islands +340 osso_db_country_martinique +609 osso_db_country_mauritania +617 osso_db_country_mauritius +334 osso_db_country_mexico +550 osso_db_country_micronesia +259 osso_db_country_republic_of_moldova +212 osso_db_country_monaco +428 osso_db_country_mongolia +354 osso_db_country_montserrat +604 osso_db_country_morocco +643 osso_db_country_mozambique +414 osso_db_country_myanmar +649 osso_db_country_namibia +536 osso_db_country_nauru +429 osso_db_country_nepal +204 osso_db_country_netherlands +362 osso_db_country_netherlands_antilles +546 osso_db_country_new_caledonia +530 osso_db_country_new_zealand +710 osso_db_country_nicaraqua +614 osso_db_country_niger +621 osso_db_country_nigeria +534 osso_db_country_northern_mariana_islands +242 osso_db_country_norway +422 osso_db_country_oman +410 osso_db_country_pakistan +552 osso_db_country_palau +714 osso_db_country_panama +537 osso_db_country_papua_new_guinea +744 osso_db_country_paraquay +716 osso_db_country_peru +515 osso_db_country_philippines +260 osso_db_country_poland +268 osso_db_country_portugal +330 osso_db_country_puerto_rico +427 osso_db_country_qatar +647 osso_db_country_reunion +226 osso_db_country_romania +250 osso_db_country_russian_federation +635 osso_db_country_rwandese_republic +356 osso_db_country_saint_kitts_and_nevis +358 osso_db_country_saint_lucia +308 osso_db_country_saint_pierre_and_miquelon +360 osso_db_country_saint_vincent_and_grenadines +549 osso_db_country_samoa +292 osso_db_country_san_marino +626 osso_db_country_sao_tome_and_principe +420 osso_db_country_saudi_arabia +608 osso_db_country_senegal +220 osso_db_country_serbia_and_montenegro +633 osso_db_country_seychelles +619 osso_db_country_sierra_leone +525 osso_db_country_singapore +231 osso_db_country_slovakia +293 osso_db_country_slovenia +540 osso_db_country_solomon_islands +637 osso_db_country_somalia +655 osso_db_country_south_africa +214 osso_db_country_spain +413 osso_db_country_sri_lanka +634 osso_db_country_sudan +746 osso_db_country_suriname +653 osso_db_country_swaziland +240 osso_db_country_sweden +228 osso_db_country_switzerland +417 osso_db_country_syrian_arab_republic +466 osso_db_country_taiwan +436 osso_db_country_tajikistan +640 osso_db_country_united_republic_of_tanzania +520 osso_db_country_thailand +615 osso_db_country_togolese_republic +539 osso_db_country_tonga +374 osso_db_country_trinidad_and_tobago +605 osso_db_country_tunisia +286 osso_db_country_turkey +438 osso_db_country_turkmenistan +376 osso_db_country_turks_and_caicos_islands +641 osso_db_country_uganda +255 osso_db_country_ukraine +424 osso_db_country_united_arab_emirates +430 osso_db_country_united_arab_emirates_abu_dhabi +431 osso_db_country_united_arab_emirates_dubai +235 osso_db_country_united_kingdom_of_great_britain_and_northern_ireland +234 osso_db_country_united_kingdom_of_great_britain_and_northern_ireland +310 osso_db_country_united_states_of_america +316 osso_db_country_united_states_of_america +311 osso_db_country_united_states_of_america +312 osso_db_country_united_states_of_america +313 osso_db_country_united_states_of_america +314 osso_db_country_united_states_of_america +315 osso_db_country_united_states_of_america +332 osso_db_country_unites_states_virgin_islands +748 osso_db_country_uruguay +434 osso_db_country_uzbekistan +541 osso_db_country_vanuatu +225 osso_db_country_the_vatican +734 osso_db_country_venezuela +452 osso_db_country_viet_nam +543 osso_db_country_wallis_and_futuna +421 osso_db_country_yemen +645 osso_db_country_zambia +648 osso_db_country_zimbabwe diff --git a/src/maemo/easysetup/mcc_mapping.en_GB b/src/maemo/easysetup/mcc_mapping.en_GB new file mode 100644 index 0000000..491e504 --- /dev/null +++ b/src/maemo/easysetup/mcc_mapping.en_GB @@ -0,0 +1,107 @@ +276 Albania +213 Andorra +722 Argentina +363 Aruba +505 Australia +232 Austria +400 Azerbaijan +426 Bahrain +470 Bangladesh +257 Belarus +206 Belgium +736 Bolivia +218 Bosnia and Herzegovina +652 Botswana +724 Brazil +528 Brunei Darussalam +284 Bulgaria +456 Cambodia +302 Canada +730 Chile +460 China +732 Colombia +219 Croatia +280 Cyprus +230 Czech Republic +238 Denmark +370 Dominican Republic +740 Ecuador +602 Egypt +706 El Salvador +248 Estonia +244 Finland +208 France +282 Georgia +262 Germany +620 Ghana +266 Gibraltar +202 Greece +340 Guadeloupe +704 Guatemala +708 Honduras +454 Hong Kong, China +216 Hungary +274 Iceland +404 India +510 Indonesia +272 Ireland +425 Israel +222 Italy +338 Jamaica +440 Japan +416 Jordan +401 Kazakhstan +639 Kenya +419 Kuwait +247 Latvia +415 Lebanon +295 Liechtenstein +246 Lithuania +270 Luxembourg +455 Macao, China +294 Macedonia +502 Malaysia +472 Maldives +278 Malta +340 Martinique +334 Mexico +259 Moldova +212 Monaco +428 Mongolia +220 Montenegro +604 Morocco +204 Netherlands +530 New Zealand +621 Nigeria +242 Norway +422 Oman +410 Pakistan +714 Panama +744 Paraguay +716 Peru +515 Philippines +260 Poland +268 Portugal +427 Qatar +226 Romania +250 Russian Federation +420 Saudi Arabia +220 Serbia +525 Singapore +231 Slovakia +293 Slovenia +655 South Africa +214 Spain +413 Sri Lanka +240 Sweden +228 Switzerland +417 Syria +466 Taiwan +520 Thailand +374 Trinidad and Tobago +286 Turkey +255 Ukraine +234 United Kingdom +748 Uruguay +310 USA +734 Venezuela diff --git a/src/maemo/easysetup/modest-easysetup-country-combo-box.c b/src/maemo/easysetup/modest-easysetup-country-combo-box.c new file mode 100644 index 0000000..7eed707 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-country-combo-box.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */ +#include + +#include "modest-easysetup-country-combo-box.h" +#include +#include +#include + +#include +#include /* For memcpy() */ + +#include /* For dgettext(). */ + +G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, GTK_TYPE_COMBO_BOX); + +#define COUNTRY_COMBO_BOX_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxPrivate)) + +typedef struct _EasysetupCountryComboBoxPrivate EasysetupCountryComboBoxPrivate; + +struct _EasysetupCountryComboBoxPrivate +{ + GtkTreeModel *model; +}; + +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); +} + +static void +easysetup_country_combo_box_finalize (GObject *object) +{ + EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (object); + + g_object_unref (G_OBJECT (priv->model)); + + 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 (EasysetupCountryComboBoxPrivate)); + + 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; +} + +enum MODEL_COLS { + MODEL_COL_NAME = 0, + MODEL_COL_ID = 1 +}; + +/** id and country must be freed. + */ +static void parse_mcc_mapping_line (const char* line, char** id, char** country) +{ + /* Initialize output parameters: */ + *id = NULL; + *country = NULL; + + g_assert(line); + + const gboolean is_valid_utf8 = g_utf8_validate (line, -1, NULL); + if(!is_valid_utf8) { + g_warning("UTF8 validation failed."); + return; + } + + /* Look at each character, to find the whitespace between the ID and name: */ + char* result_id = NULL; + char* result_country = NULL; + + const char* p = line; + const char* p_start_of_country = NULL; + while (p && *p) + { + p = g_utf8_next_char(p); + gunichar ch = g_utf8_get_char(p); + if (g_unichar_isspace(ch)) { /* Note: This checks for any whitespace, not just space. */ + if(!result_id) { + /* The text before this must be the ID: */ + const int length = p - line; + result_id = g_malloc (length + 1); /* 1 for null-termination. */ + memcpy(result_id, line, length); + result_id[length] = 0; /* Null-termination. */ + } + else if(p_start_of_country) + { + /* This whitespace is probably the newline after the country. */ + + /* The text after the whitespace, after the ID, must be the country: */ + int length = p - p_start_of_country; + result_country = g_malloc(length + 1); + memcpy(result_country, p_start_of_country, length); + result_country[length] = 0; /* Null-termination. */ + break; + } + } + else if(result_id && !p_start_of_country) { + p_start_of_country = p; + } + } + + *id = result_id; + *country = result_country; +} + +/** Note that the mcc_mapping file is installed + * by the operator-wizard-settings package. + */ +static void load_from_file (EasysetupCountryComboBox *self) +{ + EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + + /* Load the file one line at a time: */ + FILE *file = fopen("mcc_mapping", "r"); + if (!file) + { + g_warning("Could not open mcc_mapping file.\n"); + return; + } + + GtkListStore *liststore = GTK_LIST_STORE (priv->model); + + /* We use the getline() GNU extension, + * because it reads per line, which simplifies our code, + * and it doesn't require us to hard-code a buffer length. + */ + int len = 0; + char *line = NULL; + while (getline (&line, &len, file) > 0) /* getline will realloc line if necessary. */ + { + /* printf ("DBEUG: len=%d, line: %s\n", len, line); */ + + char *id_str = NULL; + char *country = NULL; + parse_mcc_mapping_line (line, &id_str, &country); + /* printf("DEBUG: parsed: id=%s, country=%s\n", id_str, country); */ + + if(id_str && country) { + guint id = (guint)g_ascii_strtod(id_str, NULL); /* Note that this parses locale-independent text. */ + + /* Get the translation for the country name: + * Note that the osso_countries_1.0 translation domain files are installed + * by the operator-wizard-settings package. */ + const gchar *name_translated = dgettext ("osso_countries_1.0", country); + if(!name_translated) + name_translated = country; + + /* Add the row to the model: */ + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set(liststore, &iter, MODEL_COL_ID, id, MODEL_COL_NAME, name_translated, -1); + } + + g_free (id_str); + g_free (country); + } + + if (line) + free (line); + + fclose (file); +} + +static void +easysetup_country_combo_box_init (EasysetupCountryComboBox *self) +{ + EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + + /* 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. + */ + priv->model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT)); + + /* Setup the combo box: */ + GtkComboBox *combobox = GTK_COMBO_BOX (self); + gtk_combo_box_set_model (combobox, priv->model); + + /* Country 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); + + /* Fill the model with rows: */ + load_from_file (self); +} + +EasysetupCountryComboBox* +easysetup_country_combo_box_new (void) +{ + return g_object_new (EASYSETUP_TYPE_COUNTRY_COMBO_BOX, NULL); +} + +/** + * Returns the MCC number of the selected country, or 0 if no country was selected. + */ +guint +easysetup_country_combo_box_get_active_country_id (EasysetupCountryComboBox *self) +{ + GtkTreeIter active; + const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &active); + if (found) { + EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + + guint id = 0; + gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &id, -1); + return id; + } + + return 0; /* Failed. */ +} + + +/* This allows us to pass more than one piece of data to the signal handler, + * and get a result: */ +typedef struct +{ + EasysetupCountryComboBox* self; + guint mcc_id; + gboolean found; +} ForEachData; + +static gboolean +on_model_foreach_select_id(GtkTreeModel *model, + GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + ForEachData *state = (ForEachData*)(user_data); + + /* Select the item if it has the matching ID: */ + guint id = 0; + gtk_tree_model_get (model, iter, MODEL_COL_ID, &id, -1); + if(id == state->mcc_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 MCC number of the selected country. + * Specify 0 to select no country. + */ +gboolean +easysetup_country_combo_box_set_active_country_id (EasysetupCountryComboBox *self, guint mcc_id) +{ + EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + + /* Create a state instance so we can send two items of data to the signal handler: */ + ForEachData *state = g_new0 (ForEachData, 1); + state->self = self; + state->mcc_id = mcc_id; + 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); + + const gboolean result = state->found; + + /* Free the state instance: */ + g_free(state); + + return result; +} + diff --git a/src/maemo/easysetup/modest-easysetup-country-combo-box.h b/src/maemo/easysetup/modest-easysetup-country-combo-box.h new file mode 100644 index 0000000..410e638 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-country-combo-box.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_COUNTRY_COMBO_BOX +#define _EASYSETUP_COUNTRY_COMBO_BOX + +#include + +G_BEGIN_DECLS + +#define EASYSETUP_TYPE_COUNTRY_COMBO_BOX easysetup_country_combo_box_get_type() + +#define EASYSETUP_COUNTRY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBox)) + +#define EASYSETUP_COUNTRY_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxClass)) + +#define EASYSETUP_IS_COUNTRY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + EASYSETUP_TYPE_COUNTRY_COMBO_BOX)) + +#define EASYSETUP_IS_COUNTRY_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + EASYSETUP_TYPE_COUNTRY_COMBO_BOX)) + +#define EASYSETUP_COUNTRY_COMBO_BOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxClass)) + +typedef struct { + GtkComboBox parent; +} EasysetupCountryComboBox; + +typedef struct { + GtkComboBoxClass parent_class; +} EasysetupCountryComboBoxClass; + +GType easysetup_country_combo_box_get_type (void); + +EasysetupCountryComboBox* easysetup_country_combo_box_new (void); + +guint easysetup_country_combo_box_get_active_country_id (EasysetupCountryComboBox *self); +gboolean easysetup_country_combo_box_set_active_country_id (EasysetupCountryComboBox *self, guint mcc_id); + +G_END_DECLS + +#endif /* _EASYSETUP_COUNTRY_COMBO_BOX */ diff --git a/src/maemo/easysetup/modest-easysetup-provider-combo-box.c b/src/maemo/easysetup/modest-easysetup-provider-combo-box.c new file mode 100644 index 0000000..c68b662 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-provider-combo-box.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */ +#include + +#include "modest-easysetup-provider-combo-box.h" +#include +#include +#include +#include + +#include +#include /* For memcpy() */ + +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_NAME = 0, + MODEL_COL_ID = 1 /* a string, not an int. */ +}; + + + +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"). + * This must match our MODEL_COLS enum constants. + */ + priv->model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING)); + + /* 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); + + /* The application should call easysetup_provider_combo_box_fill() + * to actually add some rows. */ +} + +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 country_id) +{ + EasysetupProviderComboBoxPrivate *priv = PROVIDER_COMBO_BOX_GET_PRIVATE (combobox); + + /* Remove any existing rows: */ + GtkListStore *liststore = GTK_LIST_STORE (priv->model); + gtk_list_store_clear (liststore); + + /* Add the appropriate rows for this country, from the presets file: */ + gchar ** provider_ids = NULL; + gchar ** provider_names = modest_presets_get_providers (presets, country_id, + TRUE /* include_globals */, &provider_ids); + + gchar ** iter_provider_names = provider_names; + gchar ** 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; + if(!provider_name) + continue; + + const gchar* provider_id = *iter_provider_ids; + if(!provider_id) + continue; + + /* 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, -1); + + ++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 "Other" item: */ + /* Note that ID 0 means "Other" for us: */ + /* TODO: We need a Logical ID for this text. */ + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, 0, MODEL_COL_NAME, _("Other..."), -1); + + /* Select the "Other" item: */ + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter); +} + +/** + * 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; + 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. */ +} diff --git a/src/maemo/easysetup/modest-easysetup-provider-combo-box.h b/src/maemo/easysetup/modest-easysetup-provider-combo-box.h new file mode 100644 index 0000000..d6d07c2 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-provider-combo-box.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_PROVIDER_COMBO_BOX +#define _EASYSETUP_PROVIDER_COMBO_BOX + +#include +#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)) + +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 country_id); + +gchar* easysetup_provider_combo_box_get_active_provider_id (EasysetupProviderComboBox *combobox); + +G_END_DECLS + +#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */ diff --git a/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.c b/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.c new file mode 100644 index 0000000..01c8453 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.c @@ -0,0 +1,218 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */ +#include + +#include "modest-easysetup-secureauth-combo-box.h" +#include +#include +#include +#include + +#include +#include /* For memcpy() */ + +G_DEFINE_TYPE (EasysetupSecureauthComboBox, easysetup_secureauth_combo_box, GTK_TYPE_COMBO_BOX); + +#define SECUREAUTH_COMBO_BOX_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX, EasysetupSecureauthComboBoxPrivate)) + +typedef struct _EasysetupSecureauthComboBoxPrivate EasysetupSecureauthComboBoxPrivate; + +struct _EasysetupSecureauthComboBoxPrivate +{ + GtkTreeModel *model; +}; + +static void +easysetup_secureauth_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_secureauth_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_secureauth_combo_box_dispose (GObject *object) +{ + if (G_OBJECT_CLASS (easysetup_secureauth_combo_box_parent_class)->dispose) + G_OBJECT_CLASS (easysetup_secureauth_combo_box_parent_class)->dispose (object); +} + +static void +easysetup_secureauth_combo_box_finalize (GObject *object) +{ + EasysetupSecureauthComboBoxPrivate *priv = SECUREAUTH_COMBO_BOX_GET_PRIVATE (object); + + g_object_unref (G_OBJECT (priv->model)); + + G_OBJECT_CLASS (easysetup_secureauth_combo_box_parent_class)->finalize (object); +} + +static void +easysetup_secureauth_combo_box_class_init (EasysetupSecureauthComboBoxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EasysetupSecureauthComboBoxPrivate)); + + object_class->get_property = easysetup_secureauth_combo_box_get_property; + object_class->set_property = easysetup_secureauth_combo_box_set_property; + object_class->dispose = easysetup_secureauth_combo_box_dispose; + object_class->finalize = easysetup_secureauth_combo_box_finalize; +} + +enum MODEL_COLS { + MODEL_COL_NAME = 0, /* a string */ + MODEL_COL_ID = 1 /* an int. */ +}; + +void easysetup_secureauth_combo_box_fill (EasysetupSecureauthComboBox *combobox); + +static void +easysetup_secureauth_combo_box_init (EasysetupSecureauthComboBox *self) +{ + EasysetupSecureauthComboBoxPrivate *priv = SECUREAUTH_COMBO_BOX_GET_PRIVATE (self); + + /* Create a tree model for the combo box, + * with a string for the name, and an ID for the secureauth. + * 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); + + /* Secureauth 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); + + easysetup_secureauth_combo_box_fill (self); +} + +EasysetupSecureauthComboBox* +easysetup_secureauth_combo_box_new (void) +{ + return g_object_new (EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX, NULL); +} + +/* Fill the combo box with appropriate choices. + * #combobox: The combo box. + * @protocol: IMAP or POP. + */ +void easysetup_secureauth_combo_box_fill (EasysetupSecureauthComboBox *combobox) +{ + EasysetupSecureauthComboBoxPrivate *priv = SECUREAUTH_COMBO_BOX_GET_PRIVATE (combobox); + + /* Remove any existing rows: */ + GtkListStore *liststore = GTK_LIST_STORE (priv->model); + gtk_list_store_clear (liststore); + + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_AUTH_NONE, MODEL_COL_NAME, _("mcen_fi_advsetup_smtp_none"), -1); + + /* Select the None item: */ + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter); + + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_AUTH_PASSWORD, MODEL_COL_NAME, _("mcen_fi_advsetup_smtp_login"), -1); + + /* TODO: I can't find a ModestProtocol enum flag for this: */ + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)0, MODEL_COL_NAME, _("mcen_fi_advsetup_smtp_cram_md5"), -1); +} + +/** + * Returns the selected secureauth, + * or MODEST_PROTOCOL_UNKNOWN if no secureauth was selected. + */ +ModestProtocol +easysetup_secureauth_combo_box_get_active_secureauth (EasysetupSecureauthComboBox *combobox) +{ + GtkTreeIter active; + const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active); + if (found) { + EasysetupSecureauthComboBoxPrivate *priv = SECUREAUTH_COMBO_BOX_GET_PRIVATE (combobox); + + ModestProtocol secureauth = MODEST_PROTOCOL_UNKNOWN; + gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &secureauth, -1); + return secureauth; + } + + return MODEST_PROTOCOL_UNKNOWN; /* Failed. */ +} + +/* This allows us to pass more than one piece of data to the signal handler, + * and get a result: */ +typedef struct +{ + EasysetupSecureauthComboBox* self; + gint id; + gboolean found; +} ForEachData; + +static gboolean +on_model_foreach_select_id(GtkTreeModel *model, + GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + ForEachData *state = (ForEachData*)(user_data); + + /* Select the item if it has the matching ID: */ + guint id = 0; + 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 secureauth, + * or MODEST_PROTOCOL_UNKNOWN if no secureauth was selected. + */ +gboolean +easysetup_secureauth_combo_box_set_active_secureauth (EasysetupSecureauthComboBox *combobox, ModestProtocol secureauth) +{ + EasysetupSecureauthComboBoxPrivate *priv = SECUREAUTH_COMBO_BOX_GET_PRIVATE (combobox); + + /* Create a state instance so we can send two items of data to the signal handler: */ + ForEachData *state = g_new0 (ForEachData, 1); + state->self = combobox; + state->id = secureauth; + 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); + + const gboolean result = state->found; + + /* Free the state instance: */ + g_free(state); + + return result; +} + diff --git a/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.h b/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.h new file mode 100644 index 0000000..bb1fd8e --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-secureauth-combo-box.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_SECUREAUTH_COMBO_BOX +#define _EASYSETUP_SECUREAUTH_COMBO_BOX + +#include +#include "modest-account-mgr/modest-protocol-info.h" + +G_BEGIN_DECLS + +#define EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX easysetup_secureauth_combo_box_get_type() + +#define EASYSETUP_SECUREAUTH_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX, EasysetupSecureauthComboBox)) + +#define EASYSETUP_SECUREAUTH_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX, EasysetupSecureauthComboBoxClass)) + +#define EASYSETUP_IS_SECUREAUTH_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX)) + +#define EASYSETUP_IS_SECUREAUTH_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX)) + +#define EASYSETUP_SECUREAUTH_COMBO_BOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + EASYSETUP_TYPE_SECUREAUTH_COMBO_BOX, EasysetupSecureauthComboBoxClass)) + +typedef struct { + GtkComboBox parent; +} EasysetupSecureauthComboBox; + +typedef struct { + GtkComboBoxClass parent_class; +} EasysetupSecureauthComboBoxClass; + +GType easysetup_secureauth_combo_box_get_type (void); + +EasysetupSecureauthComboBox* easysetup_secureauth_combo_box_new (void); + +ModestProtocol easysetup_secureauth_combo_box_get_active_secureauth (EasysetupSecureauthComboBox *combobox); + +gboolean easysetup_secureauth_combo_box_set_active_secureauth (EasysetupSecureauthComboBox *combobox, ModestProtocol secureauth); + + +G_END_DECLS + +#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */ diff --git a/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.c b/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.c new file mode 100644 index 0000000..5486e12 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.c @@ -0,0 +1,226 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */ +#include + +#include "modest-easysetup-serversecurity-combo-box.h" +#include +#include +#include +#include + +#include +#include /* For memcpy() */ + +G_DEFINE_TYPE (EasysetupServersecurityComboBox, easysetup_serversecurity_combo_box, GTK_TYPE_COMBO_BOX); + +#define SERVERSECURITY_COMBO_BOX_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX, EasysetupServersecurityComboBoxPrivate)) + +typedef struct _EasysetupServersecurityComboBoxPrivate EasysetupServersecurityComboBoxPrivate; + +struct _EasysetupServersecurityComboBoxPrivate +{ + GtkTreeModel *model; +}; + +static void +easysetup_serversecurity_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_serversecurity_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_serversecurity_combo_box_dispose (GObject *object) +{ + if (G_OBJECT_CLASS (easysetup_serversecurity_combo_box_parent_class)->dispose) + G_OBJECT_CLASS (easysetup_serversecurity_combo_box_parent_class)->dispose (object); +} + +static void +easysetup_serversecurity_combo_box_finalize (GObject *object) +{ + EasysetupServersecurityComboBoxPrivate *priv = SERVERSECURITY_COMBO_BOX_GET_PRIVATE (object); + + g_object_unref (G_OBJECT (priv->model)); + + G_OBJECT_CLASS (easysetup_serversecurity_combo_box_parent_class)->finalize (object); +} + +static void +easysetup_serversecurity_combo_box_class_init (EasysetupServersecurityComboBoxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EasysetupServersecurityComboBoxPrivate)); + + object_class->get_property = easysetup_serversecurity_combo_box_get_property; + object_class->set_property = easysetup_serversecurity_combo_box_set_property; + object_class->dispose = easysetup_serversecurity_combo_box_dispose; + object_class->finalize = easysetup_serversecurity_combo_box_finalize; +} + +enum MODEL_COLS { + MODEL_COL_NAME = 0, /* a string */ + MODEL_COL_ID = 1 /* an int. */ +}; + +static void +easysetup_serversecurity_combo_box_init (EasysetupServersecurityComboBox *self) +{ + EasysetupServersecurityComboBoxPrivate *priv = SERVERSECURITY_COMBO_BOX_GET_PRIVATE (self); + + /* Create a tree model for the combo box, + * with a string for the name, and an ID for the serversecurity. + * 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); + + /* Serversecurity 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); + + /* The application must call easysetup_serversecurity_combo_box_fill(). + */ +} + +EasysetupServersecurityComboBox* +easysetup_serversecurity_combo_box_new (void) +{ + return g_object_new (EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX, NULL); +} + +/* Fill the combo box with appropriate choices. + * #combobox: The combo box. + * @protocol: IMAP or POP. + */ +void easysetup_serversecurity_combo_box_fill (EasysetupServersecurityComboBox *combobox, ModestProtocol protocol) +{ + EasysetupServersecurityComboBoxPrivate *priv = SERVERSECURITY_COMBO_BOX_GET_PRIVATE (combobox); + + /* Remove any existing rows: */ + GtkListStore *liststore = GTK_LIST_STORE (priv->model); + gtk_list_store_clear (liststore); + + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_SECURITY_NONE, MODEL_COL_NAME, _("mcen_fi_advsetup_other_security_none"), -1); + + /* Select the None item: */ + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter); + + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_SECURITY_TLS, MODEL_COL_NAME, _("mcen_fi_advsetup_other_security_normal"), -1); + + /* Add security choices with protocol-specific names, as in the UI spec: + * (Note: Changing the title seems pointless. murrayc) */ + if(protocol == MODEST_PROTOCOL_STORE_POP) { + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_SECURITY_SSL, MODEL_COL_NAME, _("mcen_fi_advsetup_other_security_securepop3s"), -1); + } else if(protocol == MODEST_PROTOCOL_STORE_IMAP) { + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_SECURITY_SSL, MODEL_COL_NAME, _("mcen_fi_advsetup_other_security_secureimap4"), -1); + } else if(protocol == MODEST_PROTOCOL_TRANSPORT_SMTP) { + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_SECURITY_SSL, MODEL_COL_NAME, _("mcen_fi_advsetup_other_security_ssl"), -1); + } +} + +/** + * Returns the selected serversecurity, + * or MODEST_PROTOCOL_UNKNOWN if no serversecurity was selected. + */ +ModestProtocol +easysetup_serversecurity_combo_box_get_active_serversecurity (EasysetupServersecurityComboBox *combobox) +{ + GtkTreeIter active; + const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active); + if (found) { + EasysetupServersecurityComboBoxPrivate *priv = SERVERSECURITY_COMBO_BOX_GET_PRIVATE (combobox); + + ModestProtocol serversecurity = MODEST_PROTOCOL_UNKNOWN; + gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &serversecurity, -1); + return serversecurity; + } + + return MODEST_PROTOCOL_UNKNOWN; /* Failed. */ +} + +/* This allows us to pass more than one piece of data to the signal handler, + * and get a result: */ +typedef struct +{ + EasysetupServersecurityComboBox* self; + gint id; + gboolean found; +} ForEachData; + +static gboolean +on_model_foreach_select_id(GtkTreeModel *model, + GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + ForEachData *state = (ForEachData*)(user_data); + + /* Select the item if it has the matching ID: */ + guint id = 0; + 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 serversecurity, + * or MODEST_PROTOCOL_UNKNOWN if no serversecurity was selected. + */ +gboolean +easysetup_serversecurity_combo_box_set_active_serversecurity (EasysetupServersecurityComboBox *combobox, ModestProtocol serversecurity) +{ + EasysetupServersecurityComboBoxPrivate *priv = SERVERSECURITY_COMBO_BOX_GET_PRIVATE (combobox); + + /* Create a state instance so we can send two items of data to the signal handler: */ + ForEachData *state = g_new0 (ForEachData, 1); + state->self = combobox; + state->id = serversecurity; + 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); + + const gboolean result = state->found; + + /* Free the state instance: */ + g_free(state); + + return result; +} + diff --git a/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.h b/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.h new file mode 100644 index 0000000..fb08ec7 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-serversecurity-combo-box.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_SERVERSECURITY_COMBO_BOX +#define _EASYSETUP_SERVERSECURITY_COMBO_BOX + +#include +#include "modest-account-mgr/modest-protocol-info.h" + +G_BEGIN_DECLS + +#define EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX easysetup_serversecurity_combo_box_get_type() + +#define EASYSETUP_SERVERSECURITY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX, EasysetupServersecurityComboBox)) + +#define EASYSETUP_SERVERSECURITY_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX, EasysetupServersecurityComboBoxClass)) + +#define EASYSETUP_IS_SERVERSECURITY_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX)) + +#define EASYSETUP_IS_SERVERSECURITY_COMBO_BOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX)) + +#define EASYSETUP_SERVERSECURITY_COMBO_BOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + EASYSETUP_TYPE_SERVERSECURITY_COMBO_BOX, EasysetupServersecurityComboBoxClass)) + +typedef struct { + GtkComboBox parent; +} EasysetupServersecurityComboBox; + +typedef struct { + GtkComboBoxClass parent_class; +} EasysetupServersecurityComboBoxClass; + +GType easysetup_serversecurity_combo_box_get_type (void); + +EasysetupServersecurityComboBox* easysetup_serversecurity_combo_box_new (void); + +void easysetup_serversecurity_combo_box_fill (EasysetupServersecurityComboBox *combobox, ModestProtocol protocol); + +ModestProtocol easysetup_serversecurity_combo_box_get_active_serversecurity (EasysetupServersecurityComboBox *combobox); + +gboolean easysetup_serversecurity_combo_box_set_active_serversecurity (EasysetupServersecurityComboBox *combobox, ModestProtocol serversecurity); + + +G_END_DECLS + +#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */ diff --git a/src/maemo/easysetup/modest-easysetup-servertype-combo-box.c b/src/maemo/easysetup/modest-easysetup-servertype-combo-box.c new file mode 100644 index 0000000..7e87ecb --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-servertype-combo-box.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */ +#include + +#include "modest-easysetup-servertype-combo-box.h" +#include +#include +#include +#include + +#include +#include /* For memcpy() */ + +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_fill (EasysetupServertypeComboBox *combobox); + +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); + + easysetup_servertype_combo_box_fill (self); +} + +EasysetupServertypeComboBox* +easysetup_servertype_combo_box_new (void) +{ + return g_object_new (EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, NULL); +} + +void easysetup_servertype_combo_box_fill (EasysetupServertypeComboBox *combobox) +{ + EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox); + + /* Remove any existing rows: */ + GtkListStore *liststore = GTK_LIST_STORE (priv->model); + gtk_list_store_clear (liststore); + + GtkTreeIter iter; + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_STORE_POP, MODEL_COL_NAME, _("mail_fi_emailtype_pop3"), -1); + + /* Select the POP item: */ + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter); + + gtk_list_store_append (liststore, &iter); + gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_STORE_IMAP, MODEL_COL_NAME, _("mail_fi_emailtype_imap"), -1); +} + +/** + * Returns the selected servertype, + * or MODEST_PROTOCOL_UNKNOWN if no servertype was selected. + */ +ModestProtocol +easysetup_servertype_combo_box_get_active_servertype (EasysetupServertypeComboBox *combobox) +{ + GtkTreeIter active; + const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active); + if (found) { + EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox); + + ModestProtocol servertype = MODEST_PROTOCOL_UNKNOWN; + gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &servertype, -1); + return servertype; + } + + return MODEST_PROTOCOL_UNKNOWN; /* Failed. */ +} + +/* This allows us to pass more than one piece of data to the signal handler, + * and get a result: */ +typedef struct +{ + EasysetupServertypeComboBox* self; + gint id; + gboolean found; +} ForEachData; + +static gboolean +on_model_foreach_select_id(GtkTreeModel *model, + GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + ForEachData *state = (ForEachData*)(user_data); + + /* Select the item if it has the matching ID: */ + guint id = 0; + 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_UNKNOWN if no servertype was selected. + */ +gboolean +easysetup_servertype_combo_box_set_active_servertype (EasysetupServertypeComboBox *combobox, ModestProtocol servertype) +{ + EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox); + + /* Create a state instance so we can send two items of data to the signal handler: */ + ForEachData *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); + + const gboolean result = state->found; + + /* Free the state instance: */ + g_free(state); + + return result; +} + diff --git a/src/maemo/easysetup/modest-easysetup-servertype-combo-box.h b/src/maemo/easysetup/modest-easysetup-servertype-combo-box.h new file mode 100644 index 0000000..76c4aee --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-servertype-combo-box.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_SERVERTYPE_COMBO_BOX +#define _EASYSETUP_SERVERTYPE_COMBO_BOX + +#include +#include "modest-account-mgr/modest-protocol-info.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 (void); + +ModestProtocol easysetup_servertype_combo_box_get_active_servertype (EasysetupServertypeComboBox *combobox); + +gboolean easysetup_servertype_combo_box_set_active_servertype (EasysetupServertypeComboBox *combobox, ModestProtocol servertype); + + +G_END_DECLS + +#endif /* _EASYSETUP_PROVIDER_COMBO_BOX */ diff --git a/src/maemo/easysetup/modest-easysetup-wizard.c b/src/maemo/easysetup/modest-easysetup-wizard.c new file mode 100644 index 0000000..a9eaed6 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-wizard.c @@ -0,0 +1,1201 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + + +#include "modest-easysetup-wizard.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "modest-easysetup-country-combo-box.h" +#include "modest-easysetup-provider-combo-box.h" +#include "modest-easysetup-servertype-combo-box.h" +#include "modest-easysetup-serversecurity-combo-box.h" +#include "modest-easysetup-secureauth-combo-box.h" +#include "modest-validating-entry.h" +#include "modest-text-utils.h" +#include "modest-account-mgr/modest-account-mgr.h" +#include +#include /* For strlen(). */ + +#define EXAMPLE_EMAIL_ADDRESS "first.last@provider.com" + +G_DEFINE_TYPE (ModestEasysetupWizardDialog, modest_easysetup_wizard_dialog, MODEST_TYPE_WIZARD_DIALOG); + +#define WIZARD_DIALOG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, ModestEasysetupWizardDialogPrivate)) + +typedef struct _ModestEasysetupWizardDialogPrivate ModestEasysetupWizardDialogPrivate; + +struct _ModestEasysetupWizardDialogPrivate +{ + ModestPresets *presets; +}; + +static void +modest_easysetup_wizard_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_easysetup_wizard_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_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 = WIZARD_DIALOG_GET_PRIVATE (self); + + if (self->account_manager) + g_object_unref (G_OBJECT (self->account_manager)); + + if (priv->presets) + modest_presets_destroy (priv->presets); + + G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->finalize (object); +} + +static void +show_error (GtkWindow *parent_window, const gchar* text); + +static gboolean +create_account (ModestEasysetupWizardDialog *self); + +static void +create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self); + +static void +set_default_custom_servernames(ModestEasysetupWizardDialog *dialog); + +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_asterix(ModestEasysetupWizardDialog *self, + GtkSizeGroup *group, + const gchar *value, + GtkWidget *control, + GtkWidget *icon, + HildonCaptionStatus flag) +{ + GtkWidget *caption = hildon_caption_new (group, value, control, icon, flag); + +/* The translated strings seem to already contain the *, + * but this code can be used if that is not true in future. + */ +#if 0 + /* 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); +#endif + + /* 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, 2); + GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_intro")); + 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); +} + +static void +on_combo_account_country (GtkComboBox *widget, gpointer user_data) +{ + ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data); + g_assert(self); + ModestEasysetupWizardDialogPrivate *priv = WIZARD_DIALOG_GET_PRIVATE (self); + + /* Fill the providers combo, based on the selected country: */ + gint mcc_id = easysetup_country_combo_box_get_active_country_id ( + EASYSETUP_COUNTRY_COMBO_BOX (self->combo_account_country)); + easysetup_provider_combo_box_fill ( + EASYSETUP_PROVIDER_COMBO_BOX (self->combo_account_serviceprovider), priv->presets, mcc_id); +} + +static void +on_combo_account_serviceprovider (GtkComboBox *widget, gpointer user_data) +{ + ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data); + g_assert(self); + ModestEasysetupWizardDialogPrivate *priv = WIZARD_DIALOG_GET_PRIVATE (self); + + /* Fill the providers combo, based on the selected country: */ + gchar* provider_id = easysetup_provider_combo_box_get_active_provider_id ( + EASYSETUP_PROVIDER_COMBO_BOX (self->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 (EXAMPLE_EMAIL_ADDRESS); + + if (self->entry_user_email) + gtk_entry_set_text (GTK_ENTRY (self->entry_user_email), domain_name); + + g_free (domain_name); + + g_free (provider_id); +} + + +static GtkWidget* +create_page_account_details (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + GtkWidget *label = gtk_label_new(_("mcen_ia_accountdetails")); + gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 2); + 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: */ + self->combo_account_country = GTK_WIDGET (easysetup_country_combo_box_new ()); + GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_country"), + self->combo_account_country, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->combo_account_country); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* connect to country combo's changed signal, so we can fill the provider combo: */ + g_signal_connect (G_OBJECT (self->combo_account_country), "changed", + G_CALLBACK (on_combo_account_country), self); + + + /* The service provider widgets: */ + self->combo_account_serviceprovider = GTK_WIDGET (easysetup_provider_combo_box_new ()); + + caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_serviceprovider"), + self->combo_account_serviceprovider, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->combo_account_serviceprovider); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* connect to providers combo's changed signal, so we can fill the email address: */ + g_signal_connect (G_OBJECT (self->combo_account_serviceprovider), "changed", + G_CALLBACK (on_combo_account_serviceprovider), self); + + /* TODO: Default to the current country somehow. + * But I don't know how to get the information that is specified in the + * "Language and region" control panel. It does not seem be anywhere in gconf. murrayc. + * + * This is probably not the best choice of gconf key: + * This is the "mcc used in the last pairing", ie. the last connection you made. + * set by the osso-operator-wizard package, suggested by Dirk-Jan Binnema. + * + */ + GConfClient *client = gconf_client_get_default (); + GError *error = NULL; + const gchar* key = "/apps/osso/operator-wizard/last_mcc"; + gint mcc_id = gconf_client_get_int(client, key, &error); + + if(mcc_id < 0) + mcc_id = 0; + + if (error) { + g_warning ("Error getting gconf key %s:\n%s", key, error->message); + g_error_free (error); + error = NULL; + + mcc_id = 0; + } + + /* Note that gconf_client_get_int() seems to return 0 without an error if the key is not there + * This might just be a Maemo bug. + */ + if (mcc_id == 0) + { + /* For now, we default to Finland when there is nothing better: */ + mcc_id = 244; + } + + easysetup_country_combo_box_set_active_country_id ( + EASYSETUP_COUNTRY_COMBO_BOX (self->combo_account_country), mcc_id); + + + /* The description widgets: */ + self->entry_account_title = GTK_WIDGET (easysetup_validating_entry_new ()); + gtk_entry_set_text( GTK_ENTRY (self->entry_account_title), + _("mcen_ia_emailsetup_defaultname")); /* default description. */ + /* TODO: Check if an account with this default name exists, and increment if necessary. */ + + caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_account_title"), + self->entry_account_title, NULL, HILDON_CAPTION_MANDATORY); + gtk_widget_show (self->entry_account_title); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + 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, "^"); + easysetup_validating_entry_set_unallowed_characters ( + EASYSETUP_VALIDATING_ENTRY (self->entry_account_title), list_prevent); + g_list_free (list_prevent); + + /* 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 (self->entry_account_title), 64); + + gtk_widget_show (GTK_WIDGET (box)); + + return GTK_WIDGET (box); +} + +static GtkWidget* +create_page_user_details (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + + /* 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 name widgets: */ + self->entry_user_name = GTK_WIDGET (easysetup_validating_entry_new ()); + /* 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 (self->entry_user_name), 64); + GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, + _("mcen_li_emailsetup_name"), self->entry_user_name, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->entry_user_name); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + 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, ">"); + easysetup_validating_entry_set_unallowed_characters ( + EASYSETUP_VALIDATING_ENTRY (self->entry_user_name), list_prevent); + g_list_free (list_prevent); + + /* The username widgets: */ + self->entry_user_username = GTK_WIDGET (easysetup_validating_entry_new ()); + caption = create_caption_new_with_asterix (self, sizegroup, _("mail_fi_username"), + self->entry_user_username, NULL, HILDON_CAPTION_MANDATORY); + gtk_widget_show (self->entry_user_username); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* Prevent the use of some characters in the username, + * as required by our UI specification: */ + easysetup_validating_entry_set_unallowed_characters_whitespace ( + EASYSETUP_VALIDATING_ENTRY (self->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 (self->entry_user_username), 64); + + /* The password widgets: */ + self->entry_user_password = gtk_entry_new (); + gtk_entry_set_visibility (GTK_ENTRY (self->entry_user_password), FALSE); + /* gtk_entry_set_invisible_char (GTK_ENTRY (self->entry_user_password), '*'); */ + caption = create_caption_new_with_asterix (self, sizegroup, + _("mail_fi_password"), self->entry_user_password, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->entry_user_password); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* The email address widgets: */ + self->entry_user_email = GTK_WIDGET (easysetup_validating_entry_new ()); + caption = create_caption_new_with_asterix (self, sizegroup, + _("mcen_li_emailsetup_email_address"), self->entry_user_email, NULL, HILDON_CAPTION_MANDATORY); + gtk_entry_set_text (GTK_ENTRY (self->entry_user_email), EXAMPLE_EMAIL_ADDRESS); /* Default text. */ + gtk_widget_show (self->entry_user_email); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* 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 (self->entry_user_email), 64); + + + gtk_widget_show (GTK_WIDGET (box)); + + return GTK_WIDGET (box); +} + +static GtkWidget* create_page_complete_easysetup (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete")); + 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) +{ + ModestProtocol protocol = easysetup_servertype_combo_box_get_active_servertype ( + EASYSETUP_SERVERTYPE_COMBO_BOX (self->combo_incoming_servertype)); + const gchar* type = + (protocol == MODEST_PROTOCOL_STORE_POP ? + _("mail_fi_emailtype_pop3") : + _("mail_fi_emailtype_imap") ); + + + /* Note that this produces a compiler warning, + * because the compiler does not know that the translated string will have a %s in it. + * I do not see a way to avoid the warning while still using these Logical IDs. murrayc. */ + gchar* incomingserver_title = g_strdup_printf(_("mcen_li_emailsetup_servertype"), type); + g_object_set (G_OBJECT (self->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) +{ + ModestProtocol protocol = easysetup_servertype_combo_box_get_active_servertype ( + EASYSETUP_SERVERTYPE_COMBO_BOX (self->combo_incoming_servertype)); + + /* 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. */ + easysetup_serversecurity_combo_box_fill ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_incoming_security), protocol); +} + +void on_combo_servertype_changed(GtkComboBox *combobox, gpointer user_data) +{ + ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data); + update_incoming_server_title (self); + update_incoming_server_security_choices (self); +} + +static GtkWidget* create_page_custom_incoming (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + + /* 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 incoming server widgets: */ + if (!self->combo_incoming_servertype) + self->combo_incoming_servertype = GTK_WIDGET (easysetup_servertype_combo_box_new ()); + easysetup_servertype_combo_box_set_active_servertype ( + EASYSETUP_SERVERTYPE_COMBO_BOX (self->combo_incoming_servertype), MODEST_PROTOCOL_STORE_POP); + GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, + _("mcen_li_emailsetup_type"), self->combo_incoming_servertype, NULL, HILDON_CAPTION_MANDATORY); + gtk_widget_show (self->combo_incoming_servertype); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + if(!self->entry_incomingserver) + self->entry_incomingserver = gtk_entry_new (); + set_default_custom_servernames (self); + + if (self->caption_incoming) + gtk_widget_destroy (self->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) */ + self->caption_incoming = create_caption_new_with_asterix (self, sizegroup, + "Incoming Server", self->entry_incomingserver, NULL, HILDON_CAPTION_MANDATORY); + update_incoming_server_title (self); + gtk_widget_show (self->entry_incomingserver); + gtk_box_pack_start (GTK_BOX (box), self->caption_incoming, FALSE, FALSE, 2); + gtk_widget_show (self->caption_incoming); + + /* Change the caption title when the servertype changes, + * as in the UI spec: */ + g_signal_connect (G_OBJECT (self->combo_incoming_servertype), "changed", + G_CALLBACK (on_combo_servertype_changed), self); + + /* The secure connection widgets: */ + if (!self->combo_incoming_security) + self->combo_incoming_security = GTK_WIDGET (easysetup_serversecurity_combo_box_new ()); + update_incoming_server_security_choices (self); + easysetup_serversecurity_combo_box_set_active_serversecurity ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_incoming_security), MODEST_PROTOCOL_SECURITY_NONE); + caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_connection"), + self->combo_incoming_security, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->combo_incoming_security); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + if(!self->checkbox_incoming_auth) + self->checkbox_incoming_auth = + gtk_check_button_new_with_label (_("mcen_li_emailsetup_secure_authentication")); + gtk_box_pack_start (GTK_BOX (box), self->checkbox_incoming_auth, FALSE, FALSE, 2); + gtk_widget_show (self->checkbox_incoming_auth); + + 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 GtkWidget* create_page_custom_outgoing (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + + /* 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 (!self->entry_outgoingserver) + self->entry_outgoingserver = gtk_entry_new (); + GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, + _("mcen_li_emailsetup_smtp"), self->entry_outgoingserver, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->entry_outgoingserver); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + set_default_custom_servernames (self); + + /* The secure connection widgets: */ + if (!self->combo_outgoing_security) + self->combo_outgoing_security = GTK_WIDGET (easysetup_serversecurity_combo_box_new ()); + easysetup_serversecurity_combo_box_fill ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_outgoing_security), MODEST_PROTOCOL_TRANSPORT_SMTP); + easysetup_serversecurity_combo_box_set_active_serversecurity ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_outgoing_security), MODEST_PROTOCOL_SECURITY_NONE); + caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_connection"), + self->combo_outgoing_security, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->combo_outgoing_security); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* The secure authentication widgets: */ + if (!self->combo_outgoing_auth) + self->combo_outgoing_auth = GTK_WIDGET (easysetup_secureauth_combo_box_new ()); + caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_authentication"), + self->combo_outgoing_auth, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->combo_outgoing_auth); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* connection-specific checkbox: */ + if (!self->checkbox_outgoing_smtp_specific) { + self->checkbox_outgoing_smtp_specific = gtk_check_button_new_with_label (_("mcen_fi_advsetup_connection_smtp")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific), + FALSE); + } + gtk_box_pack_start (GTK_BOX (box), self->checkbox_outgoing_smtp_specific, FALSE, FALSE, 2); + gtk_widget_show (self->checkbox_outgoing_smtp_specific); + + /* Connection-specific SMTP-Severs Edit button: */ + if (!self->button_outgoing_smtp_servers) + self->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_emailsetup_edit")); + caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_optional_smtp"), + self->button_outgoing_smtp_servers, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->button_outgoing_smtp_servers); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + /* Only enable the button when the checkbox is checked: */ + enable_widget_for_togglebutton (self->button_outgoing_smtp_servers, + GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific)); + + + gtk_widget_show (GTK_WIDGET (box)); + + return GTK_WIDGET (box); +} + +static GtkWidget* create_page_complete_custom (ModestEasysetupWizardDialog *self) +{ + GtkWidget *box = gtk_vbox_new (FALSE, 2); + GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete")); + gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + if (!self->button_edit) + self->button_edit = gtk_button_new_with_label (_("mcen_bd_emailsetup_edit")); + GtkWidget *caption = hildon_caption_new (NULL, _("mcen_fi_advanced_settings"), + self->button_edit, NULL, HILDON_CAPTION_OPTIONAL); + gtk_widget_show (self->button_edit); + gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 2); + gtk_widget_show (caption); + + 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 +modest_easysetup_wizard_dialog_init (ModestEasysetupWizardDialog *self) +{ + /* 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 = WIZARD_DIALOG_GET_PRIVATE (self); + priv->presets = modest_presets_new ("provider-data-test.keyfile"); /* TODO: the actual filepath. */ + + /* Create the account manager object, + * so we can check for existing accounts, + * and create new accounts: */ + ModestConf *conf = modest_conf_new (); /* Just a thin wrapper around GConfClient. */ + self->account_manager = modest_account_mgr_new (conf); + g_object_unref (conf); + + /* Create the common pages, + */ + self->page_welcome = create_page_welcome (self); + self->page_account_details = create_page_account_details (self); + self->page_user_details = create_page_user_details (self); + + /* Add the common pages: */ + gtk_notebook_append_page (notebook, self->page_welcome, + gtk_label_new (_("mcen_ti_emailsetup_welcome"))); + gtk_notebook_append_page (notebook, self->page_account_details, + gtk_label_new (_("mcen_ti_accountdetails"))); + gtk_notebook_append_page (notebook, self->page_user_details, + gtk_label_new (_("mcen_ti_emailsetup_userdetails"))); + + /* Create and add the easysetup-specific pages, + * because we need _some_ final page to enable the Next and Finish buttons: */ + create_subsequent_easysetup_pages (self); + + + /* 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); +} + +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) +{ + GtkNotebook *notebook = NULL; + g_object_get (self, "wizard-notebook", ¬ebook, NULL); + g_assert(notebook); + + /* Create the custom pages: */ + if(!(self->page_custom_incoming)) { + self->page_custom_incoming = create_page_custom_incoming (self); + } + + if(!(self->page_custom_outgoing)) { + self->page_custom_outgoing = create_page_custom_outgoing (self); + } + + if(!(self->page_complete_customsetup)) { + self->page_complete_customsetup = create_page_complete_custom (self); + } + + if (!gtk_widget_get_parent (GTK_WIDGET (self->page_custom_incoming))) + gtk_notebook_append_page (notebook, self->page_custom_incoming, + gtk_label_new (_("mcen_ti_emailsetup_incomingdetails"))); + + if (!gtk_widget_get_parent (GTK_WIDGET (self->page_custom_outgoing))) + gtk_notebook_append_page (notebook, self->page_custom_outgoing, + gtk_label_new (_("mcen_ti_emailsetup_outgoingdetails"))); + + if (!gtk_widget_get_parent (GTK_WIDGET (self->page_complete_customsetup))) + gtk_notebook_append_page (notebook, self->page_complete_customsetup, + gtk_label_new (_("mcen_ti_emailsetup_complete"))); +} + +static void create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self) +{ + GtkNotebook *notebook = NULL; + g_object_get (self, "wizard-notebook", ¬ebook, NULL); + g_assert(notebook); + + /* Create the easysetup-specific pages: */ + if(!self->page_complete_easysetup) + self->page_complete_easysetup = create_page_complete_easysetup (self); + + if (!gtk_widget_get_parent (GTK_WIDGET (self->page_complete_easysetup))) + gtk_notebook_append_page (notebook, self->page_complete_easysetup, + gtk_label_new (_("mcen_ti_emailsetup_complete"))); + +} +/* 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) +{ + if (easysetup_provider_combo_box_get_active_provider_id ( + EASYSETUP_PROVIDER_COMBO_BOX (self->combo_account_serviceprovider)) == 0) { + /* "Other..." was selected: */ + + /* Make sure that the easysetup pages do not exist: */ + if(self->page_complete_easysetup) { + gtk_widget_destroy (self->page_complete_easysetup); + self->page_complete_easysetup = NULL; + } + + create_subsequent_customsetup_pages (self); + } + else { + /* A specific provider was selected: */ + { + /* Make sure that the custom pages do not exist: + * Because they will be used if they exist, when creating the account. */ + if(self->page_custom_incoming) { + gtk_widget_destroy (self->page_custom_incoming); + self->page_custom_incoming = NULL; + } + + if(self->page_custom_outgoing) { + gtk_widget_destroy (self->page_custom_outgoing); + self->page_custom_outgoing = NULL; + } + + if(self->page_complete_customsetup) { + gtk_widget_destroy (self->page_complete_customsetup); + self->page_complete_customsetup = NULL; + } + } + + /* Create the easysetup pages: */ + create_subsequent_easysetup_pages (self); + } +} + +gchar* +util_get_default_servername_from_email_address (const gchar* email_address, ModestProtocol servertype) +{ + if (!email_address) + return NULL; + + gchar* at = g_utf8_strchr (email_address, -1, '@'); + if (!at || (g_utf8_strlen (at, -1) < 2)) + return NULL; + + gchar* domain = g_utf8_next_char (at); + if(!domain) + return NULL; + + const gchar* hostname = NULL; + if (servertype == MODEST_PROTOCOL_STORE_POP) + hostname = "pop"; + else if (servertype == MODEST_PROTOCOL_STORE_IMAP) + hostname = "imap"; + else if (servertype == MODEST_PROTOCOL_TRANSPORT_SMTP) + hostname = "smtp"; + + if (!hostname) + return NULL; + + return g_strdup_printf ("%s.%s", hostname, domain); +} + +static void set_default_custom_servernames (ModestEasysetupWizardDialog *account_wizard) +{ + /* Set a default domain for the server, based on the email address, + * if no server name was already specified. + */ + const gchar* incoming_existing = gtk_entry_get_text (GTK_ENTRY (account_wizard->entry_incomingserver)); + if ((!incoming_existing || (strlen(incoming_existing) == 0)) + && account_wizard->entry_user_email) { + const ModestProtocol protocol = easysetup_servertype_combo_box_get_active_servertype ( + EASYSETUP_SERVERTYPE_COMBO_BOX (account_wizard->combo_incoming_servertype)); + const gchar* email_address = gtk_entry_get_text (GTK_ENTRY(account_wizard->entry_user_email)); + gtk_entry_set_text (GTK_ENTRY (account_wizard->entry_incomingserver), util_get_default_servername_from_email_address (email_address, protocol)); + } + + /* Set a default domain for the server, based on the email address, + * if no server name was already specified. + */ + const gchar* outgoing_existing = gtk_entry_get_text (GTK_ENTRY (account_wizard->entry_outgoingserver)); + if ((!outgoing_existing || (strlen(outgoing_existing) == 0)) + && account_wizard->entry_user_email) { + const gchar* email_address = gtk_entry_get_text (GTK_ENTRY(account_wizard->entry_user_email)); + gtk_entry_set_text (GTK_ENTRY (account_wizard->entry_outgoingserver), util_get_default_servername_from_email_address (email_address, MODEST_PROTOCOL_TRANSPORT_SMTP)); + } +} + +static gboolean +on_before_next (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page) +{ + ModestEasysetupWizardDialog *account_wizard = MODEST_EASYSETUP_WIZARD_DIALOG (dialog); + + /* 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 == account_wizard->page_account_details) { + /* Check that the title is not already in use: */ + const gchar* account_name = gtk_entry_get_text (GTK_ENTRY (account_wizard->entry_account_title)); + if ((!account_name) || (strlen(account_name) == 0)) + return FALSE; + + gboolean name_in_use = FALSE; + name_in_use = modest_account_mgr_account_exists (account_wizard->account_manager, + account_name, TRUE /* server_account */); + + if (name_in_use) { + /* Warn the user via a dialog: */ + /* TODO: The UI spec says we should increment the title, + * as well as warning. This seems contradictory. + */ + show_error (GTK_WINDOW (account_wizard), _("mail_ib_account_name_already_existing.")); + + return FALSE; + } + } + else if (current_page == account_wizard->page_user_details) { + /* Check that the email address is valud: */ + const gchar* email_address = gtk_entry_get_text (GTK_ENTRY (account_wizard->entry_user_email)); + if ((!email_address) || (strlen(email_address) == 0)) + return FALSE; + + if (!modest_text_utils_validate_email_address (email_address)) { + /* Warn the user via a dialog: */ + show_error (GTK_WINDOW (account_wizard), _("mcen_ib_invalid_email")); + + /* Return focus to the email address entry: */ + gtk_widget_grab_focus (account_wizard->entry_user_email); + + return FALSE; + } + + /* Make sure that the subsequent pages are appropriate for the provider choice. */ + create_subsequent_pages (account_wizard); + } + + /* TODO: The UI Spec wants us to check that the servernames are valid, + * but does not specify how. + */ + + if(next_page == account_wizard->page_custom_incoming) { + set_default_custom_servernames (account_wizard); + } + else if (next_page == account_wizard->page_custom_outgoing) { + set_default_custom_servernames (account_wizard); + } + + /* If this is the last page, and this is a click on Finish, + * then attempt to create the dialog. + */ + if(!next_page) /* This is NULL when this is a click on Finish. */ + { + create_account (account_wizard); + } + + + 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 + return FALSE; +} + +static void +on_enable_buttons (ModestWizardDialog *dialog, GtkWidget *current_page) +{ + ModestEasysetupWizardDialog *account_wizard = MODEST_EASYSETUP_WIZARD_DIALOG (dialog); + + gboolean enable_next = TRUE; + if (current_page == account_wizard->page_welcome) { + enable_next = TRUE; + } + else if (current_page == account_wizard->page_account_details) { + /* The account details title is mandatory: */ + if (entry_is_empty(account_wizard->entry_account_title)) + enable_next = FALSE; + } + else if (current_page == account_wizard->page_user_details) { + /* The user details username is mandatory: */ + if (entry_is_empty(account_wizard->entry_user_username)) + enable_next = FALSE; + + /* The user details email address is mandatory: */ + if (enable_next && entry_is_empty (account_wizard->entry_user_email)) + enable_next = FALSE; + } + else if (current_page == account_wizard->page_custom_incoming) { + /* The custom incoming server is mandatory: */ + if (entry_is_empty(account_wizard->entry_incomingserver)) + enable_next = FALSE; + } + + /* Enable the buttons, + * identifying them via their associated response codes: + */ + GtkDialog *dialog_base = GTK_DIALOG (dialog); + gtk_dialog_set_response_sensitive (dialog_base, + MODEST_WIZARD_DIALOG_NEXT, + enable_next); + + /* Disable the Finish button until we are on the last page, + * because HildonWizardDialog enables this for all but the first page: */ + GtkNotebook *notebook = NULL; + g_object_get (dialog_base, "wizard-notebook", ¬ebook, NULL); + + gint current = gtk_notebook_get_current_page (notebook); + gint last = gtk_notebook_get_n_pages (notebook) - 1; + gboolean is_last = (current == last); + + if(!is_last) { + gtk_dialog_set_response_sensitive (dialog_base, + MODEST_WIZARD_DIALOG_FINISH, + FALSE); + } +} + +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->get_property = modest_easysetup_wizard_dialog_get_property; + object_class->set_property = modest_easysetup_wizard_dialog_set_property; + 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; +} + +static void +show_error (GtkWindow *parent_window, const gchar* text) +{ + GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window, + (GtkDialogFlags)0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + text )); + + gtk_dialog_run (dialog); + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +/** Attempt to create the account from the information that the user has entered. + * @result: TRUE if the account was successfully created. + */ +gboolean +create_account (ModestEasysetupWizardDialog *self) +{ + ModestEasysetupWizardDialogPrivate *priv = WIZARD_DIALOG_GET_PRIVATE (self); + + const gchar* account_name = gtk_entry_get_text (GTK_ENTRY (self->entry_account_title)); + + /* Some checks: */ + if (!account_name) + return FALSE; + + /* We should have checked for this already, + * and changed that name accordingly, + * but let's check again just in case: + */ + if (modest_account_mgr_account_exists (self->account_manager, account_name, FALSE)) + return FALSE; + + /* username and password (for both incoming and outgoing): */ + const gchar* username = gtk_entry_get_text (GTK_ENTRY (self->entry_user_username)); + const gchar* password = gtk_entry_get_text (GTK_ENTRY (self->entry_user_password)); + + /* Incoming server: */ + /* Note: We need something as default for the ModestProtocol values, + * or modest_account_mgr_add_server_account will fail. */ + gchar* servername_incoming = NULL; + ModestProtocol protocol_incoming = MODEST_PROTOCOL_STORE_POP; + ModestProtocol protocol_security_incoming = MODEST_PROTOCOL_SECURITY_NONE; + ModestProtocol protocol_authentication_incoming = MODEST_PROTOCOL_AUTH_NONE; + + /* Get details from the specified presets: */ + gchar* provider_id = easysetup_provider_combo_box_get_active_provider_id ( + EASYSETUP_PROVIDER_COMBO_BOX (self->combo_account_serviceprovider)); + if(provider_id) { + /* Use presets: */ + + servername_incoming = modest_presets_get_server (priv->presets, provider_id, + TRUE /* incoming */); + + ModestPresetsServerType servertype_incoming = modest_presets_get_info_server_type (priv->presets, provider_id, + TRUE /* incoming */); + + + /* We don't check for SMTP here as that is impossible for an incoming server. */ + if (servertype_incoming == MODEST_PRESETS_SERVER_TYPE_IMAP) + protocol_incoming = MODEST_PROTOCOL_STORE_IMAP; + else if (servertype_incoming == MODEST_PRESETS_SERVER_TYPE_POP) + protocol_incoming = MODEST_PROTOCOL_STORE_POP; + + ModestPresetsSecurity security_incoming = modest_presets_get_info_server_security (priv->presets, provider_id, + TRUE /* incoming */); + + + if (security_incoming & MODEST_PRESETS_SECURITY_SECURE_INCOMING) + protocol_security_incoming = MODEST_PROTOCOL_SECURITY_SSL; /* TODO: Is this what we want? */ + + if (security_incoming & MODEST_PRESETS_SECURITY_APOP) + protocol_authentication_incoming = MODEST_PROTOCOL_AUTH_PASSWORD; /* TODO: Is this what we want? */ + } + else { + /* Use custom pages because no preset was specified: */ + servername_incoming = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry_incomingserver) )); + + protocol_incoming = easysetup_servertype_combo_box_get_active_servertype ( + EASYSETUP_SERVERTYPE_COMBO_BOX (self->combo_incoming_servertype)); + + protocol_security_incoming = easysetup_serversecurity_combo_box_get_active_serversecurity ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_incoming_security)); + + protocol_authentication_incoming = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->checkbox_incoming_auth)) + ? MODEST_PROTOCOL_AUTH_PASSWORD + : MODEST_PROTOCOL_AUTH_NONE; + + } + + gboolean created = modest_account_mgr_add_server_account (self->account_manager, + account_name, + servername_incoming, + username, password, + protocol_incoming, + protocol_security_incoming, + protocol_authentication_incoming); + + g_free (servername_incoming); + + if (!created) { + /* TODO: Provide a Logical ID for the text: */ + show_error (GTK_WINDOW (self), _("An error occurred while creating the incoming account.")); + return FALSE; + } + + /* Outgoing server: */ + gchar* servername_outgoing = NULL; + ModestProtocol protocol_outgoing = MODEST_PROTOCOL_STORE_POP; + ModestProtocol protocol_security_outgoing = MODEST_PROTOCOL_SECURITY_NONE; + ModestProtocol protocol_authentication_outgoing = MODEST_PROTOCOL_AUTH_NONE; + + if(provider_id) { + /* Use presets: */ + servername_outgoing = modest_presets_get_server (priv->presets, provider_id, + FALSE /* incoming */); + + ModestPresetsServerType servertype_outgoing = modest_presets_get_info_server_type (priv->presets, provider_id, + FALSE /* incoming */); + + /* Note: We need something as default, or modest_account_mgr_add_server_account will fail. */ + protocol_outgoing = MODEST_PROTOCOL_TRANSPORT_SENDMAIL; + if (servertype_outgoing == MODEST_PRESETS_SERVER_TYPE_SMTP) + protocol_outgoing = MODEST_PROTOCOL_TRANSPORT_SMTP; /* TODO: Is this what we want? */ + + ModestPresetsSecurity security_outgoing = + modest_presets_get_info_server_security (priv->presets, provider_id, + FALSE /* incoming */); + + protocol_security_outgoing = MODEST_PROTOCOL_SECURITY_NONE; + if (security_outgoing & MODEST_PRESETS_SECURITY_SECURE_SMTP) + protocol_security_outgoing = MODEST_PROTOCOL_SECURITY_SSL; /* TODO: Is this what we want? */ + + protocol_authentication_outgoing = MODEST_PROTOCOL_AUTH_NONE; + /* TODO: There is no SMTP authentication enum for presets. */ + } + else { + /* Use custom pages because no preset was specified: */ + servername_outgoing = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry_outgoingserver) )); + + protocol_outgoing = MODEST_PROTOCOL_TRANSPORT_SMTP; /* It's always SMTP for outgoing. */ + + protocol_security_outgoing = easysetup_serversecurity_combo_box_get_active_serversecurity ( + EASYSETUP_SERVERSECURITY_COMBO_BOX (self->combo_outgoing_security)); + + protocol_authentication_outgoing = easysetup_secureauth_combo_box_get_active_secureauth ( + EASYSETUP_SECUREAUTH_COMBO_BOX (self->combo_outgoing_auth)); + + gboolean specific = gtk_toggle_button_get_active ( + GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific)); + + } + + created = modest_account_mgr_add_server_account (self->account_manager, + account_name, + servername_outgoing, + username, password, + protocol_outgoing, + protocol_security_outgoing, + protocol_authentication_outgoing); + + g_free (servername_outgoing); + + if (!created) { + /* TODO: Provide a Logical ID for the text: */ + show_error (GTK_WINDOW (self), _("An error occurred while creating the outgoing account.")); + return FALSE; + } + + return FALSE; +} + + diff --git a/src/maemo/easysetup/modest-easysetup-wizard.h b/src/maemo/easysetup/modest-easysetup-wizard.h new file mode 100644 index 0000000..8958873 --- /dev/null +++ b/src/maemo/easysetup/modest-easysetup-wizard.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _MODEST_EAYSETUP_WIZARD_DIALOG +#define _MODEST_EAYSETUP_WIZARD_DIALOG + +/* #include */ +#include "modest-wizard-dialog.h" /* We use a copied-and-improved HildonWizardDialog. */ +#include "modest-account-mgr/modest-account-mgr.h" +#include + +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 ACCOUNT_IS_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; + + /* Used by derived widgets to query existing accounts, + * and to create new accounts: */ + ModestAccountMgr *account_manager; + + /* These widgets are only for use by derived widgets: */ + /* Pages that are common to all account wizards: */ + 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; + GtkWidget *combo_incoming_security; + GtkWidget *checkbox_incoming_auth; + + 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; + GtkWidget *button_edit; + +} ModestEasysetupWizardDialog; + +typedef struct { + ModestWizardDialogClass parent_class; + +} ModestEasysetupWizardDialogClass; + +GType modest_easysetup_wizard_dialog_get_type (void); + +ModestEasysetupWizardDialog* modest_easysetup_wizard_dialog_new (void); + +G_END_DECLS + +#endif /* _MODEST_EAYSETUP_WIZARD_DIALOG */ diff --git a/src/maemo/easysetup/modest-presets.c b/src/maemo/easysetup/modest-presets.c new file mode 100644 index 0000000..8d4e001 --- /dev/null +++ b/src/maemo/easysetup/modest-presets.c @@ -0,0 +1,319 @@ +/* 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 /* for strcmp */ +#include "modest-presets.h" + +#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_OUTGOING "OutgoingMailServer" +#define MODEST_PRESETS_KEY_MAILBOX_TYPE "MailboxType" +#define MODEST_PRESETS_KEY_MAILBOX_TYPE_POP "pop" +#define MODEST_PRESETS_KEY_MAILBOX_TYPE_IMAP "imap" +#define MODEST_PRESETS_KEY_APOP "APOPSecureLogin" +#define MODEST_PRESETS_KEY_SECURE_SMTP "SecureSMTP" +#define MODEST_PRESETS_KEY_TRUE "true" + +/** An efficient way to store the info for each provider. + */ +typedef enum _ModestPresetsInfo { + /* two bits for the server type */ + MODEST_PRESETS_INFO_NONE = 0x0000, + MODEST_PRESETS_INFO_IMAP = 0x0001, + MODEST_PRESETS_INFO_POP = 0x0002, + MODEST_PRESETS_INFO_SMTP = 0x0003, + + /* one bit for each of these */ + MODEST_PRESETS_INFO_APOP = 0x0004, + MODEST_PRESETS_INFO_SECURE_SMTP = 0x0008, + MODEST_PRESETS_INFO_SECURE_INCOMING = 0x000f +} ModestPresetsInfo; + +/** + * modest_presets_get_info: + * @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 ModestPresetsInfo with the required information + */ +static ModestPresetsInfo +modest_presets_get_info (ModestPresets *self, const gchar *provider_id, gboolean incoming_server); + + +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: %s\n", + 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); +} + + +ModestPresetsInfo +modest_presets_get_info (ModestPresets *self, const gchar *provider_id, gboolean incoming_server) +{ + ModestPresetsInfo info = 0; + gchar *val = NULL; + + g_return_val_if_fail (self && self->keyfile, 0); + + 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_MAILBOX_TYPE, NULL); + if (strcmp (val, MODEST_PRESETS_KEY_MAILBOX_TYPE_POP) == 0) + info |= MODEST_PRESETS_INFO_POP; + if (strcmp (val, MODEST_PRESETS_KEY_MAILBOX_TYPE_IMAP) == 0) + info |= MODEST_PRESETS_INFO_IMAP; + g_free (val); + + val = g_key_file_get_string (self->keyfile, provider_id, + MODEST_PRESETS_KEY_APOP, NULL); + if (val && strcmp(val, MODEST_PRESETS_KEY_TRUE) == 0) + info |= MODEST_PRESETS_INFO_APOP; + 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); + info |= MODEST_PRESETS_INFO_SMTP; + + val = g_key_file_get_string (self->keyfile, provider_id, + MODEST_PRESETS_KEY_SECURE_SMTP, NULL); + if (val && strcmp(val,MODEST_PRESETS_KEY_TRUE) == 0) + info |= MODEST_PRESETS_INFO_SECURE_SMTP; + g_free(val); + } + } + + return info; +} + +ModestPresetsServerType +modest_presets_get_info_server_type (ModestPresets *self, + const gchar *provider_id, + gboolean incoming_server) +{ + ModestPresetsInfo info = modest_presets_get_info (self, provider_id, incoming_server); + + /* The server type is stored in the first 2 bits: */ + info = info & 0x03; + + /* Convert from the internal enum to the public enum: */ + if(info == MODEST_PRESETS_INFO_IMAP) + return MODEST_PRESETS_SERVER_TYPE_IMAP; + else if(info == MODEST_PRESETS_INFO_POP) + return MODEST_PRESETS_SERVER_TYPE_POP; + else if(info == MODEST_PRESETS_INFO_SMTP) + return MODEST_PRESETS_SERVER_TYPE_SMTP; + else + return MODEST_PRESETS_SERVER_TYPE_NONE; +} + +ModestPresetsSecurity +modest_presets_get_info_server_security (ModestPresets *self, + const gchar *provider_id, + gboolean incoming_server) +{ + ModestPresetsInfo info = modest_presets_get_info (self, provider_id, incoming_server); + + /* The security flags are stored in all except the first 4 bits: */ + info = info && !0x04; + + /* Convert from the internal flags to the public flags: */ + ModestPresetsSecurity security = MODEST_PRESETS_SECURITY_NONE; + if(info && MODEST_PRESETS_INFO_APOP) + security = security | MODEST_PRESETS_SECURITY_APOP; + + if(info && MODEST_PRESETS_INFO_SECURE_SMTP) + security = security | MODEST_PRESETS_SECURITY_SECURE_SMTP; + + if(info && MODEST_PRESETS_INFO_SECURE_INCOMING) + security = security | MODEST_PRESETS_SECURITY_SECURE_INCOMING; + + return security; +} + + + + +void +modest_presets_destroy (ModestPresets *self) +{ + if (!self) + return; + + g_key_file_free (self->keyfile); + self->keyfile = NULL; + + g_free (self); +} diff --git a/src/maemo/easysetup/modest-presets.h b/src/maemo/easysetup/modest-presets.h new file mode 100644 index 0000000..7e602e0 --- /dev/null +++ b/src/maemo/easysetup/modest-presets.h @@ -0,0 +1,159 @@ +/* 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 + +struct _ModestPresets { +/* private data: don't touch */ + GKeyFile *keyfile; +}; +typedef struct _ModestPresets ModestPresets; + +typedef enum _ModestPresetsServerType { + MODEST_PRESETS_SERVER_TYPE_NONE, + MODEST_PRESETS_SERVER_TYPE_IMAP, + MODEST_PRESETS_SERVER_TYPE_POP, + MODEST_PRESETS_SERVER_TYPE_SMTP +} ModestPresetsServerType; + +/** These are flags, which should be ORed. + */ +typedef enum _ModestPresetsSecurity { + MODEST_PRESETS_SECURITY_NONE = 0, + MODEST_PRESETS_SECURITY_APOP = 1 << 0, + MODEST_PRESETS_SECURITY_SECURE_SMTP = 1 << 1, + MODEST_PRESETS_SECURITY_SECURE_INCOMING = 1 << 2 +} ModestPresetsSecurity; + +/* typedef enum _ModestPresetsInfo ModestPresetsInfo; */ + + +/** + * 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 ModestPresetsServerType with the required information + */ +ModestPresetsServerType 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: ModestPresetsSecurity ORable flags with the required information + */ +ModestPresetsSecurity modest_presets_get_info_server_security (ModestPresets *self, + const gchar *provider_id, + gboolean incoming_server); + +/** + * modest_presets_destroy: + * @self: a valid ModestPresets instance (ie. must not be NULL) + * + * destroy ModestPresets instance; this is required after you're done with it. + */ +void modest_presets_destroy (ModestPresets *self); + + +#endif /*__MODEST_PRESETS__*/ + + diff --git a/src/maemo/easysetup/modest-text-utils.c b/src/maemo/easysetup/modest-text-utils.c new file mode 100644 index 0000000..875c20d --- /dev/null +++ b/src/maemo/easysetup/modest-text-utils.c @@ -0,0 +1,923 @@ +/* Copyright (c) 2006, Nokia Corporation + * All rights reserved. + * + */ + + +#include +#include +#include +#include +#include +#include + + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H */ + +/* defines */ +#define FORWARD_STRING _("-----Forwarded Message-----") +#define FROM_STRING _("From:") +#define SENT_STRING _("Sent:") +#define TO_STRING _("To:") +#define SUBJECT_STRING _("Subject:") +#define EMPTY_STRING "" + +/* + * we need these regexps to find URLs in plain text e-mails + */ +typedef struct _url_match_pattern_t url_match_pattern_t; +struct _url_match_pattern_t { + gchar *regex; + regex_t *preg; + gchar *prefix; +}; + +typedef struct _url_match_t url_match_t; +struct _url_match_t { + guint offset; + guint len; + const gchar* prefix; +}; + +#define MAIL_VIEWER_URL_MATCH_PATTERNS { \ + { "(file|rtsp|http|ftp|https)://[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]+[-A-Za-z0-9_$%&=?/~#]",\ + NULL, NULL },\ + { "www\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ + NULL, "http://" },\ + { "ftp\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ + NULL, "ftp://" },\ + { "(voipto|callto|chatto|jabberto|xmpp):[-_a-z@0-9.\\+]+", \ + NULL, NULL}, \ + { "mailto:[-_a-z0-9.\\+]+@[-_a-z0-9.]+", \ + NULL, NULL},\ + { "[-_a-z0-9.\\+]+@[-_a-z0-9.]+",\ + NULL, "mailto:"}\ + } + +/* private */ +static gchar* cite (const time_t sent_date, const gchar *from); +static void hyperlinkify_plain_text (GString *txt); +static gint cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2); +static void chk_partial_match (const url_match_t *match, guint* offset); +static GSList* get_url_matches (GString *txt); + +static GString* get_next_line (const char *b, const gsize blen, const gchar * iter); +static int get_indent_level (const char *l); +static void unquote_line (GString * l); +static void append_quoted (GString * buf, const int indent, const GString * str, + const int cutpoint); +static int get_breakpoint_utf8 (const gchar * s, const gint indent, const gint limit); +static int get_breakpoint_ascii (const gchar * s, const gint indent, const gint limit); +static int get_breakpoint (const gchar * s, const gint indent, const gint limit); + +static gchar* modest_text_utils_quote_plain_text (const gchar *text, + const gchar *cite, + int limit); + +static gchar* modest_text_utils_quote_html (const gchar *text, + const gchar *cite, + int limit); + + +/* ******************************************************************* */ +/* ************************* PUBLIC FUNCTIONS ************************ */ +/* ******************************************************************* */ + +gchar * +modest_text_utils_quote (const gchar *text, + const gchar *content_type, + const gchar *from, + const time_t sent_date, + int limit) +{ + gchar *retval, *cited; + + g_return_val_if_fail (text, NULL); + g_return_val_if_fail (content_type, NULL); + + cited = cite (sent_date, from); + + if (content_type && strcmp (content_type, "text/html") == 0) + /* TODO: extract the of the HTML and pass it to + the function */ + retval = modest_text_utils_quote_html (text, cited, limit); + else + retval = modest_text_utils_quote_plain_text (text, cited, limit); + + g_free (cited); + + return retval; +} + + +gchar * +modest_text_utils_cite (const gchar *text, + const gchar *content_type, + const gchar *from, + time_t sent_date) +{ + gchar *tmp, *retval; + + g_return_val_if_fail (text, NULL); + g_return_val_if_fail (content_type, NULL); + + tmp = cite (sent_date, from); + retval = g_strdup_printf ("%s%s\n", tmp, text); + g_free (tmp); + + return retval; +} + +gchar * +modest_text_utils_inline (const gchar *text, + const gchar *content_type, + const gchar *from, + time_t sent_date, + const gchar *to, + const gchar *subject) +{ + gchar sent_str[101]; + const gchar *plain_format = "%s\n%s %s\n%s %s\n%s %s\n%s %s\n\n%s"; + const gchar *html_format = \ + "%s
\n\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "

%s"; + const gchar *format; + + g_return_val_if_fail (text, NULL); + g_return_val_if_fail (content_type, NULL); + g_return_val_if_fail (text, NULL); + + modest_text_utils_strftime (sent_str, 100, "%c", sent_date); + + if (!strcmp (content_type, "text/html")) + /* TODO: extract the of the HTML and pass it to + the function */ + format = html_format; + else + format = plain_format; + + return g_strdup_printf (format, + FORWARD_STRING, + FROM_STRING, (from) ? from : EMPTY_STRING, + SENT_STRING, sent_str, + TO_STRING, (to) ? to : EMPTY_STRING, + SUBJECT_STRING, (subject) ? subject : EMPTY_STRING, + text); +} + +/* just to prevent warnings: + * warning: `%x' yields only last 2 digits of year in some locales + */ +gsize +modest_text_utils_strftime(char *s, gsize max, const char *fmt, time_t timet) +{ + static GDate date; + + /* does not work on old maemo glib: + * g_date_set_time_t (&date, timet); + */ + g_date_set_time (&date, (GTime) timet); + + return g_date_strftime (s, max, fmt, (const GDate*) &date); +} + +gchar * +modest_text_utils_derived_subject (const gchar *subject, const gchar *prefix) +{ + gchar *tmp; + + g_return_val_if_fail (prefix, NULL); + + if (!subject) + return g_strdup (prefix); + + tmp = g_strchug (g_strdup (subject)); + + if (!strncmp (tmp, prefix, strlen (prefix))) { + return tmp; + } else { + g_free (tmp); + return g_strdup_printf ("%s %s", prefix, subject); + } +} + +gchar* +modest_text_utils_remove_address (const gchar *address_list, const gchar *address) +{ + gchar *dup, *token, *ptr, *result; + GString *filtered_emails; + + g_return_val_if_fail (address_list, NULL); + + if (!address) + return g_strdup (address_list); + + /* search for substring */ + if (!strstr ((const char *) address_list, (const char *) address)) + return g_strdup (address_list); + + dup = g_strdup (address_list); + filtered_emails = g_string_new (NULL); + + token = strtok_r (dup, ",", &ptr); + + while (token != NULL) { + /* Add to list if not found */ + if (!strstr ((const char *) token, (const char *) address)) { + if (filtered_emails->len == 0) + g_string_append_printf (filtered_emails, "%s", g_strstrip (token)); + else + g_string_append_printf (filtered_emails, ",%s", g_strstrip (token)); + } + token = strtok_r (NULL, ",", &ptr); + } + result = filtered_emails->str; + + /* Clean */ + g_free (dup); + g_string_free (filtered_emails, FALSE); + + return result; +} + +gchar* +modest_text_utils_convert_to_html (const gchar *data) +{ + guint i; + gboolean first_space = TRUE; + GString *html; + gsize len; + + if (!data) + return NULL; + + len = strlen (data); + html = g_string_sized_new (len + 100); /* just a guess... */ + + g_string_append_printf (html, + "" + "" + "" + "" + ""); + + /* replace with special html chars where needed*/ + for (i = 0; i != len; ++i) { + char kar = data[i]; + switch (kar) { + + case 0: break; /* ignore embedded \0s */ + case '<' : g_string_append (html, "<"); break; + case '>' : g_string_append (html, ">"); break; + case '&' : g_string_append (html, """); break; + case '\n': g_string_append (html, "
\n"); break; + default: + if (kar == ' ') { + g_string_append (html, first_space ? " " : " "); + first_space = FALSE; + } else if (kar == '\t') + g_string_append (html, "    "); + else { + int charnum = 0; + first_space = TRUE; + /* optimization trick: accumulate 'normal' chars, then copy */ + do { + kar = data [++charnum + i]; + + } while ((i + charnum < len) && + (kar > '>' || (kar != '<' && kar != '>' + && kar != '&' && kar != ' ' + && kar != '\n' && kar != '\t'))); + g_string_append_len (html, &data[i], charnum); + i += (charnum - 1); + } + } + } + + g_string_append (html, "
"); + hyperlinkify_plain_text (html); + + return g_string_free (html, FALSE); +} + +GSList * +modest_text_utils_split_addresses_list (const gchar *addresses) +{ + gchar *current, *start, *last_blank; + GSList *result = NULL; + + start = (gchar *) addresses; + current = start; + last_blank = start; + + while (*current != '\0') { + if ((start == current)&&((*current == ' ')||(*current == ','))) { + start++; + last_blank = current; + } else if (*current == ',') { + gchar *new_address = NULL; + new_address = g_strndup (start, current - last_blank); + result = g_slist_prepend (result, new_address); + start = current + 1; + last_blank = start; + } else if (*current == '\"') { + if (current == start) { + current++; + start++; + } + while ((*current != '\"')&&(*current != '\0')) + current++; + } + + current++; + } + + if (start != current) { + gchar *new_address = NULL; + new_address = g_strndup (start, current - last_blank); + result = g_slist_prepend (result, new_address); + } + + result = g_slist_reverse (result); + return result; + +} + +void +modest_text_utils_address_range_at_position (const gchar *recipients_list, + gint position, + gint *start, + gint *end) +{ + gchar *current = NULL; + gint range_start = 0; + gint range_end = 0; + gint index; + gboolean is_quoted = FALSE; + + index = 0; + for (current = (gchar *) recipients_list; *current != '\0'; current = g_utf8_find_next_char (current, NULL)) { + gunichar c = g_utf8_get_char (current); + + if ((c == ',') && (!is_quoted)) { + if (index < position) { + range_start = index + 1; + } else { + break; + } + } else if (c == '\"') { + is_quoted = !is_quoted; + } else if ((c == ' ') &&(range_start == index)) { + range_start ++; + } + index ++; + range_end = index; + } + + if (start) + *start = range_start; + if (end) + *end = range_end; +} + + +/* ******************************************************************* */ +/* ************************* UTILIY FUNCTIONS ************************ */ +/* ******************************************************************* */ + +static GString * +get_next_line (const gchar * b, const gsize blen, const gchar * iter) +{ + GString *gs; + const gchar *i0; + + if (iter > b + blen) + return g_string_new(""); + + i0 = iter; + while (iter[0]) { + if (iter[0] == '\n') + break; + iter++; + } + gs = g_string_new_len (i0, iter - i0); + return gs; +} +static int +get_indent_level (const char *l) +{ + int indent = 0; + + while (l[0]) { + if (l[0] == '>') { + indent++; + if (l[1] == ' ') { + l++; + } + } else { + break; + } + l++; + + } + + /* if we hit the signature marker "-- ", we return -(indent + 1). This + * stops reformatting. + */ + if (strcmp (l, "-- ") == 0) { + return -1 - indent; + } else { + return indent; + } +} + +static void +unquote_line (GString * l) +{ + gchar *p; + + p = l->str; + while (p[0]) { + if (p[0] == '>') { + if (p[1] == ' ') { + p++; + } + } else { + break; + } + p++; + } + g_string_erase (l, 0, p - l->str); +} + +static void +append_quoted (GString * buf, int indent, const GString * str, + const int cutpoint) +{ + int i; + + indent = indent < 0 ? abs (indent) - 1 : indent; + for (i = 0; i <= indent; i++) { + g_string_append (buf, "> "); + } + if (cutpoint > 0) { + g_string_append_len (buf, str->str, cutpoint); + } else { + g_string_append (buf, str->str); + } + g_string_append (buf, "\n"); +} + +static int +get_breakpoint_utf8 (const gchar * s, gint indent, const gint limit) +{ + gint index = 0; + const gchar *pos, *last; + gunichar *uni; + + indent = indent < 0 ? abs (indent) - 1 : indent; + + last = NULL; + pos = s; + uni = g_utf8_to_ucs4_fast (s, -1, NULL); + while (pos[0]) { + if ((index + 2 * indent > limit) && last) { + g_free (uni); + return last - s; + } + if (g_unichar_isspace (uni[index])) { + last = pos; + } + pos = g_utf8_next_char (pos); + index++; + } + g_free (uni); + return strlen (s); +} + +static int +get_breakpoint_ascii (const gchar * s, const gint indent, const gint limit) +{ + gint i, last; + + last = strlen (s); + if (last + 2 * indent < limit) + return last; + + for (i = strlen (s); i > 0; i--) { + if (s[i] == ' ') { + if (i + 2 * indent <= limit) { + return i; + } else { + last = i; + } + } + } + return last; +} + +static int +get_breakpoint (const gchar * s, const gint indent, const gint limit) +{ + + if (g_utf8_validate (s, -1, NULL)) { + return get_breakpoint_utf8 (s, indent, limit); + } else { /* assume ASCII */ + //g_warning("invalid UTF-8 in msg"); + return get_breakpoint_ascii (s, indent, limit); + } +} + +static gchar * +cite (const time_t sent_date, const gchar *from) +{ + gchar sent_str[101]; + + /* format sent_date */ + modest_text_utils_strftime (sent_str, 100, "%c", sent_date); + return g_strdup_printf (N_("On %s, %s wrote:\n"), + sent_str, + (from) ? from : EMPTY_STRING); +} + + +static gchar * +modest_text_utils_quote_plain_text (const gchar *text, + const gchar *cite, + int limit) +{ + const gchar *iter; + gint indent, breakpoint, rem_indent = 0; + GString *q, *l, *remaining; + gsize len; + + /* remaining will store the rest of the line if we have to break it */ + q = g_string_new (cite); + remaining = g_string_new (""); + + iter = text; + len = strlen(text); + do { + l = get_next_line (text, len, iter); + iter = iter + l->len + 1; + indent = get_indent_level (l->str); + unquote_line (l); + + if (remaining->len) { + if (l->len && indent == rem_indent) { + g_string_prepend (l, " "); + g_string_prepend (l, remaining->str); + } else { + do { + breakpoint = + get_breakpoint (remaining->str, + rem_indent, + limit); + append_quoted (q, rem_indent, + remaining, breakpoint); + g_string_erase (remaining, 0, + breakpoint); + if (remaining->str[0] == ' ') { + g_string_erase (remaining, 0, + 1); + } + } while (remaining->len); + } + } + g_string_free (remaining, TRUE); + breakpoint = get_breakpoint (l->str, indent, limit); + remaining = g_string_new (l->str + breakpoint); + if (remaining->str[0] == ' ') { + g_string_erase (remaining, 0, 1); + } + rem_indent = indent; + append_quoted (q, indent, l, breakpoint); + g_string_free (l, TRUE); + } while ((iter < text + len) || (remaining->str[0])); + + return g_string_free (q, FALSE); +} + +static gchar* +modest_text_utils_quote_html (const gchar *text, + const gchar *cite, + int limit) +{ + const gchar *format = \ + "\n" \ + "\n" \ + "\n" \ + "%s" \ + "
\n%s\n
\n" \ + "\n" \ + "\n"; + + return g_strdup_printf (format, cite, text); +} + +static gint +cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2) +{ + return match2->offset - match1->offset; +} + + + +/* + * check if the match is inside an existing match... */ +static void +chk_partial_match (const url_match_t *match, guint* offset) +{ + if (*offset >= match->offset && *offset < match->offset + match->len) + *offset = -1; +} + +static GSList* +get_url_matches (GString *txt) +{ + regmatch_t rm; + guint rv, i, offset = 0; + GSList *match_list = NULL; + + static url_match_pattern_t patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS; + const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t); + + /* initalize the regexps */ + for (i = 0; i != pattern_num; ++i) { + patterns[i].preg = g_slice_new0 (regex_t); + + /* this should not happen */ + g_return_val_if_fail (regcomp (patterns[i].preg, patterns[i].regex, + REG_ICASE|REG_EXTENDED|REG_NEWLINE) == 0, NULL); + } + /* find all the matches */ + for (i = 0; i != pattern_num; ++i) { + offset = 0; + while (1) { + int test_offset; + if ((rv = regexec (patterns[i].preg, txt->str + offset, 1, &rm, 0)) != 0) { + g_return_val_if_fail (rv == REG_NOMATCH, NULL); /* this should not happen */ + break; /* try next regexp */ + } + if (rm.rm_so == -1) + break; + + /* FIXME: optimize this */ + /* to avoid partial matches on something that was already found... */ + /* check_partial_match will put -1 in the data ptr if that is the case */ + test_offset = offset + rm.rm_so; + g_slist_foreach (match_list, (GFunc)chk_partial_match, &test_offset); + + /* make a list of our matches ( tupels)*/ + if (test_offset != -1) { + url_match_t *match = g_slice_new (url_match_t); + match->offset = offset + rm.rm_so; + match->len = rm.rm_eo - rm.rm_so; + match->prefix = patterns[i].prefix; + match_list = g_slist_prepend (match_list, match); + } + offset += rm.rm_eo; + } + } + + for (i = 0; i != pattern_num; ++i) { + regfree (patterns[i].preg); + g_slice_free (regex_t, patterns[i].preg); + } /* don't free patterns itself -- it's static */ + + /* now sort the list, so the matches are in reverse order of occurence. + * that way, we can do the replacements starting from the end, so we don't need + * to recalculate the offsets + */ + match_list = g_slist_sort (match_list, + (GCompareFunc)cmp_offsets_reverse); + return match_list; +} + + + +static void +hyperlinkify_plain_text (GString *txt) +{ + GSList *cursor; + GSList *match_list = get_url_matches (txt); + + /* we will work backwards, so the offsets stay valid */ + for (cursor = match_list; cursor; cursor = cursor->next) { + + url_match_t *match = (url_match_t*) cursor->data; + gchar *url = g_strndup (txt->str + match->offset, match->len); + gchar *repl = NULL; /* replacement */ + + /* the prefix is NULL: use the one that is already there */ + repl = g_strdup_printf ("%s", + match->prefix ? match->prefix : EMPTY_STRING, + url, url); + + /* replace the old thing with our hyperlink + * replacement thing */ + g_string_erase (txt, match->offset, match->len); + g_string_insert (txt, match->offset, repl); + + g_free (url); + g_free (repl); + + g_slice_free (url_match_t, match); + } + + g_slist_free (match_list); +} + + + +gchar* +modest_text_utils_get_display_address (gchar *address) +{ + gchar *cursor; + + if (!address) + return NULL; + + g_return_val_if_fail (g_utf8_validate (address, -1, NULL), NULL); + + g_strchug (address); /* remove leading whitespace */ + + /* from display name */ + cursor = g_strstr_len (address, strlen(address), "<"); + if (cursor == address) /* there's nothing else? leave it */ + return address; + if (cursor) + cursor[0]='\0'; + + /* remove (bla bla) from display name */ + cursor = g_strstr_len (address, strlen(address), "("); + if (cursor == address) /* there's nothing else? leave it */ + return address; + if (cursor) + cursor[0]='\0'; + + g_strchomp (address); /* remove trailing whitespace */ + + return address; +} + + + +gint +modest_text_utils_get_subject_prefix_len (const gchar *sub) +{ + gint i; + static const gchar* prefix[] = { + "Re:", "RE:", "Fwd:", "FWD:", "FW:", NULL + }; + + if (!sub || (sub[0] != 'R' && sub[0] != 'F')) /* optimization */ + return 0; + + i = 0; + + while (prefix[i]) { + if (g_str_has_prefix(sub, prefix[i])) { + int prefix_len = strlen(prefix[i]); + if (sub[prefix_len] == ' ') + ++prefix_len; /* ignore space after prefix as well */ + return prefix_len; + } + ++i; + } + return 0; +} + + +gint +modest_text_utils_utf8_strcmp (const gchar* s1, const gchar *s2, gboolean insensitive) +{ + gint result = 0; + gchar *n1, *n2; + + /* work even when s1 and/or s2 == NULL */ + if (G_UNLIKELY(s1 == s2)) + return 0; + + /* if it's not case sensitive */ + if (!insensitive) + return strcmp (s1 ? s1 : "", s2 ? s2 : ""); + + n1 = g_utf8_collate_key (s1 ? s1 : "", -1); + n2 = g_utf8_collate_key (s2 ? s2 : "", -1); + + result = strcmp (n1, n2); + + g_free (n1); + g_free (n2); + + return result; +} + + +gchar* +modest_text_utils_get_display_date (time_t date) +{ + time_t now; + const guint BUF_SIZE = 64; + gchar date_buf[BUF_SIZE]; + gchar now_buf [BUF_SIZE]; + + now = time (NULL); + + modest_text_utils_strftime (date_buf, BUF_SIZE, "%x", date); + modest_text_utils_strftime (now_buf, BUF_SIZE, "%x", now); /* today */ + + /* if this is today, get the time instead of the date */ + if (strcmp (date_buf, now_buf) == 0) + modest_text_utils_strftime (date_buf, BUF_SIZE, _("%X"), date); + + return g_strdup(date_buf); +} + +gboolean +modest_text_utils_validate_email_address (const gchar *email_address) +{ + int count = 0; + const gchar *c = NULL, *domain = NULL; + static gchar *rfc822_specials = "()<>@,;:\\\"[]"; + + /* first we validate the name portion (name@domain) */ + for (c = email_address; *c; c++) { + if (*c == '\"' && + (c == email_address || + *(c - 1) == '.' || + *(c - 1) == '\"')) { + while (*++c) { + if (*c == '\"') + break; + if (*c == '\\' && (*++c == ' ')) + continue; + if (*c <= ' ' || *c >= 127) + return FALSE; + } + if (!*c++) + return FALSE; + if (*c == '@') + break; + if (*c != '.') + return FALSE; + continue; + } + if (*c == '@') + break; + if (*c <= ' ' || *c >= 127) + return FALSE; + if (strchr(rfc822_specials, *c)) + return FALSE; + } + if (c == email_address || *(c - 1) == '.') + return FALSE; + + /* next we validate the domain portion (name@domain) */ + if (!*(domain = ++c)) + return FALSE; + do { + if (*c == '.') { + if (c == domain || *(c - 1) == '.') + return FALSE; + count++; + } + if (*c <= ' ' || *c >= 127) + return FALSE; + if (strchr(rfc822_specials, *c)) + return FALSE; + } while (*++c); + + return (count >= 1) ? TRUE : FALSE; +} + + + + +gchar * +modest_text_utils_get_display_size (guint size) +{ + const guint KB=1024; + const guint MB=1024 * KB; + const guint GB=1024 * MB; + const guint TB=1024 * GB; + + if (size < KB) + return g_strdup_printf (_("%0.1f Kb"), (double)size / KB); + else if (size < MB) + return g_strdup_printf (_("%d Kb"), size / KB); + else if (size < GB) + return g_strdup_printf (_("%d Mb"), size / MB); + else if (size < TB) + return g_strdup_printf (_("%d Gb"), size/ GB); + else + return g_strdup_printf (_("Very big")); +} diff --git a/src/maemo/easysetup/modest-text-utils.h b/src/maemo/easysetup/modest-text-utils.h new file mode 100644 index 0000000..18dea34 --- /dev/null +++ b/src/maemo/easysetup/modest-text-utils.h @@ -0,0 +1,253 @@ +/* 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-text-utils.h */ + +#ifndef __MODEST_TEXT_UTILS_H__ +#define __MODEST_TEXT_UTILS_H__ + +#include +#include + +/** + * modest_text_utils_derived_subject: + * @subject: a string which contains the original subject + * @prefix: the prefix for the new subject (such as 'Re:' or 'Fwd:'), + * must not be NULL + * + * create a 'derived' subject line for eg. replies and forwards + * + * Returns: a newly allocated string containing the resulting subject + * subject == NULL, then @prefix " " will be returned + */ +gchar* modest_text_utils_derived_subject (const gchar *subject, + const gchar* prefix); + + +/** + * modest_text_utils_quote: + * @text: a non-NULL string which contains the message to quote + * @from: a non-NULL sender of the original message + * @content_type: the non-NULL content type for the quoting, e.g. "text/html" + * @sent_date: sent date/time of the original message + * @limit: specifies the maximum characters per line in the quoted text + * + * quote an existing message + * + * Returns: a newly allocated string containing the quoted message + */ +gchar* modest_text_utils_quote (const gchar *text, + const gchar *content_type, + const gchar *from, + const time_t sent_date, + int limit); + + +/** + * modest_text_utils_cited_text: + * @from: sender of the message + * @sent_date: the sent date of the original message + * @text: the text of the original message + * + * cite the text in a message + * + * Returns: a newly allocated string containing the cited text + */ +gchar* modest_text_utils_cite (const gchar *text, + const gchar *content_type, + const gchar *from, + time_t sent_date); + +/** + * modest_text_utils_inlined_text + * @from: the non-NULL sender of the original message + * @sent_date: sent date/time of the original message + * @to: + * @subject: + * @text: + * + * creates a new string with the "Original message" text prepended to + * the text passed as argument and some data of the header + * + * Returns: a newly allocated string containing the quoted message + */ +gchar* modest_text_utils_inline (const gchar *text, + const gchar *content_type, + const gchar *from, + time_t sent_date, + const gchar *to, + const gchar *subject); + +/** + * modest_text_utils_remove_address + * @address_list: none-NULL string with a comma-separated list of email addresses + * @address: an specific e-mail address + * + * remove a specific address from a list of email addresses; if @address + * is NULL, returns an unchanged @address_list + * + * Returns: a newly allocated string containing the new list, or NULL + * in case of error or the original @address_list was NULL + */ +gchar* modest_text_utils_remove_address (const gchar *address_list, + const gchar *address); + +/** + * modest_text_utils_address_range_at_position: + * @address_list: utf8 string containing a list of addresses + * @position: a gint + * @start: a gint pointer + * @end: a gint pointer + * + * Finds the start and end positions of the address at @position, + * in @recipients_list, a list of addresses in the format of a + * recipient list in email. It stores the results in @start and + * @end + */ +void modest_text_utils_address_range_at_position (const gchar *recipients_list, + gint position, + gint *start, + gint *end); + + +/** + * modest_text_utils_convert_to_html: + * @txt: a string which contains the message to quote + * + * convert plain text (utf8) into html + * + * Returns: a newly allocated string containing the html + */ +gchar* modest_text_utils_convert_to_html (const gchar *txt); + + +/** + * modest_text_utils_strftime: + * @s: + * @max: + * @fmt: + * @timet: + * + * this is just an alias for strftime(3), so we can use that without + * getting warning from gcc + * + * Returns: a formatted string of max length @max in @s + */ +size_t modest_text_utils_strftime(char *s, size_t max, const char *fmt, time_t timet); + + + +/** + * modest_text_utils_get_display_addres: + * @address: original address (UTF8 string) + * + * make a 'display address' from an address: + * "Foo Bar (Bla)" --> "Foo Bar" + * ie. removes "<...>" and "(...)" parts + * the change is in-place; removes leading/trailing whitespace + * + * Returns: the new address. The string is *not* newly allocated. + * NULL in case of error + */ +gchar* modest_text_utils_get_display_address (gchar *address); + + +/** + * modest_text_utils_get_subject_prefix_len: + * @subject: original subject (UTF8 string) + * + * determine the length of the "Re:/RE:/Fwd:" prefix in an e-mail address + * + * Returns: the length of the prefix, or 0 if there is none + */ +gint modest_text_utils_get_subject_prefix_len (const gchar *subject); + + +/** + * modest_text_utils_utf8_strcmp: + * @s1: the first string + * @s2: the second string + * @insensitive: should the comparison be case-insensitive? + * + * a strcmp that is NULL-safe, can deal with UTF8 and case-insensitive comparison + * + * Returns: an integer less than, equal to, or greater than zero if s1 is found, + * respectively, to be less than, to match, or be greater than s2. + */ +gint modest_text_utils_utf8_strcmp (const gchar* s1, const gchar *s2, gboolean insensitive); + + + +/** + * modest_text_utils_get_display_date: + * @date: the date to display + * + * get a string representation for a date. + * + * Returns: the new display date, as a newly allocated string; + * free with g_free + */ +gchar* modest_text_utils_get_display_date (time_t date); + + +/** + * modest_text_utils_get_display_size: + * @size: size in bytes + * + * get a string representation for a size in bytes. + * + * Returns: the newly allocated display string for the + * size in bytes. must be freed. + */ +gchar * modest_text_utils_get_display_size (guint size); + + +/** + * modest_text_utils_validate_email_address: + * @email_address: a string + * + * validates the email address passed as argument + * + * Returns: TRUE if the address is valid, FALSE otherwise + **/ +gboolean modest_text_utils_validate_email_address (const gchar *email_address); + +/** + * modest_text_utils_split_addresses_list: + * @addresses: a string + * + * obtains a GSList of addresses from a string of addresses + * in the format understood by email protocols + * + * Returns: a GSList of strings + **/ +GSList *modest_text_utils_split_addresses_list (const gchar *addresses); + +#endif /* __MODEST_TEXT_UTILS_H__ */ diff --git a/src/maemo/easysetup/modest-validating-entry.c b/src/maemo/easysetup/modest-validating-entry.c new file mode 100644 index 0000000..79f2ea3 --- /dev/null +++ b/src/maemo/easysetup/modest-validating-entry.c @@ -0,0 +1,205 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#include "modest-validating-entry.h" +#include /* For the gtk_signal_stop_emit_by_name() convenience function. */ +#include /* For strlen(). */ + +G_DEFINE_TYPE (EasysetupValidatingEntry, easysetup_validating_entry, GTK_TYPE_ENTRY); + +#define VALIDATING_ENTRY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_VALIDATING_ENTRY, EasysetupValidatingEntryPrivate)) + +typedef struct _EasysetupValidatingEntryPrivate EasysetupValidatingEntryPrivate; + +struct _EasysetupValidatingEntryPrivate +{ + /* A list of gunichar, rather than char*, + * because gunichar is easier to deal with internally, + * but gchar* is easier to supply from the external interface. + */ + GList *list_prevent; + + gboolean prevent_whitespace; +}; + +static void +easysetup_validating_entry_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_validating_entry_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_validating_entry_dispose (GObject *object) +{ + if (G_OBJECT_CLASS (easysetup_validating_entry_parent_class)->dispose) + G_OBJECT_CLASS (easysetup_validating_entry_parent_class)->dispose (object); +} + +static void +easysetup_validating_entry_finalize (GObject *object) +{ + EasysetupValidatingEntryPrivate *priv = VALIDATING_ENTRY_GET_PRIVATE (object); + + /* Free the list and its items: */ + if (priv->list_prevent) { + g_list_foreach (priv->list_prevent, (GFunc)&g_free, NULL); + g_list_free (priv->list_prevent); + } + + G_OBJECT_CLASS (easysetup_validating_entry_parent_class)->finalize (object); +} + +static void +easysetup_validating_entry_class_init (EasysetupValidatingEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EasysetupValidatingEntryPrivate)); + + object_class->get_property = easysetup_validating_entry_get_property; + object_class->set_property = easysetup_validating_entry_set_property; + object_class->dispose = easysetup_validating_entry_dispose; + object_class->finalize = easysetup_validating_entry_finalize; +} + +static gint +on_list_compare(gconstpointer a, gconstpointer b) +{ + gunichar* unichar_a = (gunichar*)(a); + gunichar* unichar_b = (gunichar*)(b); + if(*unichar_a == *unichar_b) + return 0; + else + return -1; /* Really, we should return > and <, but we don't use this for sorting. */ +} + +static void +on_insert_text(GtkEditable *editable, + gchar *new_text, gint new_text_length, + gint *position, + gpointer user_data) +{ + EasysetupValidatingEntry *self = EASYSETUP_VALIDATING_ENTRY (user_data); + EasysetupValidatingEntryPrivate *priv = VALIDATING_ENTRY_GET_PRIVATE (self); + + if(!new_text_length) + return; + + /* Note: new_text_length is documented as the number of bytes, not characters. */ + if(!g_utf8_validate (new_text, new_text_length, NULL)) + return; + + /* Look at each UTF-8 character in the text (it could be several via a drop or a paste), + * and check them */ + gboolean allow = TRUE; + gchar *iter = new_text; /* new_text seems to be NULL-terminated, though that is not documented. */ + while (iter) + { + if(priv->list_prevent) { + /* If the character is in our prevent list, + * then do not allow this text to be entered. + * + * This prevents entry of all text, without removing the unwanted characters. + * It is debatable whether that is the best thing to do. + */ + gunichar one_char = g_utf8_get_char (iter); + GList *found = g_list_find_custom(priv->list_prevent, &one_char, &on_list_compare); + if(found) { + allow = FALSE; + break; + } + } + + if(priv->prevent_whitespace) { + /* Check for whitespace characters: */ + gunichar one_char = g_utf8_get_char (iter); + if (g_unichar_isspace (one_char)) { + allow = FALSE; + break; + } + } + + /* Crashes. Don't know why: iter = g_utf8_next_char (iter); + * Maybe it doesn't check for null-termination. */ + iter = g_utf8_find_next_char (iter, new_text + new_text_length); + } + + if(!allow) { + /* The signal documentation says + * "by connecting to this signal and then stopping the signal with + * gtk_signal_emit_stop(), it is possible to modify the inserted text, + * or prevent it from being inserted entirely." + */ + gtk_signal_emit_stop_by_name (GTK_OBJECT (self), "insert-text"); + } +} + +static void +easysetup_validating_entry_init (EasysetupValidatingEntry *self) +{ + /* Connect to the GtkEditable::insert-text signal + * so we can filter out some characters: + * We connect _before_ so we can stop the default signal handler from running. + */ + g_signal_connect (G_OBJECT (self), "insert-text", (GCallback)&on_insert_text, self); +} + +EasysetupValidatingEntry* +easysetup_validating_entry_new (void) +{ + return g_object_new (EASYSETUP_TYPE_VALIDATING_ENTRY, NULL); +} + +/** Specify characters that may not be entered into this GtkEntry. + * + * list: A list of gchar* strings. Each one identifies a UTF-8 character. + */ +void easysetup_validating_entry_set_unallowed_characters (EasysetupValidatingEntry *self, GList *list) +{ + EasysetupValidatingEntryPrivate *priv = VALIDATING_ENTRY_GET_PRIVATE (self); + + /* Free the list and its items: */ + if (priv->list_prevent) { + g_list_foreach (priv->list_prevent, (GFunc)&g_free, NULL); + g_list_free (priv->list_prevent); + } + + /* Do a deep copy of the list, converting gchar* to gunichar: */ + priv->list_prevent = NULL; + GList *iter = NULL; + for (iter = list; iter != NULL; iter = iter->next) { + gunichar *one_char = g_new0 (gunichar, 1); + if(iter->data) + *one_char = g_utf8_get_char ((gchar*)iter->data); + else + *one_char = 0; + + priv->list_prevent = g_list_append (priv->list_prevent, one_char); + } +} + +/** Specify that no whitespace characters may be entered into this GtkEntry. + * + */ +void easysetup_validating_entry_set_unallowed_characters_whitespace (EasysetupValidatingEntry *self) +{ + EasysetupValidatingEntryPrivate *priv = VALIDATING_ENTRY_GET_PRIVATE (self); + priv->prevent_whitespace = TRUE; +} diff --git a/src/maemo/easysetup/modest-validating-entry.h b/src/maemo/easysetup/modest-validating-entry.h new file mode 100644 index 0000000..e442841 --- /dev/null +++ b/src/maemo/easysetup/modest-validating-entry.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + */ + +#ifndef _EASYSETUP_VALIDATING_ENTRY +#define _EASYSETUP_VALIDATING_ENTRY + +#include + +G_BEGIN_DECLS + +#define EASYSETUP_TYPE_VALIDATING_ENTRY easysetup_validating_entry_get_type() + +#define EASYSETUP_VALIDATING_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + EASYSETUP_TYPE_VALIDATING_ENTRY, EasysetupValidatingEntry)) + +#define EASYSETUP_VALIDATING_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + EASYSETUP_TYPE_VALIDATING_ENTRY, EasysetupValidatingEntryClass)) + +#define EASYSETUP_IS_VALIDATING_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + EASYSETUP_TYPE_VALIDATING_ENTRY)) + +#define EASYSETUP_IS_VALIDATING_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + EASYSETUP_TYPE_VALIDATING_ENTRY)) + +#define EASYSETUP_VALIDATING_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + EASYSETUP_TYPE_VALIDATING_ENTRY, EasysetupValidatingEntryClass)) + +typedef struct { + GtkEntry parent; +} EasysetupValidatingEntry; + +typedef struct { + GtkEntryClass parent_class; +} EasysetupValidatingEntryClass; + +GType easysetup_validating_entry_get_type (void); + +EasysetupValidatingEntry* easysetup_validating_entry_new (void); + +void easysetup_validating_entry_set_unallowed_characters (EasysetupValidatingEntry *self, GList *list); +void easysetup_validating_entry_set_unallowed_characters_whitespace (EasysetupValidatingEntry *self); + +G_END_DECLS + +#endif /* _EASYSETUP_VALIDATING_ENTRY */ diff --git a/src/maemo/easysetup/modest-wizard-dialog.c b/src/maemo/easysetup/modest-wizard-dialog.c new file mode 100644 index 0000000..5283e61 --- /dev/null +++ b/src/maemo/easysetup/modest-wizard-dialog.c @@ -0,0 +1,536 @@ +/* + * This is a copy of modest-wizard-dialog.h with a rename and some API additions, + * for osso-modest-easysetup. + * + * This file was part of modest-libs + * + * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved. + * + */ + +/** + * SECTION:modest-wizard-dialog + * @short_description: A widget to create a guided installation + * process wizard + * + * #ModestWizardDialog is a widget to create a guided installation + * process. The dialog has four standard buttons, previous, next, + * finish, cancel, and contains several pages with optional icons. + * Response buttons are dimmed/undimmed automatically and the standard + * icon is shown/hidden in response to page navigation. The notebook + * widget provided by users contains the actual wizard pages. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "modest-wizard-dialog.h" + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* Specify the hildon-libs translation domain, + * so we can reuse its translations + * instead of repeating them in our own translations. + */ +/* #define _(String) dgettext(PACKAGE, String) */ + +#define _(String) dgettext("hildon-libs", String) + +static GtkDialogClass *parent_class; + +static void class_init (ModestWizardDialogClass *wizard_dialog_class); + +static void init (ModestWizardDialog *wizard_dialog); + +static void create_title (ModestWizardDialog *wizard_dialog); + +static void set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void finalize (GObject *object); + +static void response (ModestWizardDialog *wizard, + gint response_id, + gpointer unused); + +static void make_buttons_sensitive (ModestWizardDialog *wizard_dialog, + gboolean previous, + gboolean finish, + gboolean next); + +static gboolean invoke_before_next_vfunc (ModestWizardDialog *wizard_dialog); +static void invoke_enable_buttons_vfunc (ModestWizardDialog *wizard_dialog); + +enum { + PROP_ZERO, + PROP_WIZARD_NAME, + PROP_WIZARD_NOTEBOOK, + PROP_WIZARD_AUTOTITLE +}; + +struct _ModestWizardDialogPrivate { + gchar *wizard_name; + GtkNotebook *notebook; + GtkBox *box; + GtkWidget *image; + gboolean autotitle; +}; + + +GType +modest_wizard_dialog_get_type (void) +{ + static GType wizard_dialog_type = 0; + + if (!wizard_dialog_type) { + + static const GTypeInfo wizard_dialog_info = { + sizeof (ModestWizardDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (ModestWizardDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) init, + }; + + wizard_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, + "ModestWizardDialog", + &wizard_dialog_info, + 0); + } + + return wizard_dialog_type; +} + +static void +class_init (ModestWizardDialogClass *wizard_dialog_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wizard_dialog_class); + + parent_class = g_type_class_peek_parent (wizard_dialog_class); + + g_type_class_add_private (wizard_dialog_class, + sizeof(ModestWizardDialogPrivate)); + + /* Override virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /** + * ModestWizardDialog:wizard-name: + * + * The name of the wizard. + */ + g_object_class_install_property (object_class, PROP_WIZARD_NAME, + g_param_spec_string + ("wizard-name", + "Wizard Name", + "The name of the ModestWizardDialog", + NULL, + G_PARAM_READWRITE)); + + /** + * ModestWizardDialog:wizard-notebook: + * + * The notebook object, which is used by the ModestWizardDialog. + */ + g_object_class_install_property(object_class, PROP_WIZARD_NOTEBOOK, + g_param_spec_object + ("wizard-notebook", + "Wizard Notebook", + "GtkNotebook object to be used in the " + "ModestWizardDialog", + GTK_TYPE_NOTEBOOK, G_PARAM_READWRITE)); + + /** + * ModestWizardDialog:autotitle + * + * If the wizard should automatically try to change the window title when changing steps. + * Set to FALSE if you'd like to override the default behaviour. + * + * Since: 0.14.5 + */ + g_object_class_install_property(object_class, PROP_WIZARD_AUTOTITLE, + g_param_spec_boolean + ("autotitle", + "AutoTitle", + "If the wizard should autotitle itself", + TRUE, + G_PARAM_READWRITE)); +} + +static void +finalize (GObject *object) +{ + ModestWizardDialog *dialog = MODEST_WIZARD_DIALOG (object); + g_return_if_fail (dialog != NULL); + + if (dialog->priv->wizard_name != NULL) + g_free (MODEST_WIZARD_DIALOG (object)->priv->wizard_name); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize(object); +} + +/* Disable or enable the Previous, Next and Finish buttons */ +static void +make_buttons_sensitive (ModestWizardDialog *wizard_dialog, + gboolean previous, + gboolean finish, + gboolean next) +{ + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + MODEST_WIZARD_DIALOG_PREVIOUS, + previous); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + MODEST_WIZARD_DIALOG_FINISH, + finish); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + MODEST_WIZARD_DIALOG_NEXT, + next); +} + +static void +init (ModestWizardDialog *wizard_dialog) +{ + /* Initialize private structure for faster member access */ + ModestWizardDialogPrivate *priv = + G_TYPE_INSTANCE_GET_PRIVATE (wizard_dialog, + MODEST_TYPE_WIZARD_DIALOG, + ModestWizardDialogPrivate); + + GtkDialog *dialog = GTK_DIALOG (wizard_dialog); + + /* Init internal widgets */ + GtkWidget *vbox = gtk_vbox_new (FALSE, 0); + gtk_dialog_set_has_separator (dialog, FALSE); + wizard_dialog->priv = priv; + priv->box = GTK_BOX (gtk_hbox_new (FALSE, 0)); + priv->image = gtk_image_new_from_icon_name ("qgn_widg_wizard", + HILDON_ICON_SIZE_WIDG_WIZARD); + + /* Default values for user provided properties */ + priv->notebook = NULL; + priv->wizard_name = NULL; + priv->autotitle = TRUE; + + /* Build wizard layout */ + gtk_box_pack_start_defaults (GTK_BOX (dialog->vbox), GTK_WIDGET (priv->box)); + gtk_box_pack_start_defaults (GTK_BOX (priv->box), GTK_WIDGET (vbox)); + gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->image), FALSE, FALSE, 0); + + /* Add response buttons: finish, previous, next, cancel */ + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_finish"), MODEST_WIZARD_DIALOG_FINISH); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_previous"), MODEST_WIZARD_DIALOG_PREVIOUS); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_next"), MODEST_WIZARD_DIALOG_NEXT); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_cancel"), MODEST_WIZARD_DIALOG_CANCEL); + + /* Set initial button states: previous and finish buttons are disabled */ + make_buttons_sensitive (wizard_dialog, FALSE, FALSE, TRUE); + + /* Show all the internal widgets */ + gtk_widget_show_all (GTK_WIDGET (dialog->vbox)); + + /* connect to dialog's response signal */ + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (response), NULL); +} + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ModestWizardDialogPrivate *priv = MODEST_WIZARD_DIALOG(object)->priv; + + switch (property_id) { + + case PROP_WIZARD_AUTOTITLE: + + priv->autotitle = g_value_get_boolean (value); + + if (priv->autotitle && + priv->wizard_name && + priv->notebook) + create_title (MODEST_WIZARD_DIALOG (object)); + else if (priv->wizard_name) + gtk_window_set_title (GTK_WINDOW (object), priv->wizard_name); + + break; + + case PROP_WIZARD_NAME: + + /* Set new wizard name. This name will appear in titlebar */ + if (priv->wizard_name) + g_free (priv->wizard_name); + + gchar *str = (gchar *) g_value_get_string (value); + g_return_if_fail (str != NULL); + + priv->wizard_name = g_strdup (str); + + /* We need notebook in order to create title, since page information + is used in title generation */ + + if (priv->notebook && priv->autotitle) + create_title (MODEST_WIZARD_DIALOG (object)); + + break; + + case PROP_WIZARD_NOTEBOOK: { + + GtkNotebook *book = GTK_NOTEBOOK (g_value_get_object (value)); + g_return_if_fail (book != NULL); + + priv->notebook = book; + + /* Set the default properties for the notebook (disable tabs, + * and remove borders) to make it look like a nice wizard widget */ + gtk_notebook_set_show_tabs (priv->notebook, FALSE); + gtk_notebook_set_show_border (priv->notebook, FALSE); + gtk_box_pack_start_defaults (GTK_BOX( priv->box), GTK_WIDGET (priv->notebook)); + + /* Show the notebook so that a gtk_widget_show on the dialog is + * all that is required to display the dialog correctly */ + gtk_widget_show ( GTK_WIDGET (priv->notebook)); + + /* Update dialog title to reflect current page stats etc */ + if (priv->wizard_name && priv->autotitle) + create_title (MODEST_WIZARD_DIALOG (object)); + + } break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ModestWizardDialogPrivate *priv = MODEST_WIZARD_DIALOG (object)->priv; + + switch (property_id) { + + case PROP_WIZARD_NAME: + g_value_set_string (value, priv->wizard_name); + break; + + case PROP_WIZARD_NOTEBOOK: + g_value_set_object (value, priv->notebook); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* + * Creates the title of the dialog taking into account the current + * page of the notebook. + */ +static void +create_title (ModestWizardDialog *wizard_dialog) +{ + gint pages, current; + gchar *str = NULL; + ModestWizardDialogPrivate *priv = wizard_dialog->priv; + GtkNotebook *notebook = priv->notebook; + + if (!notebook) + return; + + /* Get page information, we'll need that when creating title */ + pages = gtk_notebook_get_n_pages (notebook); + current = gtk_notebook_get_current_page (priv->notebook); + if (current < 0) + current = 0; + + /* the welcome title on the initial page */ + if (current == 0) { + str = g_strdup_printf (_("ecdg_ti_wizard_welcome"), + priv->wizard_name, pages); + } else { + const gchar *steps = gtk_notebook_get_tab_label_text (notebook, + gtk_notebook_get_nth_page (notebook, current)); + + str = g_strdup_printf (_("ecdg_ti_wizard_step"), + priv->wizard_name, current + 1, pages, steps); + } + + /* Update the dialog to display the generated title */ + gtk_window_set_title (GTK_WINDOW (wizard_dialog), str); + g_free (str); +} + +/* + * Response signal handler. This function is needed because GtkDialog's + * handler for this signal closes the dialog and we don't want that, we + * want to change pages and, dimm certain response buttons. Overriding the + * virtual function would not work because that would be called after the + * signal handler implemented by GtkDialog. + * FIXME: There is a much saner way to do that [MDK] + */ +static void +response (ModestWizardDialog *wizard_dialog, + gint response_id, + gpointer unused) +{ + ModestWizardDialogPrivate *priv = wizard_dialog->priv; + GtkNotebook *notebook = priv->notebook; + gint current = 0; + gboolean is_first, is_last; + + switch (response_id) { + + case MODEST_WIZARD_DIALOG_PREVIOUS: + gtk_notebook_prev_page (notebook); /* go to previous page */ + break; + + case MODEST_WIZARD_DIALOG_NEXT: + if (invoke_before_next_vfunc (wizard_dialog)) + gtk_notebook_next_page (notebook); /* go to next page */ + + break; + + case MODEST_WIZARD_DIALOG_CANCEL: + return; + break; + case MODEST_WIZARD_DIALOG_FINISH: + if (invoke_before_next_vfunc (wizard_dialog)) + return; + + break; + + } + + current = gtk_notebook_get_current_page (notebook); + gint last = gtk_notebook_get_n_pages (notebook) - 1; + is_last = current == last; + is_first = current == 0; + + /* If first page, previous and finish are disabled, + if last page, next is disabled */ + make_buttons_sensitive (wizard_dialog, + !is_first /* previous */, !is_first /* finish */, !is_last /* next*/); + + /* Allow derived classes to disable buttons to prevent navigation, + * according to their own validation logic: */ + invoke_enable_buttons_vfunc (wizard_dialog); + + /* Don't let the dialog close */ + g_signal_stop_emission_by_name (wizard_dialog, "response"); + + /* We show the default image on first and last pages */ + last = gtk_notebook_get_n_pages (notebook) - 1; + if (current == last || current == 0) + gtk_widget_show (GTK_WIDGET(priv->image)); + else + gtk_widget_hide (GTK_WIDGET(priv->image)); + + /* New page number may appear in the title, update it */ + if (priv->autotitle) + create_title (wizard_dialog); +} + +/** + * modest_wizard_dialog_new: + * @parent: a #GtkWindow + * @wizard_name: the name of dialog + * @notebook: the notebook to be shown on the dialog + * + * Creates a new #ModestWizardDialog. + * + * Returns: a new #ModestWizardDialog + */ +GtkWidget* +modest_wizard_dialog_new (GtkWindow *parent, + const char *wizard_name, + GtkNotebook *notebook) +{ + GtkWidget *widget; + + g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL); + + widget = GTK_WIDGET (g_object_new + (MODEST_TYPE_WIZARD_DIALOG, + "wizard-name", wizard_name, + "wizard-notebook", notebook, NULL)); + + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (widget), parent); + + return widget; +} + +static gboolean +invoke_before_next_vfunc (ModestWizardDialog *wizard_dialog) +{ + ModestWizardDialogClass *klass = MODEST_WIZARD_DIALOG_GET_CLASS (wizard_dialog); + + /* Call the vfunc, which may be overridden by derived classes: */ + if (klass->before_next) { + ModestWizardDialogPrivate *priv = MODEST_WIZARD_DIALOG(wizard_dialog)->priv; + + gint current_page_num = gtk_notebook_get_current_page (priv->notebook); + + /* Get widgets for the two pages: */ + GtkWidget* current_page_widget = gtk_notebook_get_nth_page (priv->notebook, current_page_num); + + GtkWidget* next_page_widget = NULL; + if ((current_page_num + 1) < gtk_notebook_get_n_pages (priv->notebook)) + next_page_widget = gtk_notebook_get_nth_page (priv->notebook, current_page_num + 1); + + /* Ask the vfunc implementation whether navigation should be allowed: */ + return (*(klass->before_next))(wizard_dialog, current_page_widget, next_page_widget); + } + + /* Allow navigation by default if there is no vfunc implementation: */ + return TRUE; +} + +static void +invoke_enable_buttons_vfunc (ModestWizardDialog *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) { + ModestWizardDialogPrivate *priv = MODEST_WIZARD_DIALOG(wizard_dialog)->priv; + + gint current_page_num = gtk_notebook_get_current_page (priv->notebook); + + GtkWidget* current_page_widget = gtk_notebook_get_nth_page (priv->notebook, current_page_num); + + (*(klass->enable_buttons))(wizard_dialog, current_page_widget); + } +} diff --git a/src/maemo/easysetup/modest-wizard-dialog.h b/src/maemo/easysetup/modest-wizard-dialog.h new file mode 100644 index 0000000..772e97e --- /dev/null +++ b/src/maemo/easysetup/modest-wizard-dialog.h @@ -0,0 +1,85 @@ +/* + * This is a copy of modest-wizard-dialog.h with a rename and some API additions, + * for osso-modest-easysetup. + * + * This file was part of modest-libs + * + * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved. + * + */ + +#ifndef __MODEST_WIZARD_DIALOG_H__ +#define __MODEST_WIZARD_DIALOG_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define MODEST_TYPE_WIZARD_DIALOG (modest_wizard_dialog_get_type()) + +#define MODEST_WIZARD_DIALOG(obj) (GTK_CHECK_CAST ((obj), \ + MODEST_TYPE_WIZARD_DIALOG, ModestWizardDialog)) + +#define MODEST_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ + MODEST_TYPE_WIZARD_DIALOG, ModestWizardDialogClass)) + +#define MODEST_IS_WIZARD_DIALOG(obj) (GTK_CHECK_TYPE ((obj), \ + MODEST_TYPE_WIZARD_DIALOG)) + +#define MODEST_IS_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \ + MODEST_TYPE_WIZARD_DIALOG)) + +#define MODEST_WIZARD_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + MODEST_TYPE_WIZARD_DIALOG, ModestWizardDialogClass)) + +typedef struct _ModestWizardDialog ModestWizardDialog; + +typedef struct _ModestWizardDialogClass ModestWizardDialogClass; + +typedef struct _ModestWizardDialogPrivate ModestWizardDialogPrivate; + +/* button response IDs */ +enum { + MODEST_WIZARD_DIALOG_CANCEL = GTK_RESPONSE_CANCEL, + MODEST_WIZARD_DIALOG_PREVIOUS = 0, + MODEST_WIZARD_DIALOG_NEXT, + MODEST_WIZARD_DIALOG_FINISH +}; + +struct _ModestWizardDialog { + GtkDialog parent; + ModestWizardDialogPrivate *priv; +}; + +struct _ModestWizardDialogClass { + GtkDialogClass parent_class; + + /** Implementations of this vfunc should prepare the next page if necessary, + * and only return TRUE if the navigation should be allowed. + * You may even change the next page, via the GtkNotebook API, in the signal handler. */ + gboolean (* before_next) (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page); + + /** Implementations of this vfunc should enable or disable + * the next/forward buttons appropriately, based on the entered data. */ + void (* enable_buttons) (ModestWizardDialog *dialog, GtkWidget *current_page); + + + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType modest_wizard_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget* modest_wizard_dialog_new (GtkWindow *parent, + const char *wizard_name, + GtkNotebook *notebook); + +G_END_DECLS + +#endif /* __MODEST_WIZARD_DIALOG_H__ */ diff --git a/src/maemo/easysetup/osso_countries_1.0.mo b/src/maemo/easysetup/osso_countries_1.0.mo new file mode 100644 index 0000000000000000000000000000000000000000..a0a427bb1fe24478c17f044b031b2f6c0e56fe1c GIT binary patch literal 13730 zcmai(378~hdB=;(#YL_aR$@?#4c7v*?7`(O8<=aCWoMRQdv>|gRCm{O*G_j;Z&mdS zGX#M^07XbZkt2j73Md#66;KcY64X@^AVv~F2*!{{LVVzX5KSK8$?sqF^~{p`M(gRf ze)Zk=@xJ}if}O8(cwR>Km&|jV6+6H^aPa(Mf#du>d=-8O?()H$AAujmeYA0p!iBh- za6fnn`~!G1{5|*>RQl)PzVJ=szw17^{~~xG{ws~UY&Z!&jQ^iO<$JgBf5PwusB+(e z%6C35mE%JBA7|XBz=Ltuq4K%fgx_WSAB6|t|B4BpM`HDd3zgq$sC1hQL&(p$oR{i- z3sgOyfa;f*;GysxNY$K!$%L$(RfeZR zIX+am7n$(upyJ;P)eqk_?pL7l{|!{V7tp!N?{KL61`W@Fiq|pWS3>1~hv7p|`9BR6 z@86-)|HioYp|J`-461&;Q1Q-&DmR8y!MPGD-d*rx@KLC8UNZh~LFGH2Mu>|HS3>2t z5fa5|K(*sCsPb+z;SU@4vry&yCsg@6QJA3RXuWeB6c^RsGZ$ri3gGsLN1EC97L4}_U6~6;j&ZnT_-D$!fG5*g%74J2ua`vW?i(wBu0-gqy|D{myZ_UmO3u2voddpu$gu>Yos*T~`?14jCfnA*l4vL&bj+s=Phf{FLq>DEA3a={Fhw z5UM|}fU5VckSaJ28~>M~>hUY6bPEn~oR7o9q2l{c`Cbgw57!&_w;)~NJPlQ^x1h?| zjlop?7D0{c3B2UrfQok^RQcD#CGgwuF!&lAfD7r=!{J#FFXwWo{{1Rc`WK<<`?hiK zMPjx8P^kL%LDlmtsCr)jRsLs8_}y^h4(#V}H~bfp`8>GD@Gz(&a=CH$!uR1`2X}=d zkR#4H19EgaEvWPt!Cl}L@cr;=<9`Fx{JhP$?>Bq|&d2{rsC=I>{y#DN8C1EiLgo90 z@&9k*|E_WG(v!Ducc^?0gi6Qb;m+_SsQUff@KvaKybhKBuc6A*U@M>9;qGuhDF1_@;;n$nZxvMeC&E48 zTIj;fQ1K?A^1smV3aD|o1}gtAK*hTks$LI5jq@W={jkl1zhL-tsQg}os@H!()nmsa z^L*w()n`wr@P%+Mc%bn=8mheG4F{mg9fFz%8==ZQ8!DgB_;;YvT?ke0%c07>)`VXV z75{dqa=&QY4?yMr2vohFfU3_^Q2D)R_zG0KUqaR6EvWq8G2D?$h4P;V6>kry^!ph1 z{w918RQ(nk|D&MFT?sXQ{ZRRgz&+tOQ6cV5~_XIK-KeBsPeu9 zmH#)4`*Empo`Nd>M}|LzD(@Aj{Qd*(1>brnacwIc8Dg;4PifEveRp~@XF{zFjXQ!(K!sQ#IT zYS*QPS3%9I&q1ZX6Dq&2K$Z6}RJzBF`-f2JpEdr^L-ohMLDl;;sC2(F{_jB5W9Ost zbbCVOw;x;p7eU288mb>w8TT;!Anp=Wz3NcqL{RmcfEw3JjQ`D0@jegtf%iZcJ_dDO z{tWH`--W9G?nme87ea*}36*{bs=lMfU52V}9V*>csCrIA)%(*>^}5!C-v~MWva=gF z7bCaogXgRq**oCwt;*{yf}k;8cwu19ol(sN^u z?EN|3nx}fci0qbq<#Xt4zW)KyeAH7zjz9*GzOcg>UJpa${l>kY;mL45vbS+RVt4`E zANd-x1!*G}B0C|wAXVg#kTK+65Ir&SJ>;v%Pmr6C^O27sryxH<{u0siS>&VHm*ac_ z4x4Y`0llImiORJ~xf*rCG@dGZWA%m?21)9L#js|DAkX4o_hXxX3-78ImJ_cPS(1gd zD2{FZ^{8p}?gUM1KpNCLUfBz4<%$p`bg%*byB)4s(!v{lHDTeg0$G&;7KREe6wgr&18QNmbcBiZodX}=y#*v709rOBjc z8O%!TO$W_lo#P-4l16zVi0eUE4w5Ew#nKaTC-j4IP2H4uP0!LNoo3y$jdGKuT_a^mTn-xkE5tK?kpzHGP~u?+BNMeCvDrDsd{a{JmJT+;+R&w zsTRw0u70VqbeQz)4f%4Oa~fA0Uai>5M$ohr*{}_4HEKq!imgYYRuo$%bv25{=dO3e zHda=hi=rg} zKVnlWPEd|y*7Q`Nays5Eu>-cwX6h9OtsYe(D&)^S6Y8<=Tbe6xd;bt(-Nrb?Yko88 zw2OU5P;ocLGxb|+)Wt^HCrdtu%9Via-EtDvJ5#p4X?UC-g(4bJSnI@=Gn;@qn?_hK zCh3Hn9>pOEsvOOhc@%JH6x)Wc2E-P^yekwM#NO7TXA*mU@th1&uUV|#7Op0?O=64J zwv@Leifb0{ac|liZ&cP1IEVv?!2J~ch} z3~qXsqowJkwkt~0=kjGanwx$SrH$gI+zcw#%Q60zRyPBVgwzj{)VJKSnnBv=Sg+vC z&UrqUiB4RcbuF*z6|2?a9#Qv_s%6D%MNJm_UEWi+X-7aUnDC4DDFUq7q{Y$Z+)5f= zvpMGmOa!j)!PZW3Z)kZP4gqVoS{%yXG@`@*rpH=KTUiT zoZ@`cU8ZWyYg(JUwUKO1^g&^2hh8hN9Sb3y(kaIF+g@?mha8H2Y`+t47sj|Az3c1lYwZIn}W!W>tacHRTUO0|8<5VpBa2kkbOq2hw$ z@?h)aHl5R{TL!+}@#8eo4Y{}ywtBYPK=aSp^g1c z7+Ch&Si@zR1=8CX{qmS!^L25yB}H#UZ~iUUnFQr2EsqCjnq-P-=uZU2uFhjMJ5@_H z^00Qm;`g>3XUgOKtL)=(tj`vZ(pp$U3@qD@sCpHR;3R5GGz!PNP;{hc;2Ff#qt& zRj3w}nS-`%B=JMvHgnk6h@Ll&eNM4rO9lL?YQwi~8HswwD>r?1+rpAb0xn9-T1!Zi z*)(qJa{{b(oJ1;RG`Dh_FqdrGcdq>9DsQoZRt-CegEA{(yg1zxY$L_}CE?s+%doU^ zQf3U>QcfnB+LoLqgA_ZHJ;{`I#B6})z5%6Pz``iBGxfFvbL@dB*J5jVTFzrpj0K}S z)u~6=S|(=7)waQXWR8PEDJP`w+G@fzs(6s55ohmjUCn5L_2PJ7sSAUeSIZ`F8dW@t zHl4Ef*seP%rXIhzS<73NMC%n-f%$Gya zan(;Pr-Cg~*{gKQwFYaxFy_|iHOv}wM#b_~$6}ztW&85daz*zs3~jU}zo_eEp6j?U z<-O-b@WN^925;ih$23&s$xvp~O|pnd*+l#uc0X=PsFKAY?MzqvIcEQa7ovO??*QyU z{xo}iamq~uep+U=7y5gWYj2QGj zuGX{Jj}s2Vm2PJ3&rSV-pY$wUvTXiFU)O`4;iMkadipx`q-Qi*>DGdHya${0l1dPU z=-4NQ5xee^YSfxPa>{5=zlNC{dj=SYmG1JTOOIW$blH-n%iU$mR<1be@TK?=v1g;s z&fgVp2uo7WD7q_K1;(D0^M|l*cf7jaGwOS-m98I_*Y?dHUN<~A+Yri{-=7^kB%Nwg zhtxkWJ+j?o+O2Z2L&k}puHH1drsufXcq(Gdk9!8gDrVQPzS2Fe5~TA-n&|P(o;B=Q z$x1hDXU=5x@>OpBxjJ+YSnV!bHQ(vo?$424^JhqJGry7cnm;?-Qub#@ulaMMSK5K+ zfc(#kUhdE|&Sh!1edf=KUi0UK?=l$q9|XPZpSt1nX8%I;&iw0;eaV0JUxnF3edb>T znEh+eH~TMvipu^K=rjKUz|86oW##Xqw2*gh#qZ0l_I<`m-(E8S=HTvS*vq*N+<~secA#sa?S6zaDV;&qjXRoIUqWV=)~x7Sh44MRbiUpfinLBa7!6W8qwrTQt{X7EEQtP&mdlGGnn^n_DQ?8jIvw zV}V?oSsd5SSQyuOxkYidC2MmFqL5n*`O1cT?W{$R&z8f>So}<5a`g0N7CnM91KvrQ z!S1B4fsT*5yPnq(Za&&489UrMV|QDZ+1Yp-&3~QjXuP&M>vB8Uy38(ivay4moY}oj z&h1?5XYE?+GdtG$uHDK^jt!ZiYJF~)TAvxBW*a^v!_!c1Xc{txr6FTT8Zw3>h@oic zJ%*v78AH&}tl?)^hMsO4hiC0O!)UA6bA-%(!$)qf;Un|L9y4t0FEhiBN7vpmJZoRc zKV?rD&h00|v-XnV+&%(wdk7z0`^T`ccML}}_Kjg<&)8t>7aKBr#fHp2v0*!V#CG4V z_RdV1*x*mP{WJCkxz059g$(2o|43Kg zAIbFl5#piGk9g?st_m@8ZiMR=B}_RZ($7b>)5lo~?CZ`*SKl7V^lR-Lk#lOMPp>mN z^RUs2yBq#{w}FjD@7-wh+>N#mvAYd0D_c6Kh6*bP&6z4X>>tKN|5t-0?|rl;oL zBbi>BMH%kurFqEaTo28Hv?t}OFw;fzL#^cH9f+=3@*;N>-76Ba2 zh140%bd*t}lgy6HC`*D|jn0vE#AvQ_jB-zvjxn0+6vB)SAxA!v{h7`%)9OvRjuJl#WkD;;-0m;S|$J;H#l`7?p*^Lsu0VXosQQP$c-Q`TI1y1AKv z|91h{WUkknX0Owm&GmWn%yoG)*JGE>z&S0u4riUTCch4!kzIe!%nz3{yVu+Q1CxIS AbN~PV literal 0 HcmV?d00001 diff --git a/src/maemo/easysetup/osso_countries_1.0.po b/src/maemo/easysetup/osso_countries_1.0.po new file mode 100644 index 0000000..e0965c2 --- /dev/null +++ b/src/maemo/easysetup/osso_countries_1.0.po @@ -0,0 +1,906 @@ +# Copyright (C) 2006 Nokia Corporation. +# This file is distributed under the same license as the modest package +# +msgid "" +msgstr "" +"Project-Id-Version: osso_countries-0.1\n" +"Report-Msgid-Bugs-To: dirk-jan.binnema@nokia.com\n" +"POT-Creation-Date: 2007.01.02 11:34+0200\n" +"PO-Revision-Date: 2007.01.02 11:34+0200\n" +"Last-Translator:\n" +"Language-Team: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" # +msgid "osso_db_country_afghanistan" +msgstr "Afghanistan" + +# +msgid "osso_db_country_albania" +msgstr "Albania" + +# +msgid "osso_db_country_algeria" +msgstr "Algeria" + +# +msgid "osso_db_country_american_samoa" +msgstr "American Samoa" + +# +msgid "osso_db_country_andorra" +msgstr "Andorra" + +# +msgid "osso_db_country_angola" +msgstr "Angola" + +# +msgid "osso_db_country_anguilla" +msgstr "Anguilla" + +# +msgid "osso_db_country_antigua_and_barbuda" +msgstr "Antigua and Barbuda" + +# +msgid "osso_db_country_argentina" +msgstr "Argentine Republic" + +# +msgid "osso_db_country_armenia" +msgstr "Armenia" + +# +msgid "osso_db_country_aruba" +msgstr "Aruba" + +# +msgid "osso_db_country_australia" +msgstr "Australia" + +# +msgid "osso_db_country_austria" +msgstr "Austria" + +# +msgid "osso_db_country_azerbaijani_republic" +msgstr "Azerbaijani Republic" + +# +msgid "osso_db_country_bahamas" +msgstr "Bahamas" + +# +msgid "osso_db_country_bahrain" +msgstr "Bahrain" + +# +msgid "osso_db_country_bangladesh" +msgstr "Bangladesh" + +# +msgid "osso_db_country_barbados" +msgstr "Barbados" + +# +msgid "osso_db_country_belarus" +msgstr "Belarus" + +# +msgid "osso_db_country_belgium" +msgstr "Belgium" + +# +msgid "osso_db_country_belize" +msgstr "Belize" + +# +msgid "osso_db_country_benin" +msgstr "Benin" + +# +msgid "osso_db_country_bermuda" +msgstr "Bermuda" + +# +msgid "osso_db_country_bhutan" +msgstr "Bhutan" + +# +msgid "osso_db_country_bolivia" +msgstr "Bolivia" + +# +msgid "osso_db_country_bosnia_and_herzegovina" +msgstr "Bosnia and Herzegovina" + +# +msgid "osso_db_country_botswana" +msgstr "Botswana" + +# +msgid "osso_db_country_brazil" +msgstr "Brazil" + +# +msgid "osso_db_country_british_virgin_islands" +msgstr "British Virgin Islands" + +# +msgid "osso_db_country_brunei_darussalam" +msgstr "Brunei Darussalam" + +# +msgid "osso_db_country_bulgaria" +msgstr "Bulgaria" + +# +msgid "osso_db_country_burkina_faso" +msgstr "Burkina Faso" + +# +msgid "osso_db_country_burundi" +msgstr "Burundi" + +# +msgid "osso_db_country_cambodia" +msgstr "Cambodia" + +# +msgid "osso_db_country_cameroon" +msgstr "Cameroon" + +# +msgid "osso_db_country_canada" +msgstr "Canada" + +# +msgid "osso_db_country_canary_islands_spain" +msgstr "Canary Islands (Spain)" + +# +msgid "osso_db_country_cape_verde" +msgstr "Cape Verde" + +# +msgid "osso_db_country_cayman_islands" +msgstr "Cayman Islands" + +# +msgid "osso_db_country_central_african_republic" +msgstr "Central African Republic" + +# +msgid "osso_db_country_chad" +msgstr "Chad" + +# +msgid "osso_db_country_chile" +msgstr "Chile" + +# +msgid "osso_db_country_china" +msgstr "China" + +# +msgid "osso_db_country_colombia" +msgstr "Colombia" + +# +msgid "osso_db_country_comoros" +msgstr "Comoros" + +# +msgid "osso_db_country_republic_of_the_congo" +msgstr "Republic of the Congo" + +# +msgid "osso_db_country_cook_islands" +msgstr "Cook Islands" + +# +msgid "osso_db_country_costa_rica" +msgstr "Costa Rica" + +# +msgid "osso_db_country_cote_dlvoire" +msgstr "Cote d'Ivoire" + +# +msgid "osso_db_country_croatia" +msgstr "Croatia" + +# +msgid "osso_db_country_cuba" +msgstr "Cuba" + +# +msgid "osso_db_country_cyprus" +msgstr "Cyprus" + +# +msgid "osso_db_country_czech_republic" +msgstr "Czech Republic" + +# +msgid "osso_db_country_democratic_republic_of_the_congo" +msgstr "Democratic Republic of the Congo" + +# +msgid "osso_db_country_denmark" +msgstr "Denmark" + +# +msgid "osso_db_country_djibouti" +msgstr "Djibouti" + +# +msgid "osso_db_country_dominica" +msgstr "Dominica" + +# +msgid "osso_db_country_dominican_republic" +msgstr "Dominican Republic" + +# +msgid "osso_db_country_east_timor" +msgstr "East Timor" + +# +msgid "osso_db_country_ecuador" +msgstr "Ecuador" + +# +msgid "osso_db_country_egypt" +msgstr "Egypt" + +# +msgid "osso_db_country_el_salvador" +msgstr "El Salvador" + +# +msgid "osso_db_country_equatorial_guinea" +msgstr "Equatorial Guinea" + +# +msgid "osso_db_country_eritrea" +msgstr "Eritrea" + +# +msgid "osso_db_country_estonia" +msgstr "Estonia" + +# +msgid "osso_db_country_ethiopia" +msgstr "Ethiopia" + +# +msgid "osso_db_country_faroe_islands" +msgstr "Faroe Islands" + +# +msgid "osso_db_country_fiji" +msgstr "Fiji" + +# +msgid "osso_db_country_finland" +msgstr "Finland" + +# +msgid "osso_db_country_france" +msgstr "France" + +# +msgid "osso_db_country_french_guiana" +msgstr "French Guiana" + +# +msgid "osso_db_country_french_polynesia" +msgstr "French Polynesia" + +# +msgid "osso_db_country_gobonese_republic" +msgstr "Gabonese Republic" + +# +msgid "osso_db_country_gambia" +msgstr "Gambia" + +# +msgid "osso_db_country_georgia" +msgstr "Georgia" + +# +msgid "osso_db_country_germany" +msgstr "Germany" + +# +msgid "osso_db_country_ghana" +msgstr "Ghana" + +# +msgid "osso_db_country_gibraltar" +msgstr "Gibraltar" + +# +msgid "osso_db_country_greece" +msgstr "Greece" + +# +msgid "osso_db_country_greenland" +msgstr "Greenland" + +# +msgid "osso_db_country_hong_kong" +msgstr "Hong Kong, China" + +# +msgid "osso_db_country_grenada" +msgstr "Grenada" + +# +msgid "osso_db_country_guadeloupe" +msgstr "Guadeloupe" + +# +msgid "osso_db_country_guam" +msgstr "Guam" + +# +msgid "osso_db_country_guatemala" +msgstr "Guatemala" + +# +msgid "osso_db_country_guinea" +msgstr "Guinea" + +# +msgid "osso_db_country_guinea_bissaus" +msgstr "Guinea-Bissau" + +# +msgid "osso_db_country_guyana" +msgstr "Guyana" + +# +msgid "osso_db_country_haiti" +msgstr "Haiti" + +# +msgid "osso_db_country_honduras" +msgstr "Honduras" + +# +msgid "osso_db_country_hungary" +msgstr "Hungary" + +# +msgid "osso_db_country_iceland" +msgstr "Iceland" + +# +msgid "osso_db_country_india" +msgstr "India" + +# +msgid "osso_db_country_indonesia" +msgstr "Indonesia" + +# +msgid "osso_db_country_iran" +msgstr "Iran" + +# +msgid "osso_db_country_iraq" +msgstr "Iraq" + +# +msgid "osso_db_country_republic_of_ireland" +msgstr "Ireland" + +# +msgid "osso_db_country_israel" +msgstr "Israel" + +# +msgid "osso_db_country_italy" +msgstr "Italy" + +# +msgid "osso_db_country_jamaica" +msgstr "Jamaica" + +# +msgid "osso_db_country_japan" +msgstr "Japan" + +# +msgid "osso_db_country_jordan" +msgstr "Jordan" + +# +msgid "osso_db_country_kazakhstan" +msgstr "Kazakhstan" + +# +msgid "osso_db_country_kenya" +msgstr "Kenya" + +# +msgid "osso_db_country_kiribati" +msgstr "Kiribati" + +# +msgid "osso_db_country_korea_north" +msgstr "Korea, North" + +# +msgid "osso_db_country_country_south_korea" +msgstr "Korea, South" + +# +msgid "osso_db_country_kuwait" +msgstr "Kuwait" + +# +msgid "osso_db_country_kyrgyz_republic" +msgstr "Kyrgyz Republic" + +# +msgid "osso_db_country_laos" +msgstr "Laos" + +# +msgid "osso_db_country_latvia" +msgstr "Latvia" + +# +msgid "osso_db_country_lebanon" +msgstr "Lebanon" + +# +msgid "osso_db_country_lesotho" +msgstr "Lesotho" + +# +msgid "osso_db_country_liberia" +msgstr "Liberia" + +# +msgid "osso_db_country_libya" +msgstr "Libya" + +# +msgid "osso_db_country_liechtenstein" +msgstr "Liechtenstein" + +# +msgid "osso_db_country_lithuania" +msgstr "Lithuania" + +# +msgid "osso_db_country_luxembourg" +msgstr "Luxembourg" + +# +msgid "osso_db_country_macao" +msgstr "Macao, China" + +# +msgid "osso_db_country_the_former_yugoslav_republic_of_macedonia" +msgstr "Macedonia" + +# +msgid "osso_db_country_madagascar" +msgstr "Madagascar" + +# +msgid "osso_db_country_malawi" +msgstr "Malawi" + +# +msgid "osso_db_country_malaysia" +msgstr "Malaysia" + +# +msgid "osso_db_country_maldives" +msgstr "Maldives" + +# +msgid "osso_db_country_mali" +msgstr "Mali" + +# +msgid "osso_db_country_malta" +msgstr "Malta" + +# +msgid "osso_db_country_marshall_islands" +msgstr "Marshall Islands" + +# +msgid "osso_db_country_martinique" +msgstr "Martinique" + +# +msgid "osso_db_country_mauritania" +msgstr "Mauritania" + +# +msgid "osso_db_country_mauritius" +msgstr "Mauritius" + +# +msgid "osso_db_country_mexico" +msgstr "Mexico" + +# +msgid "osso_db_country_micronesia" +msgstr "Micronesia" + +# +msgid "osso_db_country_republic_of_moldova" +msgstr "Moldova" + +# +msgid "osso_db_country_monaco" +msgstr "Monaco" + +# +msgid "osso_db_country_mongolia" +msgstr "Mongolia" + +# +msgid "osso_db_country_montserrat" +msgstr "Montserrat" + +# +msgid "osso_db_country_morocco" +msgstr "Morocco" + +# +msgid "osso_db_country_mozambique" +msgstr "Mozambique" + +# +msgid "osso_db_country_myanmar" +msgstr "Myanmar" + +# +msgid "osso_db_country_namibia" +msgstr "Namibia" + +# +msgid "osso_db_country_nauru" +msgstr "Nauru" + +# +msgid "osso_db_country_nepal" +msgstr "Nepal" + +# +msgid "osso_db_country_netherlands" +msgstr "Netherlands" + +# +msgid "osso_db_country_netherlands_antilles" +msgstr "Netherlands Antilles" + +# +msgid "osso_db_country_new_caledonia" +msgstr "New Caledonia" + +# +msgid "osso_db_country_new_zealand" +msgstr "New Zealand" + +# +msgid "osso_db_country_nicaraqua" +msgstr "Nicaragua" + +# +msgid "osso_db_country_niger" +msgstr "Niger" + +# +msgid "osso_db_country_nigeria" +msgstr "Nigeria" + +# +msgid "osso_db_country_northern_mariana_islands" +msgstr "Northern Mariana Islands" + +# +msgid "osso_db_country_norway" +msgstr "Norway" + +# +msgid "osso_db_country_oman" +msgstr "Oman" + +# +msgid "osso_db_country_pakistan" +msgstr "Pakistan" + +# +msgid "osso_db_country_palau" +msgstr "Palau" + +# +msgid "osso_db_country_panama" +msgstr "Panama" + +# +msgid "osso_db_country_papua_new_guinea" +msgstr "Papua New Guinea" + +# +msgid "osso_db_country_paraquay" +msgstr "Paraguay" + +# +msgid "osso_db_country_peru" +msgstr "Peru" + +# +msgid "osso_db_country_philippines" +msgstr "Philippines" + +# +msgid "osso_db_country_poland" +msgstr "Poland" + +# +msgid "osso_db_country_portugal" +msgstr "Portugal" + +# +msgid "osso_db_country_puerto_rico" +msgstr "Puerto Rico" + +# +msgid "osso_db_country_qatar" +msgstr "Qatar" + +# +msgid "osso_db_country_reunion" +msgstr "Reunion" + +# +msgid "osso_db_country_romania" +msgstr "Romania" + +# +msgid "osso_db_country_russian_federation" +msgstr "Russian Federation" + +# +msgid "osso_db_country_rwandese_republic" +msgstr "Rwandese Republic" + +# +msgid "osso_db_country_saint_kitts_and_nevis" +msgstr "Saint Kitts and Nevis" + +# +msgid "osso_db_country_saint_lucia" +msgstr "Saint Lucia" + +# +msgid "osso_db_country_saint_pierre_and_miquelon" +msgstr "Saint Pierre and Miquelon" + +# +msgid "osso_db_country_saint_vincent_and_grenadines" +msgstr "Saint Vincent and the Grenadines" + +# +msgid "osso_db_country_samoa" +msgstr "Samoa" + +# +msgid "osso_db_country_san_marino" +msgstr "San Marino" + +# +msgid "osso_db_country_sao_tome_and_principe" +msgstr "Sao Tome and Principe" + +# +msgid "osso_db_country_saudi_arabia" +msgstr "Saudi Arabia" + +# +msgid "osso_db_country_senegal" +msgstr "Senegal" + +# +msgid "osso_db_country_serbia_and_montenegro" +msgstr "Serbia and Montenegro" + +# +msgid "osso_db_country_seychelles" +msgstr "Seychelles" + +# +msgid "osso_db_country_sierra_leone" +msgstr "Sierra Leone" + +# +msgid "osso_db_country_singapore" +msgstr "Singapore" + +# +msgid "osso_db_country_slovakia" +msgstr "Slovakia" + +# +msgid "osso_db_country_slovenia" +msgstr "Slovenia" + +# +msgid "osso_db_country_solomon_islands" +msgstr "Solomon Islands" + +# +msgid "osso_db_country_somalia" +msgstr "Somalia" + +# +msgid "osso_db_country_south_africa" +msgstr "South Africa" + +# +msgid "osso_db_country_spain" +msgstr "Spain" + +# +msgid "osso_db_country_sri_lanka" +msgstr "Sri Lanka" + +# +msgid "osso_db_country_sudan" +msgstr "Sudan" + +# +msgid "osso_db_country_suriname" +msgstr "Suriname" + +# +msgid "osso_db_country_swaziland" +msgstr "Swaziland" + +# +msgid "osso_db_country_sweden" +msgstr "Sweden" + +# +msgid "osso_db_country_switzerland" +msgstr "Switzerland" + +# +msgid "osso_db_country_syrian_arab_republic" +msgstr "Syria" + +# +msgid "osso_db_country_taiwan" +msgstr "Taiwan" + +# +msgid "osso_db_country_tajikistan" +msgstr "Tajikistan" + +# +msgid "osso_db_country_united_republic_of_tanzania" +msgstr "Tanzania" + +# +msgid "osso_db_country_thailand" +msgstr "Thailand" + +# +msgid "osso_db_country_the_vatican" +msgstr "Vatican City State" + +# +msgid "osso_db_country_tibet" +msgstr "Tibet" + +# +msgid "osso_db_country_tunisia" +msgstr "Tunisia" + +# +msgid "osso_db_country_turkey" +msgstr "Turkey" + +# +msgid "osso_db_country_ukraine" +msgstr "Ukraine" + +# +msgid "osso_db_country_united_arab_emirates" +msgstr "United Arab Emirates" + +# +msgid "osso_db_country_united_arab_emirates_abu_dhabi" +msgstr "United Arab Emirates (Abu Dhabi)" + +# +msgid "osso_db_country_united_arab_emirates_dubai" +msgstr "United Arab Emirates (Dubai)" + +# +msgid "osso_db_country_togolese_republic" +msgstr "Togolese Republic" + +# +msgid "osso_db_country_tonga" +msgstr "Tonga" + +# +msgid "osso_db_country_trinidad_and_tobago" +msgstr "Trinidad and Tobago" + +# +msgid "osso_db_country_turkmenistan" +msgstr "Turkmenistan" + +# +msgid "osso_db_country_turks_and_caicos_islands" +msgstr "Turks and Caicos Islands" + +# +msgid "osso_db_country_uganda" +msgstr "Uganda" + +# +msgid "osso_db_country_united_kingdom_of_great_britain_and_northern_ireland" +msgstr "United Kingdom" + +# +msgid "osso_db_country_united_states_of_america" +msgstr "United States of America" + +# +msgid "osso_db_country_unites_states_virgin_islands" +msgstr "United States Virgin Islands" + +# +msgid "osso_db_country_uruguay" +msgstr "Uruguay" + +# +msgid "osso_db_country_uzbekistan" +msgstr "Uzbekistan" + +# +msgid "osso_db_country_vanuatu" +msgstr "Vanuatu" + +# +msgid "osso_db_country_venezuela" +msgstr "Venezuela" + +# +msgid "osso_db_country_viet_nam" +msgstr "Viet Nam" + +# +msgid "osso_db_country_wallis_and_futuna" +msgstr "Wallis and Futuna" + +# +msgid "osso_db_country_yemen" +msgstr "Yemen" + +# +msgid "osso_db_country_zambia" +msgstr "Zambia" + +# +msgid "osso_db_country_zimbabwe" +msgstr "Zimbabwe" + diff --git a/src/maemo/easysetup/provider-data-test.keyfile b/src/maemo/easysetup/provider-data-test.keyfile new file mode 100644 index 0000000..899f6b0 --- /dev/null +++ b/src/maemo/easysetup/provider-data-test.keyfile @@ -0,0 +1,41 @@ +[bla.com] +Name = Bla +Domain=bla.com +MCC=0 +OutgoingMailServer=smtp.bla.com +SecureSmtp=true +IncomingMailServer=pop.bla.com:995 +IncomingSecurity=2 +MailboxType=pop +[foo.com] +Name=Foo +Domain=foo.com +MCC=0 +OutgoingMailServer=mail.foo.com +IncomingMailServer=smtp.foo.com +IncomingSecurity=0 +MailboxType=pop +[xxx.fi] +Name=XXX +Domain=xxx.fi +MCC=244 +OutgoingMailServer=smtp.xxx.fi +IncomingMailServer=mail.xxx.fi +IncomingSecurity=0 +MailboxType=imap +[zzz.fi] +Name=ZZZ +Domain=zzz.fi +MCC=244 +OutgoingMailServer=smtp.zzz.fi +IncomingMailServer=mail.zzz.fi +IncomingSecurity=0 +MailboxType=pop +[rrr.af] +Name=RRR +Domain=rrr.af +MCC=412 +OutgoingMailServer=smtp.rrr.af +IncomingMailServer=mail.rrr.af +IncomingSecurity=0 +MailboxType=imap -- 1.7.9.5
%s%s
%s%s
%s%s
%s%s